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);
189 if (tpnt->init_flag & INIT_FUNCS_CALLED) {
191 /* If the init and fini stuff has already been run, that means
192 * someone called dlopen on a library we already have opened, so
193 * we don't need to fix thing up any further... */
197 dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
198 _dl_memset(dyn_chain, 0, sizeof(struct dyn_elf));
199 dyn_chain->dyn = tpnt;
200 dyn_chain->flags = flag;
201 if (!tpnt->symbol_scope)
202 tpnt->symbol_scope = dyn_chain;
204 dyn_chain->next_handle = _dl_handles;
205 _dl_handles = rpnt = 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 _dl_debug_addr->r_state = RT_ADD;
292 if (_dl_debug_addr) {
293 dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
294 if (dl_brk != NULL) {
295 _dl_debug_addr->r_state = RT_ADD;
298 _dl_debug_addr->r_state = RT_CONSISTENT;
303 #if 0 //def __SUPPORT_LD_DEBUG__
309 /* Find the last library so we can run things in the right order */
310 for (tpnt = dyn_chain->dyn; tpnt->next!=NULL; tpnt = tpnt->next)
313 /* Run the ctors and set up the dtors */
314 for (; tpnt != dyn_chain->dyn->prev; tpnt=tpnt->prev)
316 /* Apparently crt1 for the application is responsible for handling this.
317 * We only need to run the init/fini for shared libraries
319 if (tpnt->libtype == program_interpreter)
321 if (tpnt->libtype == elf_executable)
323 if (tpnt->init_flag & INIT_FUNCS_CALLED)
325 tpnt->init_flag |= INIT_FUNCS_CALLED;
327 if (tpnt->dynamic_info[DT_INIT]) {
328 void (*dl_elf_func) (void);
329 dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]);
330 if (dl_elf_func && *dl_elf_func != NULL) {
331 #ifdef __SUPPORT_LD_DEBUG__
333 _dl_dprintf(2, "running ctors for library %s at '%x'\n", tpnt->libname, dl_elf_func);
338 if (tpnt->dynamic_info[DT_FINI]) {
339 void (*dl_elf_func) (void);
340 dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
341 if (dl_elf_func && *dl_elf_func != NULL) {
342 #ifdef __SUPPORT_LD_DEBUG__
344 _dl_dprintf(2, "setting up dtors for library %s at '%x'\n", tpnt->libname, dl_elf_func);
351 return (void *) dyn_chain;
354 /* Something went wrong. Clean up and return NULL. */
356 do_dlclose(dyn_chain, 0);
360 void *_dlsym(void *vhandle, const char *name)
362 struct elf_resolve *tpnt, *tfrom;
363 struct dyn_elf *handle;
365 struct dyn_elf *rpnt;
368 handle = (struct dyn_elf *) vhandle;
370 /* First of all verify that we have a real handle
371 of some kind. Return NULL if not a valid handle. */
374 handle = _dl_symbol_tables;
375 else if (handle != RTLD_NEXT && handle != _dl_symbol_tables) {
376 for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle)
380 _dl_error_number = LD_BAD_HANDLE;
383 } else if (handle == RTLD_NEXT) {
385 * Try and locate the module we were called from - we
386 * need this so that we know where to start searching
387 * from. We never pass RTLD_NEXT down into the actual
388 * dynamic loader itself, as it doesn't know
389 * how to properly treat it.
391 from = (ElfW(Addr)) __builtin_return_address(0);
394 for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) {
396 if (tpnt->loadaddr < from
397 && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr)) {
404 ret = _dl_find_hash((char*)name, handle, NULL, copyrel);
410 _dl_error_number = LD_NO_SYMBOL;
414 int _dlclose(void *vhandle)
416 return do_dlclose(vhandle, 1);
419 static int do_dlclose(void *vhandle, int need_fini)
421 struct dyn_elf *rpnt, *rpnt1;
422 struct dyn_elf *spnt, *spnt1;
424 struct elf_resolve *tpnt;
425 int (*dl_elf_fini) (void);
426 void (*dl_brk) (void);
427 struct dyn_elf *handle;
431 handle = (struct dyn_elf *) vhandle;
433 for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) {
434 if (rpnt == handle) {
441 _dl_error_number = LD_BAD_HANDLE;
445 /* OK, this is a valid handle - now close out the file.
446 * We check if we need to call fini () on the handle. */
447 spnt = need_fini ? handle : handle->next;
448 for (; spnt; spnt = spnt1) {
451 /* We appended the module list to the end - when we get back here,
452 quit. The access counts were not adjusted to account for being here. */
453 if (spnt == _dl_symbol_tables)
455 if (spnt->dyn->usage_count == 1
456 && spnt->dyn->libtype == loaded_file) {
458 /* Apparently crt1 for the application is responsible for handling this.
459 * We only need to run the init/fini for shared libraries
462 if (tpnt->dynamic_info[DT_FINI]) {
463 dl_elf_fini = (int (*)(void)) (tpnt->loadaddr +
464 tpnt->dynamic_info[DT_FINI]);
470 rpnt1->next_handle = rpnt->next_handle;
472 _dl_handles = rpnt->next_handle;
474 /* OK, this is a valid handle - now close out the file */
475 for (rpnt = handle; rpnt; rpnt = rpnt1) {
478 /* We appended the module list to the end - when we get back here,
479 quit. The access counts were not adjusted to account for being here. */
480 if (rpnt == _dl_symbol_tables)
483 rpnt->dyn->usage_count--;
484 if (rpnt->dyn->usage_count == 0
485 && rpnt->dyn->libtype == loaded_file) {
487 /* Apparently crt1 for the application is responsible for handling this.
488 * We only need to run the init/fini for shared libraries
492 /* We have to do this above, before we start closing objects.
493 * Otherwise when the needed symbols for _fini handling are
494 * resolved a coredump would occur. Rob Ryan (robr@cmu.edu)*/
495 if (tpnt->dynamic_info[DT_FINI]) {
496 dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
501 for (i = 0, ppnt = rpnt->dyn->ppnt;
502 i < rpnt->dyn->n_phent; ppnt++, i++) {
503 if (ppnt->p_type != PT_LOAD)
505 if (end < ppnt->p_vaddr + ppnt->p_memsz)
506 end = ppnt->p_vaddr + ppnt->p_memsz;
508 _dl_munmap((void*)rpnt->dyn->loadaddr, end);
509 /* Next, remove rpnt->dyn from the loaded_module list */
510 if (_dl_loaded_modules == rpnt->dyn) {
511 _dl_loaded_modules = rpnt->dyn->next;
512 if (_dl_loaded_modules)
513 _dl_loaded_modules->prev = 0;
515 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next)
516 if (tpnt->next == rpnt->dyn) {
517 tpnt->next = tpnt->next->next;
519 tpnt->next->prev = tpnt;
522 free(rpnt->dyn->libname);
529 if (_dl_debug_addr) {
530 dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
531 if (dl_brk != NULL) {
532 _dl_debug_addr->r_state = RT_DELETE;
535 _dl_debug_addr->r_state = RT_CONSISTENT;
543 const char *_dlerror(void)
547 if (!_dl_error_number)
549 retval = dl_error_names[_dl_error_number];
550 _dl_error_number = 0;
555 * Dump information to stderrr about the current loaded modules
557 static char *type[] = { "Lib", "Exe", "Int", "Mod" };
561 struct elf_resolve *tpnt;
562 struct dyn_elf *rpnt, *hpnt;
564 _dl_dprintf(2, "List of loaded modules\n");
565 /* First start with a complete list of all of the loaded files. */
566 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
567 _dl_dprintf(2, "\t%x %x %x %s %d %s\n",
568 (unsigned) tpnt->loadaddr, (unsigned) tpnt,
569 (unsigned) tpnt->symbol_scope,
571 tpnt->usage_count, tpnt->libname);
574 /* Next dump the module list for the application itself */
575 _dl_dprintf(2, "\nModules for application (%x):\n",
576 (unsigned) _dl_symbol_tables);
577 for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next)
578 _dl_dprintf(2, "\t%x %s\n", (unsigned) rpnt->dyn, rpnt->dyn->libname);
580 for (hpnt = _dl_handles; hpnt; hpnt = hpnt->next_handle) {
581 _dl_dprintf(2, "Modules for handle %x\n", (unsigned) hpnt);
582 for (rpnt = hpnt; rpnt; rpnt = rpnt->next)
583 _dl_dprintf(2, "\t%x %s\n", (unsigned) rpnt->dyn,
588 int _dladdr(void *__address, Dl_info * __dlip)
590 struct elf_resolve *pelf;
591 struct elf_resolve *rpnt;
596 * Try and locate the module address is in
601 _dl_dprintf(2, "dladdr( %x, %x )\n", __address, __dlip);
604 for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) {
605 struct elf_resolve *tpnt;
609 _dl_dprintf(2, "Module \"%s\" at %x\n",
610 tpnt->libname, tpnt->loadaddr);
612 if (tpnt->loadaddr < (ElfW(Addr)) __address
613 && (pelf == NULL || pelf->loadaddr < tpnt->loadaddr)) {
623 * Try and locate the symbol of address
635 symtab = (Elf32_Sym *) (pelf->dynamic_info[DT_SYMTAB] + pelf->loadaddr);
636 strtab = (char *) (pelf->dynamic_info[DT_STRTAB] + pelf->loadaddr);
639 for (hn = 0; hn < pelf->nbucket; hn++) {
640 for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) {
641 ElfW(Addr) symbol_addr;
643 symbol_addr = pelf->loadaddr + symtab[si].st_value;
644 if (symbol_addr <= (ElfW(Addr))__address && (!sf || sa < symbol_addr)) {
650 _dl_dprintf(2, "Symbol \"%s\" at %x\n",
651 strtab + symtab[si].st_name, symbol_addr);
657 __dlip->dli_fname = pelf->libname;
658 __dlip->dli_fbase = (void *)pelf->loadaddr;
659 __dlip->dli_sname = strtab + symtab[sn].st_name;
660 __dlip->dli_saddr = (void *)sa;