Eliminate the use of symlook_needed function in favor of DAGS.
Place elements on DAG lists in breadth-first order. This allows us to walk pre-built list in all cases where breadth-first dependency chain enumeration is required. Fix dlsym on special handle obtained by dlopen(NULL, ...) to do what comment claims it does. Take advantage of recently added symlook_global function to iterate over main objects and global DAGs lists properly in search of a symbol. Since rtld itself provides part of the global namespace, search rtld_obj too. Remove recursion from init_dag and symlook_needed functions. Use symlook_needed for ELF filtee processing only and change lookup order used in the function to match the order used by Solaris runtime linker under same circumstances. While there, fix weak symbol handling in the loop so that we return the first weak symbol definition if no strong one was found, instead of the last one. Reviewed by: kib MFC after: 1 month
This commit is contained in:
parent
f21f492510
commit
a04fb11238
@ -93,7 +93,6 @@ static void *fill_search_info(const char *, size_t, void *);
|
|||||||
static char *find_library(const char *, const Obj_Entry *);
|
static char *find_library(const char *, const Obj_Entry *);
|
||||||
static const char *gethints(void);
|
static const char *gethints(void);
|
||||||
static void init_dag(Obj_Entry *);
|
static void init_dag(Obj_Entry *);
|
||||||
static void init_dag1(Obj_Entry *, Obj_Entry *, DoneList *);
|
|
||||||
static void init_rtld(caddr_t, Elf_Auxinfo **);
|
static void init_rtld(caddr_t, Elf_Auxinfo **);
|
||||||
static void initlist_add_neededs(Needed_Entry *, Objlist *);
|
static void initlist_add_neededs(Needed_Entry *, Objlist *);
|
||||||
static void initlist_add_objects(Obj_Entry *, Obj_Entry **, Objlist *);
|
static void initlist_add_objects(Obj_Entry *, Obj_Entry **, Objlist *);
|
||||||
@ -1331,30 +1330,35 @@ gethints(void)
|
|||||||
static void
|
static void
|
||||||
init_dag(Obj_Entry *root)
|
init_dag(Obj_Entry *root)
|
||||||
{
|
{
|
||||||
|
const Needed_Entry *needed;
|
||||||
|
const Objlist_Entry *elm;
|
||||||
DoneList donelist;
|
DoneList donelist;
|
||||||
|
|
||||||
if (root->dag_inited)
|
if (root->dag_inited)
|
||||||
return;
|
return;
|
||||||
donelist_init(&donelist);
|
donelist_init(&donelist);
|
||||||
init_dag1(root, root, &donelist);
|
|
||||||
|
/* Root object belongs to own DAG. */
|
||||||
|
objlist_push_tail(&root->dldags, root);
|
||||||
|
objlist_push_tail(&root->dagmembers, root);
|
||||||
|
donelist_check(&donelist, root);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add dependencies of root object to DAG in breadth order
|
||||||
|
* by exploiting the fact that each new object get added
|
||||||
|
* to the tail of the dagmembers list.
|
||||||
|
*/
|
||||||
|
STAILQ_FOREACH(elm, &root->dagmembers, link) {
|
||||||
|
for (needed = elm->obj->needed; needed != NULL; needed = needed->next) {
|
||||||
|
if (needed->obj == NULL || donelist_check(&donelist, needed->obj))
|
||||||
|
continue;
|
||||||
|
objlist_push_tail(&needed->obj->dldags, root);
|
||||||
|
objlist_push_tail(&root->dagmembers, needed->obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
root->dag_inited = true;
|
root->dag_inited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
init_dag1(Obj_Entry *root, Obj_Entry *obj, DoneList *dlp)
|
|
||||||
{
|
|
||||||
const Needed_Entry *needed;
|
|
||||||
|
|
||||||
if (donelist_check(dlp, obj))
|
|
||||||
return;
|
|
||||||
|
|
||||||
objlist_push_tail(&obj->dldags, root);
|
|
||||||
objlist_push_tail(&root->dagmembers, obj);
|
|
||||||
for (needed = obj->needed; needed != NULL; needed = needed->next)
|
|
||||||
if (needed->obj != NULL)
|
|
||||||
init_dag1(root, needed->obj, dlp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the dynamic linker. The argument is the address at which
|
* Initialize the dynamic linker. The argument is the address at which
|
||||||
* the dynamic linker has been mapped into memory. The primary task of
|
* the dynamic linker has been mapped into memory. The primary task of
|
||||||
@ -2320,32 +2324,28 @@ do_dlsym(void *handle, const char *name, void *retaddr, const Ver_Entry *ve,
|
|||||||
|
|
||||||
donelist_init(&donelist);
|
donelist_init(&donelist);
|
||||||
if (obj->mainprog) {
|
if (obj->mainprog) {
|
||||||
/* Search main program and all libraries loaded by it. */
|
/* Handle obtained by dlopen(NULL, ...) implies global scope. */
|
||||||
res = symlook_list(&req, &list_main, &donelist);
|
res = symlook_global(&req, &donelist);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
def = req.sym_out;
|
def = req.sym_out;
|
||||||
defobj = req.defobj_out;
|
defobj = req.defobj_out;
|
||||||
} else {
|
}
|
||||||
/*
|
/*
|
||||||
* We do not distinguish between 'main' object and
|
* Search the dynamic linker itself, and possibly resolve the
|
||||||
* global scope. If symbol is not defined by objects
|
* symbol from there. This is how the application links to
|
||||||
* loaded at startup, continue search among
|
* dynamic linker services such as dlopen.
|
||||||
* dynamically loaded objects with RTLD_GLOBAL scope.
|
*/
|
||||||
*/
|
if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
|
||||||
res = symlook_list(&req, &list_global, &donelist);
|
res = symlook_obj(&req, &obj_rtld);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
def = req.sym_out;
|
def = req.sym_out;
|
||||||
defobj = req.defobj_out;
|
defobj = req.defobj_out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
Needed_Entry fake;
|
else {
|
||||||
|
|
||||||
/* Search the whole DAG rooted at the given object. */
|
/* Search the whole DAG rooted at the given object. */
|
||||||
fake.next = NULL;
|
res = symlook_list(&req, &obj->dagmembers, &donelist);
|
||||||
fake.obj = (Obj_Entry *)obj;
|
|
||||||
fake.name = 0;
|
|
||||||
res = symlook_needed(&req, &fake, &donelist);
|
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
def = req.sym_out;
|
def = req.sym_out;
|
||||||
defobj = req.defobj_out;
|
defobj = req.defobj_out;
|
||||||
@ -2960,54 +2960,34 @@ symlook_list(SymLook *req, const Objlist *objlist, DoneList *dlp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Search the symbol table of a shared object and all objects needed
|
* Search the chain of DAGS cointed to by the given Needed_Entry
|
||||||
* by it for a symbol of the given name. Search order is
|
* for a symbol of the given name. Each DAG is scanned completely
|
||||||
* breadth-first. Returns a pointer to the symbol, or NULL if no
|
* before advancing to the next one. Returns a pointer to the symbol,
|
||||||
* definition was found.
|
* or NULL if no definition was found.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
symlook_needed(SymLook *req, const Needed_Entry *needed, DoneList *dlp)
|
symlook_needed(SymLook *req, const Needed_Entry *needed, DoneList *dlp)
|
||||||
{
|
{
|
||||||
const Elf_Sym *def, *def_w;
|
const Elf_Sym *def;
|
||||||
const Needed_Entry *n;
|
const Needed_Entry *n;
|
||||||
const Obj_Entry *defobj, *defobj1;
|
const Obj_Entry *defobj;
|
||||||
SymLook req1;
|
SymLook req1;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
def = def_w = NULL;
|
def = NULL;
|
||||||
defobj = NULL;
|
defobj = NULL;
|
||||||
symlook_init_from_req(&req1, req);
|
symlook_init_from_req(&req1, req);
|
||||||
for (n = needed; n != NULL; n = n->next) {
|
for (n = needed; n != NULL; n = n->next) {
|
||||||
if (n->obj == NULL || donelist_check(dlp, n->obj) ||
|
if (n->obj == NULL ||
|
||||||
(res = symlook_obj(&req1, n->obj)) != 0)
|
(res = symlook_list(&req1, &n->obj->dagmembers, dlp)) != 0)
|
||||||
continue;
|
continue;
|
||||||
def = req1.sym_out;
|
if (def == NULL || ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK) {
|
||||||
defobj = req1.defobj_out;
|
def = req1.sym_out;
|
||||||
if (ELF_ST_BIND(def->st_info) != STB_WEAK) {
|
defobj = req1.defobj_out;
|
||||||
req->defobj_out = defobj;
|
if (ELF_ST_BIND(def->st_info) != STB_WEAK)
|
||||||
req->sym_out = def;
|
break;
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* 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 (n->obj == NULL)
|
|
||||||
continue;
|
|
||||||
res = symlook_needed(&req1, n->obj->needed, dlp);
|
|
||||||
if (res != 0)
|
|
||||||
continue;
|
|
||||||
def_w = req1.sym_out;
|
|
||||||
defobj1 = req1.defobj_out;
|
|
||||||
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) {
|
if (def != NULL) {
|
||||||
req->sym_out = def;
|
req->sym_out = def;
|
||||||
req->defobj_out = defobj;
|
req->defobj_out = defobj;
|
||||||
|
Loading…
Reference in New Issue
Block a user