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")));
19 #if defined (__LIBDL_SHARED__)
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 *, int)
34 __attribute__ ((__weak__, __alias__ ("foobar")));
35 extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **, struct elf_resolve *, char *, int)
36 __attribute__ ((__weak__, __alias__ ("foobar")));
37 extern struct elf_resolve * _dl_check_if_named_library_is_loaded(const char *, int)
38 __attribute__ ((__weak__, __alias__ ("foobar")));
39 extern int _dl_fixup(struct dyn_elf *rpnt, int lazy)
40 __attribute__ ((__weak__, __alias__ ("foobar")));
42 extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
43 __attribute__ ((__weak__, __alias__ ("foobar")));
46 int _dl_map_cache(void) __attribute__ ((__weak__, __alias__ ("foobar")));
47 int _dl_unmap_cache(void) __attribute__ ((__weak__, __alias__ ("foobar")));
50 extern struct dyn_elf *_dl_symbol_tables __attribute__ ((__weak__, __alias__ ("foobar1")));
51 extern struct dyn_elf *_dl_handles __attribute__ ((__weak__, __alias__ ("foobar1")));
52 extern struct elf_resolve *_dl_loaded_modules __attribute__ ((__weak__, __alias__ ("foobar1")));
53 extern struct r_debug *_dl_debug_addr __attribute__ ((__weak__, __alias__ ("foobar1")));
54 extern unsigned long _dl_error_number __attribute__ ((__weak__, __alias__ ("foobar1")));
55 extern void *(*_dl_malloc_function)(size_t) __attribute__ ((__weak__, __alias__ ("foobar1")));
56 #ifdef __SUPPORT_LD_DEBUG__
57 extern char *_dl_debug __attribute__ ((__weak__, __alias__ ("foobar1")));
58 extern char *_dl_debug_symbols __attribute__ ((__weak__, __alias__ ("foobar1")));
59 extern char *_dl_debug_move __attribute__ ((__weak__, __alias__ ("foobar1")));
60 extern char *_dl_debug_reloc __attribute__ ((__weak__, __alias__ ("foobar1")));
61 extern char *_dl_debug_detail __attribute__ ((__weak__, __alias__ ("foobar1")));
62 extern char *_dl_debug_nofixups __attribute__ ((__weak__, __alias__ ("foobar1")));
63 extern char *_dl_debug_bindings __attribute__ ((__weak__, __alias__ ("foobar1")));
64 extern int _dl_debug_file __attribute__ ((__weak__, __alias__ ("foobar1")));
67 #else /* __LIBDL_SHARED__ */
69 #ifdef __SUPPORT_LD_DEBUG__
71 char *_dl_debug_symbols = 0;
72 char *_dl_debug_move = 0;
73 char *_dl_debug_reloc = 0;
74 char *_dl_debug_detail = 0;
75 char *_dl_debug_nofixups = 0;
76 char *_dl_debug_bindings = 0;
77 int _dl_debug_file = 2;
79 char *_dl_library_path = 0;
80 char *_dl_ldsopath = 0;
81 struct r_debug *_dl_debug_addr = NULL;
82 static unsigned char *_dl_malloc_addr, *_dl_mmap_zero;
83 #include "../ldso/dl-progname.h" /* Pull in the name of ld.so */
84 #include "../ldso/dl-hash.c"
85 #define _dl_trace_loaded_objects 0
86 #include "../ldso/dl-elf.c"
87 void *(*_dl_malloc_function) (size_t size);
88 int _dl_fixup(struct dyn_elf *rpnt, int lazy);
91 static int do_dlclose(void *, int need_fini);
94 static const char *dl_error_names[] = {
97 "Unable to open /dev/zero",
99 #if defined (__i386__)
101 #elif defined (__sparc__)
103 #elif defined (__mc68000__)
106 "Unrecognized binary type",
108 "Not an ELF shared library",
109 "Unable to mmap file",
110 "No dynamic section",
111 #ifdef ELF_USES_RELOCA
112 "Unable to process REL relocs",
114 "Unable to process RELA relocs",
117 "Unable to resolve symbol"
120 static void __attribute__ ((destructor)) dl_cleanup(void)
124 for (d = _dl_handles; d; d = d->next_handle)
125 if (d->dyn->libtype == loaded_file && d->dyn->dynamic_info[DT_FINI]) {
126 (* ((int (*)(void)) (d->dyn->loadaddr + d->dyn->dynamic_info[DT_FINI]))) ();
127 d->dyn->dynamic_info[DT_FINI] = 0;
131 void *_dlopen(const char *libname, int flag)
133 struct elf_resolve *tpnt, *tfrom, *tcurr;
134 struct dyn_elf *dyn_chain, *rpnt = NULL;
135 struct dyn_elf *dpnt;
136 static int dl_init = 0;
138 struct elf_resolve *tpnt1;
139 void (*dl_brk) (void);
141 /* A bit of sanity checking... */
142 if (!(flag & (RTLD_LAZY|RTLD_NOW))) {
143 _dl_error_number = LD_BAD_HANDLE;
147 from = (ElfW(Addr)) __builtin_return_address(0);
149 /* Have the dynamic linker use the regular malloc function now */
152 _dl_malloc_function = malloc;
155 /* Cover the trivial case first */
157 return _dl_symbol_tables;
162 * Try and locate the module we were called from - we
163 * need this so that we get the correct RPATH. Note that
164 * this is the current behavior under Solaris, but the
165 * ABI+ specifies that we should only use the RPATH from
166 * the application. Thus this may go away at some time
170 for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {
172 if (tpnt->loadaddr < from
173 && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr))
177 /* Try to load the specified library */
178 #ifdef __SUPPORT_LD_DEBUG__
180 _dl_dprintf(_dl_debug_file, "Trying to dlopen '%s'\n", (char*)libname);
182 if (!(tpnt = _dl_check_if_named_library_is_loaded((char *)libname, 0)))
183 tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname, 0);
189 dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
190 _dl_memset(dyn_chain, 0, sizeof(struct dyn_elf));
191 dyn_chain->dyn = tpnt;
192 dyn_chain->flags = flag;
193 if (!tpnt->symbol_scope)
194 tpnt->symbol_scope = dyn_chain;
196 dyn_chain->next_handle = _dl_handles;
197 _dl_handles = rpnt = dyn_chain;
199 if (tpnt->init_flag & INIT_FUNCS_CALLED) {
200 /* If the init and fini stuff has already been run, that means
201 * the dlopen'd library has already been loaded, and nothing
202 * further needs to be done. */
203 return (void *) dyn_chain;
207 #ifdef __SUPPORT_LD_DEBUG__
209 _dl_dprintf(_dl_debug_file, "Looking for needed libraries\n");
212 for (tcurr = tpnt; tcurr; tcurr = tcurr->next)
216 for (dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) {
217 if (dpnt->d_tag == DT_NEEDED) {
220 lpntstr = (char*) (tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] +
222 name = _dl_get_last_path_component(lpntstr);
224 if ((tpnt1 = _dl_check_if_named_library_is_loaded(name, 0)))
227 #ifdef __SUPPORT_LD_DEBUG__
229 _dl_dprintf(_dl_debug_file, "Trying to load '%s', needed by '%s'\n",
230 lpntstr, tcurr->libname);
233 if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, 0))) {
237 rpnt->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
238 _dl_memset (rpnt->next, 0, sizeof (struct dyn_elf));
240 if (!tpnt1->symbol_scope) tpnt1->symbol_scope = rpnt;
248 * OK, now attach the entire chain at the end
250 rpnt->next = _dl_symbol_tables;
254 * Relocation of the GOT entries for MIPS have to be done
255 * after all the libraries have been loaded.
257 _dl_perform_mips_global_got_relocations(tpnt);
260 #ifdef __SUPPORT_LD_DEBUG__
262 _dl_dprintf(_dl_debug_file, "Beginning dlopen relocation fixups\n");
265 * OK, now all of the kids are tucked into bed in their proper addresses.
266 * Now we go through and look for REL and RELA records that indicate fixups
267 * to the GOT tables. We need to do this in reverse order so that COPY
268 * directives work correctly */
269 if (_dl_fixup(dyn_chain, dyn_chain->flags))
272 /* TODO: Should we set the protections of all pages back to R/O now ? */
275 /* Notify the debugger we have added some objects. */
276 if (_dl_debug_addr) {
277 dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
278 if (dl_brk != NULL) {
279 _dl_debug_addr->r_state = RT_ADD;
282 _dl_debug_addr->r_state = RT_CONSISTENT;
287 #if 0 //def __SUPPORT_LD_DEBUG__
292 #if defined (__LIBDL_SHARED__)
293 /* Find the last library so we can run things in the right order */
294 for (tpnt = dyn_chain->dyn; tpnt->next!=NULL; tpnt = tpnt->next)
297 /* Run the ctors and set up the dtors */
298 for (; tpnt != dyn_chain->dyn->prev; tpnt=tpnt->prev)
300 /* Apparently crt1 for the application is responsible for handling this.
301 * We only need to run the init/fini for shared libraries
303 if (tpnt->libtype == program_interpreter)
305 if (tpnt->libtype == elf_executable)
307 if (tpnt->init_flag & INIT_FUNCS_CALLED)
309 tpnt->init_flag |= INIT_FUNCS_CALLED;
311 if (tpnt->dynamic_info[DT_INIT]) {
312 void (*dl_elf_func) (void);
313 dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]);
314 if (dl_elf_func && *dl_elf_func != NULL) {
315 #ifdef __SUPPORT_LD_DEBUG__
317 _dl_dprintf(2, "running ctors for library %s at '%x'\n", tpnt->libname, dl_elf_func);
322 if (tpnt->dynamic_info[DT_FINI]) {
323 void (*dl_elf_func) (void);
324 dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
325 if (dl_elf_func && *dl_elf_func != NULL) {
326 #ifdef __SUPPORT_LD_DEBUG__
328 _dl_dprintf(2, "setting up dtors for library %s at '%x'\n", tpnt->libname, dl_elf_func);
335 return (void *) dyn_chain;
338 /* Something went wrong. Clean up and return NULL. */
340 do_dlclose(dyn_chain, 0);
344 void *_dlsym(void *vhandle, const char *name)
346 struct elf_resolve *tpnt, *tfrom;
347 struct dyn_elf *handle;
349 struct dyn_elf *rpnt;
352 handle = (struct dyn_elf *) vhandle;
354 /* First of all verify that we have a real handle
355 of some kind. Return NULL if not a valid handle. */
358 handle = _dl_symbol_tables;
359 else if (handle != RTLD_NEXT && handle != _dl_symbol_tables) {
360 for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle)
364 _dl_error_number = LD_BAD_HANDLE;
367 } else if (handle == RTLD_NEXT) {
369 * Try and locate the module we were called from - we
370 * need this so that we know where to start searching
371 * from. We never pass RTLD_NEXT down into the actual
372 * dynamic loader itself, as it doesn't know
373 * how to properly treat it.
375 from = (ElfW(Addr)) __builtin_return_address(0);
378 for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) {
380 if (tpnt->loadaddr < from
381 && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr)) {
388 ret = _dl_find_hash((char*)name, handle, 0);
394 _dl_error_number = LD_NO_SYMBOL;
398 int _dlclose(void *vhandle)
400 return do_dlclose(vhandle, 1);
403 static int do_dlclose(void *vhandle, int need_fini)
405 struct dyn_elf *rpnt, *rpnt1;
406 struct dyn_elf *spnt, *spnt1;
408 struct elf_resolve *tpnt;
409 int (*dl_elf_fini) (void);
410 void (*dl_brk) (void);
411 struct dyn_elf *handle;
415 handle = (struct dyn_elf *) vhandle;
417 for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) {
418 if (rpnt == handle) {
425 _dl_error_number = LD_BAD_HANDLE;
429 /* OK, this is a valid handle - now close out the file.
430 * We check if we need to call fini () on the handle. */
431 spnt = need_fini ? handle : handle->next;
432 for (; spnt; spnt = spnt1) {
435 /* We appended the module list to the end - when we get back here,
436 quit. The access counts were not adjusted to account for being here. */
437 if (spnt == _dl_symbol_tables)
439 if (spnt->dyn->usage_count == 1
440 && spnt->dyn->libtype == loaded_file) {
442 /* Apparently crt1 for the application is responsible for handling this.
443 * We only need to run the init/fini for shared libraries
446 if (tpnt->dynamic_info[DT_FINI]) {
447 dl_elf_fini = (int (*)(void)) (tpnt->loadaddr +
448 tpnt->dynamic_info[DT_FINI]);
454 rpnt1->next_handle = rpnt->next_handle;
456 _dl_handles = rpnt->next_handle;
458 /* OK, this is a valid handle - now close out the file */
459 for (rpnt = handle; rpnt; rpnt = rpnt1) {
462 /* We appended the module list to the end - when we get back here,
463 quit. The access counts were not adjusted to account for being here. */
464 if (rpnt == _dl_symbol_tables)
467 rpnt->dyn->usage_count--;
468 if (rpnt->dyn->usage_count == 0
469 && rpnt->dyn->libtype == loaded_file) {
471 /* Apparently crt1 for the application is responsible for handling this.
472 * We only need to run the init/fini for shared libraries
476 /* We have to do this above, before we start closing objects.
477 * Otherwise when the needed symbols for _fini handling are
478 * resolved a coredump would occur. Rob Ryan (robr@cmu.edu)*/
479 if (tpnt->dynamic_info[DT_FINI]) {
480 dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
485 for (i = 0, ppnt = rpnt->dyn->ppnt;
486 i < rpnt->dyn->n_phent; ppnt++, i++) {
487 if (ppnt->p_type != PT_LOAD)
489 if (end < ppnt->p_vaddr + ppnt->p_memsz)
490 end = ppnt->p_vaddr + ppnt->p_memsz;
492 _dl_munmap((void*)rpnt->dyn->loadaddr, end);
493 /* Next, remove rpnt->dyn from the loaded_module list */
494 if (_dl_loaded_modules == rpnt->dyn) {
495 _dl_loaded_modules = rpnt->dyn->next;
496 if (_dl_loaded_modules)
497 _dl_loaded_modules->prev = 0;
499 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next)
500 if (tpnt->next == rpnt->dyn) {
501 tpnt->next = tpnt->next->next;
503 tpnt->next->prev = tpnt;
506 free(rpnt->dyn->libname);
513 if (_dl_debug_addr) {
514 dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
515 if (dl_brk != NULL) {
516 _dl_debug_addr->r_state = RT_DELETE;
519 _dl_debug_addr->r_state = RT_CONSISTENT;
527 const char *_dlerror(void)
531 if (!_dl_error_number)
533 retval = dl_error_names[_dl_error_number];
534 _dl_error_number = 0;
539 * Dump information to stderrr about the current loaded modules
541 static char *type[] = { "Lib", "Exe", "Int", "Mod" };
545 struct elf_resolve *tpnt;
546 struct dyn_elf *rpnt, *hpnt;
548 _dl_dprintf(2, "List of loaded modules\n");
549 /* First start with a complete list of all of the loaded files. */
550 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
551 _dl_dprintf(2, "\t%x %x %x %s %d %s\n",
552 (unsigned) tpnt->loadaddr, (unsigned) tpnt,
553 (unsigned) tpnt->symbol_scope,
555 tpnt->usage_count, tpnt->libname);
558 /* Next dump the module list for the application itself */
559 _dl_dprintf(2, "\nModules for application (%x):\n",
560 (unsigned) _dl_symbol_tables);
561 for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next)
562 _dl_dprintf(2, "\t%x %s\n", (unsigned) rpnt->dyn, rpnt->dyn->libname);
564 for (hpnt = _dl_handles; hpnt; hpnt = hpnt->next_handle) {
565 _dl_dprintf(2, "Modules for handle %x\n", (unsigned) hpnt);
566 for (rpnt = hpnt; rpnt; rpnt = rpnt->next)
567 _dl_dprintf(2, "\t%x %s\n", (unsigned) rpnt->dyn,
572 int _dladdr(void *__address, Dl_info * __dlip)
574 struct elf_resolve *pelf;
575 struct elf_resolve *rpnt;
580 * Try and locate the module address is in
585 _dl_dprintf(2, "dladdr( %x, %x )\n", __address, __dlip);
588 for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) {
589 struct elf_resolve *tpnt;
593 _dl_dprintf(2, "Module \"%s\" at %x\n",
594 tpnt->libname, tpnt->loadaddr);
596 if (tpnt->loadaddr < (ElfW(Addr)) __address
597 && (pelf == NULL || pelf->loadaddr < tpnt->loadaddr)) {
607 * Try and locate the symbol of address
619 symtab = (Elf32_Sym *) (pelf->dynamic_info[DT_SYMTAB] + pelf->loadaddr);
620 strtab = (char *) (pelf->dynamic_info[DT_STRTAB] + pelf->loadaddr);
623 for (hn = 0; hn < pelf->nbucket; hn++) {
624 for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) {
625 ElfW(Addr) symbol_addr;
627 symbol_addr = pelf->loadaddr + symtab[si].st_value;
628 if (symbol_addr <= (ElfW(Addr))__address && (!sf || sa < symbol_addr)) {
634 _dl_dprintf(2, "Symbol \"%s\" at %x\n",
635 strtab + symtab[si].st_name, symbol_addr);
641 __dlip->dli_fname = pelf->libname;
642 __dlip->dli_fbase = (void *)pelf->loadaddr;
643 __dlip->dli_sname = strtab + symtab[sn].st_name;
644 __dlip->dli_saddr = (void *)sa;