4 * Functions required for dlopen et. al.
10 /* The public interfaces */
11 void *dlopen(const char *, int) __attribute__ ((__weak__, __alias__ ("_dlopen")));
12 int dlclose(void *) __attribute__ ((__weak__, __alias__ ("_dlclose")));
13 void *dlsym(void *, const char *) __attribute__ ((__weak__, __alias__ ("_dlsym")));
14 const char *dlerror(void) __attribute__ ((__weak__, __alias__ ("_dlerror")));
15 int dladdr(void *, Dl_info *) __attribute__ ((__weak__, __alias__ ("_dladdr")));
20 /* This is a real hack. We need access to the dynamic linker, but we
21 also need to make it possible to link against this library without any
22 unresolved externals. We provide these weak symbols to make the link
23 possible, but at run time the normal symbols are accessed. */
24 static void __attribute__ ((unused)) foobar(void)
26 const char msg[]="libdl library not correctly linked\n";
27 _dl_write(2, msg, _dl_strlen(msg));
31 static int __attribute__ ((unused)) foobar1 = (int) foobar; /* Use as pointer */
32 extern void _dl_dprintf(int, const char *, ...) __attribute__ ((__weak__, __alias__ ("foobar")));
33 extern char *_dl_find_hash(const char *, struct dyn_elf *, struct elf_resolve *, enum caller_type)
34 __attribute__ ((__weak__, __alias__ ("foobar")));
35 extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **, struct elf_resolve *, char *)
36 __attribute__ ((__weak__, __alias__ ("foobar")));
37 extern struct elf_resolve * _dl_check_if_named_library_is_loaded(const char *full_libname)
38 __attribute__ ((__weak__, __alias__ ("foobar")));
39 extern int _dl_fixup(struct elf_resolve *tpnt, int lazy)
40 __attribute__ ((__weak__, __alias__ ("foobar")));
41 extern int _dl_copy_fixups(struct dyn_elf * tpnt)
42 __attribute__ ((__weak__, __alias__ ("foobar")));
44 extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
45 __attribute__ ((__weak__, __alias__ ("foobar")));
48 int _dl_map_cache(void) __attribute__ ((__weak__, __alias__ ("foobar")));
49 int _dl_unmap_cache(void) __attribute__ ((__weak__, __alias__ ("foobar")));
52 extern struct dyn_elf *_dl_symbol_tables __attribute__ ((__weak__, __alias__ ("foobar1")));
53 extern struct dyn_elf *_dl_handles __attribute__ ((__weak__, __alias__ ("foobar1")));
54 extern struct elf_resolve *_dl_loaded_modules __attribute__ ((__weak__, __alias__ ("foobar1")));
55 extern struct r_debug *_dl_debug_addr __attribute__ ((__weak__, __alias__ ("foobar1")));
56 extern unsigned long _dl_error_number __attribute__ ((__weak__, __alias__ ("foobar1")));
57 extern void *(*_dl_malloc_function)(size_t) __attribute__ ((__weak__, __alias__ ("foobar1")));
58 #ifdef __SUPPORT_LD_DEBUG__
59 extern char *_dl_debug __attribute__ ((__weak__, __alias__ ("foobar1")));
60 extern char *_dl_debug_symbols __attribute__ ((__weak__, __alias__ ("foobar1")));
61 extern char *_dl_debug_move __attribute__ ((__weak__, __alias__ ("foobar1")));
62 extern char *_dl_debug_reloc __attribute__ ((__weak__, __alias__ ("foobar1")));
63 extern char *_dl_debug_detail __attribute__ ((__weak__, __alias__ ("foobar1")));
64 extern char *_dl_debug_nofixups __attribute__ ((__weak__, __alias__ ("foobar1")));
65 extern char *_dl_debug_bindings __attribute__ ((__weak__, __alias__ ("foobar1")));
66 extern int _dl_debug_file __attribute__ ((__weak__, __alias__ ("foobar1")));
71 #ifdef __SUPPORT_LD_DEBUG__
73 char *_dl_debug_symbols = 0;
74 char *_dl_debug_move = 0;
75 char *_dl_debug_reloc = 0;
76 char *_dl_debug_detail = 0;
77 char *_dl_debug_nofixups = 0;
78 char *_dl_debug_bindings = 0;
79 int _dl_debug_file = 2;
81 char *_dl_library_path = 0;
82 char *_dl_ldsopath = 0;
83 struct r_debug *_dl_debug_addr = NULL;
84 static char *_dl_malloc_addr, *_dl_mmap_zero;
85 #include "../ldso/_dl_progname.h" /* Pull in the name of ld.so */
86 #include "../ldso/hash.c"
87 #define _dl_trace_loaded_objects 0
88 #include "../ldso/readelflib1.c"
89 void *(*_dl_malloc_function) (size_t size);
90 int _dl_fixup(struct elf_resolve *tpnt, int lazy);
93 static int do_dlclose(void *, int need_fini);
96 static const char *dl_error_names[] = {
99 "Unable to open /dev/zero",
101 #if defined (__i386__)
103 #elif defined (__sparc__)
105 #elif defined (__mc68000__)
108 "Unrecognized binary type",
110 "Not an ELF shared library",
111 "Unable to mmap file",
112 "No dynamic section",
113 #ifdef ELF_USES_RELOCA
114 "Unable to process REL relocs",
116 "Unable to process RELA relocs",
119 "Unable to resolve symbol"
122 static void __attribute__ ((destructor)) dl_cleanup(void)
126 for (d = _dl_handles; d; d = d->next_handle)
127 if (d->dyn->libtype == loaded_file && d->dyn->dynamic_info[DT_FINI]) {
128 (* ((int (*)(void)) (d->dyn->loadaddr + d->dyn->dynamic_info[DT_FINI]))) ();
129 d->dyn->dynamic_info[DT_FINI] = 0;
133 void *_dlopen(const char *libname, int flag)
135 struct elf_resolve *tpnt, *tfrom, *tcurr;
136 struct dyn_elf *dyn_chain, *rpnt = NULL;
137 struct dyn_elf *dpnt;
138 static int dl_init = 0;
140 struct elf_resolve *tpnt1;
141 void (*dl_brk) (void);
143 /* A bit of sanity checking... */
144 if (!(flag & (RTLD_LAZY|RTLD_NOW))) {
145 _dl_error_number = LD_BAD_HANDLE;
149 from = (ElfW(Addr)) __builtin_return_address(0);
151 /* Have the dynamic linker use the regular malloc function now */
154 _dl_malloc_function = malloc;
157 /* Cover the trivial case first */
159 return _dl_symbol_tables;
164 * Try and locate the module we were called from - we
165 * need this so that we get the correct RPATH. Note that
166 * this is the current behavior under Solaris, but the
167 * ABI+ specifies that we should only use the RPATH from
168 * the application. Thus this may go away at some time
172 for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {
174 if (tpnt->loadaddr < from
175 && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr))
179 /* Try to load the specified library */
180 #ifdef __SUPPORT_LD_DEBUG__
182 _dl_dprintf(_dl_debug_file, "Trying to dlopen '%s'\n", (char*)libname);
184 tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname);
190 dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
191 _dl_memset(dyn_chain, 0, sizeof(struct dyn_elf));
192 dyn_chain->dyn = tpnt;
193 dyn_chain->flags = flag;
194 if (!tpnt->symbol_scope)
195 tpnt->symbol_scope = dyn_chain;
197 dyn_chain->next_handle = _dl_handles;
198 _dl_handles = rpnt = dyn_chain;
200 if (tpnt->init_flag & INIT_FUNCS_CALLED) {
201 /* If the init and fini stuff has already been run, that means
202 * the dlopen'd library has already been loaded, and nothing
203 * further needs to be done. */
204 return (void *) dyn_chain;
208 #ifdef __SUPPORT_LD_DEBUG__
210 _dl_dprintf(_dl_debug_file, "Looking for needed libraries\n");
213 for (tcurr = tpnt; tcurr; tcurr = tcurr->next)
217 for (dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) {
218 if (dpnt->d_tag == DT_NEEDED) {
221 lpntstr = (char*) (tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] +
223 name = _dl_get_last_path_component(lpntstr);
225 #ifdef __SUPPORT_LD_DEBUG__
227 _dl_dprintf(_dl_debug_file, "Trying to load '%s', needed by '%s'\n",
228 lpntstr, tcurr->libname);
231 if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr))) {
236 //FIXME: Enabling this is _so_ wrong....
237 /* We need global symbol resolution for everything
238 * in the dependent chain */
239 dyn_chain->flags |= RTLD_GLOBAL;
242 rpnt->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
243 _dl_memset (rpnt->next, 0, sizeof (struct dyn_elf));
245 if (!tpnt1->symbol_scope) tpnt1->symbol_scope = rpnt;
253 * OK, now attach the entire chain at the end
255 rpnt->next = _dl_symbol_tables;
259 * Relocation of the GOT entries for MIPS have to be done
260 * after all the libraries have been loaded.
262 _dl_perform_mips_global_got_relocations(tpnt);
265 #ifdef __SUPPORT_LD_DEBUG__
267 _dl_dprintf(_dl_debug_file, "Beginning dlopen relocation fixups\n");
270 * OK, now all of the kids are tucked into bed in their proper addresses.
271 * Now we go through and look for REL and RELA records that indicate fixups
272 * to the GOT tables. We need to do this in reverse order so that COPY
273 * directives work correctly */
274 if (_dl_fixup(dyn_chain->dyn, dyn_chain->flags))
277 #ifdef __SUPPORT_LD_DEBUG__
279 _dl_dprintf(_dl_debug_file, "Beginning dlopen copy fixups\n");
281 if (_dl_symbol_tables) {
282 if (_dl_copy_fixups(dyn_chain))
287 /* TODO: Should we set the protections of all pages back to R/O now ? */
290 /* Notify the debugger we have added some objects. */
291 if (_dl_debug_addr) {
292 dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
293 if (dl_brk != NULL) {
294 _dl_debug_addr->r_state = RT_ADD;
297 _dl_debug_addr->r_state = RT_CONSISTENT;
302 #if 0 //def __SUPPORT_LD_DEBUG__
308 /* Find the last library so we can run things in the right order */
309 for (tpnt = dyn_chain->dyn; tpnt->next!=NULL; tpnt = tpnt->next)
312 /* Run the ctors and set up the dtors */
313 for (; tpnt != dyn_chain->dyn->prev; tpnt=tpnt->prev)
315 /* Apparently crt1 for the application is responsible for handling this.
316 * We only need to run the init/fini for shared libraries
318 if (tpnt->libtype == program_interpreter)
320 if (tpnt->libtype == elf_executable)
322 if (tpnt->init_flag & INIT_FUNCS_CALLED)
324 tpnt->init_flag |= INIT_FUNCS_CALLED;
326 if (tpnt->dynamic_info[DT_INIT]) {
327 void (*dl_elf_func) (void);
328 dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]);
329 if (dl_elf_func && *dl_elf_func != NULL) {
330 #ifdef __SUPPORT_LD_DEBUG__
332 _dl_dprintf(2, "running ctors for library %s at '%x'\n", tpnt->libname, dl_elf_func);
337 if (tpnt->dynamic_info[DT_FINI]) {
338 void (*dl_elf_func) (void);
339 dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
340 if (dl_elf_func && *dl_elf_func != NULL) {
341 #ifdef __SUPPORT_LD_DEBUG__
343 _dl_dprintf(2, "setting up dtors for library %s at '%x'\n", tpnt->libname, dl_elf_func);
350 return (void *) dyn_chain;
353 /* Something went wrong. Clean up and return NULL. */
355 do_dlclose(dyn_chain, 0);
359 void *_dlsym(void *vhandle, const char *name)
361 struct elf_resolve *tpnt, *tfrom;
362 struct dyn_elf *handle;
364 struct dyn_elf *rpnt;
367 handle = (struct dyn_elf *) vhandle;
369 /* First of all verify that we have a real handle
370 of some kind. Return NULL if not a valid handle. */
373 handle = _dl_symbol_tables;
374 else if (handle != RTLD_NEXT && handle != _dl_symbol_tables) {
375 for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle)
379 _dl_error_number = LD_BAD_HANDLE;
382 } else if (handle == RTLD_NEXT) {
384 * Try and locate the module we were called from - we
385 * need this so that we know where to start searching
386 * from. We never pass RTLD_NEXT down into the actual
387 * dynamic loader itself, as it doesn't know
388 * how to properly treat it.
390 from = (ElfW(Addr)) __builtin_return_address(0);
393 for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) {
395 if (tpnt->loadaddr < from
396 && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr)) {
403 ret = _dl_find_hash((char*)name, handle, NULL, copyrel);
409 _dl_error_number = LD_NO_SYMBOL;
413 int _dlclose(void *vhandle)
415 return do_dlclose(vhandle, 1);
418 static int do_dlclose(void *vhandle, int need_fini)
420 struct dyn_elf *rpnt, *rpnt1;
421 struct dyn_elf *spnt, *spnt1;
423 struct elf_resolve *tpnt;
424 int (*dl_elf_fini) (void);
425 void (*dl_brk) (void);
426 struct dyn_elf *handle;
430 handle = (struct dyn_elf *) vhandle;
432 for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) {
433 if (rpnt == handle) {
440 _dl_error_number = LD_BAD_HANDLE;
444 /* OK, this is a valid handle - now close out the file.
445 * We check if we need to call fini () on the handle. */
446 spnt = need_fini ? handle : handle->next;
447 for (; spnt; spnt = spnt1) {
450 /* We appended the module list to the end - when we get back here,
451 quit. The access counts were not adjusted to account for being here. */
452 if (spnt == _dl_symbol_tables)
454 if (spnt->dyn->usage_count == 1
455 && spnt->dyn->libtype == loaded_file) {
457 /* Apparently crt1 for the application is responsible for handling this.
458 * We only need to run the init/fini for shared libraries
461 if (tpnt->dynamic_info[DT_FINI]) {
462 dl_elf_fini = (int (*)(void)) (tpnt->loadaddr +
463 tpnt->dynamic_info[DT_FINI]);
469 rpnt1->next_handle = rpnt->next_handle;
471 _dl_handles = rpnt->next_handle;
473 /* OK, this is a valid handle - now close out the file */
474 for (rpnt = handle; rpnt; rpnt = rpnt1) {
477 /* We appended the module list to the end - when we get back here,
478 quit. The access counts were not adjusted to account for being here. */
479 if (rpnt == _dl_symbol_tables)
482 rpnt->dyn->usage_count--;
483 if (rpnt->dyn->usage_count == 0
484 && rpnt->dyn->libtype == loaded_file) {
486 /* Apparently crt1 for the application is responsible for handling this.
487 * We only need to run the init/fini for shared libraries
491 /* We have to do this above, before we start closing objects.
492 * Otherwise when the needed symbols for _fini handling are
493 * resolved a coredump would occur. Rob Ryan (robr@cmu.edu)*/
494 if (tpnt->dynamic_info[DT_FINI]) {
495 dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
500 for (i = 0, ppnt = rpnt->dyn->ppnt;
501 i < rpnt->dyn->n_phent; ppnt++, i++) {
502 if (ppnt->p_type != PT_LOAD)
504 if (end < ppnt->p_vaddr + ppnt->p_memsz)
505 end = ppnt->p_vaddr + ppnt->p_memsz;
507 _dl_munmap((void*)rpnt->dyn->loadaddr, end);
508 /* Next, remove rpnt->dyn from the loaded_module list */
509 if (_dl_loaded_modules == rpnt->dyn) {
510 _dl_loaded_modules = rpnt->dyn->next;
511 if (_dl_loaded_modules)
512 _dl_loaded_modules->prev = 0;
514 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next)
515 if (tpnt->next == rpnt->dyn) {
516 tpnt->next = tpnt->next->next;
518 tpnt->next->prev = tpnt;
521 free(rpnt->dyn->libname);
528 if (_dl_debug_addr) {
529 dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
530 if (dl_brk != NULL) {
531 _dl_debug_addr->r_state = RT_DELETE;
534 _dl_debug_addr->r_state = RT_CONSISTENT;
542 const char *_dlerror(void)
546 if (!_dl_error_number)
548 retval = dl_error_names[_dl_error_number];
549 _dl_error_number = 0;
554 * Dump information to stderrr about the current loaded modules
556 static char *type[] = { "Lib", "Exe", "Int", "Mod" };
560 struct elf_resolve *tpnt;
561 struct dyn_elf *rpnt, *hpnt;
563 _dl_dprintf(2, "List of loaded modules\n");
564 /* First start with a complete list of all of the loaded files. */
565 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
566 _dl_dprintf(2, "\t%x %x %x %s %d %s\n",
567 (unsigned) tpnt->loadaddr, (unsigned) tpnt,
568 (unsigned) tpnt->symbol_scope,
570 tpnt->usage_count, tpnt->libname);
573 /* Next dump the module list for the application itself */
574 _dl_dprintf(2, "\nModules for application (%x):\n",
575 (unsigned) _dl_symbol_tables);
576 for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next)
577 _dl_dprintf(2, "\t%x %s\n", (unsigned) rpnt->dyn, rpnt->dyn->libname);
579 for (hpnt = _dl_handles; hpnt; hpnt = hpnt->next_handle) {
580 _dl_dprintf(2, "Modules for handle %x\n", (unsigned) hpnt);
581 for (rpnt = hpnt; rpnt; rpnt = rpnt->next)
582 _dl_dprintf(2, "\t%x %s\n", (unsigned) rpnt->dyn,
587 int _dladdr(void *__address, Dl_info * __dlip)
589 struct elf_resolve *pelf;
590 struct elf_resolve *rpnt;
595 * Try and locate the module address is in
600 _dl_dprintf(2, "dladdr( %x, %x )\n", __address, __dlip);
603 for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) {
604 struct elf_resolve *tpnt;
608 _dl_dprintf(2, "Module \"%s\" at %x\n",
609 tpnt->libname, tpnt->loadaddr);
611 if (tpnt->loadaddr < (ElfW(Addr)) __address
612 && (pelf == NULL || pelf->loadaddr < tpnt->loadaddr)) {
622 * Try and locate the symbol of address
634 symtab = (Elf32_Sym *) (pelf->dynamic_info[DT_SYMTAB] + pelf->loadaddr);
635 strtab = (char *) (pelf->dynamic_info[DT_STRTAB] + pelf->loadaddr);
638 for (hn = 0; hn < pelf->nbucket; hn++) {
639 for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) {
640 ElfW(Addr) symbol_addr;
642 symbol_addr = pelf->loadaddr + symtab[si].st_value;
643 if (symbol_addr <= (ElfW(Addr))__address && (!sf || sa < symbol_addr)) {
649 _dl_dprintf(2, "Symbol \"%s\" at %x\n",
650 strtab + symtab[si].st_name, symbol_addr);
656 __dlip->dli_fname = pelf->libname;
657 __dlip->dli_fbase = (void *)pelf->loadaddr;
658 __dlip->dli_sname = strtab + symtab[sn].st_name;
659 __dlip->dli_saddr = (void *)sa;