rtld.c (216489) | rtld.c (216695) |
---|---|
1/*- 2 * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra. 3 * Copyright 2003 Alexander Kabaev <kan@FreeBSD.ORG>. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 9 unchanged lines hidden (view full) --- 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * | 1/*- 2 * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra. 3 * Copyright 2003 Alexander Kabaev <kan@FreeBSD.ORG>. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 9 unchanged lines hidden (view full) --- 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * |
26 * $FreeBSD: head/libexec/rtld-elf/rtld.c 216489 2010-12-16 16:56:44Z jh $ | 26 * $FreeBSD: head/libexec/rtld-elf/rtld.c 216695 2010-12-25 08:51:20Z kib $ |
27 */ 28 29/* 30 * Dynamic linker for ELF. 31 * 32 * John Polstra <jdp@polstra.com>. 33 */ 34 --- 31 unchanged lines hidden (view full) --- 66#define PATH_RTLD "/libexec/ld-elf32.so.1" 67#endif 68 69/* Types. */ 70typedef void (*func_ptr_type)(); 71typedef void * (*path_enum_proc) (const char *path, size_t len, void *arg); 72 73/* | 27 */ 28 29/* 30 * Dynamic linker for ELF. 31 * 32 * John Polstra <jdp@polstra.com>. 33 */ 34 --- 31 unchanged lines hidden (view full) --- 66#define PATH_RTLD "/libexec/ld-elf32.so.1" 67#endif 68 69/* Types. */ 70typedef void (*func_ptr_type)(); 71typedef void * (*path_enum_proc) (const char *path, size_t len, void *arg); 72 73/* |
74 * This structure provides a reentrant way to keep a list of objects and 75 * check which ones have already been processed in some way. 76 */ 77typedef struct Struct_DoneList { 78 const Obj_Entry **objs; /* Array of object pointers */ 79 unsigned int num_alloc; /* Allocated size of the array */ 80 unsigned int num_used; /* Number of array slots used */ 81} DoneList; 82 83/* | |
84 * Function declarations. 85 */ 86static const char *basename(const char *); 87static void die(void) __dead2; 88static void digest_dynamic1(Obj_Entry *, int, const Elf_Dyn **, 89 const Elf_Dyn **); 90static void digest_dynamic2(Obj_Entry *, const Elf_Dyn *, const Elf_Dyn *); 91static void digest_dynamic(Obj_Entry *, int); 92static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *); 93static Obj_Entry *dlcheck(void *); | 74 * Function declarations. 75 */ 76static const char *basename(const char *); 77static void die(void) __dead2; 78static void digest_dynamic1(Obj_Entry *, int, const Elf_Dyn **, 79 const Elf_Dyn **); 80static void digest_dynamic2(Obj_Entry *, const Elf_Dyn *, const Elf_Dyn *); 81static void digest_dynamic(Obj_Entry *, int); 82static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *); 83static Obj_Entry *dlcheck(void *); |
84static Obj_Entry *dlopen_object(const char *name, Obj_Entry *refobj, 85 int lo_flags, int mode); |
|
94static Obj_Entry *do_load_object(int, const char *, char *, struct stat *, int); 95static int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *); 96static bool donelist_check(DoneList *, const Obj_Entry *); 97static void errmsg_restore(char *); 98static char *errmsg_save(void); 99static void *fill_search_info(const char *, size_t, void *); 100static char *find_library(const char *, const Obj_Entry *); 101static const char *gethints(void); 102static void init_dag(Obj_Entry *); 103static void init_dag1(Obj_Entry *, Obj_Entry *, DoneList *); 104static void init_rtld(caddr_t, Elf_Auxinfo **); 105static void initlist_add_neededs(Needed_Entry *, Objlist *); 106static void initlist_add_objects(Obj_Entry *, Obj_Entry **, Objlist *); 107static void linkmap_add(Obj_Entry *); 108static void linkmap_delete(Obj_Entry *); | 86static Obj_Entry *do_load_object(int, const char *, char *, struct stat *, int); 87static int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *); 88static bool donelist_check(DoneList *, const Obj_Entry *); 89static void errmsg_restore(char *); 90static char *errmsg_save(void); 91static void *fill_search_info(const char *, size_t, void *); 92static char *find_library(const char *, const Obj_Entry *); 93static const char *gethints(void); 94static void init_dag(Obj_Entry *); 95static void init_dag1(Obj_Entry *, Obj_Entry *, DoneList *); 96static void init_rtld(caddr_t, Elf_Auxinfo **); 97static void initlist_add_neededs(Needed_Entry *, Objlist *); 98static void initlist_add_objects(Obj_Entry *, Obj_Entry **, Objlist *); 99static void linkmap_add(Obj_Entry *); 100static void linkmap_delete(Obj_Entry *); |
101static void load_filtees(Obj_Entry *, int flags, RtldLockState *); 102static void unload_filtees(Obj_Entry *); |
|
109static int load_needed_objects(Obj_Entry *, int); 110static int load_preload_objects(void); 111static Obj_Entry *load_object(const char *, const Obj_Entry *, int); 112static Obj_Entry *obj_from_addr(const void *); | 103static int load_needed_objects(Obj_Entry *, int); 104static int load_preload_objects(void); 105static Obj_Entry *load_object(const char *, const Obj_Entry *, int); 106static Obj_Entry *obj_from_addr(const void *); |
113static void objlist_call_fini(Objlist *, Obj_Entry *, int *); 114static void objlist_call_init(Objlist *, int *); | 107static void objlist_call_fini(Objlist *, Obj_Entry *, RtldLockState *); 108static void objlist_call_init(Objlist *, RtldLockState *); |
115static void objlist_clear(Objlist *); 116static Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *); 117static void objlist_init(Objlist *); 118static void objlist_push_head(Objlist *, Obj_Entry *); 119static void objlist_push_tail(Objlist *, Obj_Entry *); 120static void objlist_remove(Objlist *, Obj_Entry *); 121static void *path_enumerate(const char *, path_enum_proc, void *); | 109static void objlist_clear(Objlist *); 110static Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *); 111static void objlist_init(Objlist *); 112static void objlist_push_head(Objlist *, Obj_Entry *); 113static void objlist_push_tail(Objlist *, Obj_Entry *); 114static void objlist_remove(Objlist *, Obj_Entry *); 115static void *path_enumerate(const char *, path_enum_proc, void *); |
122static int relocate_objects(Obj_Entry *, bool, Obj_Entry *); | 116static int relocate_objects(Obj_Entry *, bool, Obj_Entry *, RtldLockState *); |
123static int rtld_dirname(const char *, char *); 124static int rtld_dirname_abs(const char *, char *); 125static void rtld_exit(void); 126static char *search_library_path(const char *, const char *); 127static const void **get_program_var_addr(const char *); 128static void set_program_var(const char *, const void *); | 117static int rtld_dirname(const char *, char *); 118static int rtld_dirname_abs(const char *, char *); 119static void rtld_exit(void); 120static char *search_library_path(const char *, const char *); 121static const void **get_program_var_addr(const char *); 122static void set_program_var(const char *, const void *); |
129static const Elf_Sym *symlook_default(const char *, unsigned long, 130 const Obj_Entry *, const Obj_Entry **, const Ver_Entry *, int); 131static const Elf_Sym *symlook_list(const char *, unsigned long, const Objlist *, 132 const Obj_Entry **, const Ver_Entry *, int, DoneList *); 133static const Elf_Sym *symlook_needed(const char *, unsigned long, 134 const Needed_Entry *, const Obj_Entry **, const Ver_Entry *, 135 int, DoneList *); | 123static int symlook_default(SymLook *, const Obj_Entry *refobj); 124static void symlook_init_from_req(SymLook *, const SymLook *); 125static int symlook_list(SymLook *, const Objlist *, DoneList *); 126static int symlook_needed(SymLook *, const Needed_Entry *, DoneList *); 127static int symlook_obj1(SymLook *, const Obj_Entry *); |
136static void trace_loaded_objects(Obj_Entry *); 137static void unlink_object(Obj_Entry *); 138static void unload_object(Obj_Entry *); 139static void unref_dag(Obj_Entry *); 140static void ref_dag(Obj_Entry *); 141static int origin_subst_one(char **, const char *, const char *, 142 const char *, char *); 143static char *origin_subst(const char *, const char *); --- 8 unchanged lines hidden (view full) --- 152void r_debug_state(struct r_debug *, struct link_map *); 153 154/* 155 * Data declarations. 156 */ 157static char *error_message; /* Message for dlerror(), or NULL */ 158struct r_debug r_debug; /* for GDB; */ 159static bool libmap_disable; /* Disable libmap */ | 128static void trace_loaded_objects(Obj_Entry *); 129static void unlink_object(Obj_Entry *); 130static void unload_object(Obj_Entry *); 131static void unref_dag(Obj_Entry *); 132static void ref_dag(Obj_Entry *); 133static int origin_subst_one(char **, const char *, const char *, 134 const char *, char *); 135static char *origin_subst(const char *, const char *); --- 8 unchanged lines hidden (view full) --- 144void r_debug_state(struct r_debug *, struct link_map *); 145 146/* 147 * Data declarations. 148 */ 149static char *error_message; /* Message for dlerror(), or NULL */ 150struct r_debug r_debug; /* for GDB; */ 151static bool libmap_disable; /* Disable libmap */ |
152static bool ld_loadfltr; /* Immediate filters processing */ |
|
160static char *libmap_override; /* Maps to use in addition to libmap.conf */ 161static bool trust; /* False for setuid and setgid programs */ 162static bool dangerous_ld_env; /* True if environment variables have been 163 used to affect the libraries loaded */ 164static char *ld_bind_now; /* Environment variable for immediate binding */ 165static char *ld_debug; /* Environment variable for debugging */ 166static char *ld_library_path; /* Environment variable for search path */ 167static char *ld_preload; /* Environment variable for libraries to --- 127 unchanged lines hidden (view full) --- 295 char **env; 296 Elf_Auxinfo *aux; 297 Elf_Auxinfo *auxp; 298 const char *argv0; 299 Objlist_Entry *entry; 300 Obj_Entry *obj; 301 Obj_Entry **preload_tail; 302 Objlist initlist; | 153static char *libmap_override; /* Maps to use in addition to libmap.conf */ 154static bool trust; /* False for setuid and setgid programs */ 155static bool dangerous_ld_env; /* True if environment variables have been 156 used to affect the libraries loaded */ 157static char *ld_bind_now; /* Environment variable for immediate binding */ 158static char *ld_debug; /* Environment variable for debugging */ 159static char *ld_library_path; /* Environment variable for search path */ 160static char *ld_preload; /* Environment variable for libraries to --- 127 unchanged lines hidden (view full) --- 288 char **env; 289 Elf_Auxinfo *aux; 290 Elf_Auxinfo *auxp; 291 const char *argv0; 292 Objlist_Entry *entry; 293 Obj_Entry *obj; 294 Obj_Entry **preload_tail; 295 Objlist initlist; |
303 int lockstate; | 296 RtldLockState lockstate; |
304 305 /* 306 * On entry, the dynamic linker itself has not been relocated yet. 307 * Be very careful not to reference any global data until after 308 * init_rtld has returned. It is OK to reference file-scope statics 309 * and string constants, and to call static and global functions. 310 */ 311 --- 29 unchanged lines hidden (view full) --- 341 * If the process is tainted, then we un-set the dangerous environment 342 * variables. The process will be marked as tainted until setuid(2) 343 * is called. If any child process calls setuid(2) we do not want any 344 * future processes to honor the potentially un-safe variables. 345 */ 346 if (!trust) { 347 if (unsetenv(LD_ "PRELOAD") || unsetenv(LD_ "LIBMAP") || 348 unsetenv(LD_ "LIBRARY_PATH") || unsetenv(LD_ "LIBMAP_DISABLE") || | 297 298 /* 299 * On entry, the dynamic linker itself has not been relocated yet. 300 * Be very careful not to reference any global data until after 301 * init_rtld has returned. It is OK to reference file-scope statics 302 * and string constants, and to call static and global functions. 303 */ 304 --- 29 unchanged lines hidden (view full) --- 334 * If the process is tainted, then we un-set the dangerous environment 335 * variables. The process will be marked as tainted until setuid(2) 336 * is called. If any child process calls setuid(2) we do not want any 337 * future processes to honor the potentially un-safe variables. 338 */ 339 if (!trust) { 340 if (unsetenv(LD_ "PRELOAD") || unsetenv(LD_ "LIBMAP") || 341 unsetenv(LD_ "LIBRARY_PATH") || unsetenv(LD_ "LIBMAP_DISABLE") || |
349 unsetenv(LD_ "DEBUG") || unsetenv(LD_ "ELF_HINTS_PATH")) { | 342 unsetenv(LD_ "DEBUG") || unsetenv(LD_ "ELF_HINTS_PATH") || 343 unsetenv(LD_ "LOADFLTR")) { |
350 _rtld_error("environment corrupt; aborting"); 351 die(); 352 } 353 } 354 ld_debug = getenv(LD_ "DEBUG"); 355 libmap_disable = getenv(LD_ "LIBMAP_DISABLE") != NULL; 356 libmap_override = getenv(LD_ "LIBMAP"); 357 ld_library_path = getenv(LD_ "LIBRARY_PATH"); 358 ld_preload = getenv(LD_ "PRELOAD"); 359 ld_elf_hints_path = getenv(LD_ "ELF_HINTS_PATH"); | 344 _rtld_error("environment corrupt; aborting"); 345 die(); 346 } 347 } 348 ld_debug = getenv(LD_ "DEBUG"); 349 libmap_disable = getenv(LD_ "LIBMAP_DISABLE") != NULL; 350 libmap_override = getenv(LD_ "LIBMAP"); 351 ld_library_path = getenv(LD_ "LIBRARY_PATH"); 352 ld_preload = getenv(LD_ "PRELOAD"); 353 ld_elf_hints_path = getenv(LD_ "ELF_HINTS_PATH"); |
354 ld_loadfltr = getenv(LD_ "LOADFLTR") != NULL; |
|
360 dangerous_ld_env = libmap_disable || (libmap_override != NULL) || 361 (ld_library_path != NULL) || (ld_preload != NULL) || | 355 dangerous_ld_env = libmap_disable || (libmap_override != NULL) || 356 (ld_library_path != NULL) || (ld_preload != NULL) || |
362 (ld_elf_hints_path != NULL); | 357 (ld_elf_hints_path != NULL) || ld_loadfltr; |
363 ld_tracing = getenv(LD_ "TRACE_LOADED_OBJECTS"); 364 ld_utrace = getenv(LD_ "UTRACE"); 365 366 if ((ld_elf_hints_path == NULL) || strlen(ld_elf_hints_path) == 0) 367 ld_elf_hints_path = _PATH_ELF_HINTS; 368 369 if (ld_debug != NULL && *ld_debug != '\0') 370 debug = 1; 371 dbg("%s is initialized, base address = %p", __progname, 372 (caddr_t) aux_info[AT_BASE]->a_un.a_ptr); 373 dbg("RTLD dynamic = %p", obj_rtld.dynamic); 374 dbg("RTLD pltgot = %p", obj_rtld.pltgot); 375 | 358 ld_tracing = getenv(LD_ "TRACE_LOADED_OBJECTS"); 359 ld_utrace = getenv(LD_ "UTRACE"); 360 361 if ((ld_elf_hints_path == NULL) || strlen(ld_elf_hints_path) == 0) 362 ld_elf_hints_path = _PATH_ELF_HINTS; 363 364 if (ld_debug != NULL && *ld_debug != '\0') 365 debug = 1; 366 dbg("%s is initialized, base address = %p", __progname, 367 (caddr_t) aux_info[AT_BASE]->a_un.a_ptr); 368 dbg("RTLD dynamic = %p", obj_rtld.dynamic); 369 dbg("RTLD pltgot = %p", obj_rtld.pltgot); 370 |
371 dbg("initializing thread locks"); 372 lockdflt_init(); 373 |
|
376 /* 377 * Load the main program, or process its program header if it is 378 * already loaded. 379 */ 380 if (aux_info[AT_EXECFD] != NULL) { /* Load the main program. */ 381 int fd = aux_info[AT_EXECFD]->a_un.a_val; 382 dbg("loading main program"); 383 obj_main = map_object(fd, argv0, NULL); --- 109 unchanged lines hidden (view full) --- 493 * Allocate all the initial objects out of the static TLS 494 * block even if they didn't ask for it. 495 */ 496 allocate_tls_offset(entry->obj); 497 } 498 allocate_initial_tls(obj_list); 499 500 if (relocate_objects(obj_main, | 374 /* 375 * Load the main program, or process its program header if it is 376 * already loaded. 377 */ 378 if (aux_info[AT_EXECFD] != NULL) { /* Load the main program. */ 379 int fd = aux_info[AT_EXECFD]->a_un.a_val; 380 dbg("loading main program"); 381 obj_main = map_object(fd, argv0, NULL); --- 109 unchanged lines hidden (view full) --- 491 * Allocate all the initial objects out of the static TLS 492 * block even if they didn't ask for it. 493 */ 494 allocate_tls_offset(entry->obj); 495 } 496 allocate_initial_tls(obj_list); 497 498 if (relocate_objects(obj_main, |
501 ld_bind_now != NULL && *ld_bind_now != '\0', &obj_rtld) == -1) | 499 ld_bind_now != NULL && *ld_bind_now != '\0', &obj_rtld, NULL) == -1) |
502 die(); 503 504 dbg("doing copy relocations"); 505 if (do_copy_relocations(obj_main) == -1) 506 die(); 507 508 if (getenv(LD_ "DUMP_REL_POST") != NULL) { 509 dump_relocations(obj_main); 510 exit (0); 511 } 512 513 dbg("initializing key program variables"); 514 set_program_var("__progname", argv[0] != NULL ? basename(argv[0]) : ""); 515 set_program_var("environ", env); 516 set_program_var("__elf_aux_vector", aux); 517 | 500 die(); 501 502 dbg("doing copy relocations"); 503 if (do_copy_relocations(obj_main) == -1) 504 die(); 505 506 if (getenv(LD_ "DUMP_REL_POST") != NULL) { 507 dump_relocations(obj_main); 508 exit (0); 509 } 510 511 dbg("initializing key program variables"); 512 set_program_var("__progname", argv[0] != NULL ? basename(argv[0]) : ""); 513 set_program_var("environ", env); 514 set_program_var("__elf_aux_vector", aux); 515 |
518 dbg("initializing thread locks"); 519 lockdflt_init(); 520 | |
521 /* Make a list of init functions to call. */ 522 objlist_init(&initlist); 523 initlist_add_objects(obj_list, preload_tail, &initlist); 524 525 r_debug_state(NULL, &obj_main->linkmap); /* say hello to gdb! */ 526 | 516 /* Make a list of init functions to call. */ 517 objlist_init(&initlist); 518 initlist_add_objects(obj_list, preload_tail, &initlist); 519 520 r_debug_state(NULL, &obj_main->linkmap); /* say hello to gdb! */ 521 |
527 lockstate = wlock_acquire(rtld_bind_lock); | 522 wlock_acquire(rtld_bind_lock, &lockstate); |
528 objlist_call_init(&initlist, &lockstate); 529 objlist_clear(&initlist); | 523 objlist_call_init(&initlist, &lockstate); 524 objlist_clear(&initlist); |
530 wlock_release(rtld_bind_lock, lockstate); | 525 dbg("loading filtees"); 526 for (obj = obj_list->next; obj != NULL; obj = obj->next) { 527 if (ld_loadfltr || obj->z_loadfltr) 528 load_filtees(obj, 0, &lockstate); 529 } 530 lock_release(rtld_bind_lock, &lockstate); |
531 532 dbg("transferring control to program entry point = %p", obj_main->entry); 533 534 /* Return the exit procedure and the program entry point. */ 535 *exit_proc = rtld_exit; 536 *objp = obj_main; 537 return (func_ptr_type) obj_main->entry; 538} 539 540Elf_Addr 541_rtld_bind(Obj_Entry *obj, Elf_Size reloff) 542{ 543 const Elf_Rel *rel; 544 const Elf_Sym *def; 545 const Obj_Entry *defobj; 546 Elf_Addr *where; 547 Elf_Addr target; | 531 532 dbg("transferring control to program entry point = %p", obj_main->entry); 533 534 /* Return the exit procedure and the program entry point. */ 535 *exit_proc = rtld_exit; 536 *objp = obj_main; 537 return (func_ptr_type) obj_main->entry; 538} 539 540Elf_Addr 541_rtld_bind(Obj_Entry *obj, Elf_Size reloff) 542{ 543 const Elf_Rel *rel; 544 const Elf_Sym *def; 545 const Obj_Entry *defobj; 546 Elf_Addr *where; 547 Elf_Addr target; |
548 int lockstate; | 548 RtldLockState lockstate; |
549 | 549 |
550 lockstate = rlock_acquire(rtld_bind_lock); | 550 rlock_acquire(rtld_bind_lock, &lockstate); 551 if (setjmp(lockstate.env) != 0) 552 lock_upgrade(rtld_bind_lock, &lockstate); |
551 if (obj->pltrel) 552 rel = (const Elf_Rel *) ((caddr_t) obj->pltrel + reloff); 553 else 554 rel = (const Elf_Rel *) ((caddr_t) obj->pltrela + reloff); 555 556 where = (Elf_Addr *) (obj->relocbase + rel->r_offset); | 553 if (obj->pltrel) 554 rel = (const Elf_Rel *) ((caddr_t) obj->pltrel + reloff); 555 else 556 rel = (const Elf_Rel *) ((caddr_t) obj->pltrela + reloff); 557 558 where = (Elf_Addr *) (obj->relocbase + rel->r_offset); |
557 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL); | 559 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL, 560 &lockstate); |
558 if (def == NULL) 559 die(); 560 561 target = (Elf_Addr)(defobj->relocbase + def->st_value); 562 563 dbg("\"%s\" in \"%s\" ==> %p in \"%s\"", 564 defobj->strtab + def->st_name, basename(obj->path), 565 (void *)target, basename(defobj->path)); 566 567 /* 568 * Write the new contents for the jmpslot. Note that depending on 569 * architecture, the value which we need to return back to the 570 * lazy binding trampoline may or may not be the target 571 * address. The value returned from reloc_jmpslot() is the value 572 * that the trampoline needs. 573 */ 574 target = reloc_jmpslot(where, target, defobj, obj, rel); | 561 if (def == NULL) 562 die(); 563 564 target = (Elf_Addr)(defobj->relocbase + def->st_value); 565 566 dbg("\"%s\" in \"%s\" ==> %p in \"%s\"", 567 defobj->strtab + def->st_name, basename(obj->path), 568 (void *)target, basename(defobj->path)); 569 570 /* 571 * Write the new contents for the jmpslot. Note that depending on 572 * architecture, the value which we need to return back to the 573 * lazy binding trampoline may or may not be the target 574 * address. The value returned from reloc_jmpslot() is the value 575 * that the trampoline needs. 576 */ 577 target = reloc_jmpslot(where, target, defobj, obj, rel); |
575 rlock_release(rtld_bind_lock, lockstate); | 578 lock_release(rtld_bind_lock, &lockstate); |
576 return target; 577} 578 579/* 580 * Error reporting function. Use it like printf. If formats the message 581 * into a buffer, and sets things up so that the next call to dlerror() 582 * will return the message. 583 */ --- 132 unchanged lines hidden (view full) --- 716 * information in its Obj_Entry structure. 717 */ 718static void 719digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath, 720 const Elf_Dyn **dyn_soname) 721{ 722 const Elf_Dyn *dynp; 723 Needed_Entry **needed_tail = &obj->needed; | 579 return target; 580} 581 582/* 583 * Error reporting function. Use it like printf. If formats the message 584 * into a buffer, and sets things up so that the next call to dlerror() 585 * will return the message. 586 */ --- 132 unchanged lines hidden (view full) --- 719 * information in its Obj_Entry structure. 720 */ 721static void 722digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath, 723 const Elf_Dyn **dyn_soname) 724{ 725 const Elf_Dyn *dynp; 726 Needed_Entry **needed_tail = &obj->needed; |
727 Needed_Entry **needed_filtees_tail = &obj->needed_filtees; 728 Needed_Entry **needed_aux_filtees_tail = &obj->needed_aux_filtees; |
|
724 int plttype = DT_REL; 725 726 *dyn_rpath = NULL; 727 *dyn_soname = NULL; 728 729 obj->bind_now = false; 730 for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; dynp++) { 731 switch (dynp->d_tag) { --- 94 unchanged lines hidden (view full) --- 826 nep->obj = NULL; 827 nep->next = NULL; 828 829 *needed_tail = nep; 830 needed_tail = &nep->next; 831 } 832 break; 833 | 729 int plttype = DT_REL; 730 731 *dyn_rpath = NULL; 732 *dyn_soname = NULL; 733 734 obj->bind_now = false; 735 for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; dynp++) { 736 switch (dynp->d_tag) { --- 94 unchanged lines hidden (view full) --- 831 nep->obj = NULL; 832 nep->next = NULL; 833 834 *needed_tail = nep; 835 needed_tail = &nep->next; 836 } 837 break; 838 |
839 case DT_FILTER: 840 if (!obj->rtld) { 841 Needed_Entry *nep = NEW(Needed_Entry); 842 nep->name = dynp->d_un.d_val; 843 nep->obj = NULL; 844 nep->next = NULL; 845 846 *needed_filtees_tail = nep; 847 needed_filtees_tail = &nep->next; 848 } 849 break; 850 851 case DT_AUXILIARY: 852 if (!obj->rtld) { 853 Needed_Entry *nep = NEW(Needed_Entry); 854 nep->name = dynp->d_un.d_val; 855 nep->obj = NULL; 856 nep->next = NULL; 857 858 *needed_aux_filtees_tail = nep; 859 needed_aux_filtees_tail = &nep->next; 860 } 861 break; 862 |
|
834 case DT_PLTGOT: 835 obj->pltgot = (Elf_Addr *) (obj->relocbase + dynp->d_un.d_ptr); 836 break; 837 838 case DT_TEXTREL: 839 obj->textrel = true; 840 break; 841 --- 76 unchanged lines hidden (view full) --- 918 if ((dynp->d_un.d_val & DF_1_ORIGIN) && trust) 919 obj->z_origin = true; 920 if (dynp->d_un.d_val & DF_1_GLOBAL) 921 /* XXX */; 922 if (dynp->d_un.d_val & DF_1_BIND_NOW) 923 obj->bind_now = true; 924 if (dynp->d_un.d_val & DF_1_NODELETE) 925 obj->z_nodelete = true; | 863 case DT_PLTGOT: 864 obj->pltgot = (Elf_Addr *) (obj->relocbase + dynp->d_un.d_ptr); 865 break; 866 867 case DT_TEXTREL: 868 obj->textrel = true; 869 break; 870 --- 76 unchanged lines hidden (view full) --- 947 if ((dynp->d_un.d_val & DF_1_ORIGIN) && trust) 948 obj->z_origin = true; 949 if (dynp->d_un.d_val & DF_1_GLOBAL) 950 /* XXX */; 951 if (dynp->d_un.d_val & DF_1_BIND_NOW) 952 obj->bind_now = true; 953 if (dynp->d_un.d_val & DF_1_NODELETE) 954 obj->z_nodelete = true; |
955 if (dynp->d_un.d_val & DF_1_LOADFLTR) 956 obj->z_loadfltr = true; |
|
926 break; 927 928 default: 929 if (!early) { 930 dbg("Ignoring d_tag %ld = %#lx", (long)dynp->d_tag, 931 (long)dynp->d_tag); 932 } 933 break; --- 224 unchanged lines hidden (view full) --- 1158/* 1159 * Given a symbol number in a referencing object, find the corresponding 1160 * definition of the symbol. Returns a pointer to the symbol, or NULL if 1161 * no definition was found. Returns a pointer to the Obj_Entry of the 1162 * defining object via the reference parameter DEFOBJ_OUT. 1163 */ 1164const Elf_Sym * 1165find_symdef(unsigned long symnum, const Obj_Entry *refobj, | 957 break; 958 959 default: 960 if (!early) { 961 dbg("Ignoring d_tag %ld = %#lx", (long)dynp->d_tag, 962 (long)dynp->d_tag); 963 } 964 break; --- 224 unchanged lines hidden (view full) --- 1189/* 1190 * Given a symbol number in a referencing object, find the corresponding 1191 * definition of the symbol. Returns a pointer to the symbol, or NULL if 1192 * no definition was found. Returns a pointer to the Obj_Entry of the 1193 * defining object via the reference parameter DEFOBJ_OUT. 1194 */ 1195const Elf_Sym * 1196find_symdef(unsigned long symnum, const Obj_Entry *refobj, |
1166 const Obj_Entry **defobj_out, int flags, SymCache *cache) | 1197 const Obj_Entry **defobj_out, int flags, SymCache *cache, 1198 RtldLockState *lockstate) |
1167{ 1168 const Elf_Sym *ref; 1169 const Elf_Sym *def; 1170 const Obj_Entry *defobj; | 1199{ 1200 const Elf_Sym *ref; 1201 const Elf_Sym *def; 1202 const Obj_Entry *defobj; |
1171 const Ver_Entry *ventry; | 1203 SymLook req; |
1172 const char *name; | 1204 const char *name; |
1173 unsigned long hash; | 1205 int res; |
1174 1175 /* 1176 * If we have already found this symbol, get the information from 1177 * the cache. 1178 */ 1179 if (symnum >= refobj->nchains) 1180 return NULL; /* Bad object */ 1181 if (cache != NULL && cache[symnum].sym != NULL) { 1182 *defobj_out = cache[symnum].obj; 1183 return cache[symnum].sym; 1184 } 1185 1186 ref = refobj->symtab + symnum; 1187 name = refobj->strtab + ref->st_name; | 1206 1207 /* 1208 * If we have already found this symbol, get the information from 1209 * the cache. 1210 */ 1211 if (symnum >= refobj->nchains) 1212 return NULL; /* Bad object */ 1213 if (cache != NULL && cache[symnum].sym != NULL) { 1214 *defobj_out = cache[symnum].obj; 1215 return cache[symnum].sym; 1216 } 1217 1218 ref = refobj->symtab + symnum; 1219 name = refobj->strtab + ref->st_name; |
1220 def = NULL; |
|
1188 defobj = NULL; 1189 1190 /* 1191 * We don't have to do a full scale lookup if the symbol is local. 1192 * We know it will bind to the instance in this load module; to 1193 * which we already have a pointer (ie ref). By not doing a lookup, 1194 * we not only improve performance, but it also avoids unresolvable 1195 * symbols when local symbols are not in the hash table. This has 1196 * been seen with the ia64 toolchain. 1197 */ 1198 if (ELF_ST_BIND(ref->st_info) != STB_LOCAL) { 1199 if (ELF_ST_TYPE(ref->st_info) == STT_SECTION) { 1200 _rtld_error("%s: Bogus symbol table entry %lu", refobj->path, 1201 symnum); 1202 } | 1221 defobj = NULL; 1222 1223 /* 1224 * We don't have to do a full scale lookup if the symbol is local. 1225 * We know it will bind to the instance in this load module; to 1226 * which we already have a pointer (ie ref). By not doing a lookup, 1227 * we not only improve performance, but it also avoids unresolvable 1228 * symbols when local symbols are not in the hash table. This has 1229 * been seen with the ia64 toolchain. 1230 */ 1231 if (ELF_ST_BIND(ref->st_info) != STB_LOCAL) { 1232 if (ELF_ST_TYPE(ref->st_info) == STT_SECTION) { 1233 _rtld_error("%s: Bogus symbol table entry %lu", refobj->path, 1234 symnum); 1235 } |
1203 ventry = fetch_ventry(refobj, symnum); 1204 hash = elf_hash(name); 1205 def = symlook_default(name, hash, refobj, &defobj, ventry, flags); | 1236 symlook_init(&req, name); 1237 req.flags = flags; 1238 req.ventry = fetch_ventry(refobj, symnum); 1239 req.lockstate = lockstate; 1240 res = symlook_default(&req, refobj); 1241 if (res == 0) { 1242 def = req.sym_out; 1243 defobj = req.defobj_out; 1244 } |
1206 } else { 1207 def = ref; 1208 defobj = refobj; 1209 } 1210 1211 /* 1212 * If we found no definition and the reference is weak, treat the 1213 * symbol as having the value zero. --- 117 unchanged lines hidden (view full) --- 1331 assert(!objtmp.textrel); 1332#endif 1333 1334 /* 1335 * Temporarily put the dynamic linker entry into the object list, so 1336 * that symbols can be found. 1337 */ 1338 | 1245 } else { 1246 def = ref; 1247 defobj = refobj; 1248 } 1249 1250 /* 1251 * If we found no definition and the reference is weak, treat the 1252 * symbol as having the value zero. --- 117 unchanged lines hidden (view full) --- 1370 assert(!objtmp.textrel); 1371#endif 1372 1373 /* 1374 * Temporarily put the dynamic linker entry into the object list, so 1375 * that symbols can be found. 1376 */ 1377 |
1339 relocate_objects(&objtmp, true, &objtmp); | 1378 relocate_objects(&objtmp, true, &objtmp, NULL); |
1340 } 1341 1342 /* Initialize the object list. */ 1343 obj_tail = &obj_list; 1344 1345 /* Now that non-local variables can be accesses, copy out obj_rtld. */ 1346 memcpy(&obj_rtld, &objtmp, sizeof(obj_rtld)); 1347 --- 63 unchanged lines hidden (view full) --- 1411 obj->on_fini_list = true; 1412 } 1413} 1414 1415#ifndef FPTR_TARGET 1416#define FPTR_TARGET(f) ((Elf_Addr) (f)) 1417#endif 1418 | 1379 } 1380 1381 /* Initialize the object list. */ 1382 obj_tail = &obj_list; 1383 1384 /* Now that non-local variables can be accesses, copy out obj_rtld. */ 1385 memcpy(&obj_rtld, &objtmp, sizeof(obj_rtld)); 1386 --- 63 unchanged lines hidden (view full) --- 1450 obj->on_fini_list = true; 1451 } 1452} 1453 1454#ifndef FPTR_TARGET 1455#define FPTR_TARGET(f) ((Elf_Addr) (f)) 1456#endif 1457 |
1458static void 1459free_needed_filtees(Needed_Entry *n) 1460{ 1461 Needed_Entry *needed, *needed1; 1462 1463 for (needed = n; needed != NULL; needed = needed->next) { 1464 if (needed->obj != NULL) { 1465 dlclose(needed->obj); 1466 needed->obj = NULL; 1467 } 1468 } 1469 for (needed = n; needed != NULL; needed = needed1) { 1470 needed1 = needed->next; 1471 free(needed); 1472 } 1473} 1474 1475static void 1476unload_filtees(Obj_Entry *obj) 1477{ 1478 1479 free_needed_filtees(obj->needed_filtees); 1480 obj->needed_filtees = NULL; 1481 free_needed_filtees(obj->needed_aux_filtees); 1482 obj->needed_aux_filtees = NULL; 1483 obj->filtees_loaded = false; 1484} 1485 1486static void 1487load_filtee1(Obj_Entry *obj, Needed_Entry *needed, int flags) 1488{ 1489 1490 for (; needed != NULL; needed = needed->next) { 1491 needed->obj = dlopen_object(obj->strtab + needed->name, obj, 1492 flags, ((ld_loadfltr || obj->z_loadfltr) ? RTLD_NOW : RTLD_LAZY) | 1493 RTLD_LOCAL); 1494 } 1495} 1496 1497static void 1498load_filtees(Obj_Entry *obj, int flags, RtldLockState *lockstate) 1499{ 1500 1501 lock_restart_for_upgrade(lockstate); 1502 if (!obj->filtees_loaded) { 1503 load_filtee1(obj, obj->needed_filtees, flags); 1504 load_filtee1(obj, obj->needed_aux_filtees, flags); 1505 obj->filtees_loaded = true; 1506 } 1507} 1508 1509static int 1510process_needed(Obj_Entry *obj, Needed_Entry *needed, int flags) 1511{ 1512 Obj_Entry *obj1; 1513 1514 for (; needed != NULL; needed = needed->next) { 1515 obj1 = needed->obj = load_object(obj->strtab + needed->name, obj, 1516 flags & ~RTLD_LO_NOLOAD); 1517 if (obj1 == NULL && !ld_tracing && (flags & RTLD_LO_FILTEES) == 0) 1518 return (-1); 1519 if (obj1 != NULL && obj1->z_nodelete && !obj1->ref_nodel) { 1520 dbg("obj %s nodelete", obj1->path); 1521 init_dag(obj1); 1522 ref_dag(obj1); 1523 obj1->ref_nodel = true; 1524 } 1525 } 1526 return (0); 1527} 1528 |
|
1419/* 1420 * Given a shared object, traverse its list of needed objects, and load 1421 * each of them. Returns 0 on success. Generates an error message and 1422 * returns -1 on failure. 1423 */ 1424static int 1425load_needed_objects(Obj_Entry *first, int flags) 1426{ | 1529/* 1530 * Given a shared object, traverse its list of needed objects, and load 1531 * each of them. Returns 0 on success. Generates an error message and 1532 * returns -1 on failure. 1533 */ 1534static int 1535load_needed_objects(Obj_Entry *first, int flags) 1536{ |
1427 Obj_Entry *obj, *obj1; | 1537 Obj_Entry *obj; |
1428 1429 for (obj = first; obj != NULL; obj = obj->next) { | 1538 1539 for (obj = first; obj != NULL; obj = obj->next) { |
1430 Needed_Entry *needed; 1431 1432 for (needed = obj->needed; needed != NULL; needed = needed->next) { 1433 obj1 = needed->obj = load_object(obj->strtab + needed->name, obj, 1434 flags & ~RTLD_LO_NOLOAD); 1435 if (obj1 == NULL && !ld_tracing) 1436 return -1; 1437 if (obj1 != NULL && obj1->z_nodelete && !obj1->ref_nodel) { 1438 dbg("obj %s nodelete", obj1->path); 1439 init_dag(obj1); 1440 ref_dag(obj1); 1441 obj1->ref_nodel = true; 1442 } 1443 } | 1540 if (process_needed(obj, obj->needed, flags) == -1) 1541 return (-1); |
1444 } | 1542 } |
1445 1446 return 0; | 1543 return (0); |
1447} 1448 1449static int 1450load_preload_objects(void) 1451{ 1452 char *p = ld_preload; 1453 static const char delim[] = " \t:;"; 1454 --- 155 unchanged lines hidden (view full) --- 1610/* 1611 * Call the finalization functions for each of the objects in "list" 1612 * belonging to the DAG of "root" and referenced once. If NULL "root" 1613 * is specified, every finalization function will be called regardless 1614 * of the reference count and the list elements won't be freed. All of 1615 * the objects are expected to have non-NULL fini functions. 1616 */ 1617static void | 1544} 1545 1546static int 1547load_preload_objects(void) 1548{ 1549 char *p = ld_preload; 1550 static const char delim[] = " \t:;"; 1551 --- 155 unchanged lines hidden (view full) --- 1707/* 1708 * Call the finalization functions for each of the objects in "list" 1709 * belonging to the DAG of "root" and referenced once. If NULL "root" 1710 * is specified, every finalization function will be called regardless 1711 * of the reference count and the list elements won't be freed. All of 1712 * the objects are expected to have non-NULL fini functions. 1713 */ 1714static void |
1618objlist_call_fini(Objlist *list, Obj_Entry *root, int *lockstate) | 1715objlist_call_fini(Objlist *list, Obj_Entry *root, RtldLockState *lockstate) |
1619{ 1620 Objlist_Entry *elm; 1621 char *saved_msg; 1622 1623 assert(root == NULL || root->refcount == 1); 1624 1625 /* 1626 * Preserve the current error message since a fini function might --- 13 unchanged lines hidden (view full) --- 1640 STAILQ_REMOVE(list, elm, Struct_Objlist_Entry, link); 1641 /* 1642 * XXX: If a dlopen() call references an object while the 1643 * fini function is in progress, we might end up trying to 1644 * unload the referenced object in dlclose() or the object 1645 * won't be unloaded although its fini function has been 1646 * called. 1647 */ | 1716{ 1717 Objlist_Entry *elm; 1718 char *saved_msg; 1719 1720 assert(root == NULL || root->refcount == 1); 1721 1722 /* 1723 * Preserve the current error message since a fini function might --- 13 unchanged lines hidden (view full) --- 1737 STAILQ_REMOVE(list, elm, Struct_Objlist_Entry, link); 1738 /* 1739 * XXX: If a dlopen() call references an object while the 1740 * fini function is in progress, we might end up trying to 1741 * unload the referenced object in dlclose() or the object 1742 * won't be unloaded although its fini function has been 1743 * called. 1744 */ |
1648 wlock_release(rtld_bind_lock, *lockstate); | 1745 lock_release(rtld_bind_lock, lockstate); |
1649 call_initfini_pointer(elm->obj, elm->obj->fini); | 1746 call_initfini_pointer(elm->obj, elm->obj->fini); |
1650 *lockstate = wlock_acquire(rtld_bind_lock); | 1747 wlock_acquire(rtld_bind_lock, lockstate); |
1651 /* No need to free anything if process is going down. */ 1652 if (root != NULL) 1653 free(elm); 1654 /* 1655 * We must restart the list traversal after every fini call 1656 * because a dlclose() call from the fini function or from 1657 * another thread might have modified the reference counts. 1658 */ --- 4 unchanged lines hidden (view full) --- 1663} 1664 1665/* 1666 * Call the initialization functions for each of the objects in 1667 * "list". All of the objects are expected to have non-NULL init 1668 * functions. 1669 */ 1670static void | 1748 /* No need to free anything if process is going down. */ 1749 if (root != NULL) 1750 free(elm); 1751 /* 1752 * We must restart the list traversal after every fini call 1753 * because a dlclose() call from the fini function or from 1754 * another thread might have modified the reference counts. 1755 */ --- 4 unchanged lines hidden (view full) --- 1760} 1761 1762/* 1763 * Call the initialization functions for each of the objects in 1764 * "list". All of the objects are expected to have non-NULL init 1765 * functions. 1766 */ 1767static void |
1671objlist_call_init(Objlist *list, int *lockstate) | 1768objlist_call_init(Objlist *list, RtldLockState *lockstate) |
1672{ 1673 Objlist_Entry *elm; 1674 Obj_Entry *obj; 1675 char *saved_msg; 1676 1677 /* 1678 * Clean init_scanned flag so that objects can be rechecked and 1679 * possibly initialized earlier if any of vectors called below --- 15 unchanged lines hidden (view full) --- 1695 LD_UTRACE(UTRACE_INIT_CALL, elm->obj, (void *)elm->obj->init, 0, 0, 1696 elm->obj->path); 1697 /* 1698 * Race: other thread might try to use this object before current 1699 * one completes the initilization. Not much can be done here 1700 * without better locking. 1701 */ 1702 elm->obj->init_done = true; | 1769{ 1770 Objlist_Entry *elm; 1771 Obj_Entry *obj; 1772 char *saved_msg; 1773 1774 /* 1775 * Clean init_scanned flag so that objects can be rechecked and 1776 * possibly initialized earlier if any of vectors called below --- 15 unchanged lines hidden (view full) --- 1792 LD_UTRACE(UTRACE_INIT_CALL, elm->obj, (void *)elm->obj->init, 0, 0, 1793 elm->obj->path); 1794 /* 1795 * Race: other thread might try to use this object before current 1796 * one completes the initilization. Not much can be done here 1797 * without better locking. 1798 */ 1799 elm->obj->init_done = true; |
1703 wlock_release(rtld_bind_lock, *lockstate); | 1800 lock_release(rtld_bind_lock, lockstate); |
1704 call_initfini_pointer(elm->obj, elm->obj->init); | 1801 call_initfini_pointer(elm->obj, elm->obj->init); |
1705 *lockstate = wlock_acquire(rtld_bind_lock); | 1802 wlock_acquire(rtld_bind_lock, lockstate); |
1706 } 1707 errmsg_restore(saved_msg); 1708} 1709 1710static void 1711objlist_clear(Objlist *list) 1712{ 1713 Objlist_Entry *elm; --- 55 unchanged lines hidden (view full) --- 1769 1770/* 1771 * Relocate newly-loaded shared objects. The argument is a pointer to 1772 * the Obj_Entry for the first such object. All objects from the first 1773 * to the end of the list of objects are relocated. Returns 0 on success, 1774 * or -1 on failure. 1775 */ 1776static int | 1803 } 1804 errmsg_restore(saved_msg); 1805} 1806 1807static void 1808objlist_clear(Objlist *list) 1809{ 1810 Objlist_Entry *elm; --- 55 unchanged lines hidden (view full) --- 1866 1867/* 1868 * Relocate newly-loaded shared objects. The argument is a pointer to 1869 * the Obj_Entry for the first such object. All objects from the first 1870 * to the end of the list of objects are relocated. Returns 0 on success, 1871 * or -1 on failure. 1872 */ 1873static int |
1777relocate_objects(Obj_Entry *first, bool bind_now, Obj_Entry *rtldobj) | 1874relocate_objects(Obj_Entry *first, bool bind_now, Obj_Entry *rtldobj, 1875 RtldLockState *lockstate) |
1778{ 1779 Obj_Entry *obj; 1780 1781 for (obj = first; obj != NULL; obj = obj->next) { 1782 if (obj != rtldobj) 1783 dbg("relocating \"%s\"", obj->path); 1784 if (obj->nbuckets == 0 || obj->nchains == 0 || obj->buckets == NULL || 1785 obj->symtab == NULL || obj->strtab == NULL) { --- 8 unchanged lines hidden (view full) --- 1794 PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { 1795 _rtld_error("%s: Cannot write-enable text segment: %s", 1796 obj->path, strerror(errno)); 1797 return -1; 1798 } 1799 } 1800 1801 /* Process the non-PLT relocations. */ | 1876{ 1877 Obj_Entry *obj; 1878 1879 for (obj = first; obj != NULL; obj = obj->next) { 1880 if (obj != rtldobj) 1881 dbg("relocating \"%s\"", obj->path); 1882 if (obj->nbuckets == 0 || obj->nchains == 0 || obj->buckets == NULL || 1883 obj->symtab == NULL || obj->strtab == NULL) { --- 8 unchanged lines hidden (view full) --- 1892 PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { 1893 _rtld_error("%s: Cannot write-enable text segment: %s", 1894 obj->path, strerror(errno)); 1895 return -1; 1896 } 1897 } 1898 1899 /* Process the non-PLT relocations. */ |
1802 if (reloc_non_plt(obj, rtldobj)) | 1900 if (reloc_non_plt(obj, rtldobj, lockstate)) |
1803 return -1; 1804 1805 if (obj->textrel) { /* Re-protected the text segment. */ 1806 if (mprotect(obj->mapbase, obj->textsize, 1807 PROT_READ|PROT_EXEC) == -1) { 1808 _rtld_error("%s: Cannot write-protect text segment: %s", 1809 obj->path, strerror(errno)); 1810 return -1; 1811 } 1812 } 1813 1814 /* Process the PLT relocations. */ 1815 if (reloc_plt(obj) == -1) 1816 return -1; 1817 /* Relocate the jump slots if we are doing immediate binding. */ 1818 if (obj->bind_now || bind_now) | 1901 return -1; 1902 1903 if (obj->textrel) { /* Re-protected the text segment. */ 1904 if (mprotect(obj->mapbase, obj->textsize, 1905 PROT_READ|PROT_EXEC) == -1) { 1906 _rtld_error("%s: Cannot write-protect text segment: %s", 1907 obj->path, strerror(errno)); 1908 return -1; 1909 } 1910 } 1911 1912 /* Process the PLT relocations. */ 1913 if (reloc_plt(obj) == -1) 1914 return -1; 1915 /* Relocate the jump slots if we are doing immediate binding. */ 1916 if (obj->bind_now || bind_now) |
1819 if (reloc_jmpslots(obj) == -1) | 1917 if (reloc_jmpslots(obj, lockstate) == -1) |
1820 return -1; 1821 1822 1823 /* 1824 * Set up the magic number and version in the Obj_Entry. These 1825 * were checked in the crt1.o from the original ElfKit, so we 1826 * set them for backward compatibility. 1827 */ --- 9 unchanged lines hidden (view full) --- 1837 1838/* 1839 * Cleanup procedure. It will be called (by the atexit mechanism) just 1840 * before the process exits. 1841 */ 1842static void 1843rtld_exit(void) 1844{ | 1918 return -1; 1919 1920 1921 /* 1922 * Set up the magic number and version in the Obj_Entry. These 1923 * were checked in the crt1.o from the original ElfKit, so we 1924 * set them for backward compatibility. 1925 */ --- 9 unchanged lines hidden (view full) --- 1935 1936/* 1937 * Cleanup procedure. It will be called (by the atexit mechanism) just 1938 * before the process exits. 1939 */ 1940static void 1941rtld_exit(void) 1942{ |
1845 int lockstate; | 1943 RtldLockState lockstate; |
1846 | 1944 |
1847 lockstate = wlock_acquire(rtld_bind_lock); | 1945 wlock_acquire(rtld_bind_lock, &lockstate); |
1848 dbg("rtld_exit()"); 1849 objlist_call_fini(&list_fini, NULL, &lockstate); 1850 /* No need to remove the items from the list, since we are exiting. */ 1851 if (!libmap_disable) 1852 lm_fini(); | 1946 dbg("rtld_exit()"); 1947 objlist_call_fini(&list_fini, NULL, &lockstate); 1948 /* No need to remove the items from the list, since we are exiting. */ 1949 if (!libmap_disable) 1950 lm_fini(); |
1853 wlock_release(rtld_bind_lock, lockstate); | 1951 lock_release(rtld_bind_lock, &lockstate); |
1854} 1855 1856static void * 1857path_enumerate(const char *path, path_enum_proc callback, void *arg) 1858{ 1859#ifdef COMPAT_32BIT 1860 const char *trans; 1861#endif --- 78 unchanged lines hidden (view full) --- 1940 1941 return (p); 1942} 1943 1944int 1945dlclose(void *handle) 1946{ 1947 Obj_Entry *root; | 1952} 1953 1954static void * 1955path_enumerate(const char *path, path_enum_proc callback, void *arg) 1956{ 1957#ifdef COMPAT_32BIT 1958 const char *trans; 1959#endif --- 78 unchanged lines hidden (view full) --- 2038 2039 return (p); 2040} 2041 2042int 2043dlclose(void *handle) 2044{ 2045 Obj_Entry *root; |
1948 int lockstate; | 2046 RtldLockState lockstate; |
1949 | 2047 |
1950 lockstate = wlock_acquire(rtld_bind_lock); | 2048 wlock_acquire(rtld_bind_lock, &lockstate); |
1951 root = dlcheck(handle); 1952 if (root == NULL) { | 2049 root = dlcheck(handle); 2050 if (root == NULL) { |
1953 wlock_release(rtld_bind_lock, lockstate); | 2051 lock_release(rtld_bind_lock, &lockstate); |
1954 return -1; 1955 } 1956 LD_UTRACE(UTRACE_DLCLOSE_START, handle, NULL, 0, root->dl_refcount, 1957 root->path); 1958 1959 /* Unreference the object and its dependencies. */ 1960 root->dl_refcount--; 1961 --- 9 unchanged lines hidden (view full) --- 1971 /* Finish cleaning up the newly-unreferenced objects. */ 1972 GDB_STATE(RT_DELETE,&root->linkmap); 1973 unload_object(root); 1974 GDB_STATE(RT_CONSISTENT,NULL); 1975 } else 1976 unref_dag(root); 1977 1978 LD_UTRACE(UTRACE_DLCLOSE_STOP, handle, NULL, 0, 0, NULL); | 2052 return -1; 2053 } 2054 LD_UTRACE(UTRACE_DLCLOSE_START, handle, NULL, 0, root->dl_refcount, 2055 root->path); 2056 2057 /* Unreference the object and its dependencies. */ 2058 root->dl_refcount--; 2059 --- 9 unchanged lines hidden (view full) --- 2069 /* Finish cleaning up the newly-unreferenced objects. */ 2070 GDB_STATE(RT_DELETE,&root->linkmap); 2071 unload_object(root); 2072 GDB_STATE(RT_CONSISTENT,NULL); 2073 } else 2074 unref_dag(root); 2075 2076 LD_UTRACE(UTRACE_DLCLOSE_STOP, handle, NULL, 0, 0, NULL); |
1979 wlock_release(rtld_bind_lock, lockstate); | 2077 lock_release(rtld_bind_lock, &lockstate); |
1980 return 0; 1981} 1982 1983char * 1984dlerror(void) 1985{ 1986 char *msg = error_message; 1987 error_message = NULL; --- 20 unchanged lines hidden (view full) --- 2008 cur_context_destroy(cur_context); 2009 cur_context = context; 2010 cur_context_destroy = context_destroy; 2011} 2012 2013void * 2014dlopen(const char *name, int mode) 2015{ | 2078 return 0; 2079} 2080 2081char * 2082dlerror(void) 2083{ 2084 char *msg = error_message; 2085 error_message = NULL; --- 20 unchanged lines hidden (view full) --- 2106 cur_context_destroy(cur_context); 2107 cur_context = context; 2108 cur_context_destroy = context_destroy; 2109} 2110 2111void * 2112dlopen(const char *name, int mode) 2113{ |
2016 Obj_Entry **old_obj_tail; 2017 Obj_Entry *obj; 2018 Objlist initlist; 2019 int result, lockstate, nodelete, lo_flags; | 2114 int lo_flags; |
2020 2021 LD_UTRACE(UTRACE_DLOPEN_START, NULL, NULL, 0, mode, name); 2022 ld_tracing = (mode & RTLD_TRACE) == 0 ? NULL : "1"; 2023 if (ld_tracing != NULL) 2024 environ = (char **)*get_program_var_addr("environ"); | 2115 2116 LD_UTRACE(UTRACE_DLOPEN_START, NULL, NULL, 0, mode, name); 2117 ld_tracing = (mode & RTLD_TRACE) == 0 ? NULL : "1"; 2118 if (ld_tracing != NULL) 2119 environ = (char **)*get_program_var_addr("environ"); |
2025 nodelete = mode & RTLD_NODELETE; | |
2026 lo_flags = RTLD_LO_DLOPEN; | 2120 lo_flags = RTLD_LO_DLOPEN; |
2121 if (mode & RTLD_NODELETE) 2122 lo_flags |= RTLD_LO_NODELETE; |
|
2027 if (mode & RTLD_NOLOAD) 2028 lo_flags |= RTLD_LO_NOLOAD; 2029 if (ld_tracing != NULL) 2030 lo_flags |= RTLD_LO_TRACE; 2031 | 2123 if (mode & RTLD_NOLOAD) 2124 lo_flags |= RTLD_LO_NOLOAD; 2125 if (ld_tracing != NULL) 2126 lo_flags |= RTLD_LO_TRACE; 2127 |
2128 return (dlopen_object(name, obj_main, lo_flags, 2129 mode & (RTLD_MODEMASK | RTLD_GLOBAL))); 2130} 2131 2132static Obj_Entry * 2133dlopen_object(const char *name, Obj_Entry *refobj, int lo_flags, int mode) 2134{ 2135 Obj_Entry **old_obj_tail; 2136 Obj_Entry *obj; 2137 Objlist initlist; 2138 RtldLockState lockstate; 2139 int result; 2140 |
|
2032 objlist_init(&initlist); 2033 | 2141 objlist_init(&initlist); 2142 |
2034 lockstate = wlock_acquire(rtld_bind_lock); | 2143 wlock_acquire(rtld_bind_lock, &lockstate); |
2035 GDB_STATE(RT_ADD,NULL); 2036 2037 old_obj_tail = obj_tail; 2038 obj = NULL; 2039 if (name == NULL) { 2040 obj = obj_main; 2041 obj->refcount++; 2042 } else { | 2144 GDB_STATE(RT_ADD,NULL); 2145 2146 old_obj_tail = obj_tail; 2147 obj = NULL; 2148 if (name == NULL) { 2149 obj = obj_main; 2150 obj->refcount++; 2151 } else { |
2043 obj = load_object(name, obj_main, lo_flags); | 2152 obj = load_object(name, refobj, lo_flags); |
2044 } 2045 2046 if (obj) { 2047 obj->dl_refcount++; 2048 if (mode & RTLD_GLOBAL && objlist_find(&list_global, obj) == NULL) 2049 objlist_push_tail(&list_global, obj); | 2153 } 2154 2155 if (obj) { 2156 obj->dl_refcount++; 2157 if (mode & RTLD_GLOBAL && objlist_find(&list_global, obj) == NULL) 2158 objlist_push_tail(&list_global, obj); |
2050 mode &= RTLD_MODEMASK; | |
2051 if (*old_obj_tail != NULL) { /* We loaded something new. */ 2052 assert(*old_obj_tail == obj); | 2159 if (*old_obj_tail != NULL) { /* We loaded something new. */ 2160 assert(*old_obj_tail == obj); |
2053 result = load_needed_objects(obj, RTLD_LO_DLOPEN); | 2161 result = load_needed_objects(obj, lo_flags & RTLD_LO_DLOPEN); |
2054 init_dag(obj); 2055 ref_dag(obj); 2056 if (result != -1) 2057 result = rtld_verify_versions(&obj->dagmembers); 2058 if (result != -1 && ld_tracing) 2059 goto trace; | 2162 init_dag(obj); 2163 ref_dag(obj); 2164 if (result != -1) 2165 result = rtld_verify_versions(&obj->dagmembers); 2166 if (result != -1 && ld_tracing) 2167 goto trace; |
2060 if (result == -1 || 2061 (relocate_objects(obj, mode == RTLD_NOW, &obj_rtld)) == -1) { | 2168 if (result == -1 || (relocate_objects(obj, (mode & RTLD_MODEMASK) 2169 == RTLD_NOW, &obj_rtld, &lockstate)) == -1) { |
2062 obj->dl_refcount--; 2063 unref_dag(obj); 2064 if (obj->refcount == 0) 2065 unload_object(obj); 2066 obj = NULL; 2067 } else { 2068 /* Make list of init functions to call. */ 2069 initlist_add_objects(obj, &obj->next, &initlist); --- 4 unchanged lines hidden (view full) --- 2074 * Bump the reference counts for objects on this DAG. If 2075 * this is the first dlopen() call for the object that was 2076 * already loaded as a dependency, initialize the dag 2077 * starting at it. 2078 */ 2079 init_dag(obj); 2080 ref_dag(obj); 2081 | 2170 obj->dl_refcount--; 2171 unref_dag(obj); 2172 if (obj->refcount == 0) 2173 unload_object(obj); 2174 obj = NULL; 2175 } else { 2176 /* Make list of init functions to call. */ 2177 initlist_add_objects(obj, &obj->next, &initlist); --- 4 unchanged lines hidden (view full) --- 2182 * Bump the reference counts for objects on this DAG. If 2183 * this is the first dlopen() call for the object that was 2184 * already loaded as a dependency, initialize the dag 2185 * starting at it. 2186 */ 2187 init_dag(obj); 2188 ref_dag(obj); 2189 |
2082 if (ld_tracing) | 2190 if ((lo_flags & RTLD_LO_TRACE) != 0) |
2083 goto trace; 2084 } | 2191 goto trace; 2192 } |
2085 if (obj != NULL && (nodelete || obj->z_nodelete) && !obj->ref_nodel) { | 2193 if (obj != NULL && ((lo_flags & RTLD_LO_NODELETE) != 0 || 2194 obj->z_nodelete) && !obj->ref_nodel) { |
2086 dbg("obj %s nodelete", obj->path); 2087 ref_dag(obj); 2088 obj->z_nodelete = obj->ref_nodel = true; 2089 } 2090 } 2091 2092 LD_UTRACE(UTRACE_DLOPEN_STOP, obj, NULL, 0, obj ? obj->dl_refcount : 0, 2093 name); 2094 GDB_STATE(RT_CONSISTENT,obj ? &obj->linkmap : NULL); 2095 2096 /* Call the init functions. */ 2097 objlist_call_init(&initlist, &lockstate); 2098 objlist_clear(&initlist); | 2195 dbg("obj %s nodelete", obj->path); 2196 ref_dag(obj); 2197 obj->z_nodelete = obj->ref_nodel = true; 2198 } 2199 } 2200 2201 LD_UTRACE(UTRACE_DLOPEN_STOP, obj, NULL, 0, obj ? obj->dl_refcount : 0, 2202 name); 2203 GDB_STATE(RT_CONSISTENT,obj ? &obj->linkmap : NULL); 2204 2205 /* Call the init functions. */ 2206 objlist_call_init(&initlist, &lockstate); 2207 objlist_clear(&initlist); |
2099 wlock_release(rtld_bind_lock, lockstate); | 2208 lock_release(rtld_bind_lock, &lockstate); |
2100 return obj; 2101trace: 2102 trace_loaded_objects(obj); | 2209 return obj; 2210trace: 2211 trace_loaded_objects(obj); |
2103 wlock_release(rtld_bind_lock, lockstate); | 2212 lock_release(rtld_bind_lock, &lockstate); |
2104 exit(0); 2105} 2106 2107static void * 2108do_dlsym(void *handle, const char *name, void *retaddr, const Ver_Entry *ve, 2109 int flags) 2110{ 2111 DoneList donelist; 2112 const Obj_Entry *obj, *defobj; | 2213 exit(0); 2214} 2215 2216static void * 2217do_dlsym(void *handle, const char *name, void *retaddr, const Ver_Entry *ve, 2218 int flags) 2219{ 2220 DoneList donelist; 2221 const Obj_Entry *obj, *defobj; |
2113 const Elf_Sym *def, *symp; 2114 unsigned long hash; 2115 int lockstate; | 2222 const Elf_Sym *def; 2223 SymLook req; 2224 RtldLockState lockstate; 2225 int res; |
2116 | 2226 |
2117 hash = elf_hash(name); | |
2118 def = NULL; 2119 defobj = NULL; | 2227 def = NULL; 2228 defobj = NULL; |
2120 flags |= SYMLOOK_IN_PLT; | 2229 symlook_init(&req, name); 2230 req.ventry = ve; 2231 req.flags = flags | SYMLOOK_IN_PLT; 2232 req.lockstate = &lockstate; |
2121 | 2233 |
2122 lockstate = rlock_acquire(rtld_bind_lock); | 2234 rlock_acquire(rtld_bind_lock, &lockstate); 2235 if (setjmp(lockstate.env) != 0) 2236 lock_upgrade(rtld_bind_lock, &lockstate); |
2123 if (handle == NULL || handle == RTLD_NEXT || 2124 handle == RTLD_DEFAULT || handle == RTLD_SELF) { 2125 2126 if ((obj = obj_from_addr(retaddr)) == NULL) { 2127 _rtld_error("Cannot determine caller's shared object"); | 2237 if (handle == NULL || handle == RTLD_NEXT || 2238 handle == RTLD_DEFAULT || handle == RTLD_SELF) { 2239 2240 if ((obj = obj_from_addr(retaddr)) == NULL) { 2241 _rtld_error("Cannot determine caller's shared object"); |
2128 rlock_release(rtld_bind_lock, lockstate); | 2242 lock_release(rtld_bind_lock, &lockstate); |
2129 return NULL; 2130 } 2131 if (handle == NULL) { /* Just the caller's shared object. */ | 2243 return NULL; 2244 } 2245 if (handle == NULL) { /* Just the caller's shared object. */ |
2132 def = symlook_obj(name, hash, obj, ve, flags); 2133 defobj = obj; | 2246 res = symlook_obj(&req, obj); 2247 if (res == 0) { 2248 def = req.sym_out; 2249 defobj = req.defobj_out; 2250 } |
2134 } else if (handle == RTLD_NEXT || /* Objects after caller's */ 2135 handle == RTLD_SELF) { /* ... caller included */ 2136 if (handle == RTLD_NEXT) 2137 obj = obj->next; 2138 for (; obj != NULL; obj = obj->next) { | 2251 } else if (handle == RTLD_NEXT || /* Objects after caller's */ 2252 handle == RTLD_SELF) { /* ... caller included */ 2253 if (handle == RTLD_NEXT) 2254 obj = obj->next; 2255 for (; obj != NULL; obj = obj->next) { |
2139 if ((symp = symlook_obj(name, hash, obj, ve, flags)) != NULL) { 2140 if (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK) { 2141 def = symp; 2142 defobj = obj; | 2256 res = symlook_obj(&req, obj); 2257 if (res == 0) { 2258 if (def == NULL || 2259 ELF_ST_BIND(req.sym_out->st_info) != STB_WEAK) { 2260 def = req.sym_out; 2261 defobj = req.defobj_out; |
2143 if (ELF_ST_BIND(def->st_info) != STB_WEAK) 2144 break; 2145 } 2146 } 2147 } 2148 /* 2149 * Search the dynamic linker itself, and possibly resolve the 2150 * symbol from there. This is how the application links to 2151 * dynamic linker services such as dlopen. 2152 */ 2153 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { | 2262 if (ELF_ST_BIND(def->st_info) != STB_WEAK) 2263 break; 2264 } 2265 } 2266 } 2267 /* 2268 * Search the dynamic linker itself, and possibly resolve the 2269 * symbol from there. This is how the application links to 2270 * dynamic linker services such as dlopen. 2271 */ 2272 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { |
2154 symp = symlook_obj(name, hash, &obj_rtld, ve, flags); 2155 if (symp != NULL) { 2156 def = symp; 2157 defobj = &obj_rtld; | 2273 res = symlook_obj(&req, &obj_rtld); 2274 if (res == 0) { 2275 def = req.sym_out; 2276 defobj = req.defobj_out; |
2158 } 2159 } 2160 } else { 2161 assert(handle == RTLD_DEFAULT); | 2277 } 2278 } 2279 } else { 2280 assert(handle == RTLD_DEFAULT); |
2162 def = symlook_default(name, hash, obj, &defobj, ve, flags); | 2281 res = symlook_obj(&req, obj); 2282 if (res == 0) { 2283 defobj = req.defobj_out; 2284 def = req.sym_out; 2285 } |
2163 } 2164 } else { 2165 if ((obj = dlcheck(handle)) == NULL) { | 2286 } 2287 } else { 2288 if ((obj = dlcheck(handle)) == NULL) { |
2166 rlock_release(rtld_bind_lock, lockstate); | 2289 lock_release(rtld_bind_lock, &lockstate); |
2167 return NULL; 2168 } 2169 2170 donelist_init(&donelist); 2171 if (obj->mainprog) { 2172 /* Search main program and all libraries loaded by it. */ | 2290 return NULL; 2291 } 2292 2293 donelist_init(&donelist); 2294 if (obj->mainprog) { 2295 /* Search main program and all libraries loaded by it. */ |
2173 def = symlook_list(name, hash, &list_main, &defobj, ve, flags, 2174 &donelist); 2175 2176 /* 2177 * We do not distinguish between 'main' object and global scope. 2178 * If symbol is not defined by objects loaded at startup, continue 2179 * search among dynamically loaded objects with RTLD_GLOBAL 2180 * scope. 2181 */ 2182 if (def == NULL) 2183 def = symlook_list(name, hash, &list_global, &defobj, ve, 2184 flags, &donelist); | 2296 res = symlook_list(&req, &list_main, &donelist); 2297 if (res == 0) { 2298 def = req.sym_out; 2299 defobj = req.defobj_out; 2300 } else { 2301 /* 2302 * We do not distinguish between 'main' object and 2303 * global scope. If symbol is not defined by objects 2304 * loaded at startup, continue search among 2305 * dynamically loaded objects with RTLD_GLOBAL scope. 2306 */ 2307 res = symlook_list(&req, &list_global, &donelist); 2308 if (res == 0) { 2309 def = req.sym_out; 2310 defobj = req.defobj_out; 2311 } 2312 } |
2185 } else { 2186 Needed_Entry fake; 2187 2188 /* Search the whole DAG rooted at the given object. */ 2189 fake.next = NULL; 2190 fake.obj = (Obj_Entry *)obj; 2191 fake.name = 0; | 2313 } else { 2314 Needed_Entry fake; 2315 2316 /* Search the whole DAG rooted at the given object. */ 2317 fake.next = NULL; 2318 fake.obj = (Obj_Entry *)obj; 2319 fake.name = 0; |
2192 def = symlook_needed(name, hash, &fake, &defobj, ve, flags, 2193 &donelist); | 2320 res = symlook_needed(&req, &fake, &donelist); 2321 if (res == 0) { 2322 def = req.sym_out; 2323 defobj = req.defobj_out; 2324 } |
2194 } 2195 } 2196 2197 if (def != NULL) { | 2325 } 2326 } 2327 2328 if (def != NULL) { |
2198 rlock_release(rtld_bind_lock, lockstate); | 2329 lock_release(rtld_bind_lock, &lockstate); |
2199 2200 /* 2201 * The value required by the caller is derived from the value 2202 * of the symbol. For the ia64 architecture, we need to 2203 * construct a function descriptor which the caller can use to 2204 * call the function with the right 'gp' value. For other 2205 * architectures and for non-functions, the value is simply 2206 * the relocated value of the symbol. 2207 */ 2208 if (ELF_ST_TYPE(def->st_info) == STT_FUNC) 2209 return make_function_pointer(def, defobj); 2210 else 2211 return defobj->relocbase + def->st_value; 2212 } 2213 2214 _rtld_error("Undefined symbol \"%s\"", name); | 2330 2331 /* 2332 * The value required by the caller is derived from the value 2333 * of the symbol. For the ia64 architecture, we need to 2334 * construct a function descriptor which the caller can use to 2335 * call the function with the right 'gp' value. For other 2336 * architectures and for non-functions, the value is simply 2337 * the relocated value of the symbol. 2338 */ 2339 if (ELF_ST_TYPE(def->st_info) == STT_FUNC) 2340 return make_function_pointer(def, defobj); 2341 else 2342 return defobj->relocbase + def->st_value; 2343 } 2344 2345 _rtld_error("Undefined symbol \"%s\"", name); |
2215 rlock_release(rtld_bind_lock, lockstate); | 2346 lock_release(rtld_bind_lock, &lockstate); |
2216 return NULL; 2217} 2218 2219void * 2220dlsym(void *handle, const char *name) 2221{ 2222 return do_dlsym(handle, name, __builtin_return_address(0), NULL, 2223 SYMLOOK_DLSYM); --- 24 unchanged lines hidden (view full) --- 2248 return do_dlsym(handle, name, __builtin_return_address(0), &ventry, 2249 SYMLOOK_DLSYM); 2250} 2251 2252int 2253_rtld_addr_phdr(const void *addr, struct dl_phdr_info *phdr_info) 2254{ 2255 const Obj_Entry *obj; | 2347 return NULL; 2348} 2349 2350void * 2351dlsym(void *handle, const char *name) 2352{ 2353 return do_dlsym(handle, name, __builtin_return_address(0), NULL, 2354 SYMLOOK_DLSYM); --- 24 unchanged lines hidden (view full) --- 2379 return do_dlsym(handle, name, __builtin_return_address(0), &ventry, 2380 SYMLOOK_DLSYM); 2381} 2382 2383int 2384_rtld_addr_phdr(const void *addr, struct dl_phdr_info *phdr_info) 2385{ 2386 const Obj_Entry *obj; |
2256 int lockstate; | 2387 RtldLockState lockstate; |
2257 | 2388 |
2258 lockstate = rlock_acquire(rtld_bind_lock); | 2389 rlock_acquire(rtld_bind_lock, &lockstate); |
2259 obj = obj_from_addr(addr); 2260 if (obj == NULL) { 2261 _rtld_error("No shared object contains address"); | 2390 obj = obj_from_addr(addr); 2391 if (obj == NULL) { 2392 _rtld_error("No shared object contains address"); |
2262 rlock_release(rtld_bind_lock, lockstate); | 2393 lock_release(rtld_bind_lock, &lockstate); |
2263 return (0); 2264 } 2265 rtld_fill_dl_phdr_info(obj, phdr_info); | 2394 return (0); 2395 } 2396 rtld_fill_dl_phdr_info(obj, phdr_info); |
2266 rlock_release(rtld_bind_lock, lockstate); | 2397 lock_release(rtld_bind_lock, &lockstate); |
2267 return (1); 2268} 2269 2270int 2271dladdr(const void *addr, Dl_info *info) 2272{ 2273 const Obj_Entry *obj; 2274 const Elf_Sym *def; 2275 void *symbol_addr; 2276 unsigned long symoffset; | 2398 return (1); 2399} 2400 2401int 2402dladdr(const void *addr, Dl_info *info) 2403{ 2404 const Obj_Entry *obj; 2405 const Elf_Sym *def; 2406 void *symbol_addr; 2407 unsigned long symoffset; |
2277 int lockstate; | 2408 RtldLockState lockstate; |
2278 | 2409 |
2279 lockstate = rlock_acquire(rtld_bind_lock); | 2410 rlock_acquire(rtld_bind_lock, &lockstate); |
2280 obj = obj_from_addr(addr); 2281 if (obj == NULL) { 2282 _rtld_error("No shared object contains address"); | 2411 obj = obj_from_addr(addr); 2412 if (obj == NULL) { 2413 _rtld_error("No shared object contains address"); |
2283 rlock_release(rtld_bind_lock, lockstate); | 2414 lock_release(rtld_bind_lock, &lockstate); |
2284 return 0; 2285 } 2286 info->dli_fname = obj->path; 2287 info->dli_fbase = obj->mapbase; 2288 info->dli_saddr = (void *)0; 2289 info->dli_sname = NULL; 2290 2291 /* --- 22 unchanged lines hidden (view full) --- 2314 /* Update our idea of the nearest symbol. */ 2315 info->dli_sname = obj->strtab + def->st_name; 2316 info->dli_saddr = symbol_addr; 2317 2318 /* Exact match? */ 2319 if (info->dli_saddr == addr) 2320 break; 2321 } | 2415 return 0; 2416 } 2417 info->dli_fname = obj->path; 2418 info->dli_fbase = obj->mapbase; 2419 info->dli_saddr = (void *)0; 2420 info->dli_sname = NULL; 2421 2422 /* --- 22 unchanged lines hidden (view full) --- 2445 /* Update our idea of the nearest symbol. */ 2446 info->dli_sname = obj->strtab + def->st_name; 2447 info->dli_saddr = symbol_addr; 2448 2449 /* Exact match? */ 2450 if (info->dli_saddr == addr) 2451 break; 2452 } |
2322 rlock_release(rtld_bind_lock, lockstate); | 2453 lock_release(rtld_bind_lock, &lockstate); |
2323 return 1; 2324} 2325 2326int 2327dlinfo(void *handle, int request, void *p) 2328{ 2329 const Obj_Entry *obj; | 2454 return 1; 2455} 2456 2457int 2458dlinfo(void *handle, int request, void *p) 2459{ 2460 const Obj_Entry *obj; |
2330 int error, lockstate; | 2461 RtldLockState lockstate; 2462 int error; |
2331 | 2463 |
2332 lockstate = rlock_acquire(rtld_bind_lock); | 2464 rlock_acquire(rtld_bind_lock, &lockstate); |
2333 2334 if (handle == NULL || handle == RTLD_SELF) { 2335 void *retaddr; 2336 2337 retaddr = __builtin_return_address(0); /* __GNUC__ only */ 2338 if ((obj = obj_from_addr(retaddr)) == NULL) 2339 _rtld_error("Cannot determine caller's shared object"); 2340 } else 2341 obj = dlcheck(handle); 2342 2343 if (obj == NULL) { | 2465 2466 if (handle == NULL || handle == RTLD_SELF) { 2467 void *retaddr; 2468 2469 retaddr = __builtin_return_address(0); /* __GNUC__ only */ 2470 if ((obj = obj_from_addr(retaddr)) == NULL) 2471 _rtld_error("Cannot determine caller's shared object"); 2472 } else 2473 obj = dlcheck(handle); 2474 2475 if (obj == NULL) { |
2344 rlock_release(rtld_bind_lock, lockstate); | 2476 lock_release(rtld_bind_lock, &lockstate); |
2345 return (-1); 2346 } 2347 2348 error = 0; 2349 switch (request) { 2350 case RTLD_DI_LINKMAP: 2351 *((struct link_map const **)p) = &obj->linkmap; 2352 break; --- 6 unchanged lines hidden (view full) --- 2359 error = do_search_info(obj, request, (struct dl_serinfo *)p); 2360 break; 2361 2362 default: 2363 _rtld_error("Invalid request %d passed to dlinfo()", request); 2364 error = -1; 2365 } 2366 | 2477 return (-1); 2478 } 2479 2480 error = 0; 2481 switch (request) { 2482 case RTLD_DI_LINKMAP: 2483 *((struct link_map const **)p) = &obj->linkmap; 2484 break; --- 6 unchanged lines hidden (view full) --- 2491 error = do_search_info(obj, request, (struct dl_serinfo *)p); 2492 break; 2493 2494 default: 2495 _rtld_error("Invalid request %d passed to dlinfo()", request); 2496 error = -1; 2497 } 2498 |
2367 rlock_release(rtld_bind_lock, lockstate); | 2499 lock_release(rtld_bind_lock, &lockstate); |
2368 2369 return (error); 2370} 2371 2372static void 2373rtld_fill_dl_phdr_info(const Obj_Entry *obj, struct dl_phdr_info *phdr_info) 2374{ 2375 --- 8 unchanged lines hidden (view full) --- 2384 phdr_info->dlpi_subs = obj_loads - obj_count; 2385} 2386 2387int 2388dl_iterate_phdr(__dl_iterate_hdr_callback callback, void *param) 2389{ 2390 struct dl_phdr_info phdr_info; 2391 const Obj_Entry *obj; | 2500 2501 return (error); 2502} 2503 2504static void 2505rtld_fill_dl_phdr_info(const Obj_Entry *obj, struct dl_phdr_info *phdr_info) 2506{ 2507 --- 8 unchanged lines hidden (view full) --- 2516 phdr_info->dlpi_subs = obj_loads - obj_count; 2517} 2518 2519int 2520dl_iterate_phdr(__dl_iterate_hdr_callback callback, void *param) 2521{ 2522 struct dl_phdr_info phdr_info; 2523 const Obj_Entry *obj; |
2392 int error, bind_lockstate, phdr_lockstate; | 2524 RtldLockState bind_lockstate, phdr_lockstate; 2525 int error; |
2393 | 2526 |
2394 phdr_lockstate = wlock_acquire(rtld_phdr_lock); 2395 bind_lockstate = rlock_acquire(rtld_bind_lock); | 2527 wlock_acquire(rtld_phdr_lock, &phdr_lockstate); 2528 rlock_acquire(rtld_bind_lock, &bind_lockstate); |
2396 2397 error = 0; 2398 2399 for (obj = obj_list; obj != NULL; obj = obj->next) { 2400 rtld_fill_dl_phdr_info(obj, &phdr_info); 2401 if ((error = callback(&phdr_info, sizeof phdr_info, param)) != 0) 2402 break; 2403 2404 } | 2529 2530 error = 0; 2531 2532 for (obj = obj_list; obj != NULL; obj = obj->next) { 2533 rtld_fill_dl_phdr_info(obj, &phdr_info); 2534 if ((error = callback(&phdr_info, sizeof phdr_info, param)) != 0) 2535 break; 2536 2537 } |
2405 rlock_release(rtld_bind_lock, bind_lockstate); 2406 wlock_release(rtld_phdr_lock, phdr_lockstate); | 2538 lock_release(rtld_bind_lock, &bind_lockstate); 2539 lock_release(rtld_phdr_lock, &phdr_lockstate); |
2407 2408 return (error); 2409} 2410 2411struct fill_search_info_args { 2412 int request; 2413 unsigned int flags; 2414 Dl_serinfo *serinfo; --- 211 unchanged lines hidden (view full) --- 2626 2627/* 2628 * Get address of the pointer variable in the main program. 2629 */ 2630static const void ** 2631get_program_var_addr(const char *name) 2632{ 2633 const Obj_Entry *obj; | 2540 2541 return (error); 2542} 2543 2544struct fill_search_info_args { 2545 int request; 2546 unsigned int flags; 2547 Dl_serinfo *serinfo; --- 211 unchanged lines hidden (view full) --- 2759 2760/* 2761 * Get address of the pointer variable in the main program. 2762 */ 2763static const void ** 2764get_program_var_addr(const char *name) 2765{ 2766 const Obj_Entry *obj; |
2634 unsigned long hash; | 2767 SymLook req; |
2635 | 2768 |
2636 hash = elf_hash(name); | 2769 symlook_init(&req, name); |
2637 for (obj = obj_main; obj != NULL; obj = obj->next) { | 2770 for (obj = obj_main; obj != NULL; obj = obj->next) { |
2638 const Elf_Sym *def; 2639 2640 if ((def = symlook_obj(name, hash, obj, NULL, 0)) != NULL) { 2641 const void **addr; 2642 2643 addr = (const void **)(obj->relocbase + def->st_value); 2644 return addr; | 2771 if (symlook_obj(&req, obj) == 0) { 2772 return ((const void **)(req.defobj_out->relocbase + 2773 req.sym_out->st_value)); |
2645 } 2646 } | 2774 } 2775 } |
2647 return NULL; | 2776 return (NULL); |
2648} 2649 2650/* 2651 * Set a pointer variable in the main program to the given value. This 2652 * is used to set key variables such as "environ" before any of the 2653 * init functions are called. 2654 */ 2655static void --- 8 unchanged lines hidden (view full) --- 2664} 2665 2666/* 2667 * Given a symbol name in a referencing object, find the corresponding 2668 * definition of the symbol. Returns a pointer to the symbol, or NULL if 2669 * no definition was found. Returns a pointer to the Obj_Entry of the 2670 * defining object via the reference parameter DEFOBJ_OUT. 2671 */ | 2777} 2778 2779/* 2780 * Set a pointer variable in the main program to the given value. This 2781 * is used to set key variables such as "environ" before any of the 2782 * init functions are called. 2783 */ 2784static void --- 8 unchanged lines hidden (view full) --- 2793} 2794 2795/* 2796 * Given a symbol name in a referencing object, find the corresponding 2797 * definition of the symbol. Returns a pointer to the symbol, or NULL if 2798 * no definition was found. Returns a pointer to the Obj_Entry of the 2799 * defining object via the reference parameter DEFOBJ_OUT. 2800 */ |
2672static const Elf_Sym * 2673symlook_default(const char *name, unsigned long hash, const Obj_Entry *refobj, 2674 const Obj_Entry **defobj_out, const Ver_Entry *ventry, int flags) | 2801static int 2802symlook_default(SymLook *req, const Obj_Entry *refobj) |
2675{ 2676 DoneList donelist; 2677 const Elf_Sym *def; | 2803{ 2804 DoneList donelist; 2805 const Elf_Sym *def; |
2678 const Elf_Sym *symp; 2679 const Obj_Entry *obj; | |
2680 const Obj_Entry *defobj; 2681 const Objlist_Entry *elm; | 2806 const Obj_Entry *defobj; 2807 const Objlist_Entry *elm; |
2808 SymLook req1; 2809 int res; |
|
2682 def = NULL; 2683 defobj = NULL; 2684 donelist_init(&donelist); | 2810 def = NULL; 2811 defobj = NULL; 2812 donelist_init(&donelist); |
2813 symlook_init_from_req(&req1, req); |
|
2685 2686 /* Look first in the referencing object if linked symbolically. */ 2687 if (refobj->symbolic && !donelist_check(&donelist, refobj)) { | 2814 2815 /* Look first in the referencing object if linked symbolically. */ 2816 if (refobj->symbolic && !donelist_check(&donelist, refobj)) { |
2688 symp = symlook_obj(name, hash, refobj, ventry, flags); 2689 if (symp != NULL) { 2690 def = symp; 2691 defobj = refobj; | 2817 res = symlook_obj(&req1, refobj); 2818 if (res == 0) { 2819 def = req1.sym_out; 2820 defobj = req1.defobj_out; 2821 assert(defobj != NULL); |
2692 } 2693 } 2694 2695 /* Search all objects loaded at program start up. */ 2696 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { | 2822 } 2823 } 2824 2825 /* Search all objects loaded at program start up. */ 2826 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { |
2697 symp = symlook_list(name, hash, &list_main, &obj, ventry, flags, 2698 &donelist); 2699 if (symp != NULL && 2700 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 2701 def = symp; 2702 defobj = obj; | 2827 res = symlook_list(&req1, &list_main, &donelist); 2828 if (res == 0 && 2829 (def == NULL || ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK)) { 2830 def = req1.sym_out; 2831 defobj = req1.defobj_out; 2832 assert(defobj != NULL); |
2703 } 2704 } 2705 2706 /* Search all DAGs whose roots are RTLD_GLOBAL objects. */ 2707 STAILQ_FOREACH(elm, &list_global, link) { 2708 if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) 2709 break; | 2833 } 2834 } 2835 2836 /* Search all DAGs whose roots are RTLD_GLOBAL objects. */ 2837 STAILQ_FOREACH(elm, &list_global, link) { 2838 if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) 2839 break; |
2710 symp = symlook_list(name, hash, &elm->obj->dagmembers, &obj, ventry, 2711 flags, &donelist); 2712 if (symp != NULL && 2713 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 2714 def = symp; 2715 defobj = obj; | 2840 res = symlook_list(&req1, &elm->obj->dagmembers, &donelist); 2841 if (res == 0 && 2842 (def == NULL || ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK)) { 2843 def = req1.sym_out; 2844 defobj = req1.defobj_out; 2845 assert(defobj != NULL); |
2716 } 2717 } 2718 2719 /* Search all dlopened DAGs containing the referencing object. */ 2720 STAILQ_FOREACH(elm, &refobj->dldags, link) { 2721 if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) 2722 break; | 2846 } 2847 } 2848 2849 /* Search all dlopened DAGs containing the referencing object. */ 2850 STAILQ_FOREACH(elm, &refobj->dldags, link) { 2851 if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) 2852 break; |
2723 symp = symlook_list(name, hash, &elm->obj->dagmembers, &obj, ventry, 2724 flags, &donelist); 2725 if (symp != NULL && 2726 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 2727 def = symp; 2728 defobj = obj; | 2853 res = symlook_list(&req1, &elm->obj->dagmembers, &donelist); 2854 if (res == 0 && 2855 (def == NULL || ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK)) { 2856 def = req1.sym_out; 2857 defobj = req1.defobj_out; 2858 assert(defobj != NULL); |
2729 } 2730 } 2731 2732 /* 2733 * Search the dynamic linker itself, and possibly resolve the 2734 * symbol from there. This is how the application links to 2735 * dynamic linker services such as dlopen. 2736 */ 2737 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { | 2859 } 2860 } 2861 2862 /* 2863 * Search the dynamic linker itself, and possibly resolve the 2864 * symbol from there. This is how the application links to 2865 * dynamic linker services such as dlopen. 2866 */ 2867 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { |
2738 symp = symlook_obj(name, hash, &obj_rtld, ventry, flags); 2739 if (symp != NULL) { 2740 def = symp; 2741 defobj = &obj_rtld; | 2868 res = symlook_obj(&req1, &obj_rtld); 2869 if (res == 0) { 2870 def = req1.sym_out; 2871 defobj = req1.defobj_out; 2872 assert(defobj != NULL); |
2742 } 2743 } 2744 | 2873 } 2874 } 2875 |
2745 if (def != NULL) 2746 *defobj_out = defobj; 2747 return def; | 2876 if (def != NULL) { 2877 assert(defobj != NULL); 2878 req->defobj_out = defobj; 2879 req->sym_out = def; 2880 return (0); 2881 } 2882 return (ESRCH); |
2748} 2749 | 2883} 2884 |
2750static const Elf_Sym * 2751symlook_list(const char *name, unsigned long hash, const Objlist *objlist, 2752 const Obj_Entry **defobj_out, const Ver_Entry *ventry, int flags, 2753 DoneList *dlp) | 2885static int 2886symlook_list(SymLook *req, const Objlist *objlist, DoneList *dlp) |
2754{ | 2887{ |
2755 const Elf_Sym *symp; | |
2756 const Elf_Sym *def; 2757 const Obj_Entry *defobj; 2758 const Objlist_Entry *elm; | 2888 const Elf_Sym *def; 2889 const Obj_Entry *defobj; 2890 const Objlist_Entry *elm; |
2891 SymLook req1; 2892 int res; |
|
2759 2760 def = NULL; 2761 defobj = NULL; 2762 STAILQ_FOREACH(elm, objlist, link) { 2763 if (donelist_check(dlp, elm->obj)) 2764 continue; | 2893 2894 def = NULL; 2895 defobj = NULL; 2896 STAILQ_FOREACH(elm, objlist, link) { 2897 if (donelist_check(dlp, elm->obj)) 2898 continue; |
2765 if ((symp = symlook_obj(name, hash, elm->obj, ventry, flags)) != NULL) { 2766 if (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK) { 2767 def = symp; 2768 defobj = elm->obj; | 2899 symlook_init_from_req(&req1, req); 2900 if ((res = symlook_obj(&req1, elm->obj)) == 0) { 2901 if (def == NULL || ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK) { 2902 def = req1.sym_out; 2903 defobj = req1.defobj_out; |
2769 if (ELF_ST_BIND(def->st_info) != STB_WEAK) 2770 break; 2771 } 2772 } 2773 } | 2904 if (ELF_ST_BIND(def->st_info) != STB_WEAK) 2905 break; 2906 } 2907 } 2908 } |
2774 if (def != NULL) 2775 *defobj_out = defobj; 2776 return def; | 2909 if (def != NULL) { 2910 req->sym_out = def; 2911 req->defobj_out = defobj; 2912 return (0); 2913 } 2914 return (ESRCH); |
2777} 2778 2779/* 2780 * Search the symbol table of a shared object and all objects needed 2781 * by it for a symbol of the given name. Search order is 2782 * breadth-first. Returns a pointer to the symbol, or NULL if no 2783 * definition was found. 2784 */ | 2915} 2916 2917/* 2918 * Search the symbol table of a shared object and all objects needed 2919 * by it for a symbol of the given name. Search order is 2920 * breadth-first. Returns a pointer to the symbol, or NULL if no 2921 * definition was found. 2922 */ |
2785static const Elf_Sym * 2786symlook_needed(const char *name, unsigned long hash, const Needed_Entry *needed, 2787 const Obj_Entry **defobj_out, const Ver_Entry *ventry, int flags, 2788 DoneList *dlp) | 2923static int 2924symlook_needed(SymLook *req, const Needed_Entry *needed, DoneList *dlp) |
2789{ 2790 const Elf_Sym *def, *def_w; 2791 const Needed_Entry *n; | 2925{ 2926 const Elf_Sym *def, *def_w; 2927 const Needed_Entry *n; |
2792 const Obj_Entry *obj, *defobj, *defobj1; | 2928 const Obj_Entry *defobj, *defobj1; 2929 SymLook req1; 2930 int res; |
2793 2794 def = def_w = NULL; 2795 defobj = NULL; | 2931 2932 def = def_w = NULL; 2933 defobj = NULL; |
2934 symlook_init_from_req(&req1, req); |
|
2796 for (n = needed; n != NULL; n = n->next) { | 2935 for (n = needed; n != NULL; n = n->next) { |
2797 if ((obj = n->obj) == NULL || 2798 donelist_check(dlp, obj) || 2799 (def = symlook_obj(name, hash, obj, ventry, flags)) == NULL) | 2936 if (n->obj == NULL || donelist_check(dlp, n->obj) || 2937 (res = symlook_obj(&req1, n->obj)) != 0) |
2800 continue; | 2938 continue; |
2801 defobj = obj; | 2939 def = req1.sym_out; 2940 defobj = req1.defobj_out; |
2802 if (ELF_ST_BIND(def->st_info) != STB_WEAK) { | 2941 if (ELF_ST_BIND(def->st_info) != STB_WEAK) { |
2803 *defobj_out = defobj; 2804 return (def); | 2942 req->defobj_out = defobj; 2943 req->sym_out = def; 2944 return (0); |
2805 } 2806 } 2807 /* 2808 * There we come when either symbol definition is not found in 2809 * directly needed objects, or found symbol is weak. 2810 */ 2811 for (n = needed; n != NULL; n = n->next) { | 2945 } 2946 } 2947 /* 2948 * There we come when either symbol definition is not found in 2949 * directly needed objects, or found symbol is weak. 2950 */ 2951 for (n = needed; n != NULL; n = n->next) { |
2812 if ((obj = n->obj) == NULL) | 2952 if (n->obj == NULL) |
2813 continue; | 2953 continue; |
2814 def_w = symlook_needed(name, hash, obj->needed, &defobj1, 2815 ventry, flags, dlp); 2816 if (def_w == NULL) | 2954 res = symlook_needed(&req1, n->obj->needed, dlp); 2955 if (res != 0) |
2817 continue; | 2956 continue; |
2957 def_w = req1.sym_out; 2958 defobj1 = req1.defobj_out; |
|
2818 if (def == NULL || ELF_ST_BIND(def_w->st_info) != STB_WEAK) { 2819 def = def_w; 2820 defobj = defobj1; 2821 } 2822 if (ELF_ST_BIND(def_w->st_info) != STB_WEAK) 2823 break; 2824 } | 2959 if (def == NULL || ELF_ST_BIND(def_w->st_info) != STB_WEAK) { 2960 def = def_w; 2961 defobj = defobj1; 2962 } 2963 if (ELF_ST_BIND(def_w->st_info) != STB_WEAK) 2964 break; 2965 } |
2825 if (def != NULL) 2826 *defobj_out = defobj; 2827 return (def); | 2966 if (def != NULL) { 2967 req->sym_out = def; 2968 req->defobj_out = defobj; 2969 return (0); 2970 } 2971 return (ESRCH); |
2828} 2829 2830/* 2831 * Search the symbol table of a single shared object for a symbol of 2832 * the given name and version, if requested. Returns a pointer to the | 2972} 2973 2974/* 2975 * Search the symbol table of a single shared object for a symbol of 2976 * the given name and version, if requested. Returns a pointer to the |
2833 * symbol, or NULL if no definition was found. | 2977 * symbol, or NULL if no definition was found. If the object is 2978 * filter, return filtered symbol from filtee. |
2834 * 2835 * The symbol's hash value is passed in for efficiency reasons; that 2836 * eliminates many recomputations of the hash value. 2837 */ | 2979 * 2980 * The symbol's hash value is passed in for efficiency reasons; that 2981 * eliminates many recomputations of the hash value. 2982 */ |
2838const Elf_Sym * 2839symlook_obj(const char *name, unsigned long hash, const Obj_Entry *obj, 2840 const Ver_Entry *ventry, int flags) | 2983int 2984symlook_obj(SymLook *req, const Obj_Entry *obj) |
2841{ | 2985{ |
2986 DoneList donelist; 2987 SymLook req1; 2988 int res, mres; 2989 2990 mres = symlook_obj1(req, obj); 2991 if (mres == 0) { 2992 if (obj->needed_filtees != NULL) { 2993 load_filtees(__DECONST(Obj_Entry *, obj), 0, req->lockstate); 2994 donelist_init(&donelist); 2995 symlook_init_from_req(&req1, req); 2996 res = symlook_needed(&req1, obj->needed_filtees, &donelist); 2997 if (res == 0) { 2998 req->sym_out = req1.sym_out; 2999 req->defobj_out = req1.defobj_out; 3000 } 3001 return (res); 3002 } 3003 if (obj->needed_aux_filtees != NULL) { 3004 load_filtees(__DECONST(Obj_Entry *, obj), 0, req->lockstate); 3005 donelist_init(&donelist); 3006 symlook_init_from_req(&req1, req); 3007 res = symlook_needed(&req1, obj->needed_aux_filtees, &donelist); 3008 if (res == 0) { 3009 req->sym_out = req1.sym_out; 3010 req->defobj_out = req1.defobj_out; 3011 return (res); 3012 } 3013 } 3014 } 3015 return (mres); 3016} 3017 3018static int 3019symlook_obj1(SymLook *req, const Obj_Entry *obj) 3020{ |
|
2842 unsigned long symnum; 2843 const Elf_Sym *vsymp; 2844 Elf_Versym verndx; 2845 int vcount; 2846 2847 if (obj->buckets == NULL) | 3021 unsigned long symnum; 3022 const Elf_Sym *vsymp; 3023 Elf_Versym verndx; 3024 int vcount; 3025 3026 if (obj->buckets == NULL) |
2848 return NULL; | 3027 return (ESRCH); |
2849 2850 vsymp = NULL; 2851 vcount = 0; | 3028 3029 vsymp = NULL; 3030 vcount = 0; |
2852 symnum = obj->buckets[hash % obj->nbuckets]; | 3031 symnum = obj->buckets[req->hash % obj->nbuckets]; |
2853 2854 for (; symnum != STN_UNDEF; symnum = obj->chains[symnum]) { 2855 const Elf_Sym *symp; 2856 const char *strp; 2857 2858 if (symnum >= obj->nchains) | 3032 3033 for (; symnum != STN_UNDEF; symnum = obj->chains[symnum]) { 3034 const Elf_Sym *symp; 3035 const char *strp; 3036 3037 if (symnum >= obj->nchains) |
2859 return NULL; /* Bad object */ | 3038 return (ESRCH); /* Bad object */ |
2860 2861 symp = obj->symtab + symnum; 2862 strp = obj->strtab + symp->st_name; 2863 2864 switch (ELF_ST_TYPE(symp->st_info)) { 2865 case STT_FUNC: 2866 case STT_NOTYPE: 2867 case STT_OBJECT: 2868 if (symp->st_value == 0) 2869 continue; 2870 /* fallthrough */ 2871 case STT_TLS: 2872 if (symp->st_shndx != SHN_UNDEF) 2873 break; 2874#ifndef __mips__ | 3039 3040 symp = obj->symtab + symnum; 3041 strp = obj->strtab + symp->st_name; 3042 3043 switch (ELF_ST_TYPE(symp->st_info)) { 3044 case STT_FUNC: 3045 case STT_NOTYPE: 3046 case STT_OBJECT: 3047 if (symp->st_value == 0) 3048 continue; 3049 /* fallthrough */ 3050 case STT_TLS: 3051 if (symp->st_shndx != SHN_UNDEF) 3052 break; 3053#ifndef __mips__ |
2875 else if (((flags & SYMLOOK_IN_PLT) == 0) && | 3054 else if (((req->flags & SYMLOOK_IN_PLT) == 0) && |
2876 (ELF_ST_TYPE(symp->st_info) == STT_FUNC)) 2877 break; 2878 /* fallthrough */ 2879#endif 2880 default: 2881 continue; 2882 } | 3055 (ELF_ST_TYPE(symp->st_info) == STT_FUNC)) 3056 break; 3057 /* fallthrough */ 3058#endif 3059 default: 3060 continue; 3061 } |
2883 if (name[0] != strp[0] || strcmp(name, strp) != 0) | 3062 if (req->name[0] != strp[0] || strcmp(req->name, strp) != 0) |
2884 continue; 2885 | 3063 continue; 3064 |
2886 if (ventry == NULL) { | 3065 if (req->ventry == NULL) { |
2887 if (obj->versyms != NULL) { 2888 verndx = VER_NDX(obj->versyms[symnum]); 2889 if (verndx > obj->vernum) { 2890 _rtld_error("%s: symbol %s references wrong version %d", 2891 obj->path, obj->strtab + symnum, verndx); 2892 continue; 2893 } 2894 /* 2895 * If we are not called from dlsym (i.e. this is a normal | 3066 if (obj->versyms != NULL) { 3067 verndx = VER_NDX(obj->versyms[symnum]); 3068 if (verndx > obj->vernum) { 3069 _rtld_error("%s: symbol %s references wrong version %d", 3070 obj->path, obj->strtab + symnum, verndx); 3071 continue; 3072 } 3073 /* 3074 * If we are not called from dlsym (i.e. this is a normal |
2896 * relocation from unversioned binary, accept the symbol | 3075 * relocation from unversioned binary), accept the symbol |
2897 * immediately if it happens to have first version after 2898 * this shared object became versioned. Otherwise, if 2899 * symbol is versioned and not hidden, remember it. If it 2900 * is the only symbol with this name exported by the 2901 * shared object, it will be returned as a match at the 2902 * end of the function. If symbol is global (verndx < 2) 2903 * accept it unconditionally. 2904 */ | 3076 * immediately if it happens to have first version after 3077 * this shared object became versioned. Otherwise, if 3078 * symbol is versioned and not hidden, remember it. If it 3079 * is the only symbol with this name exported by the 3080 * shared object, it will be returned as a match at the 3081 * end of the function. If symbol is global (verndx < 2) 3082 * accept it unconditionally. 3083 */ |
2905 if ((flags & SYMLOOK_DLSYM) == 0 && verndx == VER_NDX_GIVEN) 2906 return symp; 2907 else if (verndx >= VER_NDX_GIVEN) { | 3084 if ((req->flags & SYMLOOK_DLSYM) == 0 && 3085 verndx == VER_NDX_GIVEN) { 3086 req->sym_out = symp; 3087 req->defobj_out = obj; 3088 return (0); 3089 } 3090 else if (verndx >= VER_NDX_GIVEN) { |
2908 if ((obj->versyms[symnum] & VER_NDX_HIDDEN) == 0) { 2909 if (vsymp == NULL) 2910 vsymp = symp; 2911 vcount ++; 2912 } 2913 continue; 2914 } 2915 } | 3091 if ((obj->versyms[symnum] & VER_NDX_HIDDEN) == 0) { 3092 if (vsymp == NULL) 3093 vsymp = symp; 3094 vcount ++; 3095 } 3096 continue; 3097 } 3098 } |
2916 return symp; | 3099 req->sym_out = symp; 3100 req->defobj_out = obj; 3101 return (0); |
2917 } else { 2918 if (obj->versyms == NULL) { | 3102 } else { 3103 if (obj->versyms == NULL) { |
2919 if (object_match_name(obj, ventry->name)) { | 3104 if (object_match_name(obj, req->ventry->name)) { |
2920 _rtld_error("%s: object %s should provide version %s for " | 3105 _rtld_error("%s: object %s should provide version %s for " |
2921 "symbol %s", obj_rtld.path, obj->path, ventry->name, 2922 obj->strtab + symnum); | 3106 "symbol %s", obj_rtld.path, obj->path, 3107 req->ventry->name, obj->strtab + symnum); |
2923 continue; 2924 } 2925 } else { 2926 verndx = VER_NDX(obj->versyms[symnum]); 2927 if (verndx > obj->vernum) { 2928 _rtld_error("%s: symbol %s references wrong version %d", 2929 obj->path, obj->strtab + symnum, verndx); 2930 continue; 2931 } | 3108 continue; 3109 } 3110 } else { 3111 verndx = VER_NDX(obj->versyms[symnum]); 3112 if (verndx > obj->vernum) { 3113 _rtld_error("%s: symbol %s references wrong version %d", 3114 obj->path, obj->strtab + symnum, verndx); 3115 continue; 3116 } |
2932 if (obj->vertab[verndx].hash != ventry->hash || 2933 strcmp(obj->vertab[verndx].name, ventry->name)) { | 3117 if (obj->vertab[verndx].hash != req->ventry->hash || 3118 strcmp(obj->vertab[verndx].name, req->ventry->name)) { |
2934 /* 2935 * Version does not match. Look if this is a global symbol 2936 * and if it is not hidden. If global symbol (verndx < 2) 2937 * is available, use it. Do not return symbol if we are 2938 * called by dlvsym, because dlvsym looks for a specific 2939 * version and default one is not what dlvsym wants. 2940 */ | 3119 /* 3120 * Version does not match. Look if this is a global symbol 3121 * and if it is not hidden. If global symbol (verndx < 2) 3122 * is available, use it. Do not return symbol if we are 3123 * called by dlvsym, because dlvsym looks for a specific 3124 * version and default one is not what dlvsym wants. 3125 */ |
2941 if ((flags & SYMLOOK_DLSYM) || | 3126 if ((req->flags & SYMLOOK_DLSYM) || |
2942 (obj->versyms[symnum] & VER_NDX_HIDDEN) || 2943 (verndx >= VER_NDX_GIVEN)) 2944 continue; 2945 } 2946 } | 3127 (obj->versyms[symnum] & VER_NDX_HIDDEN) || 3128 (verndx >= VER_NDX_GIVEN)) 3129 continue; 3130 } 3131 } |
2947 return symp; | 3132 req->sym_out = symp; 3133 req->defobj_out = obj; 3134 return (0); |
2948 } 2949 } | 3135 } 3136 } |
2950 return (vcount == 1) ? vsymp : NULL; | 3137 if (vcount == 1) { 3138 req->sym_out = vsymp; 3139 req->defobj_out = obj; 3140 return (0); 3141 } 3142 return (ESRCH); |
2951} 2952 2953static void 2954trace_loaded_objects(Obj_Entry *obj) 2955{ 2956 char *fmt1, *fmt2, *fmt, *main_local, *list_containers; 2957 int c; 2958 --- 107 unchanged lines hidden (view full) --- 3066 3067 /* Unmap all objects that are no longer referenced. */ 3068 linkp = &obj_list->next; 3069 while ((obj = *linkp) != NULL) { 3070 if (obj->refcount == 0) { 3071 LD_UTRACE(UTRACE_UNLOAD_OBJECT, obj, obj->mapbase, obj->mapsize, 0, 3072 obj->path); 3073 dbg("unloading \"%s\"", obj->path); | 3143} 3144 3145static void 3146trace_loaded_objects(Obj_Entry *obj) 3147{ 3148 char *fmt1, *fmt2, *fmt, *main_local, *list_containers; 3149 int c; 3150 --- 107 unchanged lines hidden (view full) --- 3258 3259 /* Unmap all objects that are no longer referenced. */ 3260 linkp = &obj_list->next; 3261 while ((obj = *linkp) != NULL) { 3262 if (obj->refcount == 0) { 3263 LD_UTRACE(UTRACE_UNLOAD_OBJECT, obj, obj->mapbase, obj->mapsize, 0, 3264 obj->path); 3265 dbg("unloading \"%s\"", obj->path); |
3266 unload_filtees(root); |
|
3074 munmap(obj->mapbase, obj->mapsize); 3075 linkmap_delete(obj); 3076 *linkp = obj->next; 3077 obj_count--; 3078 obj_free(obj); 3079 } else 3080 linkp = &obj->next; 3081 } --- 40 unchanged lines hidden (view full) --- 3122 3123/* 3124 * Common code for MD __tls_get_addr(). 3125 */ 3126void * 3127tls_get_addr_common(Elf_Addr** dtvp, int index, size_t offset) 3128{ 3129 Elf_Addr* dtv = *dtvp; | 3267 munmap(obj->mapbase, obj->mapsize); 3268 linkmap_delete(obj); 3269 *linkp = obj->next; 3270 obj_count--; 3271 obj_free(obj); 3272 } else 3273 linkp = &obj->next; 3274 } --- 40 unchanged lines hidden (view full) --- 3315 3316/* 3317 * Common code for MD __tls_get_addr(). 3318 */ 3319void * 3320tls_get_addr_common(Elf_Addr** dtvp, int index, size_t offset) 3321{ 3322 Elf_Addr* dtv = *dtvp; |
3130 int lockstate; | 3323 RtldLockState lockstate; |
3131 3132 /* Check dtv generation in case new modules have arrived */ 3133 if (dtv[0] != tls_dtv_generation) { 3134 Elf_Addr* newdtv; 3135 int to_copy; 3136 | 3324 3325 /* Check dtv generation in case new modules have arrived */ 3326 if (dtv[0] != tls_dtv_generation) { 3327 Elf_Addr* newdtv; 3328 int to_copy; 3329 |
3137 lockstate = wlock_acquire(rtld_bind_lock); | 3330 wlock_acquire(rtld_bind_lock, &lockstate); |
3138 newdtv = calloc(1, (tls_max_index + 2) * sizeof(Elf_Addr)); 3139 to_copy = dtv[1]; 3140 if (to_copy > tls_max_index) 3141 to_copy = tls_max_index; 3142 memcpy(&newdtv[2], &dtv[2], to_copy * sizeof(Elf_Addr)); 3143 newdtv[0] = tls_dtv_generation; 3144 newdtv[1] = tls_max_index; 3145 free(dtv); | 3331 newdtv = calloc(1, (tls_max_index + 2) * sizeof(Elf_Addr)); 3332 to_copy = dtv[1]; 3333 if (to_copy > tls_max_index) 3334 to_copy = tls_max_index; 3335 memcpy(&newdtv[2], &dtv[2], to_copy * sizeof(Elf_Addr)); 3336 newdtv[0] = tls_dtv_generation; 3337 newdtv[1] = tls_max_index; 3338 free(dtv); |
3146 wlock_release(rtld_bind_lock, lockstate); | 3339 lock_release(rtld_bind_lock, &lockstate); |
3147 *dtvp = newdtv; 3148 } 3149 3150 /* Dynamically allocate module TLS if necessary */ 3151 if (!dtv[index + 1]) { 3152 /* Signal safe, wlock will block out signals. */ | 3340 *dtvp = newdtv; 3341 } 3342 3343 /* Dynamically allocate module TLS if necessary */ 3344 if (!dtv[index + 1]) { 3345 /* Signal safe, wlock will block out signals. */ |
3153 lockstate = wlock_acquire(rtld_bind_lock); | 3346 wlock_acquire(rtld_bind_lock, &lockstate); |
3154 if (!dtv[index + 1]) 3155 dtv[index + 1] = (Elf_Addr)allocate_module_tls(index); | 3347 if (!dtv[index + 1]) 3348 dtv[index + 1] = (Elf_Addr)allocate_module_tls(index); |
3156 wlock_release(rtld_bind_lock, lockstate); | 3349 lock_release(rtld_bind_lock, &lockstate); |
3157 } 3158 return (void*) (dtv[index + 1] + offset); 3159} 3160 3161/* XXX not sure what variants to use for arm. */ 3162 3163#if defined(__ia64__) || defined(__powerpc__) 3164 --- 259 unchanged lines hidden (view full) --- 3424 tls_last_size = 0; 3425 } 3426} 3427 3428void * 3429_rtld_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign) 3430{ 3431 void *ret; | 3350 } 3351 return (void*) (dtv[index + 1] + offset); 3352} 3353 3354/* XXX not sure what variants to use for arm. */ 3355 3356#if defined(__ia64__) || defined(__powerpc__) 3357 --- 259 unchanged lines hidden (view full) --- 3617 tls_last_size = 0; 3618 } 3619} 3620 3621void * 3622_rtld_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign) 3623{ 3624 void *ret; |
3432 int lockstate; | 3625 RtldLockState lockstate; |
3433 | 3626 |
3434 lockstate = wlock_acquire(rtld_bind_lock); | 3627 wlock_acquire(rtld_bind_lock, &lockstate); |
3435 ret = allocate_tls(obj_list, oldtls, tcbsize, tcbalign); | 3628 ret = allocate_tls(obj_list, oldtls, tcbsize, tcbalign); |
3436 wlock_release(rtld_bind_lock, lockstate); | 3629 lock_release(rtld_bind_lock, &lockstate); |
3437 return (ret); 3438} 3439 3440void 3441_rtld_free_tls(void *tcb, size_t tcbsize, size_t tcbalign) 3442{ | 3630 return (ret); 3631} 3632 3633void 3634_rtld_free_tls(void *tcb, size_t tcbsize, size_t tcbalign) 3635{ |
3443 int lockstate; | 3636 RtldLockState lockstate; |
3444 | 3637 |
3445 lockstate = wlock_acquire(rtld_bind_lock); | 3638 wlock_acquire(rtld_bind_lock, &lockstate); |
3446 free_tls(tcb, tcbsize, tcbalign); | 3639 free_tls(tcb, tcbsize, tcbalign); |
3447 wlock_release(rtld_bind_lock, lockstate); | 3640 lock_release(rtld_bind_lock, &lockstate); |
3448} 3449 3450static void 3451object_add_name(Obj_Entry *obj, const char *name) 3452{ 3453 Name_Entry *entry; 3454 size_t len; 3455 --- 218 unchanged lines hidden (view full) --- 3674 obj->path, obj->strtab + symnum, vernum); 3675 } else if (obj->vertab[vernum].hash != 0) { 3676 return &obj->vertab[vernum]; 3677 } 3678 } 3679 return NULL; 3680} 3681 | 3641} 3642 3643static void 3644object_add_name(Obj_Entry *obj, const char *name) 3645{ 3646 Name_Entry *entry; 3647 size_t len; 3648 --- 218 unchanged lines hidden (view full) --- 3867 obj->path, obj->strtab + symnum, vernum); 3868 } else if (obj->vertab[vernum].hash != 0) { 3869 return &obj->vertab[vernum]; 3870 } 3871 } 3872 return NULL; 3873} 3874 |
3875void 3876symlook_init(SymLook *dst, const char *name) 3877{ 3878 3879 bzero(dst, sizeof(*dst)); 3880 dst->name = name; 3881 dst->hash = elf_hash(name); 3882} 3883 3884static void 3885symlook_init_from_req(SymLook *dst, const SymLook *src) 3886{ 3887 3888 dst->name = src->name; 3889 dst->hash = src->hash; 3890 dst->ventry = src->ventry; 3891 dst->flags = src->flags; 3892 dst->defobj_out = NULL; 3893 dst->sym_out = NULL; 3894 dst->lockstate = src->lockstate; 3895} 3896 |
|
3682/* 3683 * Overrides for libc_pic-provided functions. 3684 */ 3685 3686int 3687__getosreldate(void) 3688{ 3689 size_t len; --- 23 unchanged lines hidden --- | 3897/* 3898 * Overrides for libc_pic-provided functions. 3899 */ 3900 3901int 3902__getosreldate(void) 3903{ 3904 size_t len; --- 23 unchanged lines hidden --- |