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, 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 char *_dl_ldsopath = NULL; /* Location of the shared lib loader */
105 int _dl_errno = 0; /* We can't use the real errno in ldso */
106 size_t _dl_pagesize = PAGE_SIZE; /* Store the page size for use later */
107 /* This global variable is also to communicate with debuggers such as gdb. */
108 struct r_debug *_dl_debug_addr = NULL;
110 #include "../ldso/dl-array.c"
111 #include "../ldso/dl-debug.c"
114 # if defined(USE_TLS) && USE_TLS
116 * Giving this initialized value preallocates some surplus bytes in the
117 * static TLS area, see __libc_setup_tls (libc-tls.c).
119 size_t _dl_tls_static_size = 2048;
121 #include LDSO_ELFINTERP
122 #include "../ldso/dl-hash.c"
123 #define _dl_trace_loaded_objects 0
124 #include "../ldso/dl-elf.c"
127 #ifdef __SUPPORT_LD_DEBUG__
128 # define _dl_if_debug_print(fmt, args...) \
131 fprintf(stderr, "%s():%i: " fmt, __FUNCTION__, __LINE__, ## args); \
134 # define _dl_if_debug_print(fmt, args...)
137 static int do_dlclose(void *, int need_fini);
140 static const char *const dl_error_names[] = {
143 "Unable to open /dev/zero",
145 #if defined (__i386__)
147 #elif defined (__sparc__)
149 #elif defined (__mc68000__)
152 "Unrecognized binary type",
154 "Not an ELF shared library",
155 "Unable to mmap file",
156 "No dynamic section",
157 "Library contains unsupported TLS",
158 #ifdef ELF_USES_RELOCA
159 "Unable to process REL relocs",
161 "Unable to process RELA relocs",
164 "Unable to resolve symbol"
168 #if defined(USE_TLS) && USE_TLS
171 * Systems which do not have tls_index also probably have to define
172 * DONT_USE_TLS_INDEX.
175 # ifndef __TLS_GET_ADDR
176 # define __TLS_GET_ADDR __tls_get_addr
180 * Return the symbol address given the map of the module it is in and
181 * the symbol record. This is used in dl-sym.c.
185 _dl_tls_symaddr(struct link_map *map, const Elf32_Addr st_value)
187 # ifndef DONT_USE_TLS_INDEX
190 .ti_module = map->l_tls_modid,
191 .ti_offset = st_value
194 return __TLS_GET_ADDR (&tmp);
196 return __TLS_GET_ADDR (map->l_tls_modid, st_value);
201 /* Returns true when a non-empty entry was found. */
203 remove_slotinfo(size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
204 bool should_be_there)
206 if (idx - disp >= listp->len) {
207 if (listp->next == NULL) {
209 * The index is not actually valid in the slotinfo list,
210 * because this object was closed before it was fully set
211 * up due to some error.
213 _dl_assert(!should_be_there);
215 if (remove_slotinfo(idx, listp->next, disp + listp->len,
220 * No non-empty entry. Search from the end of this element's
223 idx = disp + listp->len;
226 struct link_map *old_map = listp->slotinfo[idx - disp].map;
229 * The entry might still be in its unused state if we are
230 * closing an object that wasn't fully set up.
232 if (__builtin_expect(old_map != NULL, 1)) {
233 _dl_assert(old_map->l_tls_modid == idx);
235 /* Mark the entry as unused. */
236 listp->slotinfo[idx - disp].gen = _dl_tls_generation + 1;
237 listp->slotinfo[idx - disp].map = NULL;
241 * If this is not the last currently used entry no need to
244 if (idx != _dl_tls_max_dtv_idx)
248 while (idx - disp > (disp == 0 ? 1 + _dl_tls_static_nelem : 0)) {
251 if (listp->slotinfo[idx - disp].map != NULL) {
252 /* Found a new last used index. */
253 _dl_tls_max_dtv_idx = idx;
258 /* No non-entry in this list element. */
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) {
274 void *dlopen(const char *libname, int flag)
276 struct elf_resolve *tpnt, *tfrom;
277 struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle;
279 struct elf_resolve *tpnt1;
280 void (*dl_brk) (void);
282 struct init_fini_list *tmp, *runp, *runp2, *dep_list;
283 unsigned int nlist, i;
284 struct elf_resolve **init_fini_list;
285 static bool _dl_init;
286 #if defined(USE_TLS) && USE_TLS
287 bool any_tls = false;
290 /* A bit of sanity checking... */
291 if (!(flag & (RTLD_LAZY|RTLD_NOW))) {
292 _dl_error_number = LD_BAD_HANDLE;
296 from = (ElfW(Addr)) __builtin_return_address(0);
300 _dl_malloc_function = malloc;
301 _dl_free_function = free;
303 /* Cover the trivial case first */
305 return _dl_symbol_tables;
308 # ifdef __SUPPORT_LD_DEBUG__
309 _dl_debug = getenv("LD_DEBUG");
311 if (_dl_strstr(_dl_debug, "all")) {
312 _dl_debug_detail = _dl_debug_move = _dl_debug_symbols
313 = _dl_debug_reloc = _dl_debug_bindings = _dl_debug_nofixups = (void*)1;
315 _dl_debug_detail = strstr(_dl_debug, "detail");
316 _dl_debug_move = strstr(_dl_debug, "move");
317 _dl_debug_symbols = strstr(_dl_debug, "sym");
318 _dl_debug_reloc = strstr(_dl_debug, "reloc");
319 _dl_debug_nofixups = strstr(_dl_debug, "nofix");
320 _dl_debug_bindings = strstr(_dl_debug, "bind");
329 * Try and locate the module we were called from - we
330 * need this so that we get the correct RPATH/RUNPATH. Note that
331 * this is the current behavior under Solaris, but the
332 * ABI+ specifies that we should only use the RPATH from
333 * the application. Thus this may go away at some time
337 struct dyn_elf *dpnt;
339 for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {
341 if (DL_ADDR_IN_LOADADDR(from, tpnt, tfrom))
345 for (rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt = rpnt->next)
349 now_flag = (flag & RTLD_NOW) ? RTLD_NOW : 0;
350 if (getenv("LD_BIND_NOW"))
354 /* When statically linked, the _dl_library_path is not yet initialized */
355 _dl_library_path = getenv("LD_LIBRARY_PATH");
358 /* Try to load the specified library */
359 _dl_if_debug_print("Trying to dlopen '%s', RTLD_GLOBAL:%d RTLD_NOW:%d\n",
360 (char*)libname, (flag & RTLD_GLOBAL ? 1:0), (now_flag & RTLD_NOW ? 1:0));
361 tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname, 0);
367 dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
368 _dl_memset(dyn_chain, 0, sizeof(struct dyn_elf));
369 dyn_chain->dyn = tpnt;
370 tpnt->rtld_flags |= (flag & RTLD_GLOBAL);
372 dyn_chain->next_handle = _dl_handles;
373 _dl_handles = dyn_ptr = dyn_chain;
375 if (tpnt->usage_count > 1) {
376 _dl_if_debug_print("Lib: %s already opened\n", libname);
377 /* see if there is a handle from a earlier dlopen */
378 for (handle = _dl_handles->next_handle; handle; handle = handle->next_handle) {
379 if (handle->dyn == tpnt) {
380 dyn_chain->init_fini.init_fini = handle->init_fini.init_fini;
381 dyn_chain->init_fini.nlist = handle->init_fini.nlist;
382 for (i = 0; i < dyn_chain->init_fini.nlist; i++)
383 dyn_chain->init_fini.init_fini[i]->rtld_flags |= (flag & RTLD_GLOBAL);
384 dyn_chain->next = handle->next;
391 tpnt->init_flag |= DL_OPENED;
393 _dl_if_debug_print("Looking for needed libraries\n");
395 runp = alloca(sizeof(*runp));
398 dep_list = runp2 = runp;
399 for (; runp; runp = runp->next) {
404 runp->tpnt->init_fini = NULL; /* clear any previous dependcies */
405 for (dpnt = (ElfW(Dyn) *) runp->tpnt->dynamic_addr; dpnt->d_tag; dpnt++) {
406 if (dpnt->d_tag == DT_NEEDED) {
407 lpntstr = (char*) (runp->tpnt->dynamic_info[DT_STRTAB] +
409 _dl_if_debug_print("Trying to load '%s', needed by '%s'\n",
410 lpntstr, runp->tpnt->libname);
411 tpnt1 = _dl_load_shared_library(0, &rpnt, runp->tpnt, lpntstr, 0);
415 tpnt1->rtld_flags |= (flag & RTLD_GLOBAL);
417 /* This list is for dlsym() and relocation */
418 dyn_ptr->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
419 _dl_memset (dyn_ptr->next, 0, sizeof (struct dyn_elf));
420 dyn_ptr = dyn_ptr->next;
421 dyn_ptr->dyn = tpnt1;
422 /* Used to record RTLD_LOCAL scope */
423 tmp = alloca(sizeof(struct init_fini_list));
425 tmp->next = runp->tpnt->init_fini;
426 runp->tpnt->init_fini = tmp;
428 for (tmp=dep_list; tmp; tmp = tmp->next) {
429 if (tpnt1 == tmp->tpnt) { /* if match => cirular dependency, drop it */
430 _dl_if_debug_print("Circular dependency, skipping '%s',\n",
432 tpnt1->usage_count--;
436 if (!tmp) { /* Don't add if circular dependency detected */
437 runp2->next = alloca(sizeof(*runp));
445 init_fini_list = malloc(nlist * sizeof(struct elf_resolve *));
446 dyn_chain->init_fini.init_fini = init_fini_list;
447 dyn_chain->init_fini.nlist = nlist;
449 for (runp2 = dep_list; runp2; runp2 = runp2->next) {
450 init_fini_list[i++] = runp2->tpnt;
451 for (runp = runp2->tpnt->init_fini; runp; runp = runp->next) {
452 if (!(runp->tpnt->rtld_flags & RTLD_GLOBAL)) {
453 tmp = malloc(sizeof(struct init_fini_list));
454 tmp->tpnt = runp->tpnt;
455 tmp->next = runp2->tpnt->rtld_local;
456 runp2->tpnt->rtld_local = tmp;
461 /* Sort the INIT/FINI list in dependency order. */
462 for (runp2 = dep_list; runp2; runp2 = runp2->next) {
464 for (j = 0; init_fini_list[j] != runp2->tpnt; ++j)
466 for (k = j + 1; k < nlist; ++k) {
467 struct init_fini_list *ele = init_fini_list[k]->init_fini;
469 for (; ele; ele = ele->next) {
470 if (ele->tpnt == runp2->tpnt) {
471 struct elf_resolve *here = init_fini_list[k];
472 _dl_if_debug_print("Move %s from pos %d to %d in INIT/FINI list.\n", here->libname, k, j);
473 for (i = (k - j); i; --i)
474 init_fini_list[i+j] = init_fini_list[i+j-1];
475 init_fini_list[j] = here;
482 #ifdef __SUPPORT_LD_DEBUG__
484 fprintf(stderr, "\nINIT/FINI order and dependencies:\n");
485 for (i = 0; i < nlist; i++) {
486 fprintf(stderr, "lib: %s has deps:\n", init_fini_list[i]->libname);
487 runp = init_fini_list[i]->init_fini;
488 for (; runp; runp = runp->next)
489 fprintf(stderr, " %s ", runp->tpnt->libname);
490 fprintf(stderr, "\n");
495 _dl_if_debug_print("Beginning dlopen relocation fixups\n");
497 * OK, now all of the kids are tucked into bed in their proper addresses.
498 * Now we go through and look for REL and RELA records that indicate fixups
499 * to the GOT tables. We need to do this in reverse order so that COPY
500 * directives work correctly */
503 * Relocation of the GOT entries for MIPS have to be done
504 * after all the libraries have been loaded.
506 _dl_perform_mips_global_got_relocations(tpnt, !now_flag);
509 if (_dl_fixup(dyn_chain, now_flag))
513 for (rpnt = relro_ptr->next; rpnt; rpnt = rpnt->next) {
514 if (rpnt->dyn->relro_size)
515 _dl_protect_relro(rpnt->dyn);
518 /* TODO: Should we set the protections of all pages back to R/O now ? */
521 #if defined(USE_TLS) && USE_TLS
523 for (i=0; i < nlist; i++) {
524 struct elf_resolve *tmp_tpnt = init_fini_list[i];
525 /* Only add TLS memory if this object is loaded now and
526 therefore is not yet initialized. */
528 if (!(tmp_tpnt->init_flag & INIT_FUNCS_CALLED)
529 /* Only if the module defines thread local data. */
530 && __builtin_expect (tmp_tpnt->l_tls_blocksize > 0, 0)) {
532 /* Now that we know the object is loaded successfully add
533 modules containing TLS data to the slot info table. We
534 might have to increase its size. */
535 _dl_add_to_slotinfo ((struct link_map*)tmp_tpnt);
537 /* It is the case in which we couldn't perform TLS static
538 initialization at relocation time, and we delayed it until
539 the relocation has been completed. */
541 if (tmp_tpnt->l_need_tls_init) {
542 tmp_tpnt->l_need_tls_init = 0;
544 /* Update the slot information data for at least the
545 generation of the DSO we are allocating data for. */
546 _dl_update_slotinfo (tmp_tpnt->l_tls_modid);
549 _dl_init_static_tls((struct link_map*)tmp_tpnt);
550 _dl_assert (tmp_tpnt->l_need_tls_init == 0);
553 /* We have to bump the generation counter. */
558 /* Bump the generation number if necessary. */
559 if (any_tls && __builtin_expect (++_dl_tls_generation == 0, 0)) {
560 _dl_debug_early("TLS generation counter wrapped! Please report this.");
566 /* Notify the debugger we have added some objects. */
567 if (_dl_debug_addr) {
568 dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
569 if (dl_brk != NULL) {
570 _dl_debug_addr->r_state = RT_ADD;
573 _dl_debug_addr->r_state = RT_CONSISTENT;
578 /* Run the ctors and setup the dtors */
579 for (i = nlist; i; --i) {
580 tpnt = init_fini_list[i-1];
581 if (tpnt->init_flag & INIT_FUNCS_CALLED)
583 tpnt->init_flag |= INIT_FUNCS_CALLED;
585 if (tpnt->dynamic_info[DT_INIT]) {
586 void (*dl_elf_func) (void);
587 dl_elf_func = (void (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_INIT]);
589 _dl_if_debug_print("running ctors for library %s at '%p'\n",
590 tpnt->libname, dl_elf_func);
591 DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
595 _dl_run_init_array(tpnt);
599 return (void *) dyn_chain;
602 /* Something went wrong. Clean up and return NULL. */
604 do_dlclose(dyn_chain, 0);
608 void *dlsym(void *vhandle, const char *name)
610 struct elf_resolve *tpnt, *tfrom;
611 struct dyn_elf *handle;
613 struct dyn_elf *rpnt;
615 struct elf_resolve *tls_tpnt = NULL;
616 /* Nastiness to support underscore prefixes. */
617 #ifdef __UCLIBC_UNDERSCORES__
619 char *name2 = tmp_buf;
620 size_t nlen = strlen (name) + 1;
621 if (nlen + 1 > sizeof (tmp_buf))
622 name2 = malloc (nlen + 1);
624 _dl_error_number = LD_ERROR_MMAP_FAILED;
628 memcpy (name2 + 1, name, nlen);
630 const char *name2 = name;
632 handle = (struct dyn_elf *) vhandle;
634 /* First of all verify that we have a real handle
635 of some kind. Return NULL if not a valid handle. */
638 handle = _dl_symbol_tables;
639 else if (handle != RTLD_NEXT && handle != _dl_symbol_tables) {
640 for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle)
644 _dl_error_number = LD_BAD_HANDLE;
648 } else if (handle == RTLD_NEXT) {
650 * Try and locate the module we were called from - we
651 * need this so that we know where to start searching
652 * from. We never pass RTLD_NEXT down into the actual
653 * dynamic loader itself, as it doesn't know
654 * how to properly treat it.
656 from = (ElfW(Addr)) __builtin_return_address(0);
659 for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) {
661 if (DL_ADDR_IN_LOADADDR(from, tpnt, tfrom)) {
668 if (handle == _dl_symbol_tables)
669 tpnt = handle->dyn; /* Only search RTLD_GLOBAL objs if global object */
670 ret = _dl_find_hash(name2, handle, NULL, 0, &tls_tpnt);
672 #if defined(USE_TLS) && USE_TLS && defined SHARED
674 /* The found symbol is a thread-local storage variable.
675 Return the address for to the current thread. */
676 ret = _dl_tls_symaddr ((struct link_map *)tls_tpnt, (Elf32_Addr)ret);
684 _dl_error_number = LD_NO_SYMBOL;
686 #ifdef __UCLIBC_UNDERSCORES__
687 if (name2 != tmp_buf)
694 void *dlvsym(void *vhandle, const char *name, const char *version)
696 return dlsym(vhandle, name);
700 static int do_dlclose(void *vhandle, int need_fini)
702 struct dyn_elf *rpnt, *rpnt1, *rpnt1_tmp;
703 struct init_fini_list *runp, *tmp;
705 struct elf_resolve *tpnt, *run_tpnt;
706 int (*dl_elf_fini) (void);
707 void (*dl_brk) (void);
708 struct dyn_elf *handle;
711 #if defined(USE_TLS) && USE_TLS
712 bool any_tls = false;
713 size_t tls_free_start = NO_TLS_OFFSET;
714 size_t tls_free_end = NO_TLS_OFFSET;
715 struct link_map *tls_lmap;
718 handle = (struct dyn_elf *) vhandle;
719 if (handle == _dl_symbol_tables)
722 for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) {
729 _dl_error_number = LD_BAD_HANDLE;
733 rpnt1->next_handle = rpnt->next_handle;
735 _dl_handles = rpnt->next_handle;
736 _dl_if_debug_print("%s: usage count: %d\n",
737 handle->dyn->libname, handle->dyn->usage_count);
738 if (handle->dyn->usage_count != 1 || (handle->dyn->rtld_flags & RTLD_NODELETE)) {
739 handle->dyn->usage_count--;
743 /* OK, this is a valid handle - now close out the file */
744 for (j = 0; j < handle->init_fini.nlist; ++j) {
745 tpnt = handle->init_fini.init_fini[j];
747 if (tpnt->usage_count == 0 && !(tpnt->rtld_flags & RTLD_NODELETE)) {
748 if ((tpnt->dynamic_info[DT_FINI]
749 || tpnt->dynamic_info[DT_FINI_ARRAY])
751 && !(tpnt->init_flag & FINI_FUNCS_CALLED)
753 tpnt->init_flag |= FINI_FUNCS_CALLED;
754 _dl_run_fini_array(tpnt);
756 if (tpnt->dynamic_info[DT_FINI]) {
757 dl_elf_fini = (int (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI]);
758 _dl_if_debug_print("running dtors for library %s at '%p'\n",
759 tpnt->libname, dl_elf_fini);
760 DL_CALL_FUNC_AT_ADDR (dl_elf_fini, tpnt->loadaddr, (int (*)(void)));
764 _dl_if_debug_print("unmapping: %s\n", tpnt->libname);
766 for (i = 0, ppnt = tpnt->ppnt;
767 i < tpnt->n_phent; ppnt++, i++) {
768 if (ppnt->p_type != PT_LOAD)
770 if (end < ppnt->p_vaddr + ppnt->p_memsz)
771 end = ppnt->p_vaddr + ppnt->p_memsz;
774 #if defined(USE_TLS) && USE_TLS
775 /* Do the cast to make things easy. */
776 tls_lmap = (struct link_map *) tpnt;
778 /* Remove the object from the dtv slotinfo array if it uses TLS. */
779 if (__builtin_expect (tls_lmap->l_tls_blocksize > 0, 0)) {
782 if (_dl_tls_dtv_slotinfo_list != NULL
783 && ! remove_slotinfo (tls_lmap->l_tls_modid,
784 _dl_tls_dtv_slotinfo_list, 0,
785 (tpnt->init_flag & INIT_FUNCS_CALLED)))
786 /* All dynamically loaded modules with TLS are unloaded. */
787 _dl_tls_max_dtv_idx = _dl_tls_static_nelem;
789 if (tls_lmap->l_tls_offset != NO_TLS_OFFSET) {
791 * Collect a contiguous chunk built from the objects in
792 * this search list, going in either direction. When the
793 * whole chunk is at the end of the used area then we can
796 # if defined(TLS_TCB_AT_TP)
797 if (tls_free_start == NO_TLS_OFFSET
798 || (size_t) tls_lmap->l_tls_offset == tls_free_start) {
799 /* Extend the contiguous chunk being reclaimed. */
801 = tls_lmap->l_tls_offset -
802 tls_lmap->l_tls_blocksize;
804 if (tls_free_end == NO_TLS_OFFSET)
805 tls_free_end = tls_lmap->l_tls_offset;
806 } else if (tls_lmap->l_tls_offset - tls_lmap->l_tls_blocksize
808 /* Extend the chunk backwards. */
809 tls_free_end = tls_lmap->l_tls_offset;
812 * This isn't contiguous with the last chunk freed.
813 * One of them will be leaked unless we can free
814 * one block right away.
816 if (tls_free_end == _dl_tls_static_used) {
817 _dl_tls_static_used = tls_free_start;
818 tls_free_end = tls_lmap->l_tls_offset;
820 = tls_free_end - tls_lmap->l_tls_blocksize;
821 } else if ((size_t) tls_lmap->l_tls_offset
822 == _dl_tls_static_used)
823 _dl_tls_static_used = tls_lmap->l_tls_offset -
824 tls_lmap->l_tls_blocksize;
825 else if (tls_free_end < (size_t) tls_lmap->l_tls_offset) {
827 * We pick the later block. It has a chance
830 tls_free_end = tls_lmap->l_tls_offset;
831 tls_free_start = tls_free_end -
832 tls_lmap->l_tls_blocksize;
835 # elif defined(TLS_DTV_AT_TP)
836 if ((size_t) tls_lmap->l_tls_offset == tls_free_end)
837 /* Extend the contiguous chunk being reclaimed. */
838 tls_free_end -= tls_lmap->l_tls_blocksize;
839 else if (tls_lmap->l_tls_offset + tls_lmap->l_tls_blocksize
841 /* Extend the chunk backwards. */
842 tls_free_start = tls_lmap->l_tls_offset;
845 * This isn't contiguous with the last chunk
846 * freed. One of them will be leaked.
848 if (tls_free_end == _dl_tls_static_used)
849 _dl_tls_static_used = tls_free_start;
850 tls_free_start = tls_lmap->l_tls_offset;
851 tls_free_end = tls_free_start +
852 tls_lmap->l_tls_blocksize;
855 # error Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined
859 #define TLS_DTV_UNALLOCATED ((void *) -1l)
861 dtv_t *dtv = THREAD_DTV ();
863 _dl_assert(!(dtv[tls_lmap->l_tls_modid].pointer.is_static));
864 if (dtv[tls_lmap->l_tls_modid].pointer.val != TLS_DTV_UNALLOCATED) {
865 /* Note that free is called for NULL is well. We
866 deallocate even if it is this dtv entry we are
867 supposed to load. The reason is that we call
868 memalign and not malloc. */
869 _dl_free (dtv[tls_lmap->l_tls_modid].pointer.val);
870 dtv[tls_lmap->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
876 DL_LIB_UNMAP (tpnt, end);
877 /* Free elements in RTLD_LOCAL scope list */
878 for (runp = tpnt->rtld_local; runp; runp = tmp) {
883 /* Next, remove tpnt from the loaded_module list */
884 if (_dl_loaded_modules == tpnt) {
885 _dl_loaded_modules = tpnt->next;
886 if (_dl_loaded_modules)
887 _dl_loaded_modules->prev = 0;
889 for (run_tpnt = _dl_loaded_modules; run_tpnt; run_tpnt = run_tpnt->next) {
890 if (run_tpnt->next == tpnt) {
891 _dl_if_debug_print("removing loaded_modules: %s\n", tpnt->libname);
892 run_tpnt->next = run_tpnt->next->next;
894 run_tpnt->next->prev = run_tpnt;
900 /* Next, remove tpnt from the global symbol table list */
901 if (_dl_symbol_tables) {
902 if (_dl_symbol_tables->dyn == tpnt) {
903 _dl_symbol_tables = _dl_symbol_tables->next;
904 if (_dl_symbol_tables)
905 _dl_symbol_tables->prev = 0;
907 for (rpnt1 = _dl_symbol_tables; rpnt1->next; rpnt1 = rpnt1->next) {
908 if (rpnt1->next->dyn == tpnt) {
909 _dl_if_debug_print("removing symbol_tables: %s\n", tpnt->libname);
910 rpnt1_tmp = rpnt1->next->next;
912 rpnt1->next = rpnt1_tmp;
914 rpnt1->next->prev = rpnt1;
924 free(handle->init_fini.init_fini);
927 #if defined(USE_TLS) && USE_TLS
928 /* If we removed any object which uses TLS bump the generation counter. */
930 if (__builtin_expect(++_dl_tls_generation == 0, 0)) {
931 _dl_debug_early("TLS generation counter wrapped! Please report to the uClibc mailing list.\n");
935 if (tls_free_end == _dl_tls_static_used)
936 _dl_tls_static_used = tls_free_start;
940 if (_dl_debug_addr) {
941 dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
942 if (dl_brk != NULL) {
943 _dl_debug_addr->r_state = RT_DELETE;
946 _dl_debug_addr->r_state = RT_CONSISTENT;
954 int dlclose(void *vhandle)
956 return do_dlclose(vhandle, 1);
963 if (!_dl_error_number)
965 retval = dl_error_names[_dl_error_number];
966 _dl_error_number = 0;
967 return (char *)retval;
971 * Dump information to stderr about the current loaded modules
974 static const char type[][4] = { "Lib", "Exe", "Int", "Mod" };
978 struct elf_resolve *tpnt;
979 struct dyn_elf *rpnt, *hpnt;
981 fprintf(stderr, "List of loaded modules\n");
982 /* First start with a complete list of all of the loaded files. */
983 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
984 fprintf(stderr, "\t%p %p %p %s %d %s\n",
985 DL_LOADADDR_BASE(tpnt->loadaddr), tpnt, tpnt->symbol_scope,
987 tpnt->usage_count, tpnt->libname);
990 /* Next dump the module list for the application itself */
991 fprintf(stderr, "\nModules for application (%p):\n", _dl_symbol_tables);
992 for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next)
993 fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname);
995 for (hpnt = _dl_handles; hpnt; hpnt = hpnt->next_handle) {
996 fprintf(stderr, "Modules for handle %p\n", hpnt);
997 for (rpnt = hpnt; rpnt; rpnt = rpnt->next)
998 fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname);
1003 int dladdr(const void *__address, Dl_info * __info)
1005 struct elf_resolve *pelf;
1006 struct elf_resolve *rpnt;
1011 * Try and locate the module address is in
1015 _dl_if_debug_print("__address: %p __info: %p\n", __address, __info);
1017 __address = DL_LOOKUP_ADDRESS (__address);
1019 for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) {
1020 struct elf_resolve *tpnt;
1024 _dl_if_debug_print("Module \"%s\" at %p\n",
1025 tpnt->libname, DL_LOADADDR_BASE(tpnt->loadaddr));
1027 if (DL_ADDR_IN_LOADADDR((ElfW(Addr)) __address, tpnt, pelf))
1036 * Try and locate the symbol of address
1042 unsigned int hn, si, sn, sf;
1045 /* Set the info for the object the address lies in */
1046 __info->dli_fname = pelf->libname;
1047 __info->dli_fbase = (void *)pelf->mapaddr;
1049 symtab = (ElfW(Sym) *) (pelf->dynamic_info[DT_SYMTAB]);
1050 strtab = (char *) (pelf->dynamic_info[DT_STRTAB]);
1054 #ifdef __LDSO_GNU_HASH_SUPPORT__
1055 if (pelf->l_gnu_bitmask) {
1056 for (hn = 0; hn < pelf->nbucket; hn++) {
1057 si = pelf->l_gnu_buckets[hn];
1061 const Elf32_Word *hasharr = &pelf->l_gnu_chain_zero[si];
1063 ElfW(Addr) symbol_addr;
1065 symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR(pelf->loadaddr, symtab[si].st_value);
1066 if (symbol_addr <= (ElfW(Addr))__address && (!sf || sa < symbol_addr)) {
1071 _dl_if_debug_print("Symbol \"%s\" at %p\n", strtab + symtab[si].st_name, symbol_addr);
1073 } while ((*hasharr++ & 1u) == 0);
1077 for (hn = 0; hn < pelf->nbucket; hn++) {
1078 for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) {
1079 ElfW(Addr) symbol_addr;
1081 symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR(pelf->loadaddr, symtab[si].st_value);
1082 if (symbol_addr <= (ElfW(Addr))__address && (!sf || sa < symbol_addr)) {
1088 _dl_if_debug_print("Symbol \"%s\" at %p\n",
1089 strtab + symtab[si].st_name, symbol_addr);
1094 /* A nearest symbol has been found; fill the entries */
1095 __info->dli_sname = strtab + symtab[sn].st_name;
1096 __info->dli_saddr = (void *)sa;
1098 /* No symbol found, fill entries with NULL value,
1099 only the containing object will be returned. */
1100 __info->dli_sname = NULL;
1101 __info->dli_saddr = NULL;