diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index a39a90c..e9ea39aa8 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -126,7 +126,8 @@ static int symlook_default(SymLook *, const Obj_Entry *refobj); static int symlook_global(SymLook *, DoneList *); static void symlook_init_from_req(SymLook *, const SymLook *); static int symlook_list(SymLook *, const Objlist *, DoneList *); -static int symlook_needed(SymLook *, const Needed_Entry *, DoneList *); +static int symlook_needed(SymLook *, const Needed_Entry *, DoneList *, + DoneList *); static int symlook_obj1(SymLook *, const Obj_Entry *); static void trace_loaded_objects(Obj_Entry *); static void unlink_object(Obj_Entry *); @@ -2340,12 +2341,14 @@ do_dlsym(void *handle, const char *name, void *retaddr, const Ver_Entry *ve, } } else { Needed_Entry fake; + DoneList depth; /* Search the whole DAG rooted at the given object. */ fake.next = NULL; fake.obj = (Obj_Entry *)obj; fake.name = 0; - res = symlook_needed(&req, &fake, &donelist); + donelist_init(&depth); + res = symlook_needed(&req, &fake, &donelist, &depth); if (res == 0) { def = req.sym_out; defobj = req.defobj_out; @@ -2961,7 +2964,8 @@ symlook_list(SymLook *req, const Objlist *objlist, DoneList *dlp) * definition was found. */ static int -symlook_needed(SymLook *req, const Needed_Entry *needed, DoneList *dlp) +symlook_needed(SymLook *req, const Needed_Entry *needed, DoneList *breadth, + DoneList *depth) { const Elf_Sym *def, *def_w; const Needed_Entry *n; @@ -2973,7 +2977,7 @@ symlook_needed(SymLook *req, const Needed_Entry *needed, DoneList *dlp) defobj = NULL; symlook_init_from_req(&req1, req); for (n = needed; n != NULL; n = n->next) { - if (n->obj == NULL || donelist_check(dlp, n->obj) || + if (n->obj == NULL || donelist_check(breadth, n->obj) || (res = symlook_obj(&req1, n->obj)) != 0) continue; def = req1.sym_out; @@ -2991,7 +2995,9 @@ symlook_needed(SymLook *req, const Needed_Entry *needed, DoneList *dlp) for (n = needed; n != NULL; n = n->next) { if (n->obj == NULL) continue; - res = symlook_needed(&req1, n->obj->needed, dlp); + if (depth != NULL && donelist_check(depth, n->obj)) + continue; + res = symlook_needed(&req1, n->obj->needed, breadth, depth); if (res != 0) continue; def_w = req1.sym_out; @@ -3033,7 +3039,7 @@ symlook_obj(SymLook *req, const Obj_Entry *obj) load_filtees(__DECONST(Obj_Entry *, obj), 0, req->lockstate); donelist_init(&donelist); symlook_init_from_req(&req1, req); - res = symlook_needed(&req1, obj->needed_filtees, &donelist); + res = symlook_needed(&req1, obj->needed_filtees, &donelist, NULL); if (res == 0) { req->sym_out = req1.sym_out; req->defobj_out = req1.defobj_out; @@ -3044,7 +3050,8 @@ symlook_obj(SymLook *req, const Obj_Entry *obj) load_filtees(__DECONST(Obj_Entry *, obj), 0, req->lockstate); donelist_init(&donelist); symlook_init_from_req(&req1, req); - res = symlook_needed(&req1, obj->needed_aux_filtees, &donelist); + res = symlook_needed(&req1, obj->needed_aux_filtees, &donelist, + NULL); if (res == 0) { req->sym_out = req1.sym_out; req->defobj_out = req1.defobj_out;