Changeset View
Changeset View
Standalone View
Standalone View
libexec/rtld-elf/rtld.c
Show First 20 Lines • Show All 3,631 Lines • ▼ Show 20 Lines | defobj = req.defobj_out; | ||||
handle == RTLD_SELF) { /* ... caller included */ | handle == RTLD_SELF) { /* ... caller included */ | ||||
if (handle == RTLD_NEXT) | if (handle == RTLD_NEXT) | ||||
obj = globallist_next(obj); | obj = globallist_next(obj); | ||||
for (; obj != NULL; obj = TAILQ_NEXT(obj, next)) { | for (; obj != NULL; obj = TAILQ_NEXT(obj, next)) { | ||||
if (obj->marker) | if (obj->marker) | ||||
continue; | continue; | ||||
res = symlook_obj(&req, obj); | res = symlook_obj(&req, obj); | ||||
if (res == 0) { | if (res == 0) { | ||||
if (def == NULL || | |||||
ELF_ST_BIND(req.sym_out->st_info) != STB_WEAK) { | |||||
def = req.sym_out; | def = req.sym_out; | ||||
defobj = req.defobj_out; | defobj = req.defobj_out; | ||||
if (ELF_ST_BIND(def->st_info) != STB_WEAK) | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | |||||
/* | /* | ||||
* Search the dynamic linker itself, and possibly resolve the | * Search the dynamic linker itself, and possibly resolve the | ||||
* symbol from there. This is how the application links to | * symbol from there. This is how the application links to | ||||
* dynamic linker services such as dlopen. | * dynamic linker services such as dlopen. | ||||
*/ | */ | ||||
if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { | if (def == NULL) { | ||||
kib: I suggest you to leave this (and all similar 'search the dynamic linker itself') places intact. | |||||
kibAuthorUnsubmitted Done Inline ActionsAnd one more thing. Perhaps, old behavior should not be removed completely. I suggest to add e.g. the variable ${LD}_WEAK_OLD, which if set, restores the old mode of operation where strong overrides weak (feel free to suggest more adequate name). kib: And one more thing. Perhaps, old behavior should not be removed completely. I suggest to add… | |||||
res = symlook_obj(&req, &obj_rtld); | 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 { | } else { | ||||
assert(handle == RTLD_DEFAULT); | assert(handle == RTLD_DEFAULT); | ||||
Show All 18 Lines | if (obj->mainprog) { | ||||
def = req.sym_out; | def = req.sym_out; | ||||
defobj = req.defobj_out; | defobj = req.defobj_out; | ||||
} | } | ||||
/* | /* | ||||
* Search the dynamic linker itself, and possibly resolve the | * Search the dynamic linker itself, and possibly resolve the | ||||
* symbol from there. This is how the application links to | * symbol from there. This is how the application links to | ||||
* dynamic linker services such as dlopen. | * dynamic linker services such as dlopen. | ||||
*/ | */ | ||||
if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { | if (def == NULL) { | ||||
res = symlook_obj(&req, &obj_rtld); | 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 { | else { | ||||
▲ Show 20 Lines • Show All 546 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
SymLook req1; | SymLook req1; | ||||
const Objlist_Entry *elm; | const Objlist_Entry *elm; | ||||
int res; | int res; | ||||
symlook_init_from_req(&req1, req); | symlook_init_from_req(&req1, req); | ||||
/* Search all objects loaded at program start up. */ | /* Search all objects loaded at program start up. */ | ||||
if (req->defobj_out == NULL || | if (req->defobj_out == NULL) { | ||||
ELF_ST_BIND(req->sym_out->st_info) == STB_WEAK) { | |||||
res = symlook_list(&req1, &list_main, donelist); | res = symlook_list(&req1, &list_main, donelist); | ||||
if (res == 0 && (req->defobj_out == NULL || | if (res == 0) { | ||||
ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK)) { | |||||
req->sym_out = req1.sym_out; | req->sym_out = req1.sym_out; | ||||
req->defobj_out = req1.defobj_out; | req->defobj_out = req1.defobj_out; | ||||
assert(req->defobj_out != NULL); | assert(req->defobj_out != NULL); | ||||
} | } | ||||
} | } | ||||
/* Search all DAGs whose roots are RTLD_GLOBAL objects. */ | /* Search all DAGs whose roots are RTLD_GLOBAL objects. */ | ||||
STAILQ_FOREACH(elm, &list_global, link) { | STAILQ_FOREACH(elm, &list_global, link) { | ||||
if (req->defobj_out != NULL && | if (req->defobj_out != NULL) | ||||
ELF_ST_BIND(req->sym_out->st_info) != STB_WEAK) | |||||
break; | break; | ||||
res = symlook_list(&req1, &elm->obj->dagmembers, donelist); | res = symlook_list(&req1, &elm->obj->dagmembers, donelist); | ||||
if (res == 0 && (req->defobj_out == NULL || | if (res == 0) { | ||||
ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK)) { | |||||
req->sym_out = req1.sym_out; | req->sym_out = req1.sym_out; | ||||
req->defobj_out = req1.defobj_out; | req->defobj_out = req1.defobj_out; | ||||
assert(req->defobj_out != NULL); | assert(req->defobj_out != NULL); | ||||
} | } | ||||
} | } | ||||
return (req->sym_out != NULL ? 0 : ESRCH); | return (req->sym_out != NULL ? 0 : ESRCH); | ||||
} | } | ||||
Show All 28 Lines | assert(req->defobj_out != NULL); | ||||
} | } | ||||
if (refobj->symbolic || req->defobj_out != NULL) | if (refobj->symbolic || req->defobj_out != NULL) | ||||
donelist_check(&donelist, refobj); | donelist_check(&donelist, refobj); | ||||
symlook_global(req, &donelist); | symlook_global(req, &donelist); | ||||
/* Search all dlopened DAGs containing the referencing object. */ | /* Search all dlopened DAGs containing the referencing object. */ | ||||
STAILQ_FOREACH(elm, &refobj->dldags, link) { | STAILQ_FOREACH(elm, &refobj->dldags, link) { | ||||
if (req->sym_out != NULL && | if (req->sym_out != NULL) | ||||
ELF_ST_BIND(req->sym_out->st_info) != STB_WEAK) | |||||
break; | break; | ||||
res = symlook_list(&req1, &elm->obj->dagmembers, &donelist); | res = symlook_list(&req1, &elm->obj->dagmembers, &donelist); | ||||
if (res == 0 && (req->sym_out == NULL || | if (res == 0) { | ||||
ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK)) { | |||||
req->sym_out = req1.sym_out; | req->sym_out = req1.sym_out; | ||||
req->defobj_out = req1.defobj_out; | req->defobj_out = req1.defobj_out; | ||||
assert(req->defobj_out != NULL); | assert(req->defobj_out != NULL); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Search the dynamic linker itself, and possibly resolve the | * Search the dynamic linker itself, and possibly resolve the | ||||
* symbol from there. This is how the application links to | * symbol from there. This is how the application links to | ||||
* dynamic linker services such as dlopen. | * dynamic linker services such as dlopen. | ||||
*/ | */ | ||||
if (req->sym_out == NULL || | if (req->sym_out == NULL) { | ||||
ELF_ST_BIND(req->sym_out->st_info) == STB_WEAK) { | |||||
res = symlook_obj(&req1, &obj_rtld); | res = symlook_obj(&req1, &obj_rtld); | ||||
if (res == 0) { | if (res == 0) { | ||||
req->sym_out = req1.sym_out; | req->sym_out = req1.sym_out; | ||||
req->defobj_out = req1.defobj_out; | req->defobj_out = req1.defobj_out; | ||||
assert(req->defobj_out != NULL); | assert(req->defobj_out != NULL); | ||||
} | } | ||||
} | } | ||||
Show All 11 Lines | symlook_list(SymLook *req, const Objlist *objlist, DoneList *dlp) | ||||
def = NULL; | def = NULL; | ||||
defobj = NULL; | defobj = NULL; | ||||
STAILQ_FOREACH(elm, objlist, link) { | STAILQ_FOREACH(elm, objlist, link) { | ||||
if (donelist_check(dlp, elm->obj)) | if (donelist_check(dlp, elm->obj)) | ||||
continue; | continue; | ||||
symlook_init_from_req(&req1, req); | symlook_init_from_req(&req1, req); | ||||
if ((res = symlook_obj(&req1, elm->obj)) == 0) { | if ((res = symlook_obj(&req1, elm->obj)) == 0) { | ||||
if (def == NULL || ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK) { | if (def == NULL) { | ||||
def = req1.sym_out; | def = req1.sym_out; | ||||
defobj = req1.defobj_out; | defobj = req1.defobj_out; | ||||
if (ELF_ST_BIND(def->st_info) != STB_WEAK) | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (def != NULL) { | if (def != NULL) { | ||||
req->sym_out = def; | req->sym_out = def; | ||||
req->defobj_out = defobj; | req->defobj_out = defobj; | ||||
return (0); | return (0); | ||||
} | } | ||||
Show All 17 Lines | symlook_needed(SymLook *req, const Needed_Entry *needed, DoneList *dlp) | ||||
def = 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 || | if (n->obj == NULL || | ||||
(res = symlook_list(&req1, &n->obj->dagmembers, dlp)) != 0) | (res = symlook_list(&req1, &n->obj->dagmembers, dlp)) != 0) | ||||
continue; | continue; | ||||
if (def == NULL || ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK) { | if (def == NULL) { | ||||
def = req1.sym_out; | def = req1.sym_out; | ||||
defobj = req1.defobj_out; | defobj = req1.defobj_out; | ||||
if (ELF_ST_BIND(def->st_info) != STB_WEAK) | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (def != NULL) { | if (def != NULL) { | ||||
req->sym_out = def; | req->sym_out = def; | ||||
req->defobj_out = defobj; | req->defobj_out = defobj; | ||||
return (0); | return (0); | ||||
} | } | ||||
return (ESRCH); | return (ESRCH); | ||||
▲ Show 20 Lines • Show All 1,486 Lines • Show Last 20 Lines |
I suggest you to leave this (and all similar 'search the dynamic linker itself') places intact. Basically, the biggest issue I am aware of where FreeBSD depends on the strong override of weak, is rtld export. We provide weak symbols like dlopen exported from libc weak, and rtld links to its own definition of the symbols.
If you leave this chunk as is, rtld export should still work. Then I suspect there is nothing else left that depends on this behavior in the base system.