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... */
56 extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **,
57 struct elf_resolve *, char *, int);
58 extern int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int lazy);
59 extern void _dl_protect_relro(struct elf_resolve * tpnt);
61 extern struct dyn_elf *_dl_symbol_tables;
62 extern struct dyn_elf *_dl_handles;
63 extern struct elf_resolve *_dl_loaded_modules;
64 extern void _dl_free (void *__ptr);
65 extern struct r_debug *_dl_debug_addr;
66 extern unsigned long _dl_error_number;
67 extern void *(*_dl_malloc_function)(size_t);
68 extern void (*_dl_free_function) (void *p);
69 extern void _dl_run_init_array(struct elf_resolve *);
70 extern void _dl_run_fini_array(struct elf_resolve *);
71 #ifdef __LDSO_CACHE_SUPPORT__
72 int _dl_map_cache(void);
73 int _dl_unmap_cache(void);
76 extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy);
78 #ifdef __SUPPORT_LD_DEBUG__
79 extern char *_dl_debug;
84 #define _dl_malloc malloc
87 /* When libdl is linked as a static library, we need to replace all
88 * the symbols that otherwise would have been loaded in from ldso... */
90 #ifdef __SUPPORT_LD_DEBUG__
91 char *_dl_debug = NULL;
92 char *_dl_debug_symbols = NULL;
93 char *_dl_debug_move = NULL;
94 char *_dl_debug_reloc = NULL;
95 char *_dl_debug_detail = NULL;
96 char *_dl_debug_nofixups = NULL;
97 char *_dl_debug_bindings = NULL;
98 int _dl_debug_file = 2;
100 const char *_dl_progname = ""; /* Program name */
101 void *(*_dl_malloc_function)(size_t);
102 void (*_dl_free_function) (void *p);
103 char *_dl_library_path = NULL; /* Where we look for libraries */
104 int _dl_errno = 0; /* We can't use the real errno in ldso */
105 size_t _dl_pagesize = PAGE_SIZE; /* Store the page size for use later */
106 /* This global variable is also to communicate with debuggers such as gdb. */
107 struct r_debug *_dl_debug_addr = NULL;
109 #include "../ldso/dl-array.c"
110 #include "../ldso/dl-debug.c"
113 # if defined(USE_TLS) && USE_TLS
115 * Giving this initialized value preallocates some surplus bytes in the
116 * static TLS area, see __libc_setup_tls (libc-tls.c).
118 size_t _dl_tls_static_size = 2048;
120 #include LDSO_ELFINTERP
121 #include "../ldso/dl-hash.c"
122 #define _dl_trace_loaded_objects 0
123 #include "../ldso/dl-elf.c"
126 #ifdef __SUPPORT_LD_DEBUG__
127 # define _dl_if_debug_print(fmt, args...) \
130 fprintf(stderr, "%s():%i: " fmt, __FUNCTION__, __LINE__, ## args); \
133 # define _dl_if_debug_print(fmt, args...)
136 static int do_dlclose(void *, int need_fini);
139 static const char *const dl_error_names[] = {
142 "Unable to open /dev/zero",
144 #if defined (__i386__)
146 #elif defined (__sparc__)
148 #elif defined (__mc68000__)
151 "Unrecognized binary type",
153 "Not an ELF shared library",
154 "Unable to mmap file",
155 "No dynamic section",
156 "Library contains unsupported TLS",
157 #ifdef ELF_USES_RELOCA
158 "Unable to process REL relocs",
160 "Unable to process RELA relocs",
163 "Unable to resolve symbol"
167 #if defined(USE_TLS) && USE_TLS
170 * Systems which do not have tls_index also probably have to define
171 * DONT_USE_TLS_INDEX.
174 # ifndef __TLS_GET_ADDR
175 # define __TLS_GET_ADDR __tls_get_addr
179 * Return the symbol address given the map of the module it is in and
180 * the symbol record. This is used in dl-sym.c.
184 _dl_tls_symaddr(struct link_map *map, const Elf32_Addr st_value)
186 # ifndef DONT_USE_TLS_INDEX
189 .ti_module = map->l_tls_modid,
190 .ti_offset = st_value
193 return __TLS_GET_ADDR (&tmp);
195 return __TLS_GET_ADDR (map->l_tls_modid, st_value);
200 /* Returns true when a non-empty entry was found. */
202 remove_slotinfo(size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
203 bool should_be_there)
205 if (idx - disp >= listp->len) {
206 if (listp->next == NULL) {
208 * The index is not actually valid in the slotinfo list,
209 * because this object was closed before it was fully set
210 * up due to some error.
212 _dl_assert(!should_be_there);
214 if (remove_slotinfo(idx, listp->next, disp + listp->len,
219 * No non-empty entry. Search from the end of this element's
222 idx = disp + listp->len;
225 struct link_map *old_map = listp->slotinfo[idx - disp].map;
228 * The entry might still be in its unused state if we are
229 * closing an object that wasn't fully set up.
231 if (__builtin_expect(old_map != NULL, 1)) {
232 _dl_assert(old_map->l_tls_modid == idx);
234 /* Mark the entry as unused. */
235 listp->slotinfo[idx - disp].gen = _dl_tls_generation + 1;
236 listp->slotinfo[idx - disp].map = NULL;
240 * If this is not the last currently used entry no need to
243 if (idx != _dl_tls_max_dtv_idx)
247 while (idx - disp > (disp == 0 ? 1 + _dl_tls_static_nelem : 0)) {
250 if (listp->slotinfo[idx - disp].map != NULL) {
251 /* Found a new last used index. */
252 _dl_tls_max_dtv_idx = idx;
257 /* No non-entry in this list element. */
262 #ifndef __LDSO_NO_CLEANUP__
263 void dl_cleanup(void) __attribute__ ((destructor));
264 void dl_cleanup(void)
266 struct dyn_elf *h, *n;
268 for (h = _dl_handles; h; h = n) {
275 static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list,
276 struct elf_resolve *map)
278 struct elf_resolve **p = list;
279 struct init_fini_list *q;
282 map->init_flag |= DL_RESERVED;
284 for (q = map->init_fini; q; q = q->next)
285 if (! (q->tpnt->init_flag & DL_RESERVED))
286 p += _dl_build_local_scope (p, q->tpnt);
290 void *dlopen(const char *libname, int flag)
292 struct elf_resolve *tpnt, *tfrom;
293 struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle;
295 struct elf_resolve *tpnt1;
296 void (*dl_brk) (void);
298 struct init_fini_list *tmp, *runp, *runp2, *dep_list;
299 unsigned int nlist, i;
300 struct elf_resolve **init_fini_list;
301 static bool _dl_init;
302 struct elf_resolve **local_scope;
303 struct r_scope_elem *ls;
304 #if defined(USE_TLS) && USE_TLS
305 bool any_tls = false;
308 /* A bit of sanity checking... */
309 if (!(flag & (RTLD_LAZY|RTLD_NOW))) {
310 _dl_error_number = LD_BAD_HANDLE;
314 from = (ElfW(Addr)) __builtin_return_address(0);
318 _dl_malloc_function = malloc;
319 _dl_free_function = free;
321 /* Cover the trivial case first */
323 return _dl_symbol_tables;
326 # ifdef __SUPPORT_LD_DEBUG__
327 _dl_debug = getenv("LD_DEBUG");
329 if (_dl_strstr(_dl_debug, "all")) {
330 _dl_debug_detail = _dl_debug_move = _dl_debug_symbols
331 = _dl_debug_reloc = _dl_debug_bindings = _dl_debug_nofixups = (void*)1;
333 _dl_debug_detail = strstr(_dl_debug, "detail");
334 _dl_debug_move = strstr(_dl_debug, "move");
335 _dl_debug_symbols = strstr(_dl_debug, "sym");
336 _dl_debug_reloc = strstr(_dl_debug, "reloc");
337 _dl_debug_nofixups = strstr(_dl_debug, "nofix");
338 _dl_debug_bindings = strstr(_dl_debug, "bind");
347 * Try and locate the module we were called from - we
348 * need this so that we get the correct RPATH/RUNPATH. Note that
349 * this is the current behavior under Solaris, but the
350 * ABI+ specifies that we should only use the RPATH from
351 * the application. Thus this may go away at some time
355 struct dyn_elf *dpnt;
357 for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {
359 if (DL_ADDR_IN_LOADADDR(from, tpnt, tfrom))
363 for (rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt = rpnt->next)
367 now_flag = (flag & RTLD_NOW) ? RTLD_NOW : 0;
368 if (getenv("LD_BIND_NOW"))
372 /* When statically linked, the _dl_library_path is not yet initialized */
373 _dl_library_path = getenv("LD_LIBRARY_PATH");
376 /* Try to load the specified library */
377 _dl_if_debug_print("Trying to dlopen '%s', RTLD_GLOBAL:%d RTLD_NOW:%d\n",
378 (char*)libname, (flag & RTLD_GLOBAL ? 1:0), (now_flag & RTLD_NOW ? 1:0));
379 tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname, 0);
385 dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
386 _dl_memset(dyn_chain, 0, sizeof(struct dyn_elf));
387 dyn_chain->dyn = tpnt;
388 tpnt->rtld_flags |= (flag & RTLD_GLOBAL);
390 dyn_chain->next_handle = _dl_handles;
391 _dl_handles = dyn_ptr = dyn_chain;
393 if (tpnt->usage_count > 1) {
394 _dl_if_debug_print("Lib: %s already opened\n", libname);
395 /* see if there is a handle from a earlier dlopen */
396 for (handle = _dl_handles->next_handle; handle; handle = handle->next_handle) {
397 if (handle->dyn == tpnt) {
398 dyn_chain->init_fini.init_fini = handle->init_fini.init_fini;
399 dyn_chain->init_fini.nlist = handle->init_fini.nlist;
400 for (i = 0; i < dyn_chain->init_fini.nlist; i++)
401 dyn_chain->init_fini.init_fini[i]->rtld_flags |= (flag & RTLD_GLOBAL);
402 dyn_chain->next = handle->next;
409 tpnt->init_flag |= DL_OPENED;
411 _dl_if_debug_print("Looking for needed libraries\n");
413 runp = alloca(sizeof(*runp));
416 dep_list = runp2 = runp;
417 for (; runp; runp = runp->next) {
422 runp->tpnt->init_fini = NULL; /* clear any previous dependcies */
423 for (dpnt = (ElfW(Dyn) *) runp->tpnt->dynamic_addr; dpnt->d_tag; dpnt++) {
424 if (dpnt->d_tag == DT_NEEDED) {
425 lpntstr = (char*) (runp->tpnt->dynamic_info[DT_STRTAB] +
427 _dl_if_debug_print("Trying to load '%s', needed by '%s'\n",
428 lpntstr, runp->tpnt->libname);
429 tpnt1 = _dl_load_shared_library(0, &rpnt, runp->tpnt, lpntstr, 0);
433 tpnt1->rtld_flags |= (flag & RTLD_GLOBAL);
435 /* This list is for dlsym() and relocation */
436 dyn_ptr->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
437 _dl_memset (dyn_ptr->next, 0, sizeof (struct dyn_elf));
438 dyn_ptr = dyn_ptr->next;
439 dyn_ptr->dyn = tpnt1;
440 /* Used to record RTLD_LOCAL scope */
441 tmp = alloca(sizeof(struct init_fini_list));
443 tmp->next = runp->tpnt->init_fini;
444 runp->tpnt->init_fini = tmp;
446 for (tmp=dep_list; tmp; tmp = tmp->next) {
447 if (tpnt1 == tmp->tpnt) { /* if match => cirular dependency, drop it */
448 _dl_if_debug_print("Circular dependency, skipping '%s',\n",
450 tpnt1->usage_count--;
454 if (!tmp) { /* Don't add if circular dependency detected */
455 runp2->next = alloca(sizeof(*runp));
463 init_fini_list = malloc(nlist * sizeof(struct elf_resolve *));
464 dyn_chain->init_fini.init_fini = init_fini_list;
465 dyn_chain->init_fini.nlist = nlist;
467 for (runp2 = dep_list; runp2; runp2 = runp2->next) {
468 init_fini_list[i++] = runp2->tpnt;
469 for (runp = runp2->tpnt->init_fini; runp; runp = runp->next) {
470 if (!(runp->tpnt->rtld_flags & RTLD_GLOBAL)) {
471 tmp = malloc(sizeof(struct init_fini_list));
472 tmp->tpnt = runp->tpnt;
473 tmp->next = runp2->tpnt->rtld_local;
474 runp2->tpnt->rtld_local = tmp;
479 /* Build the local scope for the dynamically loaded modules. */
480 local_scope = _dl_malloc(nlist * sizeof(struct elf_resolve *)); /* Could it allocated on stack? */
481 for (i = 0; i < nlist; i++)
482 if (init_fini_list[i]->symbol_scope.r_nlist == 0) {
484 cnt = _dl_build_local_scope(local_scope, init_fini_list[i]);
485 init_fini_list[i]->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *));
486 init_fini_list[i]->symbol_scope.r_nlist = cnt;
487 _dl_memcpy (init_fini_list[i]->symbol_scope.r_list, local_scope,
488 cnt * sizeof (struct elf_resolve *));
489 /* Restoring the init_flag.*/
490 for (k = 0; k < nlist; k++)
491 init_fini_list[k]->init_flag &= ~DL_RESERVED;
494 _dl_free(local_scope);
496 /* Sort the INIT/FINI list in dependency order. */
497 for (runp2 = dep_list; runp2; runp2 = runp2->next) {
499 for (j = 0; init_fini_list[j] != runp2->tpnt; ++j)
501 for (k = j + 1; k < nlist; ++k) {
502 struct init_fini_list *ele = init_fini_list[k]->init_fini;
504 for (; ele; ele = ele->next) {
505 if (ele->tpnt == runp2->tpnt) {
506 struct elf_resolve *here = init_fini_list[k];
507 _dl_if_debug_print("Move %s from pos %d to %d in INIT/FINI list.\n", here->libname, k, j);
508 for (i = (k - j); i; --i)
509 init_fini_list[i+j] = init_fini_list[i+j-1];
510 init_fini_list[j] = here;
517 #ifdef __SUPPORT_LD_DEBUG__
519 fprintf(stderr, "\nINIT/FINI order and dependencies:\n");
520 for (i = 0; i < nlist; i++) {
521 fprintf(stderr, "lib: %s has deps:\n", init_fini_list[i]->libname);
522 runp = init_fini_list[i]->init_fini;
523 for (; runp; runp = runp->next)
524 fprintf(stderr, " %s ", runp->tpnt->libname);
525 fprintf(stderr, "\n");
530 _dl_if_debug_print("Beginning dlopen relocation fixups\n");
532 * OK, now all of the kids are tucked into bed in their proper addresses.
533 * Now we go through and look for REL and RELA records that indicate fixups
534 * to the GOT tables. We need to do this in reverse order so that COPY
535 * directives work correctly */
538 * Relocation of the GOT entries for MIPS have to be done
539 * after all the libraries have been loaded.
541 _dl_perform_mips_global_got_relocations(tpnt, !now_flag);
543 /* Get the tail of the list */
544 for (ls = &_dl_loaded_modules->symbol_scope; ls && ls->next; ls = ls->next);
546 /* Extend the global scope by adding the local scope of the dlopened DSO. */
547 ls->next = &dyn_chain->dyn->symbol_scope;
549 if (_dl_fixup(dyn_chain, &_dl_loaded_modules->symbol_scope, now_flag))
553 for (rpnt = relro_ptr->next; rpnt; rpnt = rpnt->next) {
554 if (rpnt->dyn->relro_size)
555 _dl_protect_relro(rpnt->dyn);
558 /* TODO: Should we set the protections of all pages back to R/O now ? */
561 #if defined(USE_TLS) && USE_TLS
563 for (i=0; i < nlist; i++) {
564 struct elf_resolve *tmp_tpnt = init_fini_list[i];
565 /* Only add TLS memory if this object is loaded now and
566 therefore is not yet initialized. */
568 if (!(tmp_tpnt->init_flag & INIT_FUNCS_CALLED)
569 /* Only if the module defines thread local data. */
570 && __builtin_expect (tmp_tpnt->l_tls_blocksize > 0, 0)) {
572 /* Now that we know the object is loaded successfully add
573 modules containing TLS data to the slot info table. We
574 might have to increase its size. */
575 _dl_add_to_slotinfo ((struct link_map*)tmp_tpnt);
577 /* It is the case in which we couldn't perform TLS static
578 initialization at relocation time, and we delayed it until
579 the relocation has been completed. */
581 if (tmp_tpnt->l_need_tls_init) {
582 tmp_tpnt->l_need_tls_init = 0;
584 /* Update the slot information data for at least the
585 generation of the DSO we are allocating data for. */
586 _dl_update_slotinfo (tmp_tpnt->l_tls_modid);
589 _dl_init_static_tls((struct link_map*)tmp_tpnt);
590 _dl_assert (tmp_tpnt->l_need_tls_init == 0);
593 /* We have to bump the generation counter. */
598 /* Bump the generation number if necessary. */
599 if (any_tls && __builtin_expect (++_dl_tls_generation == 0, 0)) {
600 _dl_debug_early("TLS generation counter wrapped! Please report this.");
606 /* Notify the debugger we have added some objects. */
607 if (_dl_debug_addr) {
608 dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
609 if (dl_brk != NULL) {
610 _dl_debug_addr->r_state = RT_ADD;
613 _dl_debug_addr->r_state = RT_CONSISTENT;
618 /* Run the ctors and setup the dtors */
619 for (i = nlist; i; --i) {
620 tpnt = init_fini_list[i-1];
621 if (tpnt->init_flag & INIT_FUNCS_CALLED)
623 tpnt->init_flag |= INIT_FUNCS_CALLED;
625 if (tpnt->dynamic_info[DT_INIT]) {
626 void (*dl_elf_func) (void);
627 dl_elf_func = (void (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_INIT]);
629 _dl_if_debug_print("running ctors for library %s at '%p'\n",
630 tpnt->libname, dl_elf_func);
631 DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
635 _dl_run_init_array(tpnt);
639 return (void *) dyn_chain;
642 /* Something went wrong. Clean up and return NULL. */
644 do_dlclose(dyn_chain, 0);
648 void *dlsym(void *vhandle, const char *name)
650 struct elf_resolve *tpnt, *tfrom;
651 struct dyn_elf *handle;
653 struct dyn_elf *rpnt;
655 struct symbol_ref sym_ref = { NULL, NULL };
656 /* Nastiness to support underscore prefixes. */
657 #ifdef __UCLIBC_UNDERSCORES__
659 char *name2 = tmp_buf;
660 size_t nlen = strlen (name) + 1;
661 if (nlen + 1 > sizeof (tmp_buf))
662 name2 = malloc (nlen + 1);
664 _dl_error_number = LD_ERROR_MMAP_FAILED;
668 memcpy (name2 + 1, name, nlen);
670 const char *name2 = name;
672 handle = (struct dyn_elf *) vhandle;
674 /* First of all verify that we have a real handle
675 of some kind. Return NULL if not a valid handle. */
678 handle = _dl_symbol_tables;
679 else if (handle != RTLD_NEXT && handle != _dl_symbol_tables) {
680 for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle)
684 _dl_error_number = LD_BAD_HANDLE;
688 } else if (handle == RTLD_NEXT) {
690 * Try and locate the module we were called from - we
691 * need this so that we know where to start searching
692 * from. We never pass RTLD_NEXT down into the actual
693 * dynamic loader itself, as it doesn't know
694 * how to properly treat it.
696 from = (ElfW(Addr)) __builtin_return_address(0);
699 for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) {
701 if (DL_ADDR_IN_LOADADDR(from, tpnt, tfrom)) {
708 if (handle == _dl_symbol_tables)
709 tpnt = handle->dyn; /* Only search RTLD_GLOBAL objs if global object */
710 ret = _dl_find_hash(name2, &handle->dyn->symbol_scope, tpnt, ELF_RTYPE_CLASS_DLSYM, &sym_ref);
712 #if defined(USE_TLS) && USE_TLS && defined SHARED
713 if (sym_ref.sym && (ELF_ST_TYPE(sym_ref.sym->st_info) == STT_TLS) && (sym_ref.tpnt)) {
714 /* The found symbol is a thread-local storage variable.
715 Return its address for the current thread. */
716 ret = _dl_tls_symaddr ((struct link_map *)sym_ref.tpnt, (Elf32_Addr)ret);
724 _dl_error_number = LD_NO_SYMBOL;
726 #ifdef __UCLIBC_UNDERSCORES__
727 if (name2 != tmp_buf)
734 void *dlvsym(void *vhandle, const char *name, const char *version)
736 return dlsym(vhandle, name);
740 static int do_dlclose(void *vhandle, int need_fini)
742 struct dyn_elf *rpnt, *rpnt1, *rpnt1_tmp;
743 struct init_fini_list *runp, *tmp;
745 struct elf_resolve *tpnt, *run_tpnt;
746 int (*dl_elf_fini) (void);
747 void (*dl_brk) (void);
748 struct dyn_elf *handle;
751 struct r_scope_elem *ls;
752 #if defined(USE_TLS) && USE_TLS
753 bool any_tls = false;
754 size_t tls_free_start = NO_TLS_OFFSET;
755 size_t tls_free_end = NO_TLS_OFFSET;
756 struct link_map *tls_lmap;
759 handle = (struct dyn_elf *) vhandle;
760 if (handle == _dl_symbol_tables)
763 for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) {
770 _dl_error_number = LD_BAD_HANDLE;
774 rpnt1->next_handle = rpnt->next_handle;
776 _dl_handles = rpnt->next_handle;
777 _dl_if_debug_print("%s: usage count: %d\n",
778 handle->dyn->libname, handle->dyn->usage_count);
779 if (handle->dyn->usage_count != 1 || (handle->dyn->rtld_flags & RTLD_NODELETE)) {
780 handle->dyn->usage_count--;
784 /* OK, this is a valid handle - now close out the file */
785 for (j = 0; j < handle->init_fini.nlist; ++j) {
786 tpnt = handle->init_fini.init_fini[j];
788 if (tpnt->usage_count == 0 && !(tpnt->rtld_flags & RTLD_NODELETE)) {
789 if ((tpnt->dynamic_info[DT_FINI]
790 || tpnt->dynamic_info[DT_FINI_ARRAY])
792 && !(tpnt->init_flag & FINI_FUNCS_CALLED)
794 tpnt->init_flag |= FINI_FUNCS_CALLED;
795 _dl_run_fini_array(tpnt);
797 if (tpnt->dynamic_info[DT_FINI]) {
798 dl_elf_fini = (int (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI]);
799 _dl_if_debug_print("running dtors for library %s at '%p'\n",
800 tpnt->libname, dl_elf_fini);
801 DL_CALL_FUNC_AT_ADDR (dl_elf_fini, tpnt->loadaddr, (int (*)(void)));
805 _dl_if_debug_print("unmapping: %s\n", tpnt->libname);
807 for (i = 0, ppnt = tpnt->ppnt;
808 i < tpnt->n_phent; ppnt++, i++) {
809 if (ppnt->p_type != PT_LOAD)
811 if (end < ppnt->p_vaddr + ppnt->p_memsz)
812 end = ppnt->p_vaddr + ppnt->p_memsz;
815 #if defined(USE_TLS) && USE_TLS
816 /* Do the cast to make things easy. */
817 tls_lmap = (struct link_map *) tpnt;
819 /* Remove the object from the dtv slotinfo array if it uses TLS. */
820 if (__builtin_expect (tls_lmap->l_tls_blocksize > 0, 0)) {
823 if (_dl_tls_dtv_slotinfo_list != NULL
824 && ! remove_slotinfo (tls_lmap->l_tls_modid,
825 _dl_tls_dtv_slotinfo_list, 0,
826 (tpnt->init_flag & INIT_FUNCS_CALLED)))
827 /* All dynamically loaded modules with TLS are unloaded. */
828 _dl_tls_max_dtv_idx = _dl_tls_static_nelem;
830 if (tls_lmap->l_tls_offset != NO_TLS_OFFSET) {
832 * Collect a contiguous chunk built from the objects in
833 * this search list, going in either direction. When the
834 * whole chunk is at the end of the used area then we can
837 # if defined(TLS_TCB_AT_TP)
838 if (tls_free_start == NO_TLS_OFFSET
839 || (size_t) tls_lmap->l_tls_offset == tls_free_start) {
840 /* Extend the contiguous chunk being reclaimed. */
842 = tls_lmap->l_tls_offset -
843 tls_lmap->l_tls_blocksize;
845 if (tls_free_end == NO_TLS_OFFSET)
846 tls_free_end = tls_lmap->l_tls_offset;
847 } else if (tls_lmap->l_tls_offset - tls_lmap->l_tls_blocksize
849 /* Extend the chunk backwards. */
850 tls_free_end = tls_lmap->l_tls_offset;
853 * This isn't contiguous with the last chunk freed.
854 * One of them will be leaked unless we can free
855 * one block right away.
857 if (tls_free_end == _dl_tls_static_used) {
858 _dl_tls_static_used = tls_free_start;
859 tls_free_end = tls_lmap->l_tls_offset;
861 = tls_free_end - tls_lmap->l_tls_blocksize;
862 } else if ((size_t) tls_lmap->l_tls_offset
863 == _dl_tls_static_used)
864 _dl_tls_static_used = tls_lmap->l_tls_offset -
865 tls_lmap->l_tls_blocksize;
866 else if (tls_free_end < (size_t) tls_lmap->l_tls_offset) {
868 * We pick the later block. It has a chance
871 tls_free_end = tls_lmap->l_tls_offset;
872 tls_free_start = tls_free_end -
873 tls_lmap->l_tls_blocksize;
876 # elif defined(TLS_DTV_AT_TP)
877 if ((size_t) tls_lmap->l_tls_offset == tls_free_end)
878 /* Extend the contiguous chunk being reclaimed. */
879 tls_free_end -= tls_lmap->l_tls_blocksize;
880 else if (tls_lmap->l_tls_offset + tls_lmap->l_tls_blocksize
882 /* Extend the chunk backwards. */
883 tls_free_start = tls_lmap->l_tls_offset;
886 * This isn't contiguous with the last chunk
887 * freed. One of them will be leaked.
889 if (tls_free_end == _dl_tls_static_used)
890 _dl_tls_static_used = tls_free_start;
891 tls_free_start = tls_lmap->l_tls_offset;
892 tls_free_end = tls_free_start +
893 tls_lmap->l_tls_blocksize;
896 # error Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined
900 #define TLS_DTV_UNALLOCATED ((void *) -1l)
902 dtv_t *dtv = THREAD_DTV ();
904 _dl_assert(!(dtv[tls_lmap->l_tls_modid].pointer.is_static));
905 if (dtv[tls_lmap->l_tls_modid].pointer.val != TLS_DTV_UNALLOCATED) {
906 /* Note that free is called for NULL is well. We
907 deallocate even if it is this dtv entry we are
908 supposed to load. The reason is that we call
909 memalign and not malloc. */
910 _dl_free (dtv[tls_lmap->l_tls_modid].pointer.val);
911 dtv[tls_lmap->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
917 DL_LIB_UNMAP (tpnt, end - tpnt->mapaddr);
918 /* Free elements in RTLD_LOCAL scope list */
919 for (runp = tpnt->rtld_local; runp; runp = tmp) {
924 /* Next, remove tpnt from the loaded_module list */
925 if (_dl_loaded_modules == tpnt) {
926 _dl_loaded_modules = tpnt->next;
927 if (_dl_loaded_modules)
928 _dl_loaded_modules->prev = 0;
930 for (run_tpnt = _dl_loaded_modules; run_tpnt; run_tpnt = run_tpnt->next) {
931 if (run_tpnt->next == tpnt) {
932 _dl_if_debug_print("removing loaded_modules: %s\n", tpnt->libname);
933 run_tpnt->next = run_tpnt->next->next;
935 run_tpnt->next->prev = run_tpnt;
941 if (handle->dyn == tpnt) {
942 /* Unlink the local scope from global one */
943 for (ls = &_dl_loaded_modules->symbol_scope; ls; ls = ls->next)
944 if (ls->next->r_list[0] == tpnt) {
945 _dl_if_debug_print("removing symbol_scope: %s\n", tpnt->libname);
948 ls->next = ls->next->next;
951 /* Next, remove tpnt from the global symbol table list */
952 if (_dl_symbol_tables) {
953 if (_dl_symbol_tables->dyn == tpnt) {
954 _dl_symbol_tables = _dl_symbol_tables->next;
955 if (_dl_symbol_tables)
956 _dl_symbol_tables->prev = 0;
958 for (rpnt1 = _dl_symbol_tables; rpnt1->next; rpnt1 = rpnt1->next) {
959 if (rpnt1->next->dyn == tpnt) {
960 _dl_if_debug_print("removing symbol_tables: %s\n", tpnt->libname);
961 rpnt1_tmp = rpnt1->next->next;
963 rpnt1->next = rpnt1_tmp;
965 rpnt1->next->prev = rpnt1;
972 free(tpnt->symbol_scope.r_list);
976 for (rpnt1 = handle->next; rpnt1; rpnt1 = rpnt1_tmp) {
977 rpnt1_tmp = rpnt1->next;
980 free(handle->init_fini.init_fini);
983 #if defined(USE_TLS) && USE_TLS
984 /* If we removed any object which uses TLS bump the generation counter. */
986 if (__builtin_expect(++_dl_tls_generation == 0, 0)) {
987 _dl_debug_early("TLS generation counter wrapped! Please report to the uClibc mailing list.\n");
991 if (tls_free_end == _dl_tls_static_used)
992 _dl_tls_static_used = tls_free_start;
996 if (_dl_debug_addr) {
997 dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
998 if (dl_brk != NULL) {
999 _dl_debug_addr->r_state = RT_DELETE;
1002 _dl_debug_addr->r_state = RT_CONSISTENT;
1010 int dlclose(void *vhandle)
1012 return do_dlclose(vhandle, 1);
1019 if (!_dl_error_number)
1021 retval = dl_error_names[_dl_error_number];
1022 _dl_error_number = 0;
1023 return (char *)retval;
1027 * Dump information to stderr about the current loaded modules
1030 static const char type[][4] = { "Lib", "Exe", "Int", "Mod" };
1034 struct elf_resolve *tpnt;
1035 struct dyn_elf *rpnt, *hpnt;
1037 fprintf(stderr, "List of loaded modules\n");
1038 /* First start with a complete list of all of the loaded files. */
1039 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
1040 fprintf(stderr, "\t%p %p %p %s %d %s\n",
1041 DL_LOADADDR_BASE(tpnt->loadaddr), tpnt, tpnt->symbol_scope,
1042 type[tpnt->libtype],
1043 tpnt->usage_count, tpnt->libname);
1046 /* Next dump the module list for the application itself */
1047 fprintf(stderr, "\nModules for application (%p):\n", _dl_symbol_tables);
1048 for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next)
1049 fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname);
1051 for (hpnt = _dl_handles; hpnt; hpnt = hpnt->next_handle) {
1052 fprintf(stderr, "Modules for handle %p\n", hpnt);
1053 for (rpnt = hpnt; rpnt; rpnt = rpnt->next)
1054 fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname);
1059 int dladdr(const void *__address, Dl_info * __info)
1061 struct elf_resolve *pelf;
1062 struct elf_resolve *rpnt;
1067 * Try and locate the module address is in
1071 _dl_if_debug_print("__address: %p __info: %p\n", __address, __info);
1073 __address = DL_LOOKUP_ADDRESS (__address);
1075 for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) {
1076 struct elf_resolve *tpnt;
1080 _dl_if_debug_print("Module \"%s\" at %p\n",
1081 tpnt->libname, DL_LOADADDR_BASE(tpnt->loadaddr));
1083 if (DL_ADDR_IN_LOADADDR((ElfW(Addr)) __address, tpnt, pelf))
1092 * Try and locate the symbol of address
1098 unsigned int hn, si, sn, sf;
1101 /* Set the info for the object the address lies in */
1102 __info->dli_fname = pelf->libname;
1103 __info->dli_fbase = (void *)pelf->mapaddr;
1105 symtab = (ElfW(Sym) *) (pelf->dynamic_info[DT_SYMTAB]);
1106 strtab = (char *) (pelf->dynamic_info[DT_STRTAB]);
1110 #ifdef __LDSO_GNU_HASH_SUPPORT__
1111 if (pelf->l_gnu_bitmask) {
1112 for (hn = 0; hn < pelf->nbucket; hn++) {
1113 si = pelf->l_gnu_buckets[hn];
1117 const Elf32_Word *hasharr = &pelf->l_gnu_chain_zero[si];
1119 ElfW(Addr) symbol_addr;
1121 symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR(pelf->loadaddr, symtab[si].st_value);
1122 if ((symtab[si].st_shndx != SHN_UNDEF
1123 || symtab[si].st_value != 0)
1124 && ELF_ST_TYPE(symtab[si].st_info) != STT_TLS
1125 && DL_ADDR_SYM_MATCH(symbol_addr, &symtab[si], sa,
1126 (ElfW(Addr)) __address)) {
1131 _dl_if_debug_print("Symbol \"%s\" at %p\n", strtab + symtab[si].st_name, symbol_addr);
1133 } while ((*hasharr++ & 1u) == 0);
1137 for (hn = 0; hn < pelf->nbucket; hn++) {
1138 for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) {
1139 ElfW(Addr) symbol_addr;
1141 symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR(pelf->loadaddr, symtab[si].st_value);
1142 if ((symtab[si].st_shndx != SHN_UNDEF
1143 || symtab[si].st_value != 0)
1144 && ELF_ST_TYPE(symtab[si].st_info) != STT_TLS
1145 && DL_ADDR_SYM_MATCH(symbol_addr, &symtab[si], sa,
1146 (ElfW(Addr)) __address)) {
1152 _dl_if_debug_print("Symbol \"%s\" at %p\n",
1153 strtab + symtab[si].st_name, symbol_addr);
1158 /* A nearest symbol has been found; fill the entries */
1159 __info->dli_sname = strtab + symtab[sn].st_name;
1160 __info->dli_saddr = (void *)sa;
1162 /* No symbol found, fill entries with NULL value,
1163 only the containing object will be returned. */
1164 __info->dli_sname = NULL;
1165 __info->dli_saddr = NULL;