OSDN Git Service

libdl: remove _dl_ldsopath from libdl.a
[uclinux-h8/uClibc.git] / ldso / libdl / libdl.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Program to load an ELF binary on a linux system, and run it
4  * after resolving ELF shared library symbols
5  *
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
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
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.
18  *
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
29  * SUCH DAMAGE.
30  */
31
32
33 #include <ldso.h>
34 #include <stdio.h>
35 #include <string.h> /* Needed for 'strstr' prototype' */
36 #include <stdbool.h>
37
38 #ifdef __UCLIBC_HAS_TLS__
39 #include <tls.h>
40 #endif
41
42 #if defined(USE_TLS) && USE_TLS
43 #include <ldsodefs.h>
44 extern void _dl_add_to_slotinfo(struct link_map  *l);
45 #endif
46
47 #ifdef SHARED
48 # if defined(USE_TLS) && USE_TLS
49 # include <dl-tls.h>
50 extern struct link_map *_dl_update_slotinfo(unsigned long int req_modid);
51 # endif
52
53 /* When libdl is loaded as a shared library, we need to load in
54  * and use a pile of symbols from ldso... */
55
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);
60 extern int _dl_errno;
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);
74 #endif
75 #ifdef __mips__
76 extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy);
77 #endif
78 #ifdef __SUPPORT_LD_DEBUG__
79 extern char *_dl_debug;
80 #endif
81
82 #else /* !SHARED */
83
84 #define _dl_malloc malloc
85 #define _dl_free free
86
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... */
89
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;
99 #endif
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;
108
109 #include "../ldso/dl-array.c"
110 #include "../ldso/dl-debug.c"
111
112
113 # if defined(USE_TLS) && USE_TLS
114 /*
115  * Giving this initialized value preallocates some surplus bytes in the
116  * static TLS area, see __libc_setup_tls (libc-tls.c).
117  */
118 size_t _dl_tls_static_size = 2048;
119 # endif
120 #include LDSO_ELFINTERP
121 #include "../ldso/dl-hash.c"
122 #define _dl_trace_loaded_objects    0
123 #include "../ldso/dl-elf.c"
124 #endif /* SHARED */
125
126 #ifdef __SUPPORT_LD_DEBUG__
127 # define _dl_if_debug_print(fmt, args...) \
128         do { \
129         if (_dl_debug) \
130                 fprintf(stderr, "%s():%i: " fmt, __FUNCTION__, __LINE__, ## args); \
131         } while (0)
132 #else
133 # define _dl_if_debug_print(fmt, args...)
134 #endif
135
136 static int do_dlclose(void *, int need_fini);
137
138
139 static const char *const dl_error_names[] = {
140         "",
141         "File not found",
142         "Unable to open /dev/zero",
143         "Not an ELF file",
144 #if defined (__i386__)
145         "Not i386 binary",
146 #elif defined (__sparc__)
147         "Not sparc binary",
148 #elif defined (__mc68000__)
149         "Not m68k binary",
150 #else
151         "Unrecognized binary type",
152 #endif
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",
159 #else
160         "Unable to process RELA relocs",
161 #endif
162         "Bad handle",
163         "Unable to resolve symbol"
164 };
165
166
167 #if defined(USE_TLS) && USE_TLS
168 #ifdef SHARED
169 /*
170  * Systems which do not have tls_index also probably have to define
171  * DONT_USE_TLS_INDEX.
172  */
173
174 # ifndef __TLS_GET_ADDR
175 #  define __TLS_GET_ADDR __tls_get_addr
176 # endif
177
178 /*
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.
181  */
182 static void *
183 internal_function
184 _dl_tls_symaddr(struct link_map *map, const Elf32_Addr st_value)
185 {
186 # ifndef DONT_USE_TLS_INDEX
187         tls_index tmp =
188         {
189                 .ti_module = map->l_tls_modid,
190                 .ti_offset = st_value
191         };
192
193         return __TLS_GET_ADDR (&tmp);
194 # else
195         return __TLS_GET_ADDR (map->l_tls_modid, st_value);
196 # endif
197 }
198 #endif
199
200 /* Returns true when a non-empty entry was found.  */
201 static bool
202 remove_slotinfo(size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
203          bool should_be_there)
204 {
205         if (idx - disp >= listp->len) {
206                 if (listp->next == NULL) {
207                         /*
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.
211                          */
212                         _dl_assert(!should_be_there);
213                 } else {
214                         if (remove_slotinfo(idx, listp->next, disp + listp->len,
215                                         should_be_there))
216                                 return true;
217
218                         /*
219                          * No non-empty entry. Search from the end of this element's
220                          * slotinfo array.
221                          */
222                         idx = disp + listp->len;
223                 }
224         } else {
225                 struct link_map *old_map = listp->slotinfo[idx - disp].map;
226
227                 /*
228                  * The entry might still be in its unused state if we are
229                  * closing an object that wasn't fully set up.
230                  */
231                 if (__builtin_expect(old_map != NULL, 1)) {
232                         _dl_assert(old_map->l_tls_modid == idx);
233
234                         /* Mark the entry as unused. */
235                         listp->slotinfo[idx - disp].gen = _dl_tls_generation + 1;
236                         listp->slotinfo[idx - disp].map = NULL;
237                 }
238
239                 /*
240                  * If this is not the last currently used entry no need to
241                  * look further.
242                  */
243                 if (idx != _dl_tls_max_dtv_idx)
244                         return true;
245         }
246
247         while (idx - disp > (disp == 0 ? 1 + _dl_tls_static_nelem : 0)) {
248                 --idx;
249
250                 if (listp->slotinfo[idx - disp].map != NULL) {
251                         /* Found a new last used index.  */
252                         _dl_tls_max_dtv_idx = idx;
253                         return true;
254                 }
255         }
256
257         /* No non-entry in this list element.  */
258         return false;
259 }
260 #endif
261
262 #ifndef __LDSO_NO_CLEANUP__
263 void dl_cleanup(void) __attribute__ ((destructor));
264 void dl_cleanup(void)
265 {
266         struct dyn_elf *h, *n;
267
268         for (h = _dl_handles; h; h = n) {
269                 n = h->next_handle;
270                 do_dlclose(h, 1);
271         }
272 }
273 #endif
274
275 static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list,
276         struct elf_resolve *map)
277 {
278         struct elf_resolve **p = list;
279         struct init_fini_list *q;
280
281         *p++ = map;
282         map->init_flag |= DL_RESERVED;
283         if (map->init_fini)
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);
287         return p - list;
288 }
289
290 void *dlopen(const char *libname, int flag)
291 {
292         struct elf_resolve *tpnt, *tfrom;
293         struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle;
294         ElfW(Addr) from;
295         struct elf_resolve *tpnt1;
296         void (*dl_brk) (void);
297         int now_flag;
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;
306 #endif
307
308         /* A bit of sanity checking... */
309         if (!(flag & (RTLD_LAZY|RTLD_NOW))) {
310                 _dl_error_number = LD_BAD_HANDLE;
311                 return NULL;
312         }
313
314         from = (ElfW(Addr)) __builtin_return_address(0);
315
316         if (!_dl_init) {
317                 _dl_init = true;
318                 _dl_malloc_function = malloc;
319                 _dl_free_function = free;
320         }
321         /* Cover the trivial case first */
322         if (!libname)
323                 return _dl_symbol_tables;
324
325 #ifndef SHARED
326 # ifdef __SUPPORT_LD_DEBUG__
327         _dl_debug = getenv("LD_DEBUG");
328         if (_dl_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;
332                 } else {
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");
339                 }
340         }
341 # endif
342 #endif
343
344         _dl_map_cache();
345
346         /*
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
352          * in the future.
353          */
354         {
355                 struct dyn_elf *dpnt;
356                 tfrom = NULL;
357                 for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {
358                         tpnt = dpnt->dyn;
359                         if (DL_ADDR_IN_LOADADDR(from, tpnt, tfrom))
360                                 tfrom = tpnt;
361                 }
362         }
363         for (rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt = rpnt->next)
364                 continue;
365
366         relro_ptr = rpnt;
367         now_flag = (flag & RTLD_NOW) ? RTLD_NOW : 0;
368         if (getenv("LD_BIND_NOW"))
369                 now_flag = RTLD_NOW;
370
371 #ifndef SHARED
372         /* When statically linked, the _dl_library_path is not yet initialized */
373         _dl_library_path = getenv("LD_LIBRARY_PATH");
374 #endif
375
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);
380
381         if (tpnt == NULL) {
382                 _dl_unmap_cache();
383                 return NULL;
384         }
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);
389
390         dyn_chain->next_handle = _dl_handles;
391         _dl_handles = dyn_ptr = dyn_chain;
392
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;
403                                 break;
404                         }
405                 }
406                 return dyn_chain;
407         }
408
409         tpnt->init_flag |= DL_OPENED;
410
411         _dl_if_debug_print("Looking for needed libraries\n");
412         nlist = 0;
413         runp = alloca(sizeof(*runp));
414         runp->tpnt = tpnt;
415         runp->next = NULL;
416         dep_list = runp2 = runp;
417         for (; runp; runp = runp->next) {
418                 ElfW(Dyn) *dpnt;
419                 char *lpntstr;
420
421                 nlist++;
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] +
426                                                 dpnt->d_un.d_val);
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);
430                                 if (!tpnt1)
431                                         goto oops;
432
433                                 tpnt1->rtld_flags |= (flag & RTLD_GLOBAL);
434
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));
442                                 tmp->tpnt = tpnt1;
443                                 tmp->next = runp->tpnt->init_fini;
444                                 runp->tpnt->init_fini = tmp;
445
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",
449                                                                    tmp->tpnt->libname);
450                                                 tpnt1->usage_count--;
451                                                 break;
452                                         }
453                                 }
454                                 if (!tmp) { /* Don't add if circular dependency detected */
455                                         runp2->next = alloca(sizeof(*runp));
456                                         runp2 = runp2->next;
457                                         runp2->tpnt = tpnt1;
458                                         runp2->next = NULL;
459                                 }
460                         }
461                 }
462         }
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;
466         i = 0;
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;
475                         }
476                 }
477
478         }
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) {
483                         int k, cnt;
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;
492                 }
493
494         _dl_free(local_scope);
495
496         /* Sort the INIT/FINI list in dependency order. */
497         for (runp2 = dep_list; runp2; runp2 = runp2->next) {
498                 unsigned int j, k;
499                 for (j = 0; init_fini_list[j] != runp2->tpnt; ++j)
500                         /* Empty */;
501                 for (k = j + 1; k < nlist; ++k) {
502                         struct init_fini_list *ele = init_fini_list[k]->init_fini;
503
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;
511                                         ++j;
512                                         break;
513                                 }
514                         }
515                 }
516         }
517 #ifdef __SUPPORT_LD_DEBUG__
518         if (_dl_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");
526                 }
527         }
528 #endif
529
530         _dl_if_debug_print("Beginning dlopen relocation fixups\n");
531         /*
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 */
536 #ifdef __mips__
537         /*
538          * Relocation of the GOT entries for MIPS have to be done
539          * after all the libraries have been loaded.
540          */
541         _dl_perform_mips_global_got_relocations(tpnt, !now_flag);
542 #endif
543         /* Get the tail of the list */
544         for (ls = &_dl_loaded_modules->symbol_scope; ls && ls->next; ls = ls->next);
545
546         /* Extend the global scope by adding the local scope of the dlopened DSO. */
547         ls->next = &dyn_chain->dyn->symbol_scope;
548
549         if (_dl_fixup(dyn_chain, &_dl_loaded_modules->symbol_scope, now_flag))
550                 goto oops;
551
552         if (relro_ptr) {
553                 for (rpnt = relro_ptr->next; rpnt; rpnt = rpnt->next) {
554                         if (rpnt->dyn->relro_size)
555                                 _dl_protect_relro(rpnt->dyn);
556                 }
557         }
558         /* TODO:  Should we set the protections of all pages back to R/O now ? */
559
560
561 #if defined(USE_TLS) && USE_TLS
562
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.  */
567
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)) {
571
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);
576
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. */
580
581                         if (tmp_tpnt->l_need_tls_init) {
582                                 tmp_tpnt->l_need_tls_init = 0;
583 # ifdef SHARED
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);
587 # endif
588
589                                 _dl_init_static_tls((struct link_map*)tmp_tpnt);
590                                 _dl_assert (tmp_tpnt->l_need_tls_init == 0);
591                 }
592
593                 /* We have to bump the generation counter. */
594                 any_tls = true;
595                 }
596         }
597
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.");
601                 _dl_exit(30);
602         }
603
604 #endif
605
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;
611                         (*dl_brk) ();
612
613                         _dl_debug_addr->r_state = RT_CONSISTENT;
614                         (*dl_brk) ();
615                 }
616         }
617
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)
622                         continue;
623                 tpnt->init_flag |= INIT_FUNCS_CALLED;
624
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]);
628                         if (dl_elf_func) {
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)));
632                         }
633                 }
634
635                 _dl_run_init_array(tpnt);
636         }
637
638         _dl_unmap_cache();
639         return (void *) dyn_chain;
640
641 oops:
642         /* Something went wrong.  Clean up and return NULL. */
643         _dl_unmap_cache();
644         do_dlclose(dyn_chain, 0);
645         return NULL;
646 }
647
648 void *dlsym(void *vhandle, const char *name)
649 {
650         struct elf_resolve *tpnt, *tfrom;
651         struct dyn_elf *handle;
652         ElfW(Addr) from;
653         struct dyn_elf *rpnt;
654         void *ret;
655         struct symbol_ref sym_ref = { NULL, NULL };
656         /* Nastiness to support underscore prefixes.  */
657 #ifdef __UCLIBC_UNDERSCORES__
658         char tmp_buf[80];
659         char *name2 = tmp_buf;
660         size_t nlen = strlen (name) + 1;
661         if (nlen + 1 > sizeof (tmp_buf))
662                 name2 = malloc (nlen + 1);
663         if (name2 == 0) {
664                 _dl_error_number = LD_ERROR_MMAP_FAILED;
665                 return 0;
666         }
667         name2[0] = '_';
668         memcpy (name2 + 1, name, nlen);
669 #else
670         const char *name2 = name;
671 #endif
672         handle = (struct dyn_elf *) vhandle;
673
674         /* First of all verify that we have a real handle
675            of some kind.  Return NULL if not a valid handle. */
676
677         if (handle == NULL)
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)
681                         if (rpnt == handle)
682                                 break;
683                 if (!rpnt) {
684                         _dl_error_number = LD_BAD_HANDLE;
685                         ret = NULL;
686                         goto out;
687                 }
688         } else if (handle == RTLD_NEXT) {
689                 /*
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.
695                  */
696                 from = (ElfW(Addr)) __builtin_return_address(0);
697
698                 tfrom = NULL;
699                 for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) {
700                         tpnt = rpnt->dyn;
701                         if (DL_ADDR_IN_LOADADDR(from, tpnt, tfrom)) {
702                                 tfrom = tpnt;
703                                 handle = rpnt->next;
704                         }
705                 }
706         }
707         tpnt = NULL;
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);
711
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);
717         }
718 #endif
719
720         /*
721          * Nothing found.
722          */
723         if (!ret)
724                 _dl_error_number = LD_NO_SYMBOL;
725 out:
726 #ifdef __UCLIBC_UNDERSCORES__
727         if (name2 != tmp_buf)
728                 free (name2);
729 #endif
730         return ret;
731 }
732
733 #if 0
734 void *dlvsym(void *vhandle, const char *name, const char *version)
735 {
736         return dlsym(vhandle, name);
737 }
738 #endif
739
740 static int do_dlclose(void *vhandle, int need_fini)
741 {
742         struct dyn_elf *rpnt, *rpnt1, *rpnt1_tmp;
743         struct init_fini_list *runp, *tmp;
744         ElfW(Phdr) *ppnt;
745         struct elf_resolve *tpnt, *run_tpnt;
746         int (*dl_elf_fini) (void);
747         void (*dl_brk) (void);
748         struct dyn_elf *handle;
749         unsigned int end;
750         unsigned int i, j;
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;
757 #endif
758
759         handle = (struct dyn_elf *) vhandle;
760         if (handle == _dl_symbol_tables)
761                 return 0;
762         rpnt1 = NULL;
763         for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) {
764                 if (rpnt == handle)
765                         break;
766                 rpnt1 = rpnt;
767         }
768
769         if (!rpnt) {
770                 _dl_error_number = LD_BAD_HANDLE;
771                 return 1;
772         }
773         if (rpnt1)
774                 rpnt1->next_handle = rpnt->next_handle;
775         else
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--;
781                 free(handle);
782                 return 0;
783         }
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];
787                 tpnt->usage_count--;
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])
791                          && need_fini
792                          && !(tpnt->init_flag & FINI_FUNCS_CALLED)
793                         ) {
794                                 tpnt->init_flag |= FINI_FUNCS_CALLED;
795                                 _dl_run_fini_array(tpnt);
796
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)));
802                                 }
803                         }
804
805                         _dl_if_debug_print("unmapping: %s\n", tpnt->libname);
806                         end = 0;
807                         for (i = 0, ppnt = tpnt->ppnt;
808                                         i < tpnt->n_phent; ppnt++, i++) {
809                                 if (ppnt->p_type != PT_LOAD)
810                                         continue;
811                                 if (end < ppnt->p_vaddr + ppnt->p_memsz)
812                                         end = ppnt->p_vaddr + ppnt->p_memsz;
813                         }
814
815 #if defined(USE_TLS) && USE_TLS
816                         /* Do the cast to make things easy. */
817                         tls_lmap = (struct link_map *) tpnt;
818
819                         /* Remove the object from the dtv slotinfo array if it uses TLS. */
820                         if (__builtin_expect (tls_lmap->l_tls_blocksize > 0, 0)) {
821                                 any_tls = true;
822
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;
829
830                                 if (tls_lmap->l_tls_offset != NO_TLS_OFFSET) {
831                                         /*
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
835                                          * reclaim it.
836                                          */
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. */
841                                                 tls_free_start
842                                                         = tls_lmap->l_tls_offset -
843                                                           tls_lmap->l_tls_blocksize;
844
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
848                                                         == tls_free_end)
849                                                 /* Extend the chunk backwards.  */
850                                                 tls_free_end = tls_lmap->l_tls_offset;
851                                         else {
852                                                 /*
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.
856                                                  */
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;
860                                                         tls_free_start
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) {
867                                                         /*
868                                                          * We pick the later block. It has a chance
869                                                          * to be freed.
870                                                          */
871                                                         tls_free_end = tls_lmap->l_tls_offset;
872                                                         tls_free_start = tls_free_end -
873                                                                 tls_lmap->l_tls_blocksize;
874                                                 }
875                                         }
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
881                                                         == tls_free_start)
882                                                 /* Extend the chunk backwards. */
883                                                 tls_free_start = tls_lmap->l_tls_offset;
884                                         else {
885                                                 /*
886                                                  * This isn't contiguous with the last chunk
887                                                  * freed. One of them will be leaked.
888                                                  */
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;
894                                         }
895 # else
896 #  error Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined
897 # endif
898                                 } else {
899
900 #define TLS_DTV_UNALLOCATED     ((void *) -1l)
901
902                                         dtv_t *dtv = THREAD_DTV ();
903
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;
912                                         }
913                                 }
914                         }
915 #endif
916
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) {
920                                 tmp = runp->next;
921                                 free(runp);
922                         }
923
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;
929                         } else {
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;
934                                                 if (run_tpnt->next)
935                                                         run_tpnt->next->prev = run_tpnt;
936                                                 break;
937                                         }
938                                 }
939                         }
940
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);
946                                                 break;
947                                         }
948                                 ls->next = ls->next->next;
949                         }
950
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;
957                                 } else {
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;
962                                                         free(rpnt1->next);
963                                                         rpnt1->next = rpnt1_tmp;
964                                                         if (rpnt1->next)
965                                                                 rpnt1->next->prev = rpnt1;
966                                                         break;
967                                                 }
968                                         }
969                                 }
970                         }
971                         free(tpnt->libname);
972                         free(tpnt->symbol_scope.r_list);
973                         free(tpnt);
974                 }
975         }
976         for (rpnt1 = handle->next; rpnt1; rpnt1 = rpnt1_tmp) {
977                 rpnt1_tmp = rpnt1->next;
978                 free(rpnt1);
979         }
980         free(handle->init_fini.init_fini);
981         free(handle);
982
983 #if defined(USE_TLS) && USE_TLS
984         /* If we removed any object which uses TLS bump the generation counter.  */
985         if (any_tls) {
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");
988                         _dl_exit(30);
989                 }
990
991                 if (tls_free_end == _dl_tls_static_used)
992                         _dl_tls_static_used = tls_free_start;
993         }
994 #endif
995
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;
1000                         (*dl_brk) ();
1001
1002                         _dl_debug_addr->r_state = RT_CONSISTENT;
1003                         (*dl_brk) ();
1004                 }
1005         }
1006
1007         return 0;
1008 }
1009
1010 int dlclose(void *vhandle)
1011 {
1012         return do_dlclose(vhandle, 1);
1013 }
1014
1015 char *dlerror(void)
1016 {
1017         const char *retval;
1018
1019         if (!_dl_error_number)
1020                 return NULL;
1021         retval = dl_error_names[_dl_error_number];
1022         _dl_error_number = 0;
1023         return (char *)retval;
1024 }
1025
1026 /*
1027  * Dump information to stderr about the current loaded modules
1028  */
1029 #ifdef __USE_GNU
1030 static const char type[][4] = { "Lib", "Exe", "Int", "Mod" };
1031
1032 int dlinfo(void)
1033 {
1034         struct elf_resolve *tpnt;
1035         struct dyn_elf *rpnt, *hpnt;
1036
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);
1044         }
1045
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);
1050
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);
1055         }
1056         return 0;
1057 }
1058
1059 int dladdr(const void *__address, Dl_info * __info)
1060 {
1061         struct elf_resolve *pelf;
1062         struct elf_resolve *rpnt;
1063
1064         _dl_map_cache();
1065
1066         /*
1067          * Try and locate the module address is in
1068          */
1069         pelf = NULL;
1070
1071         _dl_if_debug_print("__address: %p  __info: %p\n", __address, __info);
1072
1073         __address = DL_LOOKUP_ADDRESS (__address);
1074
1075         for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) {
1076                 struct elf_resolve *tpnt;
1077
1078                 tpnt = rpnt;
1079
1080                 _dl_if_debug_print("Module \"%s\" at %p\n",
1081                                    tpnt->libname, DL_LOADADDR_BASE(tpnt->loadaddr));
1082
1083                 if (DL_ADDR_IN_LOADADDR((ElfW(Addr)) __address, tpnt, pelf))
1084                         pelf = tpnt;
1085         }
1086
1087         if (!pelf) {
1088                 return 0;
1089         }
1090
1091         /*
1092          * Try and locate the symbol of address
1093          */
1094
1095         {
1096                 char *strtab;
1097                 ElfW(Sym) *symtab;
1098                 unsigned int hn, si, sn, sf;
1099                 ElfW(Addr) sa = 0;
1100
1101                 /* Set the info for the object the address lies in */
1102                 __info->dli_fname = pelf->libname;
1103                 __info->dli_fbase = (void *)pelf->mapaddr;
1104
1105                 symtab = (ElfW(Sym) *) (pelf->dynamic_info[DT_SYMTAB]);
1106                 strtab = (char *) (pelf->dynamic_info[DT_STRTAB]);
1107
1108                 sf = sn = 0;
1109
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];
1114                                 if (!si)
1115                                         continue;
1116
1117                                 const Elf32_Word *hasharr = &pelf->l_gnu_chain_zero[si];
1118                                 do {
1119                                         ElfW(Addr) symbol_addr;
1120
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)) {
1127                                                 sa = symbol_addr;
1128                                                 sn = si;
1129                                                 sf = 1;
1130                                         }
1131                                         _dl_if_debug_print("Symbol \"%s\" at %p\n", strtab + symtab[si].st_name, symbol_addr);
1132                                         ++si;
1133                                 } while ((*hasharr++ & 1u) == 0);
1134                         }
1135                 } else
1136 #endif
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;
1140
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)) {
1147                                         sa = symbol_addr;
1148                                         sn = si;
1149                                         sf = 1;
1150                                 }
1151
1152                                 _dl_if_debug_print("Symbol \"%s\" at %p\n",
1153                                                    strtab + symtab[si].st_name, symbol_addr);
1154                         }
1155                 }
1156
1157                 if (sf) {
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;
1161                 } else {
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;
1166                 }
1167                 return 1;
1168         }
1169 }
1170 #endif