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 if (!(tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname))) {
188 //tpnt->libtype = loaded_file;
191 dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
192 _dl_memset(dyn_chain, 0, sizeof(struct dyn_elf));
193 dyn_chain->dyn = tpnt;
194 dyn_chain->flags = flag;
195 if (!tpnt->symbol_scope)
196 tpnt->symbol_scope = dyn_chain;
198 dyn_chain->next_handle = _dl_handles;
199 _dl_handles = rpnt = dyn_chain;
202 #ifdef __SUPPORT_LD_DEBUG__
204 _dl_dprintf(_dl_debug_file, "Looking for needed libraries\n");
206 for (tcurr = tpnt; tcurr; tcurr = tcurr->next)
210 for (dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) {
211 if (dpnt->d_tag == DT_NEEDED) {
214 lpntstr = (char*) (tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] +
216 name = _dl_get_last_path_component(lpntstr);
218 #ifdef __SUPPORT_LD_DEBUG__
220 _dl_dprintf(_dl_debug_file, "Trying to load '%s', needed by '%s'\n",
221 lpntstr, tcurr->libname);
224 if ((tpnt1 = _dl_check_if_named_library_is_loaded(name)))
226 /* If the needed library is already loaded, then we
227 * need to override all globals and weaks in the current
228 * chain... Or something. */
233 if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr))) {
236 /* We need global symbol resolution for everything
237 * in the dependent chain */
238 dyn_chain->flags |= RTLD_GLOBAL;
240 rpnt->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
241 _dl_memset (rpnt->next, 0, sizeof (struct dyn_elf));
243 if (!tpnt1->symbol_scope) tpnt1->symbol_scope = rpnt;
251 * OK, now attach the entire chain at the end
253 rpnt->next = _dl_symbol_tables;
257 * Relocation of the GOT entries for MIPS have to be done
258 * after all the libraries have been loaded.
260 _dl_perform_mips_global_got_relocations(tpnt);
263 #ifdef __SUPPORT_LD_DEBUG__
265 _dl_dprintf(_dl_debug_file, "Beginning dlopen relocation fixups\n");
268 * OK, now all of the kids are tucked into bed in their proper addresses.
269 * Now we go through and look for REL and RELA records that indicate fixups
270 * to the GOT tables. We need to do this in reverse order so that COPY
271 * directives work correctly */
272 if (_dl_fixup(dyn_chain->dyn, (dyn_chain->flags & RTLD_LAZY)))
275 #ifdef __SUPPORT_LD_DEBUG__
277 _dl_dprintf(_dl_debug_file, "Beginning dlopen copy fixups\n");
279 if (_dl_symbol_tables) {
280 if (_dl_copy_fixups(dyn_chain))
285 /* TODO: Should we set the protections of all pages back to R/O now ? */
288 /* Notify the debugger we have added some objects. */
289 _dl_debug_addr->r_state = RT_ADD;
290 if (_dl_debug_addr) {
291 dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
292 if (dl_brk != NULL) {
293 _dl_debug_addr->r_state = RT_ADD;
296 _dl_debug_addr->r_state = RT_CONSISTENT;
301 #if 0 //def __SUPPORT_LD_DEBUG__
307 /* Find the last library so we can run things in the right order */
308 for (tpnt = dyn_chain->dyn; tpnt->next!=NULL; tpnt = tpnt->next)
311 /* Run the ctors and set up the dtors */
312 for (; tpnt != dyn_chain->dyn->prev; tpnt=tpnt->prev)
314 /* Apparently crt1 for the application is responsible for handling this.
315 * We only need to run the init/fini for shared libraries
317 if (tpnt->libtype == program_interpreter)
319 if (tpnt->libtype == elf_executable)
321 if (tpnt->init_flag & INIT_FUNCS_CALLED)
323 tpnt->init_flag |= INIT_FUNCS_CALLED;
325 if (tpnt->dynamic_info[DT_INIT]) {
326 void (*dl_elf_func) (void);
327 dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]);
328 if (dl_elf_func && *dl_elf_func != NULL) {
329 #ifdef __SUPPORT_LD_DEBUG__
331 _dl_dprintf(2, "running ctors for library %s at '%x'\n", tpnt->libname, dl_elf_func);
336 if (tpnt->dynamic_info[DT_FINI]) {
337 void (*dl_elf_func) (void);
338 dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
339 if (dl_elf_func && *dl_elf_func != NULL) {
340 #ifdef __SUPPORT_LD_DEBUG__
342 _dl_dprintf(2, "setting up dtors for library %s at '%x'\n", tpnt->libname, dl_elf_func);
349 return (void *) dyn_chain;
352 /* Something went wrong. Clean up and return NULL. */
354 do_dlclose(dyn_chain, 0);
358 void *_dlsym(void *vhandle, const char *name)
360 struct elf_resolve *tpnt, *tfrom;
361 struct dyn_elf *handle;
363 struct dyn_elf *rpnt;
366 handle = (struct dyn_elf *) vhandle;
368 /* First of all verify that we have a real handle
369 of some kind. Return NULL if not a valid handle. */
372 handle = _dl_symbol_tables;
373 else if (handle != RTLD_NEXT && handle != _dl_symbol_tables) {
374 for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle)
378 _dl_error_number = LD_BAD_HANDLE;
381 } else if (handle == RTLD_NEXT) {
383 * Try and locate the module we were called from - we
384 * need this so that we know where to start searching
385 * from. We never pass RTLD_NEXT down into the actual
386 * dynamic loader itself, as it doesn't know
387 * how to properly treat it.
389 from = (ElfW(Addr)) __builtin_return_address(0);
392 for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) {
394 if (tpnt->loadaddr < from
395 && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr)) {
402 ret = _dl_find_hash((char*)name, handle, NULL, copyrel);
408 _dl_error_number = LD_NO_SYMBOL;
412 int _dlclose(void *vhandle)
414 return do_dlclose(vhandle, 1);
417 static int do_dlclose(void *vhandle, int need_fini)
419 struct dyn_elf *rpnt, *rpnt1;
420 struct dyn_elf *spnt, *spnt1;
422 struct elf_resolve *tpnt;
423 int (*dl_elf_fini) (void);
424 void (*dl_brk) (void);
425 struct dyn_elf *handle;
429 handle = (struct dyn_elf *) vhandle;
431 for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) {
432 if (rpnt == handle) {
439 _dl_error_number = LD_BAD_HANDLE;
443 /* OK, this is a valid handle - now close out the file.
444 * We check if we need to call fini () on the handle. */
445 spnt = need_fini ? handle : handle->next;
446 for (; spnt; spnt = spnt1) {
449 /* We appended the module list to the end - when we get back here,
450 quit. The access counts were not adjusted to account for being here. */
451 if (spnt == _dl_symbol_tables)
453 if (spnt->dyn->usage_count == 1
454 && spnt->dyn->libtype == loaded_file) {
456 /* Apparently crt1 for the application is responsible for handling this.
457 * We only need to run the init/fini for shared libraries
460 if (tpnt->dynamic_info[DT_FINI]) {
461 dl_elf_fini = (int (*)(void)) (tpnt->loadaddr +
462 tpnt->dynamic_info[DT_FINI]);
468 rpnt1->next_handle = rpnt->next_handle;
470 _dl_handles = rpnt->next_handle;
472 /* OK, this is a valid handle - now close out the file */
473 for (rpnt = handle; rpnt; rpnt = rpnt1) {
476 /* We appended the module list to the end - when we get back here,
477 quit. The access counts were not adjusted to account for being here. */
478 if (rpnt == _dl_symbol_tables)
481 rpnt->dyn->usage_count--;
482 if (rpnt->dyn->usage_count == 0
483 && rpnt->dyn->libtype == loaded_file) {
485 /* Apparently crt1 for the application is responsible for handling this.
486 * We only need to run the init/fini for shared libraries
490 /* We have to do this above, before we start closing objects.
491 * Otherwise when the needed symbols for _fini handling are
492 * resolved a coredump would occur. Rob Ryan (robr@cmu.edu)*/
493 if (tpnt->dynamic_info[DT_FINI]) {
494 dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
499 for (i = 0, ppnt = rpnt->dyn->ppnt;
500 i < rpnt->dyn->n_phent; ppnt++, i++) {
501 if (ppnt->p_type != PT_LOAD)
503 if (end < ppnt->p_vaddr + ppnt->p_memsz)
504 end = ppnt->p_vaddr + ppnt->p_memsz;
506 _dl_munmap((void*)rpnt->dyn->loadaddr, end);
507 /* Next, remove rpnt->dyn from the loaded_module list */
508 if (_dl_loaded_modules == rpnt->dyn) {
509 _dl_loaded_modules = rpnt->dyn->next;
510 if (_dl_loaded_modules)
511 _dl_loaded_modules->prev = 0;
513 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next)
514 if (tpnt->next == rpnt->dyn) {
515 tpnt->next = tpnt->next->next;
517 tpnt->next->prev = tpnt;
520 free(rpnt->dyn->libname);
527 if (_dl_debug_addr) {
528 dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
529 if (dl_brk != NULL) {
530 _dl_debug_addr->r_state = RT_DELETE;
533 _dl_debug_addr->r_state = RT_CONSISTENT;
541 const char *_dlerror(void)
545 if (!_dl_error_number)
547 retval = dl_error_names[_dl_error_number];
548 _dl_error_number = 0;
553 * Dump information to stderrr about the current loaded modules
555 static char *type[] = { "Lib", "Exe", "Int", "Mod" };
559 struct elf_resolve *tpnt;
560 struct dyn_elf *rpnt, *hpnt;
562 _dl_dprintf(2, "List of loaded modules\n");
563 /* First start with a complete list of all of the loaded files. */
564 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
565 _dl_dprintf(2, "\t%x %x %x %s %d %s\n",
566 (unsigned) tpnt->loadaddr, (unsigned) tpnt,
567 (unsigned) tpnt->symbol_scope,
569 tpnt->usage_count, tpnt->libname);
572 /* Next dump the module list for the application itself */
573 _dl_dprintf(2, "\nModules for application (%x):\n",
574 (unsigned) _dl_symbol_tables);
575 for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next)
576 _dl_dprintf(2, "\t%x %s\n", (unsigned) rpnt->dyn, rpnt->dyn->libname);
578 for (hpnt = _dl_handles; hpnt; hpnt = hpnt->next_handle) {
579 _dl_dprintf(2, "Modules for handle %x\n", (unsigned) hpnt);
580 for (rpnt = hpnt; rpnt; rpnt = rpnt->next)
581 _dl_dprintf(2, "\t%x %s\n", (unsigned) rpnt->dyn,
586 int _dladdr(void *__address, Dl_info * __dlip)
588 struct elf_resolve *pelf;
589 struct elf_resolve *rpnt;
594 * Try and locate the module address is in
599 _dl_dprintf(2, "dladdr( %x, %x )\n", __address, __dlip);
602 for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) {
603 struct elf_resolve *tpnt;
607 _dl_dprintf(2, "Module \"%s\" at %x\n",
608 tpnt->libname, tpnt->loadaddr);
610 if (tpnt->loadaddr < (ElfW(Addr)) __address
611 && (pelf == NULL || pelf->loadaddr < tpnt->loadaddr)) {
621 * Try and locate the symbol of address
633 symtab = (Elf32_Sym *) (pelf->dynamic_info[DT_SYMTAB] + pelf->loadaddr);
634 strtab = (char *) (pelf->dynamic_info[DT_STRTAB] + pelf->loadaddr);
637 for (hn = 0; hn < pelf->nbucket; hn++) {
638 for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) {
639 ElfW(Addr) symbol_addr;
641 symbol_addr = pelf->loadaddr + symtab[si].st_value;
642 if (symbol_addr <= (ElfW(Addr))__address && (!sf || sa < symbol_addr)) {
648 _dl_dprintf(2, "Symbol \"%s\" at %x\n",
649 strtab + symtab[si].st_name, symbol_addr);
655 __dlip->dli_fname = pelf->libname;
656 __dlip->dli_fbase = (void *)pelf->loadaddr;
657 __dlip->dli_sname = strtab + symtab[sn].st_name;
658 __dlip->dli_saddr = (void *)sa;