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 ---