summaryrefslogtreecommitdiff
path: root/libexec/ld.so/dlfcn.c
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2005-09-16 23:19:44 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2005-09-16 23:19:44 +0000
commitaf3616ed51f4eb0fd16d93f503c40bc80f7f50c3 (patch)
tree2580ab1dca2725647349467a20e61a10d25295e0 /libexec/ld.so/dlfcn.c
parent9d9cb5a7061046352d3c2131dcc90e03844265fc (diff)
Rework symbol lookup to more closely match sun's documentation, now
treats dlopens as load groups. ok kurt@
Diffstat (limited to 'libexec/ld.so/dlfcn.c')
-rw-r--r--libexec/ld.so/dlfcn.c60
1 files changed, 35 insertions, 25 deletions
diff --git a/libexec/ld.so/dlfcn.c b/libexec/ld.so/dlfcn.c
index 0095023b1c1..c7e6a5e65b7 100644
--- a/libexec/ld.so/dlfcn.c
+++ b/libexec/ld.so/dlfcn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dlfcn.c,v 1.49 2005/09/13 03:32:15 drahn Exp $ */
+/* $OpenBSD: dlfcn.c,v 1.50 2005/09/16 23:19:41 drahn Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -49,6 +49,7 @@ dlopen(const char *libname, int flags)
{
elf_object_t *object, *dynobj;
Elf_Dyn *dynp;
+ struct dep_node *n;
if (libname == NULL)
return _dl_objects;
@@ -56,18 +57,28 @@ dlopen(const char *libname, int flags)
DL_DEB(("dlopen: loading: %s\n", libname));
_dl_thread_kern_stop();
+
object = _dl_load_shlib(libname, _dl_objects, OBJTYPE_DLO, flags);
if (object == 0) {
_dl_thread_kern_go();
return((void *)0);
}
+ if (object->refcount > 1)
+ return((void *)object); /* Already loaded */
+
/* this add_object should not be here, XXX */
_dl_add_object(object);
- _dl_link_sub(object, _dl_objects);
- _dl_thread_kern_go();
- if (object->refcount > 1)
- return((void *)object); /* Already loaded */
+ DL_DEB(("head [%s]\n", object->load_name ));
+ object->load_object = object;
+ _dl_loading_object = object;
+
+ n = _dl_malloc(sizeof *n);
+ if (n == NULL)
+ _dl_exit(5);
+ n->data = object;
+ TAILQ_INSERT_TAIL(&object->dload_list, n, next_sib);
+
/*
* Check for 'needed' objects. For each 'needed' object we
@@ -90,7 +101,6 @@ dlopen(const char *libname, int flags)
deplibname = dynobj->dyn.strtab + dynp->d_un.d_val;
DL_DEB(("dlopen: loading: %s required by %s\n",
deplibname, libname));
- _dl_thread_kern_stop();
depobj = _dl_load_shlib(deplibname, dynobj, OBJTYPE_LIB,
flags|RTLD_GLOBAL);
if (!depobj)
@@ -98,7 +108,6 @@ dlopen(const char *libname, int flags)
/* this add_object should not be here, XXX */
_dl_add_object(depobj);
_dl_link_sub(depobj, dynobj);
- _dl_thread_kern_go();
tmpobj->dep_next = _dl_malloc(sizeof(elf_object_t));
tmpobj->dep_next->next = depobj;
@@ -107,11 +116,13 @@ dlopen(const char *libname, int flags)
dynobj = dynobj->next;
}
+ _dl_link_dlopen(object);
_dl_rtld(object);
_dl_call_init(object);
- _dl_link_dlopen(object);
+ _dl_loading_object = NULL;
+ DL_DEB(("tail %s\n", object->load_name ));
if (_dl_debug_map->r_brk) {
_dl_debug_map->r_state = RT_ADD;
@@ -120,6 +131,8 @@ dlopen(const char *libname, int flags)
(*((void (*)(void))_dl_debug_map->r_brk))();
}
+ _dl_thread_kern_go();
+
DL_DEB(("dlopen: %s: done.\n", libname));
return((void *)object);
@@ -132,7 +145,7 @@ dlsym(void *handle, const char *name)
elf_object_t *dynobj;
void *retval;
const Elf_Sym *sym = NULL;
- int flags;
+ int flags;
if (handle == NULL || handle == RTLD_NEXT ||
handle == RTLD_SELF) {
@@ -145,25 +158,19 @@ dlsym(void *handle, const char *name)
return(0);
}
- if (handle == RTLD_NEXT) {
- object = object->next;
- if (object == NULL) {
- _dl_errno = DL_NO_SYMBOL;
- return(0);
- }
- }
-
- if (handle == NULL)
+ if (handle == RTLD_NEXT)
+ flags = SYM_SEARCH_NEXT|SYM_PLT;
+ else if (handle == RTLD_SELF)
flags = SYM_SEARCH_SELF|SYM_PLT;
else
- flags = SYM_SEARCH_ALL|SYM_PLT;
+ flags = SYM_DLSYM|SYM_PLT;
} else if (handle == RTLD_DEFAULT) {
object = _dl_objects;
flags = SYM_SEARCH_ALL|SYM_PLT;
} else {
object = (elf_object_t *)handle;
- flags = SYM_SEARCH_SELF|SYM_NOTPLT;
+ flags = SYM_DLSYM|SYM_PLT;
dynobj = _dl_objects;
while (dynobj && dynobj != object)
@@ -175,8 +182,8 @@ dlsym(void *handle, const char *name)
}
}
- retval = (void *)_dl_find_symbol(name, object, &sym, NULL,
- flags|SYM_NOWARNNOTFOUND, 0, object);
+ retval = (void *)_dl_find_symbol(name, &sym,
+ flags|SYM_NOWARNNOTFOUND, 0, object, NULL);
if (sym != NULL) {
retval += sym->st_value;
@@ -219,8 +226,12 @@ dlclose(void *handle)
if (handle == _dl_objects)
return 0;
+ _dl_thread_kern_stop();
+
retval = _dl_real_close(handle);
+ _dl_thread_kern_go();
+
if (_dl_debug_map->r_brk) {
_dl_debug_map->r_state = RT_DELETE;
(*((void (*)(void))_dl_debug_map->r_brk))();
@@ -246,9 +257,10 @@ _dl_real_close(void *handle)
return (1);
}
- _dl_unlink_dlopen(object);
+
_dl_notify_unload_shlib(object);
_dl_run_all_dtors();
+ _dl_unlink_dlopen(object);
_dl_unload_shlib(object);
return (0);
}
@@ -307,8 +319,6 @@ dlerror(void)
void
_dl_show_objects(void)
{
- extern int _dl_symcachestat_hits;
- extern int _dl_symcachestat_lookups;
elf_object_t *object;
char *objtypename;
int outputfd;