rtld.c (e39756439c7255bc16ba14b7b991cb01ba1c93bd) | rtld.c (630df077ab61c69ad927873957c53efc22de140a) |
---|---|
1/*- 2 * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 44 unchanged lines hidden (view full) --- 53#include "rtld.h" 54 55#define END_SYM "_end" 56#define PATH_RTLD "/usr/libexec/ld-elf.so.1" 57 58/* Types. */ 59typedef void (*func_ptr_type)(); 60 | 1/*- 2 * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 44 unchanged lines hidden (view full) --- 53#include "rtld.h" 54 55#define END_SYM "_end" 56#define PATH_RTLD "/usr/libexec/ld-elf.so.1" 57 58/* Types. */ 59typedef void (*func_ptr_type)(); 60 |
61typedef struct Struct_LockInfo { 62 void *context; /* Client context for creating locks */ 63 void *thelock; /* The one big lock */ 64 /* Methods */ 65 void (*rlock_acquire)(void *lock); 66 void (*wlock_acquire)(void *lock); 67 void (*lock_release)(void *lock); 68 void (*lock_destroy)(void *lock); 69 void (*context_destroy)(void *context); 70} LockInfo; | 61/* 62 * This structure provides a reentrant way to keep a list of objects and 63 * check which ones have already been processed in some way. 64 */ 65typedef struct Struct_DoneList { 66 Obj_Entry **objs; /* Array of object pointers */ 67 unsigned int num_alloc; /* Allocated size of the array */ 68 unsigned int num_used; /* Number of array slots used */ 69} DoneList; |
71 72/* 73 * Function declarations. 74 */ 75static const char *basename(const char *); 76static void die(void); 77static void digest_dynamic(Obj_Entry *); 78static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *); 79static Obj_Entry *dlcheck(void *); | 70 71/* 72 * Function declarations. 73 */ 74static const char *basename(const char *); 75static void die(void); 76static void digest_dynamic(Obj_Entry *); 77static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *); 78static Obj_Entry *dlcheck(void *); |
79static bool donelist_check(DoneList *, Obj_Entry *); |
|
80static char *find_library(const char *, const Obj_Entry *); 81static void funclist_call(Funclist *); 82static void funclist_clear(Funclist *); 83static void funclist_init(Funclist *); 84static void funclist_push_head(Funclist *, InitFunc); 85static void funclist_push_tail(Funclist *, InitFunc); 86static const char *gethints(void); 87static void init_dag(Obj_Entry *); | 80static char *find_library(const char *, const Obj_Entry *); 81static void funclist_call(Funclist *); 82static void funclist_clear(Funclist *); 83static void funclist_init(Funclist *); 84static void funclist_push_head(Funclist *, InitFunc); 85static void funclist_push_tail(Funclist *, InitFunc); 86static const char *gethints(void); 87static void init_dag(Obj_Entry *); |
88static void init_dag1(Obj_Entry *root, Obj_Entry *obj); | 88static void init_dag1(Obj_Entry *root, Obj_Entry *obj, DoneList *); |
89static void init_rtld(caddr_t); 90static bool is_exported(const Elf_Sym *); 91static void linkmap_add(Obj_Entry *); 92static void linkmap_delete(Obj_Entry *); 93static int load_needed_objects(Obj_Entry *); 94static int load_preload_objects(void); 95static Obj_Entry *load_object(char *); | 89static void init_rtld(caddr_t); 90static bool is_exported(const Elf_Sym *); 91static void linkmap_add(Obj_Entry *); 92static void linkmap_delete(Obj_Entry *); 93static int load_needed_objects(Obj_Entry *); 94static int load_preload_objects(void); 95static Obj_Entry *load_object(char *); |
96static void lock_nop(void *); | 96static void lock_check(void); |
97static Obj_Entry *obj_from_addr(const void *); 98static void objlist_add(Objlist *, Obj_Entry *); 99static Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *); 100static void objlist_remove(Objlist *, Obj_Entry *); | 97static Obj_Entry *obj_from_addr(const void *); 98static void objlist_add(Objlist *, Obj_Entry *); 99static Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *); 100static void objlist_remove(Objlist *, Obj_Entry *); |
101static void prebind(void *); | |
102static int relocate_objects(Obj_Entry *, bool); 103static void rtld_exit(void); 104static char *search_library_path(const char *, const char *); 105static void set_program_var(const char *, const void *); 106static const Elf_Sym *symlook_list(const char *, unsigned long, | 101static int relocate_objects(Obj_Entry *, bool); 102static void rtld_exit(void); 103static char *search_library_path(const char *, const char *); 104static void set_program_var(const char *, const void *); 105static const Elf_Sym *symlook_list(const char *, unsigned long, |
107 Objlist *, const Obj_Entry **, bool in_plt); | 106 Objlist *, const Obj_Entry **, bool in_plt, DoneList *); |
108static void trace_loaded_objects(Obj_Entry *obj); 109static void unload_object(Obj_Entry *); 110static void unref_dag(Obj_Entry *); 111 112void r_debug_state(void); 113void xprintf(const char *, ...); 114 115/* --- 7 unchanged lines hidden (view full) --- 123static char *ld_library_path; /* Environment variable for search path */ 124static char *ld_preload; /* Environment variable for libraries to 125 load first */ 126static char *ld_tracing; /* Called from ldd to print libs */ 127static Obj_Entry *obj_list; /* Head of linked list of shared objects */ 128static Obj_Entry **obj_tail; /* Link field of last object in list */ 129static Obj_Entry *obj_main; /* The main program shared object */ 130static Obj_Entry obj_rtld; /* The dynamic linker shared object */ | 107static void trace_loaded_objects(Obj_Entry *obj); 108static void unload_object(Obj_Entry *); 109static void unref_dag(Obj_Entry *); 110 111void r_debug_state(void); 112void xprintf(const char *, ...); 113 114/* --- 7 unchanged lines hidden (view full) --- 122static char *ld_library_path; /* Environment variable for search path */ 123static char *ld_preload; /* Environment variable for libraries to 124 load first */ 125static char *ld_tracing; /* Called from ldd to print libs */ 126static Obj_Entry *obj_list; /* Head of linked list of shared objects */ 127static Obj_Entry **obj_tail; /* Link field of last object in list */ 128static Obj_Entry *obj_main; /* The main program shared object */ 129static Obj_Entry obj_rtld; /* The dynamic linker shared object */ |
131static unsigned long curmark; /* Current mark value */ | 130static unsigned int obj_count; /* Number of objects in obj_list */ |
132 133static Objlist list_global = /* Objects dlopened with RTLD_GLOBAL */ 134 STAILQ_HEAD_INITIALIZER(list_global); 135static Objlist list_main = /* Objects loaded at program startup */ 136 STAILQ_HEAD_INITIALIZER(list_main); 137 138static LockInfo lockinfo; 139 --- 22 unchanged lines hidden (view full) --- 162 163/* 164 * Global declarations normally provided by crt1. The dynamic linker is 165 * not built with crt1, so we have to provide them ourselves. 166 */ 167char *__progname; 168char **environ; 169 | 131 132static Objlist list_global = /* Objects dlopened with RTLD_GLOBAL */ 133 STAILQ_HEAD_INITIALIZER(list_global); 134static Objlist list_main = /* Objects loaded at program startup */ 135 STAILQ_HEAD_INITIALIZER(list_main); 136 137static LockInfo lockinfo; 138 --- 22 unchanged lines hidden (view full) --- 161 162/* 163 * Global declarations normally provided by crt1. The dynamic linker is 164 * not built with crt1, so we have to provide them ourselves. 165 */ 166char *__progname; 167char **environ; 168 |
169/* 170 * Fill in a DoneList with an allocation large enough to hold all of 171 * the currently-loaded objects. Keep this as a macro since it calls 172 * alloca and we want that to occur within the scope of the caller. 173 */ 174#define donelist_init(dlp) \ 175 ((dlp)->objs = alloca(obj_count * sizeof (dlp)->objs[0]), \ 176 assert((dlp)->objs != NULL), \ 177 (dlp)->num_alloc = obj_count, \ 178 (dlp)->num_used = 0) 179 |
|
170static __inline void 171rlock_acquire(void) 172{ 173 lockinfo.rlock_acquire(lockinfo.thelock); | 180static __inline void 181rlock_acquire(void) 182{ 183 lockinfo.rlock_acquire(lockinfo.thelock); |
184 atomic_incr_int(&lockinfo.rcount); 185 lock_check(); |
|
174} 175 176static __inline void 177wlock_acquire(void) 178{ 179 lockinfo.wlock_acquire(lockinfo.thelock); | 186} 187 188static __inline void 189wlock_acquire(void) 190{ 191 lockinfo.wlock_acquire(lockinfo.thelock); |
192 atomic_incr_int(&lockinfo.wcount); 193 lock_check(); |
|
180} 181 182static __inline void | 194} 195 196static __inline void |
183lock_release(void) | 197rlock_release(void) |
184{ | 198{ |
185 lockinfo.lock_release(lockinfo.thelock); | 199 atomic_decr_int(&lockinfo.rcount); 200 lockinfo.rlock_release(lockinfo.thelock); |
186} 187 | 201} 202 |
203static __inline void 204wlock_release(void) 205{ 206 atomic_decr_int(&lockinfo.wcount); 207 lockinfo.wlock_release(lockinfo.thelock); 208} 209 |
|
188/* 189 * Main entry point for dynamic linking. The first argument is the 190 * stack pointer. The stack is expected to be laid out as described 191 * in the SVR4 ABI specification, Intel 386 Processor Supplement. 192 * Specifically, the stack pointer points to a word containing 193 * ARGC. Following that in the stack is a null-terminated sequence 194 * of pointers to argument strings. Then comes a null-terminated 195 * sequence of pointers to environment strings. Finally, there is a --- 115 unchanged lines hidden (view full) --- 311 digest_dynamic(obj_main); 312 313 linkmap_add(obj_main); 314 linkmap_add(&obj_rtld); 315 316 /* Link the main program into the list of objects. */ 317 *obj_tail = obj_main; 318 obj_tail = &obj_main->next; | 210/* 211 * Main entry point for dynamic linking. The first argument is the 212 * stack pointer. The stack is expected to be laid out as described 213 * in the SVR4 ABI specification, Intel 386 Processor Supplement. 214 * Specifically, the stack pointer points to a word containing 215 * ARGC. Following that in the stack is a null-terminated sequence 216 * of pointers to argument strings. Then comes a null-terminated 217 * sequence of pointers to environment strings. Finally, there is a --- 115 unchanged lines hidden (view full) --- 333 digest_dynamic(obj_main); 334 335 linkmap_add(obj_main); 336 linkmap_add(&obj_rtld); 337 338 /* Link the main program into the list of objects. */ 339 *obj_tail = obj_main; 340 obj_tail = &obj_main->next; |
341 obj_count++; |
|
319 obj_main->refcount++; 320 321 /* Initialize a fake symbol for resolving undefined weak references. */ 322 sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE); 323 sym_zero.st_shndx = SHN_ABS; 324 325 dbg("loading LD_PRELOAD libraries"); 326 if (load_preload_objects() == -1) --- 26 unchanged lines hidden (view full) --- 353 dbg("doing copy relocations"); 354 if (do_copy_relocations(obj_main) == -1) 355 die(); 356 357 dbg("initializing key program variables"); 358 set_program_var("__progname", argv[0] != NULL ? basename(argv[0]) : ""); 359 set_program_var("environ", env); 360 | 342 obj_main->refcount++; 343 344 /* Initialize a fake symbol for resolving undefined weak references. */ 345 sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE); 346 sym_zero.st_shndx = SHN_ABS; 347 348 dbg("loading LD_PRELOAD libraries"); 349 if (load_preload_objects() == -1) --- 26 unchanged lines hidden (view full) --- 376 dbg("doing copy relocations"); 377 if (do_copy_relocations(obj_main) == -1) 378 die(); 379 380 dbg("initializing key program variables"); 381 set_program_var("__progname", argv[0] != NULL ? basename(argv[0]) : ""); 382 set_program_var("environ", env); 383 |
361 dbg("initializing default locks"); 362 dllockinit(NULL, NULL, NULL, NULL, NULL, NULL, NULL); | 384 dbg("initializing thread locks"); 385 lockdflt_init(&lockinfo); 386 lockinfo.thelock = lockinfo.lock_create(lockinfo.context); |
363 364 r_debug_state(); /* say hello to gdb! */ 365 366 funclist_call(&initlist); 367 wlock_acquire(); 368 funclist_clear(&initlist); | 387 388 r_debug_state(); /* say hello to gdb! */ 389 390 funclist_call(&initlist); 391 wlock_acquire(); 392 funclist_clear(&initlist); |
369 lock_release(); | 393 wlock_release(); |
370 371 dbg("transferring control to program entry point = %p", obj_main->entry); 372 373 /* Return the exit procedure and the program entry point. */ 374 *exit_proc = rtld_exit; 375 *objp = obj_main; 376 return (func_ptr_type) obj_main->entry; 377} 378 379Elf_Addr 380_rtld_bind(Obj_Entry *obj, Elf_Word reloff) 381{ 382 const Elf_Rel *rel; 383 const Elf_Sym *def; 384 const Obj_Entry *defobj; 385 Elf_Addr *where; 386 Elf_Addr target; 387 | 394 395 dbg("transferring control to program entry point = %p", obj_main->entry); 396 397 /* Return the exit procedure and the program entry point. */ 398 *exit_proc = rtld_exit; 399 *objp = obj_main; 400 return (func_ptr_type) obj_main->entry; 401} 402 403Elf_Addr 404_rtld_bind(Obj_Entry *obj, Elf_Word reloff) 405{ 406 const Elf_Rel *rel; 407 const Elf_Sym *def; 408 const Obj_Entry *defobj; 409 Elf_Addr *where; 410 Elf_Addr target; 411 |
388 wlock_acquire(); | 412 rlock_acquire(); |
389 if (obj->pltrel) 390 rel = (const Elf_Rel *) ((caddr_t) obj->pltrel + reloff); 391 else 392 rel = (const Elf_Rel *) ((caddr_t) obj->pltrela + reloff); 393 394 where = (Elf_Addr *) (obj->relocbase + rel->r_offset); 395 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true); 396 if (def == NULL) 397 die(); 398 399 target = (Elf_Addr)(defobj->relocbase + def->st_value); 400 401 dbg("\"%s\" in \"%s\" ==> %p in \"%s\"", 402 defobj->strtab + def->st_name, basename(obj->path), 403 (void *)target, basename(defobj->path)); 404 405 reloc_jmpslot(where, target); | 413 if (obj->pltrel) 414 rel = (const Elf_Rel *) ((caddr_t) obj->pltrel + reloff); 415 else 416 rel = (const Elf_Rel *) ((caddr_t) obj->pltrela + reloff); 417 418 where = (Elf_Addr *) (obj->relocbase + rel->r_offset); 419 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true); 420 if (def == NULL) 421 die(); 422 423 target = (Elf_Addr)(defobj->relocbase + def->st_value); 424 425 dbg("\"%s\" in \"%s\" ==> %p in \"%s\"", 426 defobj->strtab + def->st_name, basename(obj->path), 427 (void *)target, basename(defobj->path)); 428 429 reloc_jmpslot(where, target); |
406 lock_release(); | 430 rlock_release(); |
407 return target; 408} 409 410/* 411 * Error reporting function. Use it like printf. If formats the message 412 * into a buffer, and sets things up so that the next call to dlerror() 413 * will return the message. 414 */ --- 251 unchanged lines hidden (view full) --- 666 if (obj == NULL || obj->dl_refcount == 0) { 667 _rtld_error("Invalid shared object handle %p", handle); 668 return NULL; 669 } 670 return obj; 671} 672 673/* | 431 return target; 432} 433 434/* 435 * Error reporting function. Use it like printf. If formats the message 436 * into a buffer, and sets things up so that the next call to dlerror() 437 * will return the message. 438 */ --- 251 unchanged lines hidden (view full) --- 690 if (obj == NULL || obj->dl_refcount == 0) { 691 _rtld_error("Invalid shared object handle %p", handle); 692 return NULL; 693 } 694 return obj; 695} 696 697/* |
698 * If the given object is already in the donelist, return true. Otherwise 699 * add the object to the list and return false. 700 */ 701static bool 702donelist_check(DoneList *dlp, Obj_Entry *obj) 703{ 704 unsigned int i; 705 706 for (i = 0; i < dlp->num_used; i++) 707 if (dlp->objs[i] == obj) 708 return true; 709 /* 710 * Our donelist allocation should always be sufficient. But if 711 * our threads locking isn't working properly, more shared objects 712 * could have been loaded since we allocated the list. That should 713 * never happen, but we'll handle it properly just in case it does. 714 */ 715 if (dlp->num_used < dlp->num_alloc) 716 dlp->objs[dlp->num_used++] = obj; 717 return false; 718} 719 720/* |
|
674 * Hash function for symbol table lookup. Don't even think about changing 675 * this. It is specified by the System V ABI. 676 */ 677unsigned long 678elf_hash(const char *name) 679{ 680 const unsigned char *p = (const unsigned char *) name; 681 unsigned long h = 0; --- 54 unchanged lines hidden (view full) --- 736 * definition of the symbol. Returns a pointer to the symbol, or NULL if 737 * no definition was found. Returns a pointer to the Obj_Entry of the 738 * defining object via the reference parameter DEFOBJ_OUT. 739 */ 740const Elf_Sym * 741find_symdef(unsigned long symnum, Obj_Entry *refobj, 742 const Obj_Entry **defobj_out, bool in_plt) 743{ | 721 * Hash function for symbol table lookup. Don't even think about changing 722 * this. It is specified by the System V ABI. 723 */ 724unsigned long 725elf_hash(const char *name) 726{ 727 const unsigned char *p = (const unsigned char *) name; 728 unsigned long h = 0; --- 54 unchanged lines hidden (view full) --- 783 * definition of the symbol. Returns a pointer to the symbol, or NULL if 784 * no definition was found. Returns a pointer to the Obj_Entry of the 785 * defining object via the reference parameter DEFOBJ_OUT. 786 */ 787const Elf_Sym * 788find_symdef(unsigned long symnum, Obj_Entry *refobj, 789 const Obj_Entry **defobj_out, bool in_plt) 790{ |
791 DoneList donelist; |
|
744 const Elf_Sym *ref; 745 const Elf_Sym *def; 746 const Elf_Sym *symp; 747 const Obj_Entry *obj; 748 const Obj_Entry *defobj; 749 const Objlist_Entry *elm; 750 const char *name; 751 unsigned long hash; 752 753 ref = refobj->symtab + symnum; 754 name = refobj->strtab + ref->st_name; 755 hash = elf_hash(name); 756 def = NULL; 757 defobj = NULL; | 792 const Elf_Sym *ref; 793 const Elf_Sym *def; 794 const Elf_Sym *symp; 795 const Obj_Entry *obj; 796 const Obj_Entry *defobj; 797 const Objlist_Entry *elm; 798 const char *name; 799 unsigned long hash; 800 801 ref = refobj->symtab + symnum; 802 name = refobj->strtab + ref->st_name; 803 hash = elf_hash(name); 804 def = NULL; 805 defobj = NULL; |
758 curmark++; | 806 donelist_init(&donelist); |
759 | 807 |
760 if (refobj->symbolic) { /* Look first in the referencing object */ | 808 /* Look first in the referencing object if linked symbolically. */ 809 if (refobj->symbolic && !donelist_check(&donelist, refobj)) { |
761 symp = symlook_obj(name, hash, refobj, in_plt); | 810 symp = symlook_obj(name, hash, refobj, in_plt); |
762 refobj->mark = curmark; | |
763 if (symp != NULL) { 764 def = symp; 765 defobj = refobj; 766 } 767 } 768 769 /* Search all objects loaded at program start up. */ 770 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { | 811 if (symp != NULL) { 812 def = symp; 813 defobj = refobj; 814 } 815 } 816 817 /* Search all objects loaded at program start up. */ 818 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { |
771 symp = symlook_list(name, hash, &list_main, &obj, in_plt); | 819 symp = symlook_list(name, hash, &list_main, &obj, in_plt, &donelist); |
772 if (symp != NULL && 773 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 774 def = symp; 775 defobj = obj; 776 } 777 } 778 779 /* Search all dlopened DAGs containing the referencing object. */ 780 STAILQ_FOREACH(elm, &refobj->dldags, link) { 781 if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) 782 break; | 820 if (symp != NULL && 821 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 822 def = symp; 823 defobj = obj; 824 } 825 } 826 827 /* Search all dlopened DAGs containing the referencing object. */ 828 STAILQ_FOREACH(elm, &refobj->dldags, link) { 829 if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) 830 break; |
783 symp = symlook_list(name, hash, &elm->obj->dagmembers, &obj, in_plt); | 831 symp = symlook_list(name, hash, &elm->obj->dagmembers, &obj, in_plt, 832 &donelist); |
784 if (symp != NULL && 785 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 786 def = symp; 787 defobj = obj; 788 } 789 } 790 791 /* Search all RTLD_GLOBAL objects. */ 792 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { | 833 if (symp != NULL && 834 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 835 def = symp; 836 defobj = obj; 837 } 838 } 839 840 /* Search all RTLD_GLOBAL objects. */ 841 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { |
793 symp = symlook_list(name, hash, &list_global, &obj, in_plt); | 842 symp = symlook_list(name, hash, &list_global, &obj, in_plt, &donelist); |
794 if (symp != NULL && 795 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 796 def = symp; 797 defobj = obj; 798 } 799 } 800 801 /* --- 112 unchanged lines hidden (view full) --- 914 close(fd); 915 } 916 return hints[0] != '\0' ? hints : NULL; 917} 918 919static void 920init_dag(Obj_Entry *root) 921{ | 843 if (symp != NULL && 844 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 845 def = symp; 846 defobj = obj; 847 } 848 } 849 850 /* --- 112 unchanged lines hidden (view full) --- 963 close(fd); 964 } 965 return hints[0] != '\0' ? hints : NULL; 966} 967 968static void 969init_dag(Obj_Entry *root) 970{ |
922 curmark++; 923 init_dag1(root, root); | 971 DoneList donelist; 972 973 donelist_init(&donelist); 974 init_dag1(root, root, &donelist); |
924} 925 926static void | 975} 976 977static void |
927init_dag1(Obj_Entry *root, Obj_Entry *obj) | 978init_dag1(Obj_Entry *root, Obj_Entry *obj, DoneList *dlp) |
928{ 929 const Needed_Entry *needed; 930 | 979{ 980 const Needed_Entry *needed; 981 |
931 if (obj->mark == curmark) | 982 if (donelist_check(dlp, obj)) |
932 return; | 983 return; |
933 obj->mark = curmark; | |
934 objlist_add(&obj->dldags, root); 935 objlist_add(&root->dagmembers, obj); 936 for (needed = obj->needed; needed != NULL; needed = needed->next) 937 if (needed->obj != NULL) | 984 objlist_add(&obj->dldags, root); 985 objlist_add(&root->dagmembers, obj); 986 for (needed = obj->needed; needed != NULL; needed = needed->next) 987 if (needed->obj != NULL) |
938 init_dag1(root, needed->obj); | 988 init_dag1(root, needed->obj, dlp); |
939} 940 941/* 942 * Initialize the dynamic linker. The argument is the address at which 943 * the dynamic linker has been mapped into memory. The primary task of 944 * this function is to relocate the dynamic linker. 945 */ 946static void --- 19 unchanged lines hidden (view full) --- 966 assert(!obj_rtld.textrel); 967 968 /* 969 * Temporarily put the dynamic linker entry into the object list, so 970 * that symbols can be found. 971 */ 972 obj_list = &obj_rtld; 973 obj_tail = &obj_rtld.next; | 989} 990 991/* 992 * Initialize the dynamic linker. The argument is the address at which 993 * the dynamic linker has been mapped into memory. The primary task of 994 * this function is to relocate the dynamic linker. 995 */ 996static void --- 19 unchanged lines hidden (view full) --- 1016 assert(!obj_rtld.textrel); 1017 1018 /* 1019 * Temporarily put the dynamic linker entry into the object list, so 1020 * that symbols can be found. 1021 */ 1022 obj_list = &obj_rtld; 1023 obj_tail = &obj_rtld.next; |
1024 obj_count = 1; |
|
974 975 relocate_objects(&obj_rtld, true); 976 } 977 978 /* Make the object list empty again. */ 979 obj_list = NULL; 980 obj_tail = &obj_list; | 1025 1026 relocate_objects(&obj_rtld, true); 1027 } 1028 1029 /* Make the object list empty again. */ 1030 obj_list = NULL; 1031 obj_tail = &obj_list; |
1032 obj_count = 0; |
|
981 982 /* Replace the path with a dynamically allocated copy. */ 983 obj_rtld.path = xstrdup(obj_rtld.path); 984 985 r_debug.r_brk = r_debug_state; 986 r_debug.r_state = RT_CONSISTENT; 987} 988 --- 124 unchanged lines hidden (view full) --- 1113 return NULL; 1114 } 1115 1116 obj->path = path; 1117 digest_dynamic(obj); 1118 1119 *obj_tail = obj; 1120 obj_tail = &obj->next; | 1033 1034 /* Replace the path with a dynamically allocated copy. */ 1035 obj_rtld.path = xstrdup(obj_rtld.path); 1036 1037 r_debug.r_brk = r_debug_state; 1038 r_debug.r_state = RT_CONSISTENT; 1039} 1040 --- 124 unchanged lines hidden (view full) --- 1165 return NULL; 1166 } 1167 1168 obj->path = path; 1169 digest_dynamic(obj); 1170 1171 *obj_tail = obj; 1172 obj_tail = &obj->next; |
1173 obj_count++; |
|
1121 linkmap_add(obj); /* for GDB */ 1122 1123 dbg(" %p .. %p: %s", obj->mapbase, 1124 obj->mapbase + obj->mapsize - 1, obj->path); 1125 if (obj->textrel) 1126 dbg(" WARNING: %s has impure text", obj->path); 1127 } else 1128 free(path); 1129 1130 obj->refcount++; 1131 return obj; 1132} 1133 | 1174 linkmap_add(obj); /* for GDB */ 1175 1176 dbg(" %p .. %p: %s", obj->mapbase, 1177 obj->mapbase + obj->mapsize - 1, obj->path); 1178 if (obj->textrel) 1179 dbg(" WARNING: %s has impure text", obj->path); 1180 } else 1181 free(path); 1182 1183 obj->refcount++; 1184 return obj; 1185} 1186 |
1187/* 1188 * Check for locking violations and die if one is found. 1189 */ |
|
1134static void | 1190static void |
1135lock_nop(void *lock) | 1191lock_check(void) |
1136{ | 1192{ |
1193 int rcount, wcount; 1194 1195 rcount = lockinfo.rcount; 1196 wcount = lockinfo.wcount; 1197 assert(rcount >= 0); 1198 assert(wcount >= 0); 1199 if (wcount > 1 || (wcount != 0 && rcount != 0)) { 1200 _rtld_error("Application locking error: %d readers and %d writers" 1201 " in dynamic linker. See DLLOCKINIT(3) in manual pages.", 1202 rcount, wcount); 1203 die(); 1204 } |
|
1137} 1138 1139static Obj_Entry * 1140obj_from_addr(const void *addr) 1141{ 1142 unsigned long endhash; 1143 Obj_Entry *obj; 1144 --- 167 unchanged lines hidden (view full) --- 1312{ 1313 Obj_Entry *root; 1314 Obj_Entry *obj; 1315 Funclist finilist; 1316 1317 wlock_acquire(); 1318 root = dlcheck(handle); 1319 if (root == NULL) { | 1205} 1206 1207static Obj_Entry * 1208obj_from_addr(const void *addr) 1209{ 1210 unsigned long endhash; 1211 Obj_Entry *obj; 1212 --- 167 unchanged lines hidden (view full) --- 1380{ 1381 Obj_Entry *root; 1382 Obj_Entry *obj; 1383 Funclist finilist; 1384 1385 wlock_acquire(); 1386 root = dlcheck(handle); 1387 if (root == NULL) { |
1320 lock_release(); | 1388 wlock_release(); |
1321 return -1; 1322 } 1323 1324 /* Unreference the object and its dependencies. */ 1325 root->dl_refcount--; 1326 unref_dag(root); 1327 1328 if (root->refcount == 0) { 1329 /* 1330 * The object is no longer referenced, so we must unload it. 1331 * First, make a list of the fini functions and then call them 1332 * with no locks held. 1333 */ 1334 funclist_init(&finilist); 1335 for (obj = obj_list->next; obj != NULL; obj = obj->next) 1336 if (obj->refcount == 0 && obj->fini != NULL) 1337 funclist_push_tail(&finilist, obj->fini); 1338 | 1389 return -1; 1390 } 1391 1392 /* Unreference the object and its dependencies. */ 1393 root->dl_refcount--; 1394 unref_dag(root); 1395 1396 if (root->refcount == 0) { 1397 /* 1398 * The object is no longer referenced, so we must unload it. 1399 * First, make a list of the fini functions and then call them 1400 * with no locks held. 1401 */ 1402 funclist_init(&finilist); 1403 for (obj = obj_list->next; obj != NULL; obj = obj->next) 1404 if (obj->refcount == 0 && obj->fini != NULL) 1405 funclist_push_tail(&finilist, obj->fini); 1406 |
1339 lock_release(); | 1407 wlock_release(); |
1340 funclist_call(&finilist); 1341 wlock_acquire(); 1342 funclist_clear(&finilist); 1343 1344 /* Finish cleaning up the newly-unreferenced objects. */ 1345 GDB_STATE(RT_DELETE); 1346 unload_object(root); 1347 GDB_STATE(RT_CONSISTENT); 1348 } | 1408 funclist_call(&finilist); 1409 wlock_acquire(); 1410 funclist_clear(&finilist); 1411 1412 /* Finish cleaning up the newly-unreferenced objects. */ 1413 GDB_STATE(RT_DELETE); 1414 unload_object(root); 1415 GDB_STATE(RT_CONSISTENT); 1416 } |
1349 lock_release(); | 1417 wlock_release(); |
1350 return 0; 1351} 1352 1353const char * 1354dlerror(void) 1355{ 1356 char *msg = error_message; 1357 error_message = NULL; 1358 return msg; 1359} 1360 | 1418 return 0; 1419} 1420 1421const char * 1422dlerror(void) 1423{ 1424 char *msg = error_message; 1425 error_message = NULL; 1426 return msg; 1427} 1428 |
1429/* 1430 * This function is deprecated and has no effect. 1431 */ |
|
1361void 1362dllockinit(void *context, 1363 void *(*lock_create)(void *context), 1364 void (*rlock_acquire)(void *lock), 1365 void (*wlock_acquire)(void *lock), 1366 void (*lock_release)(void *lock), 1367 void (*lock_destroy)(void *lock), 1368 void (*context_destroy)(void *context)) 1369{ | 1432void 1433dllockinit(void *context, 1434 void *(*lock_create)(void *context), 1435 void (*rlock_acquire)(void *lock), 1436 void (*wlock_acquire)(void *lock), 1437 void (*lock_release)(void *lock), 1438 void (*lock_destroy)(void *lock), 1439 void (*context_destroy)(void *context)) 1440{ |
1370 bool is_dflt = false; | 1441 static void *cur_context; 1442 static void (*cur_context_destroy)(void *); |
1371 | 1443 |
1372 /* NULL arguments mean reset to the built-in locks. */ 1373 if (lock_create == NULL) { 1374 is_dflt = true; 1375 context = NULL; 1376 lock_create = lockdflt_create; 1377 rlock_acquire = wlock_acquire = lockdflt_acquire; 1378 lock_release = lockdflt_release; 1379 lock_destroy = lockdflt_destroy; 1380 context_destroy = NULL; 1381 } 1382 1383 /* Temporarily set locking methods to no-ops. */ 1384 lockinfo.rlock_acquire = lock_nop; 1385 lockinfo.wlock_acquire = lock_nop; 1386 lockinfo.lock_release = lock_nop; 1387 1388 /* Release any existing locks and context. */ 1389 if (lockinfo.lock_destroy != NULL) 1390 lockinfo.lock_destroy(lockinfo.thelock); 1391 if (lockinfo.context_destroy != NULL) 1392 lockinfo.context_destroy(lockinfo.context); 1393 1394 /* 1395 * Make sure the shared objects containing the locking methods are 1396 * fully bound, to avoid infinite recursion when they are called 1397 * from the lazy binding code. 1398 */ 1399 if (!is_dflt) { 1400 prebind((void *)rlock_acquire); 1401 prebind((void *)wlock_acquire); 1402 prebind((void *)lock_release); 1403 } 1404 1405 /* Allocate our lock. */ 1406 lockinfo.thelock = lock_create(lockinfo.context); 1407 1408 /* Record the new method information. */ 1409 lockinfo.context = context; 1410 lockinfo.rlock_acquire = rlock_acquire; 1411 lockinfo.wlock_acquire = wlock_acquire; 1412 lockinfo.lock_release = lock_release; 1413 lockinfo.lock_destroy = lock_destroy; 1414 lockinfo.context_destroy = context_destroy; | 1444 /* Just destroy the context from the previous call, if necessary. */ 1445 if (cur_context_destroy != NULL) 1446 cur_context_destroy(cur_context); 1447 cur_context = context; 1448 cur_context_destroy = context_destroy; |
1415} 1416 | 1449} 1450 |
1417static void 1418prebind(void *addr) 1419{ 1420 Obj_Entry *obj; 1421 1422 if ((obj = obj_from_addr(addr)) == NULL) { 1423 _rtld_error("Cannot determine shared object of locking method at %p", 1424 addr); 1425 die(); 1426 } 1427 if (!obj->rtld && !obj->jmpslots_done) { 1428 dbg("Pre-binding %s for locking", obj->path); 1429 if (reloc_jmpslots(obj) == -1) 1430 die(); 1431 } 1432} 1433 | |
1434void * 1435dlopen(const char *name, int mode) 1436{ 1437 Obj_Entry **old_obj_tail; 1438 Obj_Entry *obj; 1439 Obj_Entry *initobj; 1440 Funclist initlist; 1441 --- 35 unchanged lines hidden (view full) --- 1477 funclist_push_head(&initlist, initobj->init); 1478 } 1479 } 1480 } 1481 1482 GDB_STATE(RT_CONSISTENT); 1483 1484 /* Call the init functions with no locks held. */ | 1451void * 1452dlopen(const char *name, int mode) 1453{ 1454 Obj_Entry **old_obj_tail; 1455 Obj_Entry *obj; 1456 Obj_Entry *initobj; 1457 Funclist initlist; 1458 --- 35 unchanged lines hidden (view full) --- 1494 funclist_push_head(&initlist, initobj->init); 1495 } 1496 } 1497 } 1498 1499 GDB_STATE(RT_CONSISTENT); 1500 1501 /* Call the init functions with no locks held. */ |
1485 lock_release(); | 1502 wlock_release(); |
1486 funclist_call(&initlist); 1487 wlock_acquire(); 1488 funclist_clear(&initlist); | 1503 funclist_call(&initlist); 1504 wlock_acquire(); 1505 funclist_clear(&initlist); |
1489 lock_release(); | 1506 wlock_release(); |
1490 return obj; 1491} 1492 1493void * 1494dlsym(void *handle, const char *name) 1495{ 1496 const Obj_Entry *obj; 1497 unsigned long hash; 1498 const Elf_Sym *def; 1499 const Obj_Entry *defobj; 1500 1501 hash = elf_hash(name); 1502 def = NULL; 1503 defobj = NULL; 1504 | 1507 return obj; 1508} 1509 1510void * 1511dlsym(void *handle, const char *name) 1512{ 1513 const Obj_Entry *obj; 1514 unsigned long hash; 1515 const Elf_Sym *def; 1516 const Obj_Entry *defobj; 1517 1518 hash = elf_hash(name); 1519 def = NULL; 1520 defobj = NULL; 1521 |
1505 wlock_acquire(); | 1522 rlock_acquire(); |
1506 if (handle == NULL || handle == RTLD_NEXT) { 1507 void *retaddr; 1508 1509 retaddr = __builtin_return_address(0); /* __GNUC__ only */ 1510 if ((obj = obj_from_addr(retaddr)) == NULL) { 1511 _rtld_error("Cannot determine caller's shared object"); | 1523 if (handle == NULL || handle == RTLD_NEXT) { 1524 void *retaddr; 1525 1526 retaddr = __builtin_return_address(0); /* __GNUC__ only */ 1527 if ((obj = obj_from_addr(retaddr)) == NULL) { 1528 _rtld_error("Cannot determine caller's shared object"); |
1512 lock_release(); | 1529 rlock_release(); |
1513 return NULL; 1514 } 1515 if (handle == NULL) { /* Just the caller's shared object. */ 1516 def = symlook_obj(name, hash, obj, true); 1517 defobj = obj; 1518 } else { /* All the shared objects after the caller's */ 1519 while ((obj = obj->next) != NULL) { 1520 if ((def = symlook_obj(name, hash, obj, true)) != NULL) { 1521 defobj = obj; 1522 break; 1523 } 1524 } 1525 } 1526 } else { 1527 if ((obj = dlcheck(handle)) == NULL) { | 1530 return NULL; 1531 } 1532 if (handle == NULL) { /* Just the caller's shared object. */ 1533 def = symlook_obj(name, hash, obj, true); 1534 defobj = obj; 1535 } else { /* All the shared objects after the caller's */ 1536 while ((obj = obj->next) != NULL) { 1537 if ((def = symlook_obj(name, hash, obj, true)) != NULL) { 1538 defobj = obj; 1539 break; 1540 } 1541 } 1542 } 1543 } else { 1544 if ((obj = dlcheck(handle)) == NULL) { |
1528 lock_release(); | 1545 rlock_release(); |
1529 return NULL; 1530 } 1531 1532 if (obj->mainprog) { | 1546 return NULL; 1547 } 1548 1549 if (obj->mainprog) { |
1550 DoneList donelist; 1551 |
|
1533 /* Search main program and all libraries loaded by it. */ | 1552 /* Search main program and all libraries loaded by it. */ |
1534 curmark++; 1535 def = symlook_list(name, hash, &list_main, &defobj, true); | 1553 donelist_init(&donelist); 1554 def = symlook_list(name, hash, &list_main, &defobj, true, 1555 &donelist); |
1536 } else { 1537 /* 1538 * XXX - This isn't correct. The search should include the whole 1539 * DAG rooted at the given object. 1540 */ 1541 def = symlook_obj(name, hash, obj, true); 1542 defobj = obj; 1543 } 1544 } 1545 1546 if (def != NULL) { | 1556 } else { 1557 /* 1558 * XXX - This isn't correct. The search should include the whole 1559 * DAG rooted at the given object. 1560 */ 1561 def = symlook_obj(name, hash, obj, true); 1562 defobj = obj; 1563 } 1564 } 1565 1566 if (def != NULL) { |
1547 lock_release(); | 1567 rlock_release(); |
1548 return defobj->relocbase + def->st_value; 1549 } 1550 1551 _rtld_error("Undefined symbol \"%s\"", name); | 1568 return defobj->relocbase + def->st_value; 1569 } 1570 1571 _rtld_error("Undefined symbol \"%s\"", name); |
1552 lock_release(); | 1572 rlock_release(); |
1553 return NULL; 1554} 1555 1556int 1557dladdr(const void *addr, Dl_info *info) 1558{ 1559 const Obj_Entry *obj; 1560 const Elf_Sym *def; 1561 void *symbol_addr; 1562 unsigned long symoffset; 1563 | 1573 return NULL; 1574} 1575 1576int 1577dladdr(const void *addr, Dl_info *info) 1578{ 1579 const Obj_Entry *obj; 1580 const Elf_Sym *def; 1581 void *symbol_addr; 1582 unsigned long symoffset; 1583 |
1564 wlock_acquire(); | 1584 rlock_acquire(); |
1565 obj = obj_from_addr(addr); 1566 if (obj == NULL) { 1567 _rtld_error("No shared object contains address"); | 1585 obj = obj_from_addr(addr); 1586 if (obj == NULL) { 1587 _rtld_error("No shared object contains address"); |
1568 lock_release(); | 1588 rlock_release(); |
1569 return 0; 1570 } 1571 info->dli_fname = obj->path; 1572 info->dli_fbase = obj->mapbase; 1573 info->dli_saddr = (void *)0; 1574 info->dli_sname = NULL; 1575 1576 /* --- 22 unchanged lines hidden (view full) --- 1599 /* Update our idea of the nearest symbol. */ 1600 info->dli_sname = obj->strtab + def->st_name; 1601 info->dli_saddr = symbol_addr; 1602 1603 /* Exact match? */ 1604 if (info->dli_saddr == addr) 1605 break; 1606 } | 1589 return 0; 1590 } 1591 info->dli_fname = obj->path; 1592 info->dli_fbase = obj->mapbase; 1593 info->dli_saddr = (void *)0; 1594 info->dli_sname = NULL; 1595 1596 /* --- 22 unchanged lines hidden (view full) --- 1619 /* Update our idea of the nearest symbol. */ 1620 info->dli_sname = obj->strtab + def->st_name; 1621 info->dli_saddr = symbol_addr; 1622 1623 /* Exact match? */ 1624 if (info->dli_saddr == addr) 1625 break; 1626 } |
1607 lock_release(); | 1627 rlock_release(); |
1608 return 1; 1609} 1610 1611static void 1612linkmap_add(Obj_Entry *obj) 1613{ 1614 struct link_map *l = &obj->linkmap; 1615 struct link_map *prev; --- 74 unchanged lines hidden (view full) --- 1690 *addr = value; 1691 break; 1692 } 1693 } 1694} 1695 1696static const Elf_Sym * 1697symlook_list(const char *name, unsigned long hash, Objlist *objlist, | 1628 return 1; 1629} 1630 1631static void 1632linkmap_add(Obj_Entry *obj) 1633{ 1634 struct link_map *l = &obj->linkmap; 1635 struct link_map *prev; --- 74 unchanged lines hidden (view full) --- 1710 *addr = value; 1711 break; 1712 } 1713 } 1714} 1715 1716static const Elf_Sym * 1717symlook_list(const char *name, unsigned long hash, Objlist *objlist, |
1698 const Obj_Entry **defobj_out, bool in_plt) | 1718 const Obj_Entry **defobj_out, bool in_plt, DoneList *dlp) |
1699{ 1700 const Elf_Sym *symp; 1701 const Elf_Sym *def; 1702 const Obj_Entry *defobj; 1703 const Objlist_Entry *elm; 1704 1705 def = NULL; 1706 defobj = NULL; 1707 STAILQ_FOREACH(elm, objlist, link) { | 1719{ 1720 const Elf_Sym *symp; 1721 const Elf_Sym *def; 1722 const Obj_Entry *defobj; 1723 const Objlist_Entry *elm; 1724 1725 def = NULL; 1726 defobj = NULL; 1727 STAILQ_FOREACH(elm, objlist, link) { |
1708 if (elm->obj->mark == curmark) | 1728 if (donelist_check(dlp, elm->obj)) |
1709 continue; | 1729 continue; |
1710 elm->obj->mark = curmark; | |
1711 if ((symp = symlook_obj(name, hash, elm->obj, in_plt)) != NULL) { 1712 if (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK) { 1713 def = symp; 1714 defobj = elm->obj; 1715 if (ELF_ST_BIND(def->st_info) != STB_WEAK) 1716 break; 1717 } 1718 } --- 153 unchanged lines hidden (view full) --- 1872 /* Unmap all objects that are no longer referenced. */ 1873 linkp = &obj_list->next; 1874 while ((obj = *linkp) != NULL) { 1875 if (obj->refcount == 0) { 1876 dbg("unloading \"%s\"", obj->path); 1877 munmap(obj->mapbase, obj->mapsize); 1878 linkmap_delete(obj); 1879 *linkp = obj->next; | 1730 if ((symp = symlook_obj(name, hash, elm->obj, in_plt)) != NULL) { 1731 if (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK) { 1732 def = symp; 1733 defobj = elm->obj; 1734 if (ELF_ST_BIND(def->st_info) != STB_WEAK) 1735 break; 1736 } 1737 } --- 153 unchanged lines hidden (view full) --- 1891 /* Unmap all objects that are no longer referenced. */ 1892 linkp = &obj_list->next; 1893 while ((obj = *linkp) != NULL) { 1894 if (obj->refcount == 0) { 1895 dbg("unloading \"%s\"", obj->path); 1896 munmap(obj->mapbase, obj->mapsize); 1897 linkmap_delete(obj); 1898 *linkp = obj->next; |
1899 obj_count--; |
|
1880 obj_free(obj); 1881 } else 1882 linkp = &obj->next; 1883 } 1884 obj_tail = linkp; 1885} 1886 1887static void --- 27 unchanged lines hidden --- | 1900 obj_free(obj); 1901 } else 1902 linkp = &obj->next; 1903 } 1904 obj_tail = linkp; 1905} 1906 1907static void --- 27 unchanged lines hidden --- |