1 /* vi: set sw=4 ts=4: */
3 * Program to load an ELF binary on a linux system, and run it
4 * after resolving ELF shared library symbols
6 * Copyright (C) 2000-2006 by Erik Andersen <andersen@uclibc.org>
7 * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
8 * David Engel, Hongjiu Lu and Mitch D'Souza
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. The name of the above contributors may not be
16 * used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <string.h> /* Needed for 'strstr' prototype' */
38 #ifdef __UCLIBC_HAS_TLS__
42 #if defined(USE_TLS) && USE_TLS
44 extern void _dl_add_to_slotinfo(struct link_map *l);
48 # if defined(USE_TLS) && USE_TLS
50 extern struct link_map *_dl_update_slotinfo(unsigned long int req_modid);
53 /* When libdl is loaded as a shared library, we need to load in
54 * and use a pile of symbols from ldso... */
57 extern struct elf_resolve * _dl_load_shared_library(unsigned, struct dyn_elf **,
58 struct elf_resolve *, char *, int);
59 extern int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int lazy);
60 extern void _dl_protect_relro(struct elf_resolve * tpnt);
63 extern struct dyn_elf *_dl_symbol_tables;
64 extern struct dyn_elf *_dl_handles;
65 extern struct elf_resolve *_dl_loaded_modules;
66 extern void _dl_free (void *__ptr);
67 extern struct r_debug *_dl_debug_addr;
68 extern unsigned long _dl_error_number;
69 extern void *(*_dl_malloc_function)(size_t);
70 extern void (*_dl_free_function) (void *p);
71 extern void _dl_run_init_array(struct elf_resolve *);
72 extern void _dl_run_fini_array(struct elf_resolve *);
73 #ifdef __LDSO_CACHE_SUPPORT__
74 int _dl_map_cache(void);
75 int _dl_unmap_cache(void);
78 extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy);
80 #ifdef __SUPPORT_LD_DEBUG__
81 extern char *_dl_debug;
86 #define _dl_malloc malloc
89 /* When libdl is linked as a static library, we need to replace all
90 * the symbols that otherwise would have been loaded in from ldso... */
92 #ifdef __SUPPORT_LD_DEBUG__
93 char *_dl_debug = NULL;
94 char *_dl_debug_symbols = NULL;
95 char *_dl_debug_move = NULL;
96 char *_dl_debug_reloc = NULL;
97 char *_dl_debug_detail = NULL;
98 char *_dl_debug_nofixups = NULL;
99 char *_dl_debug_bindings = NULL;
100 int _dl_debug_file = 2;
102 const char *_dl_progname = ""; /* Program name */
103 void *(*_dl_malloc_function)(size_t);
104 void (*_dl_free_function) (void *p);
105 #ifdef __LDSO_LD_LIBRARY_PATH__
106 char *_dl_library_path = NULL; /* Where we look for libraries */
108 int _dl_errno = 0; /* We can't use the real errno in ldso */
109 size_t _dl_pagesize = PAGE_SIZE; /* Store the page size for use later */
110 /* This global variable is also to communicate with debuggers such as gdb. */
111 struct r_debug *_dl_debug_addr = NULL;
113 #include "../ldso/dl-array.c"
114 #include "../ldso/dl-debug.c"
117 # if defined(USE_TLS) && USE_TLS
119 * Giving this initialized value preallocates some surplus bytes in the
120 * static TLS area, see __libc_setup_tls (libc-tls.c).
122 size_t _dl_tls_static_size = 2048;
124 #include LDSO_ELFINTERP
125 #include "../ldso/dl-hash.c"
126 #define _dl_trace_loaded_objects 0
127 #include "../ldso/dl-elf.c"
130 #ifdef __SUPPORT_LD_DEBUG__
131 # define _dl_if_debug_print(fmt, args...) \
134 fprintf(stderr, "%s():%i: " fmt, __FUNCTION__, __LINE__, ## args); \
137 # define _dl_if_debug_print(fmt, args...)
140 static int do_dlclose(void *, int need_fini);
143 static const char *const dl_error_names[] = {
146 "Unable to open /dev/zero",
148 #if defined (__i386__)
150 #elif defined (__sparc__)
152 #elif defined (__mc68000__)
155 "Unrecognized binary type",
157 "Not an ELF shared library",
158 "Unable to mmap file",
159 "No dynamic section",
160 "Library contains unsupported TLS",
161 #ifdef ELF_USES_RELOCA
162 "Unable to process REL relocs",
164 "Unable to process RELA relocs",
167 "Unable to resolve symbol"
171 #if defined(USE_TLS) && USE_TLS
174 * Systems which do not have tls_index also probably have to define
175 * DONT_USE_TLS_INDEX.
178 # ifndef __TLS_GET_ADDR
179 # define __TLS_GET_ADDR __tls_get_addr
183 * Return the symbol address given the map of the module it is in and
184 * the symbol record. This is used in dl-sym.c.
188 _dl_tls_symaddr(struct link_map *map, const Elf32_Addr st_value)
190 # ifndef DONT_USE_TLS_INDEX
193 .ti_module = map->l_tls_modid,
194 .ti_offset = st_value
197 return __TLS_GET_ADDR (&tmp);
199 return __TLS_GET_ADDR (map->l_tls_modid, st_value);
204 /* Returns true when a non-empty entry was found. */
206 remove_slotinfo(size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
207 bool should_be_there)
209 if (idx - disp >= listp->len) {
210 if (listp->next == NULL) {
212 * The index is not actually valid in the slotinfo list,
213 * because this object was closed before it was fully set
214 * up due to some error.
216 _dl_assert(!should_be_there);
218 if (remove_slotinfo(idx, listp->next, disp + listp->len,
223 * No non-empty entry. Search from the end of this element's
226 idx = disp + listp->len;
229 struct link_map *old_map = listp->slotinfo[idx - disp].map;
232 * The entry might still be in its unused state if we are
233 * closing an object that wasn't fully set up.
235 if (__builtin_expect(old_map != NULL, 1)) {
236 _dl_assert(old_map->l_tls_modid == idx);
238 /* Mark the entry as unused. */
239 listp->slotinfo[idx - disp].gen = _dl_tls_generation + 1;
240 listp->slotinfo[idx - disp].map = NULL;
244 * If this is not the last currently used entry no need to
247 if (idx != _dl_tls_max_dtv_idx)
251 while (idx - disp > (disp == 0 ? 1 + _dl_tls_static_nelem : 0)) {
254 if (listp->slotinfo[idx - disp].map != NULL) {
255 /* Found a new last used index. */
256 _dl_tls_max_dtv_idx = idx;
261 /* No non-entry in this list element. */
266 #ifndef __LDSO_NO_CLEANUP__
267 void dl_cleanup(void) __attribute__ ((destructor));
268 void dl_cleanup(void)
270 struct dyn_elf *h, *n;
272 for (h = _dl_handles; h; h = n) {
279 static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list,
280 struct elf_resolve *map)
282 struct elf_resolve **p = list;
283 struct init_fini_list *q;
286 map->init_flag |= DL_RESERVED;
288 for (q = map->init_fini; q; q = q->next)
289 if (! (q->tpnt->init_flag & DL_RESERVED))
290 p += _dl_build_local_scope (p, q->tpnt);
294 void *dlopen(const char *libname, int flag)
296 struct elf_resolve *tpnt, *tfrom;
297 struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle;
299 struct elf_resolve *tpnt1;
300 void (*dl_brk) (void);
302 struct init_fini_list *tmp, *runp, *runp2, *dep_list;
303 unsigned int nlist, i;
304 struct elf_resolve **init_fini_list;
305 static bool _dl_init;
306 struct elf_resolve **local_scope;
307 struct r_scope_elem *ls;
308 #if defined(USE_TLS) && USE_TLS
309 bool any_tls = false;
312 /* A bit of sanity checking... */
313 if (!(flag & (RTLD_LAZY|RTLD_NOW|RTLD_NOLOAD))) {
314 _dl_error_number = LD_BAD_HANDLE;
318 from = (ElfW(Addr)) __builtin_return_address(0);
322 _dl_malloc_function = malloc;
323 _dl_free_function = free;
325 /* Cover the trivial case first */
327 return _dl_symbol_tables;
330 # ifdef __SUPPORT_LD_DEBUG__
331 _dl_debug = getenv("LD_DEBUG");
333 if (_dl_strstr(_dl_debug, "all")) {
334 _dl_debug_detail = _dl_debug_move = _dl_debug_symbols
335 = _dl_debug_reloc = _dl_debug_bindings = _dl_debug_nofixups = (void*)1;
337 _dl_debug_detail = strstr(_dl_debug, "detail");
338 _dl_debug_move = strstr(_dl_debug, "move");
339 _dl_debug_symbols = strstr(_dl_debug, "sym");
340 _dl_debug_reloc = strstr(_dl_debug, "reloc");
341 _dl_debug_nofixups = strstr(_dl_debug, "nofix");
342 _dl_debug_bindings = strstr(_dl_debug, "bind");
351 * Try and locate the module we were called from - we
352 * need this so that we get the correct RPATH/RUNPATH. Note that
353 * this is the current behavior under Solaris, but the
354 * ABI+ specifies that we should only use the RPATH from
355 * the application. Thus this may go away at some time
359 struct dyn_elf *dpnt;
361 for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {
363 if (DL_ADDR_IN_LOADADDR(from, tpnt, tfrom))
367 for (rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt = rpnt->next)
371 now_flag = (flag & RTLD_NOW) ? RTLD_NOW : 0;
372 if (getenv("LD_BIND_NOW"))
375 #if !defined SHARED && defined __LDSO_LIBRARY_PATH__
376 /* When statically linked, the _dl_library_path is not yet initialized */
377 _dl_library_path = getenv("LD_LIBRARY_PATH");
380 /* Try to load the specified library */
381 _dl_if_debug_print("Trying to dlopen '%s', RTLD_GLOBAL:%d RTLD_NOW:%d\n",
382 (char*)libname, (flag & RTLD_GLOBAL ? 1:0), (now_flag & RTLD_NOW ? 1:0));
384 tpnt = _dl_load_shared_library((flag & RTLD_NOLOAD) ? DL_RESOLVE_NOLOAD : 0,
385 &rpnt, tfrom, (char*)libname, 0);
390 dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
391 _dl_memset(dyn_chain, 0, sizeof(struct dyn_elf));
392 dyn_chain->dyn = tpnt;
393 tpnt->rtld_flags |= (flag & RTLD_GLOBAL);
395 dyn_chain->next_handle = _dl_handles;
396 _dl_handles = dyn_ptr = dyn_chain;
398 if (tpnt->usage_count > 1) {
399 _dl_if_debug_print("Lib: %s already opened\n", libname);
400 /* see if there is a handle from a earlier dlopen */
401 for (handle = _dl_handles->next_handle; handle; handle = handle->next_handle) {
402 if (handle->dyn == tpnt) {
403 dyn_chain->init_fini.init_fini = handle->init_fini.init_fini;
404 dyn_chain->init_fini.nlist = handle->init_fini.nlist;
405 for (i = 0; i < dyn_chain->init_fini.nlist; i++)
406 dyn_chain->init_fini.init_fini[i]->rtld_flags |= (flag & RTLD_GLOBAL);
407 dyn_chain->next = handle->next;
414 tpnt->init_flag |= DL_OPENED;
416 _dl_if_debug_print("Looking for needed libraries\n");
418 runp = alloca(sizeof(*runp));
421 dep_list = runp2 = runp;
422 for (; runp; runp = runp->next) {
427 runp->tpnt->init_fini = NULL; /* clear any previous dependcies */
428 for (dpnt = (ElfW(Dyn) *) runp->tpnt->dynamic_addr; dpnt->d_tag; dpnt++) {
429 if (dpnt->d_tag == DT_NEEDED) {
430 lpntstr = (char*) (runp->tpnt->dynamic_info[DT_STRTAB] +
432 _dl_if_debug_print("Trying to load '%s', needed by '%s'\n",
433 lpntstr, runp->tpnt->libname);
434 tpnt1 = _dl_load_shared_library(0, &rpnt, runp->tpnt, lpntstr, 0);
438 tpnt1->rtld_flags |= (flag & RTLD_GLOBAL);
440 /* This list is for dlsym() and relocation */
441 dyn_ptr->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
442 _dl_memset (dyn_ptr->next, 0, sizeof (struct dyn_elf));
443 dyn_ptr = dyn_ptr->next;
444 dyn_ptr->dyn = tpnt1;
445 /* Used to record RTLD_LOCAL scope */
446 tmp = alloca(sizeof(struct init_fini_list));
448 tmp->next = runp->tpnt->init_fini;
449 runp->tpnt->init_fini = tmp;
451 for (tmp=dep_list; tmp; tmp = tmp->next) {
452 if (tpnt1 == tmp->tpnt) { /* if match => cirular dependency, drop it */
453 _dl_if_debug_print("Circular dependency, skipping '%s',\n",
455 tpnt1->usage_count--;
459 if (!tmp) { /* Don't add if circular dependency detected */
460 runp2->next = alloca(sizeof(*runp));
468 init_fini_list = malloc(nlist * sizeof(struct elf_resolve *));
469 dyn_chain->init_fini.init_fini = init_fini_list;
470 dyn_chain->init_fini.nlist = nlist;
472 for (runp2 = dep_list; runp2; runp2 = runp2->next) {
473 init_fini_list[i++] = runp2->tpnt;
474 for (runp = runp2->tpnt->init_fini; runp; runp = runp->next) {
475 if (!(runp->tpnt->rtld_flags & RTLD_GLOBAL)) {
476 tmp = malloc(sizeof(struct init_fini_list));
477 tmp->tpnt = runp->tpnt;
478 tmp->next = runp2->tpnt->rtld_local;
479 runp2->tpnt->rtld_local = tmp;
484 /* Build the local scope for the dynamically loaded modules. */
485 local_scope = _dl_malloc(nlist * sizeof(struct elf_resolve *)); /* Could it allocated on stack? */
486 for (i = 0; i < nlist; i++)
487 if (init_fini_list[i]->symbol_scope.r_nlist == 0) {
489 cnt = _dl_build_local_scope(local_scope, init_fini_list[i]);
490 init_fini_list[i]->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *));
491 init_fini_list[i]->symbol_scope.r_nlist = cnt;
492 _dl_memcpy (init_fini_list[i]->symbol_scope.r_list, local_scope,
493 cnt * sizeof (struct elf_resolve *));
494 /* Restoring the init_flag.*/
495 for (k = 0; k < nlist; k++)
496 init_fini_list[k]->init_flag &= ~DL_RESERVED;
499 _dl_free(local_scope);
501 /* Sort the INIT/FINI list in dependency order. */
502 for (runp2 = dep_list; runp2; runp2 = runp2->next) {
504 for (j = 0; init_fini_list[j] != runp2->tpnt; ++j)
506 for (k = j + 1; k < nlist; ++k) {
507 struct init_fini_list *ele = init_fini_list[k]->init_fini;
509 for (; ele; ele = ele->next) {
510 if (ele->tpnt == runp2->tpnt) {
511 struct elf_resolve *here = init_fini_list[k];
512 _dl_if_debug_print("Move %s from pos %d to %d in INIT/FINI list.\n", here->libname, k, j);
513 for (i = (k - j); i; --i)
514 init_fini_list[i+j] = init_fini_list[i+j-1];
515 init_fini_list[j] = here;
522 #ifdef __SUPPORT_LD_DEBUG__
524 fprintf(stderr, "\nINIT/FINI order and dependencies:\n");
525 for (i = 0; i < nlist; i++) {
526 fprintf(stderr, "lib: %s has deps:\n", init_fini_list[i]->libname);
527 runp = init_fini_list[i]->init_fini;
528 for (; runp; runp = runp->next)
529 fprintf(stderr, " %s ", runp->tpnt->libname);
530 fprintf(stderr, "\n");
535 _dl_if_debug_print("Beginning dlopen relocation fixups\n");
537 * OK, now all of the kids are tucked into bed in their proper addresses.
538 * Now we go through and look for REL and RELA records that indicate fixups
539 * to the GOT tables. We need to do this in reverse order so that COPY
540 * directives work correctly */
543 * Relocation of the GOT entries for MIPS have to be done
544 * after all the libraries have been loaded.
546 _dl_perform_mips_global_got_relocations(tpnt, !now_flag);
548 /* Get the tail of the list */
549 for (ls = &_dl_loaded_modules->symbol_scope; ls && ls->next; ls = ls->next);
551 /* Extend the global scope by adding the local scope of the dlopened DSO. */
552 ls->next = &dyn_chain->dyn->symbol_scope;
554 if (_dl_fixup(dyn_chain, &_dl_loaded_modules->symbol_scope, now_flag))
558 for (rpnt = relro_ptr->next; rpnt; rpnt = rpnt->next) {
559 if (rpnt->dyn->relro_size)
560 _dl_protect_relro(rpnt->dyn);
563 /* TODO: Should we set the protections of all pages back to R/O now ? */
566 #if defined(USE_TLS) && USE_TLS
568 for (i=0; i < nlist; i++) {
569 struct elf_resolve *tmp_tpnt = init_fini_list[i];
570 /* Only add TLS memory if this object is loaded now and
571 therefore is not yet initialized. */
573 if (!(tmp_tpnt->init_flag & INIT_FUNCS_CALLED)
574 /* Only if the module defines thread local data. */
575 && __builtin_expect (tmp_tpnt->l_tls_blocksize > 0, 0)) {
577 /* Now that we know the object is loaded successfully add
578 modules containing TLS data to the slot info table. We
579 might have to increase its size. */
580 _dl_add_to_slotinfo ((struct link_map*)tmp_tpnt);
582 /* It is the case in which we couldn't perform TLS static
583 initialization at relocation time, and we delayed it until
584 the relocation has been completed. */
586 if (tmp_tpnt->l_need_tls_init) {
587 tmp_tpnt->l_need_tls_init = 0;
589 /* Update the slot information data for at least the
590 generation of the DSO we are allocating data for. */
591 _dl_update_slotinfo (tmp_tpnt->l_tls_modid);
594 _dl_init_static_tls((struct link_map*)tmp_tpnt);
595 _dl_assert (tmp_tpnt->l_need_tls_init == 0);
598 /* We have to bump the generation counter. */
603 /* Bump the generation number if necessary. */
604 if (any_tls && __builtin_expect (++_dl_tls_generation == 0, 0)) {
605 _dl_debug_early("TLS generation counter wrapped! Please report this.");
611 /* Notify the debugger we have added some objects. */
612 if (_dl_debug_addr) {
613 dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
614 if (dl_brk != NULL) {
615 _dl_debug_addr->r_state = RT_ADD;
618 _dl_debug_addr->r_state = RT_CONSISTENT;
623 /* Run the ctors and setup the dtors */
624 for (i = nlist; i; --i) {
625 tpnt = init_fini_list[i-1];
626 if (tpnt->init_flag & INIT_FUNCS_CALLED)
628 tpnt->init_flag |= INIT_FUNCS_CALLED;
630 if (tpnt->dynamic_info[DT_INIT]) {
631 void (*dl_elf_func) (void);
632 dl_elf_func = (void (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_INIT]);
634 _dl_if_debug_print("running ctors for library %s at '%p'\n",
635 tpnt->libname, dl_elf_func);
636 DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
640 _dl_run_init_array(tpnt);
644 return (void *) dyn_chain;
647 /* Something went wrong. Clean up and return NULL. */
649 do_dlclose(dyn_chain, 0);
653 void *dlsym(void *vhandle, const char *name)
655 struct elf_resolve *tpnt, *tfrom;
656 struct dyn_elf *handle;
658 struct dyn_elf *rpnt;
660 struct symbol_ref sym_ref = { NULL, NULL };
661 /* Nastiness to support underscore prefixes. */
662 #ifdef __UCLIBC_UNDERSCORES__
664 char *name2 = tmp_buf;
665 size_t nlen = strlen (name) + 1;
666 if (nlen + 1 > sizeof (tmp_buf))
667 name2 = malloc (nlen + 1);
669 _dl_error_number = LD_ERROR_MMAP_FAILED;
673 memcpy (name2 + 1, name, nlen);
675 const char *name2 = name;
677 handle = (struct dyn_elf *) vhandle;
679 /* First of all verify that we have a real handle
680 of some kind. Return NULL if not a valid handle. */
683 handle = _dl_symbol_tables;
684 else if (handle != RTLD_NEXT && handle != _dl_symbol_tables) {
685 for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle)
689 _dl_error_number = LD_BAD_HANDLE;
693 } else if (handle == RTLD_NEXT) {
695 * Try and locate the module we were called from - we
696 * need this so that we know where to start searching
697 * from. We never pass RTLD_NEXT down into the actual
698 * dynamic loader itself, as it doesn't know
699 * how to properly treat it.
701 from = (ElfW(Addr)) __builtin_return_address(0);
704 for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) {
706 if (DL_ADDR_IN_LOADADDR(from, tpnt, tfrom)) {
713 if (handle == _dl_symbol_tables)
714 tpnt = handle->dyn; /* Only search RTLD_GLOBAL objs if global object */
715 ret = _dl_find_hash(name2, &handle->dyn->symbol_scope, tpnt, ELF_RTYPE_CLASS_DLSYM, &sym_ref);
717 #if defined(USE_TLS) && USE_TLS && defined SHARED
718 if (sym_ref.sym && (ELF_ST_TYPE(sym_ref.sym->st_info) == STT_TLS) && (sym_ref.tpnt)) {
719 /* The found symbol is a thread-local storage variable.
720 Return its address for the current thread. */
721 ret = _dl_tls_symaddr ((struct link_map *)sym_ref.tpnt, (Elf32_Addr)ret);
729 _dl_error_number = LD_NO_SYMBOL;
731 #ifdef __UCLIBC_UNDERSCORES__
732 if (name2 != tmp_buf)
739 void *dlvsym(void *vhandle, const char *name, const char *version)
741 return dlsym(vhandle, name);
745 static int do_dlclose(void *vhandle, int need_fini)
747 struct dyn_elf *rpnt, *rpnt1, *rpnt1_tmp;
748 struct init_fini_list *runp, *tmp;
750 struct elf_resolve *tpnt, *run_tpnt;
751 int (*dl_elf_fini) (void);
752 void (*dl_brk) (void);
753 struct dyn_elf *handle;
756 struct r_scope_elem *ls;
757 #if defined(USE_TLS) && USE_TLS
758 bool any_tls = false;
759 size_t tls_free_start = NO_TLS_OFFSET;
760 size_t tls_free_end = NO_TLS_OFFSET;
761 struct link_map *tls_lmap;
764 handle = (struct dyn_elf *) vhandle;
765 if (handle == _dl_symbol_tables)
768 for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) {
775 _dl_error_number = LD_BAD_HANDLE;
779 rpnt1->next_handle = rpnt->next_handle;
781 _dl_handles = rpnt->next_handle;
782 _dl_if_debug_print("%s: usage count: %d\n",
783 handle->dyn->libname, handle->dyn->usage_count);
784 if (handle->dyn->usage_count != 1 || (handle->dyn->rtld_flags & RTLD_NODELETE)) {
785 handle->dyn->usage_count--;
789 /* OK, this is a valid handle - now close out the file */
790 for (j = 0; j < handle->init_fini.nlist; ++j) {
791 tpnt = handle->init_fini.init_fini[j];
793 if (tpnt->usage_count == 0 && !(tpnt->rtld_flags & RTLD_NODELETE)) {
794 if ((tpnt->dynamic_info[DT_FINI]
795 || tpnt->dynamic_info[DT_FINI_ARRAY])
797 && !(tpnt->init_flag & FINI_FUNCS_CALLED)
799 tpnt->init_flag |= FINI_FUNCS_CALLED;
800 _dl_run_fini_array(tpnt);
802 if (tpnt->dynamic_info[DT_FINI]) {
803 dl_elf_fini = (int (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI]);
804 _dl_if_debug_print("running dtors for library %s at '%p'\n",
805 tpnt->libname, dl_elf_fini);
806 DL_CALL_FUNC_AT_ADDR (dl_elf_fini, tpnt->loadaddr, (int (*)(void)));
810 _dl_if_debug_print("unmapping: %s\n", tpnt->libname);
812 for (i = 0, ppnt = tpnt->ppnt;
813 i < tpnt->n_phent; ppnt++, i++) {
814 if (ppnt->p_type != PT_LOAD)
816 if (end < ppnt->p_vaddr + ppnt->p_memsz)
817 end = ppnt->p_vaddr + ppnt->p_memsz;
820 #if defined(USE_TLS) && USE_TLS
821 /* Do the cast to make things easy. */
822 tls_lmap = (struct link_map *) tpnt;
824 /* Remove the object from the dtv slotinfo array if it uses TLS. */
825 if (__builtin_expect (tls_lmap->l_tls_blocksize > 0, 0)) {
828 if (_dl_tls_dtv_slotinfo_list != NULL
829 && ! remove_slotinfo (tls_lmap->l_tls_modid,
830 _dl_tls_dtv_slotinfo_list, 0,
831 (tpnt->init_flag & INIT_FUNCS_CALLED)))
832 /* All dynamically loaded modules with TLS are unloaded. */
833 _dl_tls_max_dtv_idx = _dl_tls_static_nelem;
835 if (tls_lmap->l_tls_offset != NO_TLS_OFFSET) {
837 * Collect a contiguous chunk built from the objects in
838 * this search list, going in either direction. When the
839 * whole chunk is at the end of the used area then we can
842 # if defined(TLS_TCB_AT_TP)
843 if (tls_free_start == NO_TLS_OFFSET
844 || (size_t) tls_lmap->l_tls_offset == tls_free_start) {
845 /* Extend the contiguous chunk being reclaimed. */
847 = tls_lmap->l_tls_offset -
848 tls_lmap->l_tls_blocksize;
850 if (tls_free_end == NO_TLS_OFFSET)
851 tls_free_end = tls_lmap->l_tls_offset;
852 } else if (tls_lmap->l_tls_offset - tls_lmap->l_tls_blocksize
854 /* Extend the chunk backwards. */
855 tls_free_end = tls_lmap->l_tls_offset;
858 * This isn't contiguous with the last chunk freed.
859 * One of them will be leaked unless we can free
860 * one block right away.
862 if (tls_free_end == _dl_tls_static_used) {
863 _dl_tls_static_used = tls_free_start;
864 tls_free_end = tls_lmap->l_tls_offset;
866 = tls_free_end - tls_lmap->l_tls_blocksize;
867 } else if ((size_t) tls_lmap->l_tls_offset
868 == _dl_tls_static_used)
869 _dl_tls_static_used = tls_lmap->l_tls_offset -
870 tls_lmap->l_tls_blocksize;
871 else if (tls_free_end < (size_t) tls_lmap->l_tls_offset) {
873 * We pick the later block. It has a chance
876 tls_free_end = tls_lmap->l_tls_offset;
877 tls_free_start = tls_free_end -
878 tls_lmap->l_tls_blocksize;
881 # elif defined(TLS_DTV_AT_TP)
882 if ((size_t) tls_lmap->l_tls_offset == tls_free_end)
883 /* Extend the contiguous chunk being reclaimed. */
884 tls_free_end -= tls_lmap->l_tls_blocksize;
885 else if (tls_lmap->l_tls_offset + tls_lmap->l_tls_blocksize
887 /* Extend the chunk backwards. */
888 tls_free_start = tls_lmap->l_tls_offset;
891 * This isn't contiguous with the last chunk
892 * freed. One of them will be leaked.
894 if (tls_free_end == _dl_tls_static_used)
895 _dl_tls_static_used = tls_free_start;
896 tls_free_start = tls_lmap->l_tls_offset;
897 tls_free_end = tls_free_start +
898 tls_lmap->l_tls_blocksize;
901 # error Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined
905 #define TLS_DTV_UNALLOCATED ((void *) -1l)
907 dtv_t *dtv = THREAD_DTV ();
909 _dl_assert(!(dtv[tls_lmap->l_tls_modid].pointer.is_static));
910 if (dtv[tls_lmap->l_tls_modid].pointer.val != TLS_DTV_UNALLOCATED) {
911 /* Note that free is called for NULL is well. We
912 deallocate even if it is this dtv entry we are
913 supposed to load. The reason is that we call
914 memalign and not malloc. */
915 _dl_free (dtv[tls_lmap->l_tls_modid].pointer.val);
916 dtv[tls_lmap->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
922 DL_LIB_UNMAP (tpnt, end - tpnt->mapaddr);
923 /* Free elements in RTLD_LOCAL scope list */
924 for (runp = tpnt->rtld_local; runp; runp = tmp) {
929 /* Next, remove tpnt from the loaded_module list */
930 if (_dl_loaded_modules == tpnt) {
931 _dl_loaded_modules = tpnt->next;
932 if (_dl_loaded_modules)
933 _dl_loaded_modules->prev = 0;
935 for (run_tpnt = _dl_loaded_modules; run_tpnt; run_tpnt = run_tpnt->next) {
936 if (run_tpnt->next == tpnt) {
937 _dl_if_debug_print("removing loaded_modules: %s\n", tpnt->libname);
938 run_tpnt->next = run_tpnt->next->next;
940 run_tpnt->next->prev = run_tpnt;
946 if (handle->dyn == tpnt) {
947 /* Unlink the local scope from global one */
948 for (ls = &_dl_loaded_modules->symbol_scope; ls; ls = ls->next)
949 if (ls->next->r_list[0] == tpnt) {
950 _dl_if_debug_print("removing symbol_scope: %s\n", tpnt->libname);
953 ls->next = ls->next->next;
956 /* Next, remove tpnt from the global symbol table list */
957 if (_dl_symbol_tables) {
958 if (_dl_symbol_tables->dyn == tpnt) {
959 _dl_symbol_tables = _dl_symbol_tables->next;
960 if (_dl_symbol_tables)
961 _dl_symbol_tables->prev = 0;
963 for (rpnt1 = _dl_symbol_tables; rpnt1->next; rpnt1 = rpnt1->next) {
964 if (rpnt1->next->dyn == tpnt) {
965 _dl_if_debug_print("removing symbol_tables: %s\n", tpnt->libname);
966 rpnt1_tmp = rpnt1->next->next;
968 rpnt1->next = rpnt1_tmp;
970 rpnt1->next->prev = rpnt1;
977 free(tpnt->symbol_scope.r_list);
981 for (rpnt1 = handle->next; rpnt1; rpnt1 = rpnt1_tmp) {
982 rpnt1_tmp = rpnt1->next;
985 free(handle->init_fini.init_fini);
988 #if defined(USE_TLS) && USE_TLS
989 /* If we removed any object which uses TLS bump the generation counter. */
991 if (__builtin_expect(++_dl_tls_generation == 0, 0)) {
992 _dl_debug_early("TLS generation counter wrapped! Please report to the uClibc mailing list.\n");
996 if (tls_free_end == _dl_tls_static_used)
997 _dl_tls_static_used = tls_free_start;
1001 if (_dl_debug_addr) {
1002 dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
1003 if (dl_brk != NULL) {
1004 _dl_debug_addr->r_state = RT_DELETE;
1007 _dl_debug_addr->r_state = RT_CONSISTENT;
1015 int dlclose(void *vhandle)
1017 return do_dlclose(vhandle, 1);
1024 if (!_dl_error_number)
1026 retval = dl_error_names[_dl_error_number];
1027 _dl_error_number = 0;
1028 return (char *)retval;
1032 * Dump information to stderr about the current loaded modules
1035 static const char type[][4] = { "Lib", "Exe", "Int", "Mod" };
1039 struct elf_resolve *tpnt;
1040 struct dyn_elf *rpnt, *hpnt;
1042 fprintf(stderr, "List of loaded modules\n");
1043 /* First start with a complete list of all of the loaded files. */
1044 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
1045 fprintf(stderr, "\t%p %p %p %s %d %s\n",
1046 DL_LOADADDR_BASE(tpnt->loadaddr), tpnt, tpnt->symbol_scope,
1047 type[tpnt->libtype],
1048 tpnt->usage_count, tpnt->libname);
1051 /* Next dump the module list for the application itself */
1052 fprintf(stderr, "\nModules for application (%p):\n", _dl_symbol_tables);
1053 for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next)
1054 fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname);
1056 for (hpnt = _dl_handles; hpnt; hpnt = hpnt->next_handle) {
1057 fprintf(stderr, "Modules for handle %p\n", hpnt);
1058 for (rpnt = hpnt; rpnt; rpnt = rpnt->next)
1059 fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname);
1064 int dladdr(const void *__address, Dl_info * __info)
1066 struct elf_resolve *pelf;
1067 struct elf_resolve *rpnt;
1072 * Try and locate the module address is in
1076 _dl_if_debug_print("__address: %p __info: %p\n", __address, __info);
1078 __address = DL_LOOKUP_ADDRESS (__address);
1080 for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) {
1081 struct elf_resolve *tpnt;
1085 _dl_if_debug_print("Module \"%s\" at %p\n",
1086 tpnt->libname, DL_LOADADDR_BASE(tpnt->loadaddr));
1088 if (DL_ADDR_IN_LOADADDR((ElfW(Addr)) __address, tpnt, pelf))
1097 * Try and locate the symbol of address
1103 unsigned int hn, si, sn, sf;
1106 /* Set the info for the object the address lies in */
1107 __info->dli_fname = pelf->libname;
1108 __info->dli_fbase = (void *)pelf->mapaddr;
1110 symtab = (ElfW(Sym) *) (pelf->dynamic_info[DT_SYMTAB]);
1111 strtab = (char *) (pelf->dynamic_info[DT_STRTAB]);
1115 #ifdef __LDSO_GNU_HASH_SUPPORT__
1116 if (pelf->l_gnu_bitmask) {
1117 for (hn = 0; hn < pelf->nbucket; hn++) {
1118 si = pelf->l_gnu_buckets[hn];
1122 const Elf32_Word *hasharr = &pelf->l_gnu_chain_zero[si];
1124 ElfW(Addr) symbol_addr;
1126 symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR(pelf->loadaddr, symtab[si].st_value);
1127 if ((symtab[si].st_shndx != SHN_UNDEF
1128 || symtab[si].st_value != 0)
1129 && ELF_ST_TYPE(symtab[si].st_info) != STT_TLS
1130 && DL_ADDR_SYM_MATCH(symbol_addr, &symtab[si], sa,
1131 (ElfW(Addr)) __address)) {
1136 _dl_if_debug_print("Symbol \"%s\" at %p\n", strtab + symtab[si].st_name, symbol_addr);
1138 } while ((*hasharr++ & 1u) == 0);
1142 for (hn = 0; hn < pelf->nbucket; hn++) {
1143 for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) {
1144 ElfW(Addr) symbol_addr;
1146 symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR(pelf->loadaddr, symtab[si].st_value);
1147 if ((symtab[si].st_shndx != SHN_UNDEF
1148 || symtab[si].st_value != 0)
1149 && ELF_ST_TYPE(symtab[si].st_info) != STT_TLS
1150 && DL_ADDR_SYM_MATCH(symbol_addr, &symtab[si], sa,
1151 (ElfW(Addr)) __address)) {
1157 _dl_if_debug_print("Symbol \"%s\" at %p\n",
1158 strtab + symtab[si].st_name, symbol_addr);
1163 /* A nearest symbol has been found; fill the entries */
1164 __info->dli_sname = strtab + symtab[sn].st_name;
1165 __info->dli_saddr = (void *)sa;
1167 /* No symbol found, fill entries with NULL value,
1168 only the containing object will be returned. */
1169 __info->dli_sname = NULL;
1170 __info->dli_saddr = NULL;