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
37 #include <bits/uClibc_mutex.h>
39 #ifdef __UCLIBC_HAS_TLS__
43 #if defined(USE_TLS) && USE_TLS
45 extern void _dl_add_to_slotinfo(struct link_map *l);
48 /* TODO: get rid of global lock and use more finegrained locking, or
49 * perhaps RCU for the global structures */
50 __UCLIBC_MUTEX_STATIC(_dl_mutex, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
53 # if defined(USE_TLS) && USE_TLS
55 extern struct link_map *_dl_update_slotinfo(unsigned long int req_modid);
58 /* When libdl is loaded as a shared library, we need to load in
59 * and use a pile of symbols from ldso... */
62 extern struct elf_resolve * _dl_load_shared_library(unsigned, struct dyn_elf **,
63 struct elf_resolve *, char *, int);
64 extern int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int lazy);
65 extern void _dl_protect_relro(struct elf_resolve * tpnt);
68 extern struct dyn_elf *_dl_symbol_tables;
69 extern struct dyn_elf *_dl_handles;
70 extern struct elf_resolve *_dl_loaded_modules;
71 extern void _dl_free (void *__ptr);
72 extern struct r_debug *_dl_debug_addr;
73 extern unsigned long _dl_error_number;
74 extern void *(*_dl_malloc_function)(size_t);
75 extern void (*_dl_free_function) (void *p);
76 extern void _dl_run_init_array(struct elf_resolve *);
77 extern void _dl_run_fini_array(struct elf_resolve *);
78 #ifdef __LDSO_CACHE_SUPPORT__
79 int _dl_map_cache(void);
80 int _dl_unmap_cache(void);
83 extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy);
85 #ifdef __SUPPORT_LD_DEBUG__
86 extern char *_dl_debug;
91 #define _dl_malloc malloc
94 /* When libdl is linked as a static library, we need to replace all
95 * the symbols that otherwise would have been loaded in from ldso... */
97 #ifdef __SUPPORT_LD_DEBUG__
98 char *_dl_debug = NULL;
99 char *_dl_debug_symbols = NULL;
100 char *_dl_debug_move = NULL;
101 char *_dl_debug_reloc = NULL;
102 char *_dl_debug_detail = NULL;
103 char *_dl_debug_nofixups = NULL;
104 char *_dl_debug_bindings = NULL;
105 int _dl_debug_file = 2;
107 const char *_dl_progname = ""; /* Program name */
108 void *(*_dl_malloc_function)(size_t);
109 void (*_dl_free_function) (void *p);
110 #ifdef __LDSO_LD_LIBRARY_PATH__
111 char *_dl_library_path = NULL; /* Where we look for libraries */
113 int _dl_errno = 0; /* We can't use the real errno in ldso */
114 size_t _dl_pagesize = PAGE_SIZE; /* Store the page size for use later */
115 /* This global variable is also to communicate with debuggers such as gdb. */
116 struct r_debug *_dl_debug_addr = NULL;
118 #include "../ldso/dl-array.c"
119 #include "../ldso/dl-debug.c"
122 # if defined(USE_TLS) && USE_TLS
124 * Giving this initialized value preallocates some surplus bytes in the
125 * static TLS area, see __libc_setup_tls (libc-tls.c).
127 size_t _dl_tls_static_size = 2048;
129 #include LDSO_ELFINTERP
130 #include "../ldso/dl-hash.c"
131 #define _dl_trace_loaded_objects 0
132 #include "../ldso/dl-elf.c"
135 #ifdef __SUPPORT_LD_DEBUG__
136 # define _dl_if_debug_print(fmt, args...) \
139 fprintf(stderr, "%s():%i: " fmt, __func__, __LINE__, ## args); \
142 # define _dl_if_debug_print(fmt, args...)
145 static int do_dlclose(void *, int need_fini);
148 static const char *const dl_error_names[] = {
151 "Unable to open /dev/zero",
153 #if defined (__i386__)
155 #elif defined (__sparc__)
157 #elif defined (__mc68000__)
160 "Unrecognized binary type",
162 "Not an ELF shared library",
163 "Unable to mmap file",
164 "No dynamic section",
165 "Library contains unsupported TLS",
166 #ifdef ELF_USES_RELOCA
167 "Unable to process REL relocs",
169 "Unable to process RELA relocs",
172 "Unable to resolve symbol"
176 #if defined(USE_TLS) && USE_TLS
179 * Systems which do not have tls_index also probably have to define
180 * DONT_USE_TLS_INDEX.
183 # ifndef __TLS_GET_ADDR
184 # define __TLS_GET_ADDR __tls_get_addr
188 * Return the symbol address given the map of the module it is in and
189 * the symbol record. This is used in dl-sym.c.
193 _dl_tls_symaddr(struct link_map *map, const Elf32_Addr st_value)
195 # ifndef DONT_USE_TLS_INDEX
198 .ti_module = map->l_tls_modid,
199 .ti_offset = st_value
202 return __TLS_GET_ADDR (&tmp);
204 return __TLS_GET_ADDR (map->l_tls_modid, st_value);
209 /* Returns true when a non-empty entry was found. */
211 remove_slotinfo(size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
212 bool should_be_there)
214 if (idx - disp >= listp->len) {
215 if (listp->next == NULL) {
217 * The index is not actually valid in the slotinfo list,
218 * because this object was closed before it was fully set
219 * up due to some error.
221 _dl_assert(!should_be_there);
223 if (remove_slotinfo(idx, listp->next, disp + listp->len,
228 * No non-empty entry. Search from the end of this element's
231 idx = disp + listp->len;
234 struct link_map *old_map = listp->slotinfo[idx - disp].map;
237 * The entry might still be in its unused state if we are
238 * closing an object that wasn't fully set up.
240 if (__builtin_expect(old_map != NULL, 1)) {
241 _dl_assert(old_map->l_tls_modid == idx);
243 /* Mark the entry as unused. */
244 listp->slotinfo[idx - disp].gen = _dl_tls_generation + 1;
245 listp->slotinfo[idx - disp].map = NULL;
249 * If this is not the last currently used entry no need to
252 if (idx != _dl_tls_max_dtv_idx)
256 while (idx - disp > (disp == 0 ? 1 + _dl_tls_static_nelem : 0)) {
259 if (listp->slotinfo[idx - disp].map != NULL) {
260 /* Found a new last used index. */
261 _dl_tls_max_dtv_idx = idx;
266 /* No non-entry in this list element. */
271 #ifndef __LDSO_NO_CLEANUP__
272 void dl_cleanup(void) attribute_hidden __attribute__ ((destructor));
273 void dl_cleanup(void)
275 struct dyn_elf *h, *n;
277 for (h = _dl_handles; h; h = n) {
284 static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list,
285 struct elf_resolve *map)
287 struct elf_resolve **p = list;
288 struct init_fini_list *q;
291 map->init_flag |= DL_RESERVED;
293 for (q = map->init_fini; q; q = q->next)
294 if (! (q->tpnt->init_flag & DL_RESERVED))
295 p += _dl_build_local_scope (p, q->tpnt);
299 static void *do_dlopen(const char *libname, int flag)
301 struct elf_resolve *tpnt, *tfrom;
302 struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle;
304 struct elf_resolve *tpnt1;
305 void (*dl_brk) (void);
307 struct init_fini_list *tmp, *runp, *runp2, *dep_list;
308 unsigned int nlist, i;
309 struct elf_resolve **init_fini_list;
310 static bool _dl_init;
311 struct elf_resolve **local_scope;
312 struct r_scope_elem *ls;
313 #if defined(USE_TLS) && USE_TLS
314 bool any_tls = false;
317 /* A bit of sanity checking... */
318 if (!(flag & (RTLD_LAZY|RTLD_NOW|RTLD_NOLOAD))) {
319 _dl_error_number = LD_BAD_HANDLE;
323 from = (ElfW(Addr)) __builtin_return_address(0);
327 _dl_malloc_function = malloc;
328 _dl_free_function = free;
330 /* Cover the trivial case first */
332 return _dl_symbol_tables;
335 # ifdef __SUPPORT_LD_DEBUG__
336 _dl_debug = getenv("LD_DEBUG");
338 if (_dl_strstr(_dl_debug, "all")) {
339 _dl_debug_detail = _dl_debug_move = _dl_debug_symbols
340 = _dl_debug_reloc = _dl_debug_bindings = _dl_debug_nofixups = (void*)1;
342 _dl_debug_detail = strstr(_dl_debug, "detail");
343 _dl_debug_move = strstr(_dl_debug, "move");
344 _dl_debug_symbols = strstr(_dl_debug, "sym");
345 _dl_debug_reloc = strstr(_dl_debug, "reloc");
346 _dl_debug_nofixups = strstr(_dl_debug, "nofix");
347 _dl_debug_bindings = strstr(_dl_debug, "bind");
356 * Try and locate the module we were called from - we
357 * need this so that we get the correct RPATH/RUNPATH. Note that
358 * this is the current behavior under Solaris, but the
359 * ABI+ specifies that we should only use the RPATH from
360 * the application. Thus this may go away at some time
364 struct dyn_elf *dpnt;
366 for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {
368 if (DL_ADDR_IN_LOADADDR(from, tpnt, tfrom))
372 for (rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt = rpnt->next)
376 now_flag = (flag & RTLD_NOW) ? RTLD_NOW : 0;
377 if (getenv("LD_BIND_NOW"))
380 #if !defined SHARED && defined __LDSO_LIBRARY_PATH__
381 /* When statically linked, the _dl_library_path is not yet initialized */
382 _dl_library_path = getenv("LD_LIBRARY_PATH");
385 /* Try to load the specified library */
386 _dl_if_debug_print("Trying to dlopen '%s', RTLD_GLOBAL:%d RTLD_NOW:%d\n",
387 (char*)libname, (flag & RTLD_GLOBAL ? 1:0), (now_flag & RTLD_NOW ? 1:0));
389 tpnt = _dl_load_shared_library((flag & RTLD_NOLOAD) ? DL_RESOLVE_NOLOAD : 0,
390 &rpnt, tfrom, (char*)libname, 0);
395 dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
396 memset(dyn_chain, 0, sizeof(struct dyn_elf));
397 dyn_chain->dyn = tpnt;
398 tpnt->rtld_flags |= (flag & RTLD_GLOBAL);
400 dyn_chain->next_handle = _dl_handles;
401 _dl_handles = dyn_ptr = dyn_chain;
403 if (tpnt->usage_count > 1) {
404 _dl_if_debug_print("Lib: %s already opened\n", libname);
405 /* see if there is a handle from a earlier dlopen */
406 for (handle = _dl_handles->next_handle; handle; handle = handle->next_handle) {
407 if (handle->dyn == tpnt) {
408 dyn_chain->init_fini.init_fini = handle->init_fini.init_fini;
409 dyn_chain->init_fini.nlist = handle->init_fini.nlist;
410 for (i = 0; i < dyn_chain->init_fini.nlist; i++)
411 dyn_chain->init_fini.init_fini[i]->rtld_flags |= (flag & RTLD_GLOBAL);
412 dyn_chain->next = handle->next;
419 tpnt->init_flag |= DL_OPENED;
421 _dl_if_debug_print("Looking for needed libraries\n");
423 runp = alloca(sizeof(*runp));
426 dep_list = runp2 = runp;
427 for (; runp; runp = runp->next) {
432 runp->tpnt->init_fini = NULL; /* clear any previous dependcies */
433 for (dpnt = (ElfW(Dyn) *) runp->tpnt->dynamic_addr; dpnt->d_tag; dpnt++) {
434 if (dpnt->d_tag == DT_NEEDED) {
435 lpntstr = (char*) (runp->tpnt->dynamic_info[DT_STRTAB] +
437 _dl_if_debug_print("Trying to load '%s', needed by '%s'\n",
438 lpntstr, runp->tpnt->libname);
439 tpnt1 = _dl_load_shared_library(0, &rpnt, runp->tpnt, lpntstr, 0);
443 tpnt1->rtld_flags |= (flag & RTLD_GLOBAL);
445 /* This list is for dlsym() and relocation */
446 dyn_ptr->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
447 memset (dyn_ptr->next, 0, sizeof (struct dyn_elf));
448 dyn_ptr = dyn_ptr->next;
449 dyn_ptr->dyn = tpnt1;
450 /* Used to record RTLD_LOCAL scope */
451 tmp = alloca(sizeof(struct init_fini_list));
453 tmp->next = runp->tpnt->init_fini;
454 runp->tpnt->init_fini = tmp;
456 for (tmp=dep_list; tmp; tmp = tmp->next) {
457 if (tpnt1 == tmp->tpnt) { /* if match => cirular dependency, drop it */
458 _dl_if_debug_print("Circular dependency, skipping '%s',\n",
460 tpnt1->usage_count--;
464 if (!tmp) { /* Don't add if circular dependency detected */
465 runp2->next = alloca(sizeof(*runp));
473 init_fini_list = malloc(nlist * sizeof(struct elf_resolve *));
474 dyn_chain->init_fini.init_fini = init_fini_list;
475 dyn_chain->init_fini.nlist = nlist;
477 for (runp2 = dep_list; runp2; runp2 = runp2->next) {
478 init_fini_list[i++] = runp2->tpnt;
479 for (runp = runp2->tpnt->init_fini; runp; runp = runp->next) {
480 if (!(runp->tpnt->rtld_flags & RTLD_GLOBAL)) {
481 tmp = malloc(sizeof(struct init_fini_list));
482 tmp->tpnt = runp->tpnt;
483 tmp->next = runp2->tpnt->rtld_local;
484 runp2->tpnt->rtld_local = tmp;
489 /* Build the local scope for the dynamically loaded modules. */
490 local_scope = _dl_malloc(nlist * sizeof(struct elf_resolve *)); /* Could it allocated on stack? */
491 for (i = 0; i < nlist; i++)
492 if (init_fini_list[i]->symbol_scope.r_nlist == 0) {
494 cnt = _dl_build_local_scope(local_scope, init_fini_list[i]);
495 init_fini_list[i]->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *));
496 init_fini_list[i]->symbol_scope.r_nlist = cnt;
497 _dl_memcpy (init_fini_list[i]->symbol_scope.r_list, local_scope,
498 cnt * sizeof (struct elf_resolve *));
499 /* Restoring the init_flag.*/
500 for (k = 0; k < nlist; k++)
501 init_fini_list[k]->init_flag &= ~DL_RESERVED;
504 _dl_free(local_scope);
506 /* Sort the INIT/FINI list in dependency order. */
507 for (runp2 = dep_list; runp2; runp2 = runp2->next) {
509 for (j = 0; init_fini_list[j] != runp2->tpnt; ++j)
511 for (k = j + 1; k < nlist; ++k) {
512 struct init_fini_list *ele = init_fini_list[k]->init_fini;
514 for (; ele; ele = ele->next) {
515 if (ele->tpnt == runp2->tpnt) {
516 struct elf_resolve *here = init_fini_list[k];
517 _dl_if_debug_print("Move %s from pos %d to %d in INIT/FINI list.\n", here->libname, k, j);
518 for (i = (k - j); i; --i)
519 init_fini_list[i+j] = init_fini_list[i+j-1];
520 init_fini_list[j] = here;
527 #ifdef __SUPPORT_LD_DEBUG__
529 fprintf(stderr, "\nINIT/FINI order and dependencies:\n");
530 for (i = 0; i < nlist; i++) {
531 fprintf(stderr, "lib: %s has deps:\n", init_fini_list[i]->libname);
532 runp = init_fini_list[i]->init_fini;
533 for (; runp; runp = runp->next)
534 fprintf(stderr, " %s ", runp->tpnt->libname);
535 fprintf(stderr, "\n");
540 _dl_if_debug_print("Beginning dlopen relocation fixups\n");
542 * OK, now all of the kids are tucked into bed in their proper addresses.
543 * Now we go through and look for REL and RELA records that indicate fixups
544 * to the GOT tables. We need to do this in reverse order so that COPY
545 * directives work correctly */
547 /* Get the tail of the list */
548 for (ls = &_dl_loaded_modules->symbol_scope; ls && ls->next; ls = ls->next);
550 /* Extend the global scope by adding the local scope of the dlopened DSO. */
551 ls->next = &dyn_chain->dyn->symbol_scope;
554 * Relocation of the GOT entries for MIPS have to be done
555 * after all the libraries have been loaded.
557 _dl_perform_mips_global_got_relocations(tpnt, !now_flag);
560 if (_dl_fixup(dyn_chain, &_dl_loaded_modules->symbol_scope, now_flag))
564 for (rpnt = relro_ptr->next; rpnt; rpnt = rpnt->next) {
565 if (rpnt->dyn->relro_size)
566 _dl_protect_relro(rpnt->dyn);
569 /* TODO: Should we set the protections of all pages back to R/O now ? */
572 #if defined(USE_TLS) && USE_TLS
574 for (i=0; i < nlist; i++) {
575 struct elf_resolve *tmp_tpnt = init_fini_list[i];
576 /* Only add TLS memory if this object is loaded now and
577 therefore is not yet initialized. */
579 if (!(tmp_tpnt->init_flag & INIT_FUNCS_CALLED)
580 /* Only if the module defines thread local data. */
581 && __builtin_expect (tmp_tpnt->l_tls_blocksize > 0, 0)) {
583 /* Now that we know the object is loaded successfully add
584 modules containing TLS data to the slot info table. We
585 might have to increase its size. */
586 _dl_add_to_slotinfo ((struct link_map*)tmp_tpnt);
588 /* It is the case in which we couldn't perform TLS static
589 initialization at relocation time, and we delayed it until
590 the relocation has been completed. */
592 if (tmp_tpnt->l_need_tls_init) {
593 tmp_tpnt->l_need_tls_init = 0;
595 /* Update the slot information data for at least the
596 generation of the DSO we are allocating data for. */
597 _dl_update_slotinfo (tmp_tpnt->l_tls_modid);
600 _dl_init_static_tls((struct link_map*)tmp_tpnt);
601 _dl_assert (tmp_tpnt->l_need_tls_init == 0);
604 /* We have to bump the generation counter. */
609 /* Bump the generation number if necessary. */
610 if (any_tls && __builtin_expect (++_dl_tls_generation == 0, 0)) {
611 _dl_debug_early("TLS generation counter wrapped! Please report this.");
617 /* Notify the debugger we have added some objects. */
618 if (_dl_debug_addr) {
619 dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
620 if (dl_brk != NULL) {
621 _dl_debug_addr->r_state = RT_ADD;
624 _dl_debug_addr->r_state = RT_CONSISTENT;
629 /* Run the ctors and setup the dtors */
630 for (i = nlist; i; --i) {
631 tpnt = init_fini_list[i-1];
632 if (tpnt->init_flag & INIT_FUNCS_CALLED)
634 tpnt->init_flag |= INIT_FUNCS_CALLED;
636 if (tpnt->dynamic_info[DT_INIT]) {
637 void (*dl_elf_func) (void);
638 dl_elf_func = (void (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_INIT]);
640 _dl_if_debug_print("running ctors for library %s at '%p'\n",
641 tpnt->libname, dl_elf_func);
642 DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
646 _dl_run_init_array(tpnt);
650 return (void *) dyn_chain;
653 /* Something went wrong. Clean up and return NULL. */
655 do_dlclose(dyn_chain, 0);
659 void *dlopen(const char *libname, int flag)
663 __UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1);
664 ret = do_dlopen(libname, flag);
665 __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1);
670 static void *do_dlsym(void *vhandle, const char *name, void *caller_address)
672 struct elf_resolve *tpnt, *tfrom;
673 struct dyn_elf *handle;
675 struct dyn_elf *rpnt;
677 struct symbol_ref sym_ref = { NULL, NULL };
678 /* Nastiness to support underscore prefixes. */
679 #ifdef __UCLIBC_UNDERSCORES__
681 char *name2 = tmp_buf;
682 size_t nlen = strlen (name) + 1;
683 if (nlen + 1 > sizeof (tmp_buf))
684 name2 = malloc (nlen + 1);
686 _dl_error_number = LD_ERROR_MMAP_FAILED;
690 memcpy (name2 + 1, name, nlen);
692 const char *name2 = name;
694 handle = (struct dyn_elf *) vhandle;
696 /* First of all verify that we have a real handle
697 of some kind. Return NULL if not a valid handle. */
700 handle = _dl_symbol_tables;
701 else if (handle != RTLD_NEXT && handle != _dl_symbol_tables) {
702 for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle)
706 _dl_error_number = LD_BAD_HANDLE;
710 } else if (handle == RTLD_NEXT) {
712 * Try and locate the module we were called from - we
713 * need this so that we know where to start searching
714 * from. We never pass RTLD_NEXT down into the actual
715 * dynamic loader itself, as it doesn't know
716 * how to properly treat it.
718 from = (ElfW(Addr)) caller_address;
721 for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) {
723 if (DL_ADDR_IN_LOADADDR(from, tpnt, tfrom)) {
730 if (handle == _dl_symbol_tables)
731 tpnt = handle->dyn; /* Only search RTLD_GLOBAL objs if global object */
732 ret = _dl_find_hash(name2, &handle->dyn->symbol_scope, tpnt, ELF_RTYPE_CLASS_DLSYM, &sym_ref);
734 #if defined(USE_TLS) && USE_TLS && defined SHARED
735 if (sym_ref.sym && (ELF_ST_TYPE(sym_ref.sym->st_info) == STT_TLS) && (sym_ref.tpnt)) {
736 /* The found symbol is a thread-local storage variable.
737 Return its address for the current thread. */
738 ret = _dl_tls_symaddr ((struct link_map *)sym_ref.tpnt, (Elf32_Addr)ret);
746 _dl_error_number = LD_NO_SYMBOL;
748 #ifdef __UCLIBC_UNDERSCORES__
749 if (name2 != tmp_buf)
755 void *dlsym(void *vhandle, const char *name)
759 __UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1);
760 ret = do_dlsym(vhandle, name, __builtin_return_address(0));
761 __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1);
767 void *dlvsym(void *vhandle, const char *name, const char *version)
769 return dlsym(vhandle, name);
773 static int do_dlclose(void *vhandle, int need_fini)
775 struct dyn_elf *rpnt, *rpnt1, *rpnt1_tmp;
776 struct init_fini_list *runp, *tmp;
778 struct elf_resolve *tpnt, *run_tpnt;
779 int (*dl_elf_fini) (void);
780 void (*dl_brk) (void);
781 struct dyn_elf *handle;
782 unsigned int end = 0, start = 0xffffffff;
784 struct r_scope_elem *ls, *ls_next = NULL;
785 struct elf_resolve **handle_rlist;
787 #if defined(USE_TLS) && USE_TLS
788 bool any_tls = false;
789 size_t tls_free_start = NO_TLS_OFFSET;
790 size_t tls_free_end = NO_TLS_OFFSET;
791 struct link_map *tls_lmap;
794 handle = (struct dyn_elf *) vhandle;
795 if (handle == _dl_symbol_tables)
798 for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) {
805 _dl_error_number = LD_BAD_HANDLE;
809 rpnt1->next_handle = rpnt->next_handle;
811 _dl_handles = rpnt->next_handle;
812 _dl_if_debug_print("%s: usage count: %d\n",
813 handle->dyn->libname, handle->dyn->usage_count);
814 if (handle->dyn->usage_count != 1 || (handle->dyn->rtld_flags & RTLD_NODELETE)) {
815 handle->dyn->usage_count--;
820 /* Store the handle's local scope array for later removal */
821 handle_rlist = handle->dyn->symbol_scope.r_list;
823 /* Store references to the local scope entries for later removal */
824 for (ls = &_dl_loaded_modules->symbol_scope; ls && ls->next; ls = ls->next)
825 if (ls->next->r_list[0] == handle->dyn) {
828 /* ls points to the previous local symbol scope */
830 ls_next = ls->next->next;
832 /* OK, this is a valid handle - now close out the file */
833 for (j = 0; j < handle->init_fini.nlist; ++j) {
834 tpnt = handle->init_fini.init_fini[j];
836 if (tpnt->usage_count == 0 && !(tpnt->rtld_flags & RTLD_NODELETE)) {
837 if ((tpnt->dynamic_info[DT_FINI]
838 || tpnt->dynamic_info[DT_FINI_ARRAY])
840 && !(tpnt->init_flag & FINI_FUNCS_CALLED)
842 tpnt->init_flag |= FINI_FUNCS_CALLED;
843 _dl_run_fini_array(tpnt);
845 if (tpnt->dynamic_info[DT_FINI]) {
846 dl_elf_fini = (int (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI]);
847 _dl_if_debug_print("running dtors for library %s at '%p'\n",
848 tpnt->libname, dl_elf_fini);
849 DL_CALL_FUNC_AT_ADDR (dl_elf_fini, tpnt->loadaddr, (int (*)(void)));
853 _dl_if_debug_print("unmapping: %s\n", tpnt->libname);
855 for (i = 0, ppnt = tpnt->ppnt;
856 i < tpnt->n_phent; ppnt++, i++) {
857 if (ppnt->p_type != PT_LOAD)
859 if (ppnt->p_vaddr < start)
860 start = ppnt->p_vaddr;
861 if (end < ppnt->p_vaddr + ppnt->p_memsz)
862 end = ppnt->p_vaddr + ppnt->p_memsz;
865 #if defined(USE_TLS) && USE_TLS
866 /* Do the cast to make things easy. */
867 tls_lmap = (struct link_map *) tpnt;
869 /* Remove the object from the dtv slotinfo array if it uses TLS. */
870 if (__builtin_expect (tls_lmap->l_tls_blocksize > 0, 0)) {
873 if (_dl_tls_dtv_slotinfo_list != NULL
874 && ! remove_slotinfo (tls_lmap->l_tls_modid,
875 _dl_tls_dtv_slotinfo_list, 0,
876 (tpnt->init_flag & INIT_FUNCS_CALLED)))
877 /* All dynamically loaded modules with TLS are unloaded. */
878 _dl_tls_max_dtv_idx = _dl_tls_static_nelem;
880 if (tls_lmap->l_tls_offset != NO_TLS_OFFSET) {
882 * Collect a contiguous chunk built from the objects in
883 * this search list, going in either direction. When the
884 * whole chunk is at the end of the used area then we can
887 # if defined(TLS_TCB_AT_TP)
888 if (tls_free_start == NO_TLS_OFFSET
889 || (size_t) tls_lmap->l_tls_offset == tls_free_start) {
890 /* Extend the contiguous chunk being reclaimed. */
892 = tls_lmap->l_tls_offset -
893 tls_lmap->l_tls_blocksize;
895 if (tls_free_end == NO_TLS_OFFSET)
896 tls_free_end = tls_lmap->l_tls_offset;
897 } else if (tls_lmap->l_tls_offset - tls_lmap->l_tls_blocksize
899 /* Extend the chunk backwards. */
900 tls_free_end = tls_lmap->l_tls_offset;
903 * This isn't contiguous with the last chunk freed.
904 * One of them will be leaked unless we can free
905 * one block right away.
907 if (tls_free_end == _dl_tls_static_used) {
908 _dl_tls_static_used = tls_free_start;
909 tls_free_end = tls_lmap->l_tls_offset;
911 = tls_free_end - tls_lmap->l_tls_blocksize;
912 } else if ((size_t) tls_lmap->l_tls_offset
913 == _dl_tls_static_used)
914 _dl_tls_static_used = tls_lmap->l_tls_offset -
915 tls_lmap->l_tls_blocksize;
916 else if (tls_free_end < (size_t) tls_lmap->l_tls_offset) {
918 * We pick the later block. It has a chance
921 tls_free_end = tls_lmap->l_tls_offset;
922 tls_free_start = tls_free_end -
923 tls_lmap->l_tls_blocksize;
926 # elif defined(TLS_DTV_AT_TP)
927 if ((size_t) tls_lmap->l_tls_offset == tls_free_end)
928 /* Extend the contiguous chunk being reclaimed. */
929 tls_free_end -= tls_lmap->l_tls_blocksize;
930 else if (tls_lmap->l_tls_offset + tls_lmap->l_tls_blocksize
932 /* Extend the chunk backwards. */
933 tls_free_start = tls_lmap->l_tls_offset;
936 * This isn't contiguous with the last chunk
937 * freed. One of them will be leaked.
939 if (tls_free_end == _dl_tls_static_used)
940 _dl_tls_static_used = tls_free_start;
941 tls_free_start = tls_lmap->l_tls_offset;
942 tls_free_end = tls_free_start +
943 tls_lmap->l_tls_blocksize;
946 # error Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined
950 #define TLS_DTV_UNALLOCATED ((void *) -1l)
952 dtv_t *dtv = THREAD_DTV ();
954 _dl_assert(!(dtv[tls_lmap->l_tls_modid].pointer.is_static));
955 if (dtv[tls_lmap->l_tls_modid].pointer.val != TLS_DTV_UNALLOCATED) {
956 /* Note that free is called for NULL is well. We
957 deallocate even if it is this dtv entry we are
958 supposed to load. The reason is that we call
959 memalign and not malloc. */
960 _dl_free (dtv[tls_lmap->l_tls_modid].pointer.val);
961 dtv[tls_lmap->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
967 end = (end + ADDR_ALIGN) & PAGE_ALIGN;
968 start = start & ~ADDR_ALIGN;
969 DL_LIB_UNMAP (tpnt, end - start);
970 /* Free elements in RTLD_LOCAL scope list */
971 for (runp = tpnt->rtld_local; runp; runp = tmp) {
976 /* Next, remove tpnt from the loaded_module list */
977 if (_dl_loaded_modules == tpnt) {
978 _dl_loaded_modules = tpnt->next;
979 if (_dl_loaded_modules)
980 _dl_loaded_modules->prev = 0;
982 for (run_tpnt = _dl_loaded_modules; run_tpnt; run_tpnt = run_tpnt->next) {
983 if (run_tpnt->next == tpnt) {
984 _dl_if_debug_print("removing loaded_modules: %s\n", tpnt->libname);
985 run_tpnt->next = run_tpnt->next->next;
987 run_tpnt->next->prev = run_tpnt;
993 /* Next, remove tpnt from the global symbol table list */
994 if (_dl_symbol_tables) {
995 if (_dl_symbol_tables->dyn == tpnt) {
996 _dl_symbol_tables = _dl_symbol_tables->next;
997 if (_dl_symbol_tables)
998 _dl_symbol_tables->prev = 0;
1000 for (rpnt1 = _dl_symbol_tables; rpnt1->next; rpnt1 = rpnt1->next) {
1001 if (rpnt1->next->dyn == tpnt) {
1002 _dl_if_debug_print("removing symbol_tables: %s\n", tpnt->libname);
1003 rpnt1_tmp = rpnt1->next->next;
1005 rpnt1->next = rpnt1_tmp;
1007 rpnt1->next->prev = rpnt1;
1013 free(tpnt->libname);
1014 if (handle->dyn != tpnt)
1015 free(tpnt->symbol_scope.r_list);
1019 /* Unlink and release the handle's local scope from global one */
1024 for (rpnt1 = handle->next; rpnt1; rpnt1 = rpnt1_tmp) {
1025 rpnt1_tmp = rpnt1->next;
1028 free(handle->init_fini.init_fini);
1031 #if defined(USE_TLS) && USE_TLS
1032 /* If we removed any object which uses TLS bump the generation counter. */
1034 if (__builtin_expect(++_dl_tls_generation == 0, 0)) {
1035 _dl_debug_early("TLS generation counter wrapped! Please report to the uClibc mailing list.\n");
1039 if (tls_free_end == _dl_tls_static_used)
1040 _dl_tls_static_used = tls_free_start;
1044 if (_dl_debug_addr) {
1045 dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
1046 if (dl_brk != NULL) {
1047 _dl_debug_addr->r_state = RT_DELETE;
1050 _dl_debug_addr->r_state = RT_CONSISTENT;
1058 int dlclose(void *vhandle)
1062 __UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1);
1063 ret = do_dlclose(vhandle, 1);
1064 __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1);
1073 if (!_dl_error_number)
1075 retval = dl_error_names[_dl_error_number];
1076 _dl_error_number = 0;
1077 return (char *)retval;
1081 * Dump information to stderr about the current loaded modules
1084 static const char type[][4] = { "Lib", "Exe", "Int", "Mod" };
1088 struct elf_resolve *tpnt;
1089 struct dyn_elf *rpnt, *hpnt;
1091 fprintf(stderr, "List of loaded modules\n");
1092 /* First start with a complete list of all of the loaded files. */
1093 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
1094 fprintf(stderr, "\t%p %p %p %s %d %s\n",
1095 DL_LOADADDR_BASE(tpnt->loadaddr), tpnt, tpnt->symbol_scope,
1096 type[tpnt->libtype],
1097 tpnt->usage_count, tpnt->libname);
1100 /* Next dump the module list for the application itself */
1101 fprintf(stderr, "\nModules for application (%p):\n", _dl_symbol_tables);
1102 for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next)
1103 fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname);
1105 for (hpnt = _dl_handles; hpnt; hpnt = hpnt->next_handle) {
1106 fprintf(stderr, "Modules for handle %p\n", hpnt);
1107 for (rpnt = hpnt; rpnt; rpnt = rpnt->next)
1108 fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname);
1113 static int do_dladdr(const void *__address, Dl_info * __info)
1115 struct elf_resolve *pelf;
1116 struct elf_resolve *rpnt;
1121 * Try and locate the module address is in
1125 _dl_if_debug_print("__address: %p __info: %p\n", __address, __info);
1127 __address = DL_LOOKUP_ADDRESS (__address);
1129 for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) {
1130 struct elf_resolve *tpnt;
1134 _dl_if_debug_print("Module \"%s\" at %p\n",
1135 tpnt->libname, DL_LOADADDR_BASE(tpnt->loadaddr));
1137 if (DL_ADDR_IN_LOADADDR((ElfW(Addr)) __address, tpnt, pelf))
1146 * Try and locate the symbol of address
1152 unsigned int hn, si, sn, sf;
1155 /* Set the info for the object the address lies in */
1156 __info->dli_fname = pelf->libname;
1157 __info->dli_fbase = (void *)pelf->mapaddr;
1159 symtab = (ElfW(Sym) *) (pelf->dynamic_info[DT_SYMTAB]);
1160 strtab = (char *) (pelf->dynamic_info[DT_STRTAB]);
1164 #ifdef __LDSO_GNU_HASH_SUPPORT__
1165 if (pelf->l_gnu_bitmask) {
1166 for (hn = 0; hn < pelf->nbucket; hn++) {
1167 si = pelf->l_gnu_buckets[hn];
1171 const Elf32_Word *hasharr = &pelf->l_gnu_chain_zero[si];
1173 ElfW(Addr) symbol_addr;
1175 symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR(pelf->loadaddr, symtab[si].st_value);
1176 if ((symtab[si].st_shndx != SHN_UNDEF
1177 || symtab[si].st_value != 0)
1178 && ELF_ST_TYPE(symtab[si].st_info) != STT_TLS
1179 && DL_ADDR_SYM_MATCH(symbol_addr, &symtab[si], sa,
1180 (ElfW(Addr)) __address)) {
1185 _dl_if_debug_print("Symbol \"%s\" at %p\n", strtab + symtab[si].st_name, symbol_addr);
1187 } while ((*hasharr++ & 1u) == 0);
1191 for (hn = 0; hn < pelf->nbucket; hn++) {
1192 for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) {
1193 ElfW(Addr) symbol_addr;
1195 symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR(pelf->loadaddr, symtab[si].st_value);
1196 if ((symtab[si].st_shndx != SHN_UNDEF
1197 || symtab[si].st_value != 0)
1198 && ELF_ST_TYPE(symtab[si].st_info) != STT_TLS
1199 && DL_ADDR_SYM_MATCH(symbol_addr, &symtab[si], sa,
1200 (ElfW(Addr)) __address)) {
1206 _dl_if_debug_print("Symbol \"%s\" at %p\n",
1207 strtab + symtab[si].st_name, symbol_addr);
1212 /* A nearest symbol has been found; fill the entries */
1213 __info->dli_sname = strtab + symtab[sn].st_name;
1214 __info->dli_saddr = (void *)sa;
1216 /* No symbol found, fill entries with NULL value,
1217 only the containing object will be returned. */
1218 __info->dli_sname = NULL;
1219 __info->dli_saddr = NULL;
1226 int dladdr(const void *__address, Dl_info * __info)
1230 __UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1);
1231 ret = do_dladdr(__address, __info);
1232 __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1);