mirror of
https://git.FreeBSD.org/src.git
synced 2024-11-24 07:40:52 +00:00
Fix the buggy rev. 1.117. dagmembers are only initialized for dlopen'ed
dso that are actually loading. If dso a.so depends on b.so, then dlsym with handle from dlopen("b.so") will fail unconditionally. Correct implementation shall use the Obj_Entry.needed list to walk dependencies DAG. Test provided by: jkim Tested (prev. version) by: jkim, Nicolas Blais <nb_root at videotron ca>, h.blanke at chello nl Pointy hat to: kib Approved by: kan (mentor)
This commit is contained in:
parent
b58ab5f02a
commit
5fd885b07b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=162438
@ -125,6 +125,9 @@ static const Elf_Sym *symlook_default(const char *, unsigned long,
|
||||
const Obj_Entry *, const Obj_Entry **, const Ver_Entry *, int);
|
||||
static const Elf_Sym *symlook_list(const char *, unsigned long, const Objlist *,
|
||||
const Obj_Entry **, const Ver_Entry *, int flags, DoneList *);
|
||||
static const Elf_Sym *symlook_needed(const char *, unsigned long,
|
||||
const Needed_Entry *, const Obj_Entry **, const Ver_Entry *,
|
||||
int flags, DoneList *dlp);
|
||||
static void trace_loaded_objects(Obj_Entry *obj);
|
||||
static void unlink_object(Obj_Entry *);
|
||||
static void unload_object(Obj_Entry *);
|
||||
@ -1852,17 +1855,21 @@ do_dlsym(void *handle, const char *name, void *retaddr, const Ver_Entry *ve,
|
||||
}
|
||||
|
||||
DoneList donelist;
|
||||
const Objlist *srch_list;
|
||||
donelist_init(&donelist);
|
||||
if (obj->mainprog) {
|
||||
/* Search main program and all libraries loaded by it. */
|
||||
srch_list = &list_main;
|
||||
def = symlook_list(name, hash, &list_main, &defobj, ve, flags,
|
||||
&donelist);
|
||||
} else {
|
||||
Needed_Entry fake;
|
||||
|
||||
/* Search the whole DAG rooted at the given object. */
|
||||
srch_list = &(obj->dagmembers);
|
||||
fake.next = NULL;
|
||||
fake.obj = (Obj_Entry *)obj;
|
||||
fake.name = 0;
|
||||
def = symlook_needed(name, hash, &fake, &defobj, ve, flags,
|
||||
&donelist);
|
||||
}
|
||||
def = symlook_list(name, hash, srch_list, &defobj, ve, flags,
|
||||
&donelist);
|
||||
}
|
||||
|
||||
if (def != NULL) {
|
||||
@ -2361,6 +2368,57 @@ symlook_list(const char *name, unsigned long hash, const Objlist *objlist,
|
||||
return def;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search the symbol table of a shared object and all objects needed
|
||||
* by it for a symbol of the given name. Search order is
|
||||
* breadth-first. Returns a pointer to the symbol, or NULL if no
|
||||
* definition was found.
|
||||
*/
|
||||
static const Elf_Sym *
|
||||
symlook_needed(const char *name, unsigned long hash, const Needed_Entry *needed,
|
||||
const Obj_Entry **defobj_out, const Ver_Entry *ventry, int flags,
|
||||
DoneList *dlp)
|
||||
{
|
||||
const Elf_Sym *def, *def_w;
|
||||
const Needed_Entry *n;
|
||||
const Obj_Entry *obj, *defobj, *defobj1;
|
||||
|
||||
def = def_w = NULL;
|
||||
defobj = NULL;
|
||||
for (n = needed; n != NULL; n = n->next) {
|
||||
if ((obj = n->obj) == NULL ||
|
||||
donelist_check(dlp, obj) ||
|
||||
(def = symlook_obj(name, hash, obj, ventry, flags)) == NULL)
|
||||
continue;
|
||||
defobj = obj;
|
||||
if (ELF_ST_BIND(def->st_info) != STB_WEAK) {
|
||||
*defobj_out = defobj;
|
||||
return (def);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* There we come when either symbol definition is not found in
|
||||
* directly needed objects, or found symbol is weak.
|
||||
*/
|
||||
for (n = needed; n != NULL; n = n->next) {
|
||||
if ((obj = n->obj) == NULL)
|
||||
continue;
|
||||
def_w = symlook_needed(name, hash, obj->needed, &defobj1,
|
||||
ventry, flags, dlp);
|
||||
if (def_w == NULL)
|
||||
continue;
|
||||
if (def == NULL || ELF_ST_BIND(def_w->st_info) != STB_WEAK) {
|
||||
def = def_w;
|
||||
defobj = defobj1;
|
||||
}
|
||||
if (ELF_ST_BIND(def_w->st_info) != STB_WEAK)
|
||||
break;
|
||||
}
|
||||
if (def != NULL)
|
||||
*defobj_out = defobj;
|
||||
return def;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search the symbol table of a single shared object for a symbol of
|
||||
* the given name and version, if requested. Returns a pointer to the
|
||||
|
Loading…
Reference in New Issue
Block a user