Same iteration variable used for inner and outer loop
[uclibc-ng.git] / ldso / ldso / ldso.c
blobc18d96bdb193c747ed29cacfab61c9cb573d5d4e
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
6 * Copyright (C) 2005 by Joakim Tjernlund
7 * Copyright (C) 2000-2006 by Erik Andersen <andersen@codepoet.org>
8 * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
9 * David Engel, Hongjiu Lu and Mitch D'Souza
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. The name of the above contributors may not be
17 * used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
33 #include "ldso.h"
34 #include "unsecvars.h"
36 /* Pull in common debug code */
37 #include "dl-debug.c"
39 #define ALLOW_ZERO_PLTGOT
41 #if defined(USE_TLS) && USE_TLS
42 #include "dl-tls.c"
43 #endif
45 /* Pull in the value of _dl_progname */
46 #include LDSO_ELFINTERP
48 /* Global variables used within the shared library loader */
49 #ifdef __LDSO_LD_LIBRARY_PATH__
50 char *_dl_library_path = NULL; /* Where we look for libraries */
51 #endif
52 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
53 char *_dl_preload = NULL; /* Things to be loaded before the libs */
54 #endif
55 int _dl_errno = 0; /* We can't use the real errno in ldso */
56 size_t _dl_pagesize = 0; /* Store the page size for use later */
57 struct r_debug *_dl_debug_addr = NULL; /* Used to communicate with the gdb debugger */
58 void *(*_dl_malloc_function) (size_t size) = NULL;
59 void (*_dl_free_function) (void *p) = NULL;
61 #ifdef __LDSO_PRELINK_SUPPORT__
62 char *_dl_trace_prelink = NULL; /* Library for prelinking trace */
63 struct elf_resolve *_dl_trace_prelink_map = NULL; /* Library module for prelinking trace */
64 bool _dl_verbose = true; /* On by default */
65 bool prelinked = false;
66 #endif
67 int _dl_secure = 1; /* Are we dealing with setuid stuff? */
69 #ifdef __SUPPORT_LD_DEBUG__
70 char *_dl_debug = NULL;
71 char *_dl_debug_symbols = NULL;
72 char *_dl_debug_move = NULL;
73 char *_dl_debug_reloc = NULL;
74 char *_dl_debug_detail = NULL;
75 char *_dl_debug_nofixups = NULL;
76 char *_dl_debug_bindings = NULL;
77 int _dl_debug_file = 2;
78 #endif
80 #ifdef __DSBT__
81 void **_dl_ldso_dsbt = NULL;
82 #endif
84 unsigned long attribute_hidden _dl_skip_args = 0;
86 const char *_dl_progname = UCLIBC_LDSO; /* The name of the executable being run */
87 #include "dl-startup.c"
88 #include "dl-symbols.c"
89 #include "dl-array.c"
92 * This stub function is used by some debuggers. The idea is that they
93 * can set an internal breakpoint on it, so that we are notified when the
94 * address mapping is changed in some way.
96 void _dl_debug_state(void);
97 rtld_hidden_proto(_dl_debug_state, noinline);
98 void _dl_debug_state(void)
100 /* Make sure GCC doesn't recognize this function as pure, to avoid
101 * having the calls optimized away.
103 __asm__("");
105 rtld_hidden_def(_dl_debug_state);
107 static unsigned char *_dl_malloc_addr = NULL; /* Lets _dl_malloc use the already allocated memory page */
108 static unsigned char *_dl_mmap_zero = NULL; /* Also used by _dl_malloc */
110 static struct elf_resolve **init_fini_list;
111 static struct elf_resolve **scope_elem_list;
112 static unsigned int nlist; /* # items in init_fini_list */
113 extern void _start(void);
115 #ifdef __UCLIBC_HAS_SSP__
116 # include <dl-osinfo.h>
117 static uintptr_t stack_chk_guard;
118 # ifndef THREAD_SET_STACK_GUARD
119 /* Only exported for architectures that don't store the stack guard canary
120 * in local thread area. */
121 uintptr_t __stack_chk_guard attribute_relro;
122 # endif
123 #endif
125 #ifdef __LDSO_SEARCH_INTERP_PATH__
126 const char *_dl_ldsopath = NULL; /* Location of the shared lib loader */
128 static void _dl_ldsopath_init(struct elf_resolve *tpnt)
130 char *ldsopath, *ptmp;
133 * Store the path where the shared lib loader was found for later use.
134 * Note that this logic isn't bullet proof when it comes to relative
135 * paths: if you use "./lib/ldso.so", and then the app does chdir()
136 * followed by dlopen(), the old ldso path won't get searched. But
137 * that is a fairly pathological use case, so if you don't like that,
138 * then set a full path to your interp and be done :P.
140 ldsopath = _dl_strdup(tpnt->libname);
141 ptmp = _dl_strrchr(ldsopath, '/');
143 * If there is no "/", then set the path to "", and the code
144 * later on will take this to implicitly mean "search $PWD".
146 if (!ptmp)
147 ptmp = ldsopath;
148 *ptmp = '\0';
150 _dl_ldsopath = ldsopath;
151 _dl_debug_early("Lib Loader: (%x) %s: using path: %s\n",
152 (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname,
153 _dl_ldsopath);
155 #else
156 #define _dl_ldsopath_init(tpnt)
157 #endif
159 char *_dl_getenv(const char *symbol, char **envp)
161 char *pnt;
162 const char *pnt1;
164 while ((pnt = *envp++)) {
165 pnt1 = symbol;
166 while (*pnt && *pnt == *pnt1)
167 pnt1++, pnt++;
168 if (!*pnt || *pnt != '=' || *pnt1)
169 continue;
170 return pnt + 1;
172 return 0;
175 void _dl_unsetenv(const char *symbol, char **envp)
177 char *pnt;
178 const char *pnt1;
179 char **newenvp = envp;
181 for (pnt = *envp; pnt; pnt = *++envp) {
182 pnt1 = symbol;
183 while (*pnt && *pnt == *pnt1)
184 pnt1++, pnt++;
185 if (!*pnt || *pnt != '=' || *pnt1)
186 *newenvp++ = *envp;
188 *newenvp++ = *envp;
189 return;
192 static int _dl_suid_ok(void)
194 __kernel_uid_t uid, euid;
195 __kernel_gid_t gid, egid;
197 uid = _dl_getuid();
198 euid = _dl_geteuid();
199 gid = _dl_getgid();
200 egid = _dl_getegid();
202 if (uid == euid && gid == egid) {
203 return 1;
205 return 0;
208 void *_dl_malloc(size_t size)
210 void *retval;
212 #if 0
213 _dl_debug_early("request for %d bytes\n", size);
214 #endif
216 if (_dl_malloc_function)
217 return (*_dl_malloc_function) (size);
219 if (_dl_malloc_addr - _dl_mmap_zero + size > _dl_pagesize) {
220 size_t rounded_size;
222 /* Since the above assumes we get a full page even if
223 we request less than that, make sure we request a
224 full page, since uClinux may give us less than than
225 a full page. We might round even
226 larger-than-a-page sizes, but we end up never
227 reusing _dl_mmap_zero/_dl_malloc_addr in that case,
228 so we don't do it.
230 The actual page size doesn't really matter; as long
231 as we're self-consistent here, we're safe. */
232 if (size < _dl_pagesize)
233 rounded_size = (size + ADDR_ALIGN) & _dl_pagesize;
234 else
235 rounded_size = size;
237 _dl_debug_early("mmapping more memory\n");
238 _dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, rounded_size,
239 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZED, -1, 0);
240 if (_dl_mmap_check_error(_dl_mmap_zero)) {
241 _dl_dprintf(2, "%s: mmap of a spare page failed!\n", _dl_progname);
242 _dl_exit(20);
245 retval = _dl_malloc_addr;
246 _dl_malloc_addr += size;
249 * Align memory to DL_MALLOC_ALIGN byte boundary. Some
250 * platforms require this, others simply get better
251 * performance.
253 _dl_malloc_addr = (unsigned char *) (((unsigned long) _dl_malloc_addr + DL_MALLOC_ALIGN - 1) & ~(DL_MALLOC_ALIGN - 1));
254 return retval;
257 static void *_dl_zalloc(size_t size)
259 void *p = _dl_malloc(size);
260 if (p)
261 _dl_memset(p, 0, size);
262 else
263 _dl_exit(1);
264 return p;
267 void _dl_free(void *p)
269 if (_dl_free_function)
270 (*_dl_free_function) (p);
273 #if defined(USE_TLS) && USE_TLS
274 void *_dl_memalign(size_t __boundary, size_t __size)
276 void *result;
277 int i = 0;
278 size_t delta;
279 size_t rounded = 0;
281 if (_dl_memalign_function)
282 return (*_dl_memalign_function) (__boundary, __size);
284 while (rounded < __boundary) {
285 rounded = (1 << i++);
288 delta = (((size_t) _dl_malloc_addr + __size) & (rounded - 1));
290 if ((result = _dl_malloc(rounded - delta)) == NULL)
291 return result;
293 result = _dl_malloc(__size);
295 return result;
297 #endif
299 static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void)
301 unsigned int i;
302 struct elf_resolve * tpnt;
304 for (i = 0; i < nlist; ++i) {
305 tpnt = init_fini_list[i];
306 if (tpnt->init_flag & FINI_FUNCS_CALLED)
307 continue;
308 tpnt->init_flag |= FINI_FUNCS_CALLED;
309 _dl_run_fini_array(tpnt);
310 if (tpnt->dynamic_info[DT_FINI]) {
311 void (*dl_elf_func) (void);
313 dl_elf_func = (void (*)(void)) (intptr_t) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI]);
314 _dl_if_debug_dprint("\ncalling FINI: %s\n\n", tpnt->libname);
315 DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
320 #ifdef __LDSO_PRELINK_SUPPORT__
321 static void trace_objects(struct elf_resolve *tpnt, char *str_name)
323 if (_dl_strcmp(_dl_trace_prelink, tpnt->libname) == 0)
324 _dl_trace_prelink_map = tpnt;
325 if (tpnt->libtype == elf_executable) {
326 /* Main executeble */
327 _dl_dprintf(1, "\t%s => %s (%x, %x)", tpnt->libname, tpnt->libname,
328 tpnt->mapaddr, DL_LOADADDR_BASE(tpnt->loadaddr));
329 } else {
330 /* Preloaded, Needed or interpreter */
331 _dl_dprintf(1, "\t%s => %s (%x, %x)", str_name, tpnt->libname,
332 tpnt->mapaddr, DL_LOADADDR_BASE(tpnt->loadaddr));
335 #if defined USE_TLS && USE_TLS
336 if ((tpnt->libtype != program_interpreter) && (tpnt->l_tls_modid))
337 _dl_dprintf (1, " TLS(%x, %x)\n", tpnt->l_tls_modid,
338 (size_t) tpnt->l_tls_offset);
339 else
340 #endif
341 _dl_dprintf (1, "\n");
343 #endif
345 static struct elf_resolve * add_ldso(struct elf_resolve *tpnt,
346 DL_LOADADDR_TYPE load_addr,
347 ElfW(Addr) ldso_mapaddr,
348 ElfW(auxv_t) auxvt[AT_EGID + 1],
349 struct dyn_elf *rpnt)
351 ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
352 ElfW(Phdr) *myppnt = (ElfW(Phdr) *)
353 DL_RELOC_ADDR(DL_GET_RUN_ADDR(load_addr, ldso_mapaddr),
354 epnt->e_phoff);
355 int j;
356 struct stat st;
358 tpnt = _dl_add_elf_hash_table(tpnt->libname, tpnt->loadaddr,
359 tpnt->dynamic_info, (unsigned long)tpnt->dynamic_addr,
362 tpnt->mapaddr = ldso_mapaddr;
363 if (_dl_stat(tpnt->libname, &st) >= 0) {
364 tpnt->st_dev = st.st_dev;
365 tpnt->st_ino = st.st_ino;
367 tpnt->n_phent = epnt->e_phnum;
368 tpnt->ppnt = myppnt;
369 for (j = 0; j < epnt->e_phnum; j++, myppnt++) {
370 if (myppnt->p_type == PT_GNU_RELRO) {
371 tpnt->relro_addr = myppnt->p_vaddr;
372 tpnt->relro_size = myppnt->p_memsz;
373 break;
376 tpnt->libtype = program_interpreter;
377 if (rpnt) {
378 rpnt->next = _dl_zalloc(sizeof(struct dyn_elf));
379 rpnt->next->prev = rpnt;
380 rpnt = rpnt->next;
381 } else {
382 rpnt = _dl_zalloc(sizeof(struct dyn_elf));
384 rpnt->dyn = tpnt;
385 tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */
387 return tpnt;
390 static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list,
391 struct elf_resolve *map)
393 struct elf_resolve **p = list;
394 struct init_fini_list *q;
396 *p++ = map;
397 map->init_flag |= DL_RESERVED;
398 if (map->init_fini)
399 for (q = map->init_fini; q; q = q->next)
400 if (! (q->tpnt->init_flag & DL_RESERVED))
401 p += _dl_build_local_scope (p, q->tpnt);
402 return p - list;
405 static void _dl_setup_progname(const char *argv0)
407 char image[PATH_MAX];
408 ssize_t s;
410 s = _dl_readlink(AT_FDCWD, "/proc/self/exe", image, sizeof(image));
411 if (s > 0 && image[0] == '/') {
412 image[s] = 0;
413 _dl_progname = _dl_strdup(image);
414 } else if (argv0) {
415 _dl_progname = argv0;
419 void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
420 ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv
421 DL_GET_READY_TO_RUN_EXTRA_PARMS)
423 ElfW(Addr) app_mapaddr = 0, ldso_mapaddr = 0;
424 ElfW(Phdr) *ppnt;
425 ElfW(Dyn) *dpnt;
426 char *lpntstr;
427 unsigned int i, cnt, nscope_elem;
428 int unlazy = 0, trace_loaded_objects = 0;
429 struct dyn_elf *rpnt;
430 struct elf_resolve *tcurr;
431 struct elf_resolve *tpnt1;
432 struct elf_resolve *ldso_tpnt = NULL;
433 struct elf_resolve app_tpnt_tmp;
434 struct elf_resolve *app_tpnt = &app_tpnt_tmp;
435 struct r_debug *debug_addr;
436 unsigned long *lpnt;
437 unsigned long *_dl_envp; /* The environment address */
438 ElfW(Addr) relro_addr = 0;
439 size_t relro_size = 0;
440 struct r_scope_elem *global_scope;
441 struct elf_resolve **local_scope;
443 #if defined(USE_TLS) && USE_TLS
444 void *tcbp = NULL;
445 #endif
447 /* Wahoo!!! We managed to make a function call! Get malloc
448 * setup so we can use _dl_dprintf() to print debug noise
449 * instead of the SEND_STDERR macros used in dl-startup.c */
451 _dl_memset(app_tpnt, 0, sizeof(*app_tpnt));
453 /* Store the page size for later use */
454 _dl_pagesize = (auxvt[AT_PAGESZ].a_un.a_val) ? (size_t) auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE;
455 /* Make it so _dl_malloc can use the page of memory we have already
456 * allocated. We shouldn't need to grab any more memory. This must
457 * be first since things like _dl_dprintf() use _dl_malloc()...
459 _dl_malloc_addr = (unsigned char *)_dl_pagesize;
460 _dl_mmap_zero = 0;
462 /* Wahoo!!! */
463 _dl_debug_early("Cool, ldso survived making function calls\n");
465 /* Now we have done the mandatory linking of some things. We are now
466 * free to start using global variables, since these things have all
467 * been fixed up by now. Still no function calls outside of this
468 * library, since the dynamic resolver is not yet ready.
470 _dl_setup_progname(argv[0]);
472 #ifdef __DSBT__
473 _dl_ldso_dsbt = (void *)tpnt->dynamic_info[DT_DSBT_BASE_IDX];
474 _dl_ldso_dsbt[tpnt->dynamic_info[DT_DSBT_INDEX_IDX]] = _dl_ldso_dsbt;
475 #endif
477 #ifndef __LDSO_STANDALONE_SUPPORT__
478 if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
479 _dl_dprintf(2, "Standalone execution is not enabled\n");
480 _dl_exit(1);
482 #endif
484 /* Start to build the tables of the modules that are required for
485 * this beast to run. We start with the basic executable, and then
486 * go from there. Eventually we will run across ourself, and we
487 * will need to properly deal with that as well.
489 rpnt = NULL;
490 if (_dl_getenv("LD_BIND_NOW", envp))
491 unlazy = RTLD_NOW;
493 /* Now we need to figure out what kind of options are selected.
494 * Note that for SUID programs we ignore the settings in
495 * LD_LIBRARY_PATH.
497 if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && _dl_suid_ok()) ||
498 (auxvt[AT_UID].a_un.a_val != (size_t)-1 &&
499 auxvt[AT_UID].a_un.a_val == auxvt[AT_EUID].a_un.a_val &&
500 auxvt[AT_GID].a_un.a_val == auxvt[AT_EGID].a_un.a_val)) {
501 _dl_secure = 0;
502 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
503 _dl_preload = _dl_getenv("LD_PRELOAD", envp);
504 #endif
505 #ifdef __LDSO_LD_LIBRARY_PATH__
506 _dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp);
507 #endif
508 } else {
509 static const char unsecure_envvars[] =
510 #ifdef EXTRA_UNSECURE_ENVVARS
511 EXTRA_UNSECURE_ENVVARS
512 #endif
513 UNSECURE_ENVVARS;
514 const char *nextp;
515 _dl_secure = 1;
517 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
518 _dl_preload = _dl_getenv("LD_PRELOAD", envp);
519 #endif
520 nextp = unsecure_envvars;
521 do {
522 _dl_unsetenv (nextp, envp);
523 /* We could use rawmemchr but this need not be fast. */
524 nextp = _dl_strchr(nextp, '\0') + 1;
525 } while (*nextp != '\0');
526 #ifdef __LDSO_LD_LIBRARY_PATH__
527 _dl_library_path = NULL;
528 #endif
529 /* SUID binaries can be exploited if they do LAZY relocation. */
530 unlazy = RTLD_NOW;
533 #if defined(USE_TLS) && USE_TLS
534 _dl_error_catch_tsd = &_dl_initial_error_catch_tsd;
535 _dl_init_static_tls = &_dl_nothread_init_static_tls;
536 #endif
538 #ifdef __LDSO_STANDALONE_SUPPORT__
539 if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
540 ElfW(Addr) *aux_dat = (ElfW(Addr) *) argv;
541 int argc = (int) aux_dat[-1];
543 tpnt->libname = argv[0];
544 while (argc > 1)
545 if (! _dl_strcmp (argv[1], "--library-path") && argc > 2) {
546 #ifdef __LDSO_LD_LIBRARY_PATH__
547 _dl_library_path = argv[2];
548 #endif
549 _dl_skip_args += 2;
550 argc -= 2;
551 argv += 2;
552 } else
553 break;
556 * If we have no further argument the program was called incorrectly.
557 * Grant the user some education.
560 if (argc < 2) {
561 _dl_dprintf(1, "\
562 Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\
563 You have invoked `ld.so', the helper program for shared library executables.\n\
564 This program usually lives in the file `/lib/ld.so', and special directives\n\
565 in executable files using ELF shared libraries tell the system's program\n\
566 loader to load the helper program from this file. This helper program loads\n\
567 the shared libraries needed by the program executable, prepares the program\n\
568 to run, and runs it. You may invoke this helper program directly from the\n\
569 command line to load and run an ELF executable file; this is like executing\n\
570 that file itself, but always uses this helper program from the file you\n\
571 specified, instead of the helper program file specified in the executable\n\
572 file you run. This is mostly of use for maintainers to test new versions\n\
573 of this helper program; chances are you did not intend to run this program.\n\
575 --library-path PATH use given PATH instead of content of the environment\n\
576 variable LD_LIBRARY_PATH\n");
577 _dl_exit(1);
580 ++_dl_skip_args;
581 ++argv;
582 _dl_progname = argv[0];
584 _dl_symbol_tables = rpnt = _dl_zalloc(sizeof(struct dyn_elf));
586 * It needs to load the _dl_progname and to map it
587 * Usually it is the main application launched by means of the ld.so
588 * but it could be also a shared object (when ld.so used for tracing)
589 * We keep the misleading app_tpnt name to avoid variable pollution
591 app_tpnt = _dl_load_elf_shared_library(_dl_secure ? __RTLD_SECURE : 0,
592 &rpnt, _dl_progname);
593 if (!app_tpnt) {
594 _dl_dprintf(2, "can't load '%s'\n", _dl_progname);
595 _dl_exit(16);
598 * FIXME: it needs to properly handle a PIE executable
599 * Usually for a main application, loadaddr is computed as difference
600 * between auxvt entry points and phdr, so if it is not 0, that it is a
601 * PIE executable. In this case instead we need to set the loadaddr to 0
602 * because we are actually mapping the ELF for the main application by
603 * ourselves. So the PIE case must be checked.
606 app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
609 * This is used by gdb to locate the chain of shared libraries that are
610 * currently loaded.
612 debug_addr = _dl_zalloc(sizeof(struct r_debug));
613 ppnt = (ElfW(Phdr) *)app_tpnt->ppnt;
614 for (i = 0; i < app_tpnt->n_phent; i++, ppnt++) {
615 if (ppnt->p_type == PT_DYNAMIC) {
616 dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
617 _dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr);
621 _dl_ldsopath_init(tpnt);
622 } else {
623 #endif
625 /* At this point we are now free to examine the user application,
626 * and figure out which libraries are supposed to be called. Until
627 * we have this list, we will not be completely ready for dynamic
628 * linking.
631 /* Find the runtime load address of the main executable. This may be
632 * different from what the ELF header says for ET_DYN/PIE executables.
635 unsigned int idx;
636 ElfW(Phdr) *phdr = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
638 for (idx = 0; idx < auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++)
639 if (phdr->p_type == PT_PHDR) {
640 DL_INIT_LOADADDR_PROG(app_tpnt->loadaddr, auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr);
641 break;
644 if (DL_LOADADDR_BASE(app_tpnt->loadaddr))
645 _dl_debug_early("Position Independent Executable: "
646 "app_tpnt->loadaddr=%x\n", DL_LOADADDR_BASE(app_tpnt->loadaddr));
650 * This is used by gdb to locate the chain of shared libraries that are
651 * currently loaded.
653 debug_addr = _dl_zalloc(sizeof(struct r_debug));
655 ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
656 for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
657 if (ppnt->p_type == PT_GNU_RELRO) {
658 relro_addr = ppnt->p_vaddr;
659 relro_size = ppnt->p_memsz;
661 if (!app_mapaddr && (ppnt->p_type == PT_LOAD)) {
662 app_mapaddr = DL_RELOC_ADDR (app_tpnt->loadaddr, ppnt->p_vaddr);
664 if (ppnt->p_type == PT_DYNAMIC) {
665 dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
666 _dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr);
667 #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
668 /* Ugly, ugly. We need to call mprotect to change the
669 * protection of the text pages so that we can do the
670 * dynamic linking. We can set the protection back
671 * again once we are done.
673 /* Now cover the application program. */
674 if (app_tpnt->dynamic_info[DT_TEXTREL]) {
675 int j;
676 ElfW(Phdr) *ppnt_outer = ppnt;
677 _dl_debug_early("calling mprotect on the application program\n");
678 ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
679 for (j = 0; j < auxvt[AT_PHNUM].a_un.a_val; j++, ppnt++) {
680 if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))
681 _dl_mprotect((void *) (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & PAGE_ALIGN),
682 (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & ADDR_ALIGN) +
683 (unsigned long) ppnt->p_filesz,
684 PROT_READ | PROT_WRITE | PROT_EXEC);
686 ppnt = ppnt_outer;
688 #else
689 if (app_tpnt->dynamic_info[DT_TEXTREL]) {
690 _dl_dprintf(2, "Can't modify application's text section; use the GCC option -fPIE for position-independent executables.\n");
691 _dl_exit(1);
693 #endif
695 #ifndef ALLOW_ZERO_PLTGOT
696 /* make sure it's really there. */
697 if (app_tpnt->dynamic_info[DT_PLTGOT] == 0)
698 continue;
699 #endif
700 /* OK, we have what we need - slip this one into the list. */
701 app_tpnt = _dl_add_elf_hash_table(_dl_progname, app_tpnt->loadaddr,
702 app_tpnt->dynamic_info,
703 (unsigned long) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr),
704 ppnt->p_filesz);
705 _dl_loaded_modules->libtype = elf_executable;
706 _dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
707 _dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val;
708 _dl_symbol_tables = rpnt = _dl_zalloc(sizeof(struct dyn_elf));
709 rpnt->dyn = _dl_loaded_modules;
710 app_tpnt->mapaddr = app_mapaddr;
711 app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
712 app_tpnt->usage_count++;
713 #ifdef __DSBT__
714 _dl_ldso_dsbt[0] = app_tpnt->dsbt_table;
715 _dl_memcpy(app_tpnt->dsbt_table, _dl_ldso_dsbt,
716 app_tpnt->dsbt_size * sizeof(tpnt->dsbt_table[0]));
717 #endif
718 lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]);
719 #ifdef ALLOW_ZERO_PLTGOT
720 if (lpnt)
721 #endif
722 INIT_GOT(lpnt, _dl_loaded_modules);
725 /* OK, fill this in - we did not have this before */
726 if (ppnt->p_type == PT_INTERP) {
727 tpnt->libname = (char *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
729 _dl_ldsopath_init(tpnt);
732 /* Discover any TLS sections if the target supports them. */
733 if (ppnt->p_type == PT_TLS) {
734 #if defined(USE_TLS) && USE_TLS
735 if (ppnt->p_memsz > 0) {
736 app_tpnt->l_tls_blocksize = ppnt->p_memsz;
737 app_tpnt->l_tls_align = ppnt->p_align;
738 if (ppnt->p_align == 0)
739 app_tpnt->l_tls_firstbyte_offset = 0;
740 else
741 app_tpnt->l_tls_firstbyte_offset =
742 (ppnt->p_vaddr & (ppnt->p_align - 1));
743 app_tpnt->l_tls_initimage_size = ppnt->p_filesz;
744 app_tpnt->l_tls_initimage = (void *) ppnt->p_vaddr;
746 /* This image gets the ID one. */
747 _dl_tls_max_dtv_idx = app_tpnt->l_tls_modid = 1;
750 _dl_debug_early("Found TLS header for application program\n");
751 break;
752 #else
753 _dl_dprintf(2, "Program uses unsupported TLS data!\n");
754 _dl_exit(1);
755 #endif
758 app_tpnt->relro_addr = relro_addr;
759 app_tpnt->relro_size = relro_size;
761 #if defined(USE_TLS) && USE_TLS
763 * Adjust the address of the TLS initialization image in
764 * case the executable is actually an ET_DYN object.
766 if (app_tpnt->l_tls_initimage != NULL) {
767 char *tmp attribute_unused =
768 (char *) app_tpnt->l_tls_initimage;
769 app_tpnt->l_tls_initimage =
770 (char *) app_tpnt->l_tls_initimage + app_tpnt->loadaddr;
771 _dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n",
772 tmp, app_tpnt->l_tls_initimage, app_tpnt->l_tls_initimage_size);
774 #endif
776 #ifdef __LDSO_STANDALONE_SUPPORT__
777 } /* ! ldso standalone mode */
778 #endif
780 #ifdef __SUPPORT_LD_DEBUG__
781 _dl_debug = _dl_getenv("LD_DEBUG", envp);
782 if (_dl_debug) {
783 if (_dl_strstr(_dl_debug, "all")) {
784 _dl_debug_detail = _dl_debug_move = _dl_debug_symbols
785 = _dl_debug_reloc = _dl_debug_bindings = _dl_debug_nofixups = (void*)1;
786 } else {
787 _dl_debug_detail = _dl_strstr(_dl_debug, "detail");
788 _dl_debug_move = _dl_strstr(_dl_debug, "move");
789 _dl_debug_symbols = _dl_strstr(_dl_debug, "sym");
790 _dl_debug_reloc = _dl_strstr(_dl_debug, "reloc");
791 _dl_debug_nofixups = _dl_strstr(_dl_debug, "nofix");
792 _dl_debug_bindings = _dl_strstr(_dl_debug, "bind");
797 const char *dl_debug_output;
799 dl_debug_output = _dl_getenv("LD_DEBUG_OUTPUT", envp);
801 if (dl_debug_output) {
802 char tmp[22], *tmp1, *filename;
803 int len1, len2;
805 _dl_memset(tmp, 0, sizeof(tmp));
806 tmp1 = _dl_simple_ltoa( tmp, (unsigned long)_dl_getpid());
808 len1 = _dl_strlen(dl_debug_output);
809 len2 = _dl_strlen(tmp1);
811 filename = _dl_malloc(len1 + len2 + 2);
813 if (filename) {
814 _dl_strcpy (filename, dl_debug_output);
815 filename[len1] = '.';
816 _dl_strcpy (&filename[len1+1], tmp1);
818 _dl_debug_file = _dl_open(filename, O_WRONLY|O_CREAT, 0644);
819 if (_dl_debug_file < 0) {
820 _dl_debug_file = 2;
821 _dl_dprintf(_dl_debug_file, "can't open file: '%s'\n",filename);
826 #endif
828 #ifdef __LDSO_PRELINK_SUPPORT__
830 char *ld_warn = _dl_getenv ("LD_WARN", envp);
832 if (ld_warn && *ld_warn == '\0')
833 _dl_verbose = false;
835 _dl_trace_prelink = _dl_getenv("LD_TRACE_PRELINKING", envp);
836 #endif
838 if (_dl_getenv("LD_TRACE_LOADED_OBJECTS", envp) != NULL) {
839 trace_loaded_objects++;
842 #ifndef __LDSO_LDD_SUPPORT__
843 if (trace_loaded_objects) {
844 _dl_dprintf(2, "Use the ldd provided by uClibc\n");
845 _dl_exit(1);
847 #endif
849 ldso_mapaddr = (ElfW(Addr)) auxvt[AT_BASE].a_un.a_val;
851 * OK, fix one more thing - set up debug_addr so it will point
852 * to our chain. Later we may need to fill in more fields, but this
853 * should be enough for now.
855 debug_addr->r_map = (struct link_map *) _dl_loaded_modules;
856 debug_addr->r_version = 1;
857 debug_addr->r_ldbase = (ElfW(Addr))
858 DL_LOADADDR_BASE(DL_GET_RUN_ADDR(load_addr, ldso_mapaddr));
859 debug_addr->r_brk = (unsigned long) &_dl_debug_state;
860 _dl_debug_addr = debug_addr;
862 /* Do not notify the debugger until the interpreter is in the list */
864 /* OK, we now have the application in the list, and we have some
865 * basic stuff in place. Now search through the list for other shared
866 * libraries that should be loaded, and insert them on the list in the
867 * correct order.
870 _dl_map_cache();
872 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
873 if (_dl_preload) {
874 char c, *str, *str2;
876 str = _dl_preload;
877 while (*str == ':' || *str == ' ' || *str == '\t')
878 str++;
880 while (*str) {
881 str2 = str;
882 while (*str2 && *str2 != ':' && *str2 != ' ' && *str2 != '\t')
883 str2++;
884 c = *str2;
885 *str2 = '\0';
887 if (!_dl_secure || _dl_strchr(str, '/') == NULL) {
888 _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", str, _dl_progname);
890 tpnt1 = _dl_load_shared_library(
891 _dl_secure ? __RTLD_SECURE : 0,
892 &rpnt, NULL, str, trace_loaded_objects);
893 if (!tpnt1) {
894 #ifdef __LDSO_LDD_SUPPORT__
895 if (trace_loaded_objects || _dl_trace_prelink)
896 _dl_dprintf(1, "\t%s => not found\n", str);
897 else
898 #endif
900 _dl_dprintf(2, "%s: library '%s' "
901 "from LD_PRELOAD can't be preloaded: ignored.\n",
902 _dl_progname, str);
904 } else {
905 tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
907 _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
909 #ifdef __LDSO_LDD_SUPPORT__
910 if (trace_loaded_objects && !_dl_trace_prelink &&
911 !(tpnt1->init_flag & DL_OPENED2)) {
912 /* This is a real hack to make
913 * ldd not print the library
914 * itself when run on a
915 * library.
917 if (_dl_strcmp(_dl_progname, str) != 0)
918 _dl_dprintf(1, "\t%s => %s (%x)\n", str, tpnt1->libname,
919 DL_LOADADDR_BASE(tpnt1->loadaddr));
921 #endif
925 *str2 = c;
926 str = str2;
927 while (*str == ':' || *str == ' ' || *str == '\t')
928 str++;
931 #endif /* __LDSO_PRELOAD_ENV_SUPPORT__ */
933 #ifdef __LDSO_PRELOAD_FILE_SUPPORT__
934 do {
935 char *preload;
936 int fd;
937 char c, *cp, *cp2;
938 struct stat st;
940 if (_dl_stat(LDSO_PRELOAD, &st) || st.st_size == 0) {
941 break;
944 if ((fd = _dl_open(LDSO_PRELOAD, O_RDONLY, 0)) < 0) {
945 _dl_dprintf(2, "%s: can't open file '%s'\n",
946 _dl_progname, LDSO_PRELOAD);
947 break;
950 preload = (caddr_t) _dl_mmap(0, st.st_size + 1,
951 PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
952 _dl_close(fd);
953 if (preload == (caddr_t) -1) {
954 _dl_dprintf(2, "%s:%i: can't map '%s'\n",
955 _dl_progname, __LINE__, LDSO_PRELOAD);
956 break;
959 /* convert all separators and comments to spaces */
960 for (cp = preload; *cp; /*nada */ ) {
961 if (*cp == ':' || *cp == '\t' || *cp == '\n') {
962 *cp++ = ' ';
963 } else if (*cp == '#') {
964 do {
965 *cp++ = ' ';
966 } while (*cp != '\n' && *cp != '\0');
967 } else {
968 cp++;
972 /* find start of first library */
973 for (cp = preload; *cp && *cp == ' '; cp++)
974 /*nada */ ;
976 while (*cp) {
977 /* find end of library */
978 for (cp2 = cp; *cp && *cp != ' '; cp++)
979 /*nada */ ;
980 c = *cp;
981 *cp = '\0';
983 _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", cp2, _dl_progname);
985 tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2, trace_loaded_objects);
986 if (!tpnt1) {
987 # ifdef __LDSO_LDD_SUPPORT__
988 if (trace_loaded_objects || _dl_trace_prelink)
989 _dl_dprintf(1, "\t%s => not found\n", cp2);
990 else
991 # endif
993 _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, cp2);
994 _dl_exit(15);
996 } else {
997 tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
999 _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
1001 # ifdef __LDSO_LDD_SUPPORT__
1002 if (trace_loaded_objects && !_dl_trace_prelink &&
1003 !(tpnt1->init_flag & DL_OPENED2)) {
1004 _dl_dprintf(1, "\t%s => %s (%x)\n",
1005 cp2, tpnt1->libname,
1006 DL_LOADADDR_BASE(tpnt1->loadaddr));
1008 # endif
1011 /* find start of next library */
1012 *cp = c;
1013 for ( /*nada */ ; *cp && *cp == ' '; cp++)
1014 /*nada */ ;
1017 _dl_munmap(preload, st.st_size + 1);
1018 } while (0);
1019 #endif /* __LDSO_PRELOAD_FILE_SUPPORT__ */
1021 nlist = 0;
1022 for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) {
1023 ElfW(Dyn) *this_dpnt;
1025 nlist++;
1026 for (this_dpnt = (ElfW(Dyn) *) tcurr->dynamic_addr; this_dpnt->d_tag; this_dpnt++) {
1027 if (this_dpnt->d_tag == DT_NEEDED) {
1028 char *name;
1029 struct init_fini_list *tmp;
1031 lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + this_dpnt->d_un.d_val);
1032 name = _dl_get_last_path_component(lpntstr);
1033 _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", lpntstr, _dl_progname);
1035 if (_dl_strcmp(name, UCLIBC_LDSO) == 0) {
1036 if (!ldso_tpnt) {
1037 /* Insert the ld.so only once */
1038 ldso_tpnt = add_ldso(tpnt, load_addr,
1039 ldso_mapaddr, auxvt, rpnt);
1040 } else {
1041 ldso_tpnt->init_flag |= DL_OPENED2;
1043 ldso_tpnt->usage_count++;
1044 tpnt1 = ldso_tpnt;
1045 } else
1046 tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects);
1048 if (!tpnt1) {
1049 #ifdef __LDSO_LDD_SUPPORT__
1050 if (trace_loaded_objects || _dl_trace_prelink) {
1051 _dl_dprintf(1, "\t%s => not found\n", lpntstr);
1052 continue;
1053 } else
1054 #endif
1056 _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, lpntstr);
1057 _dl_exit(16);
1061 tmp = alloca(sizeof(struct init_fini_list)); /* Allocates on stack, no need to free this memory */
1062 tmp->tpnt = tpnt1;
1063 tmp->next = tcurr->init_fini;
1064 tcurr->init_fini = tmp;
1066 tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
1068 _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
1070 #ifdef __LDSO_LDD_SUPPORT__
1071 if (trace_loaded_objects && !_dl_trace_prelink &&
1072 !(tpnt1->init_flag & DL_OPENED2)) {
1073 _dl_dprintf(1, "\t%s => %s (%x)\n",
1074 lpntstr, tpnt1->libname,
1075 DL_LOADADDR_BASE(tpnt1->loadaddr));
1077 #endif
1081 _dl_unmap_cache();
1083 /* Keep track of the number of elements in the global scope */
1084 nscope_elem = nlist;
1086 if (_dl_loaded_modules->libtype == elf_executable) {
1087 --nlist; /* Exclude the application. */
1088 tcurr = _dl_loaded_modules->next;
1089 } else
1090 tcurr = _dl_loaded_modules;
1091 init_fini_list = _dl_malloc(nlist * sizeof(struct elf_resolve *));
1092 i = 0;
1093 for (; tcurr; tcurr = tcurr->next)
1094 init_fini_list[i++] = tcurr;
1096 /* Sort the INIT/FINI list in dependency order. */
1097 for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
1098 unsigned int j, k;
1100 for (j = 0; init_fini_list[j] != tcurr; ++j)
1101 /* Empty */;
1102 for (k = j + 1; k < nlist; ++k) {
1103 struct init_fini_list *runp = init_fini_list[k]->init_fini;
1105 for (; runp; runp = runp->next) {
1106 if (runp->tpnt == tcurr) {
1107 struct elf_resolve *here = init_fini_list[k];
1108 _dl_if_debug_dprint("Move %s from pos %d to %d in INIT/FINI list\n", here->libname, k, j);
1109 for (i = (k - j); i; --i)
1110 init_fini_list[i+j] = init_fini_list[i+j-1];
1111 init_fini_list[j] = here;
1112 ++j;
1113 break;
1118 #ifdef __SUPPORT_LD_DEBUG__
1119 if (_dl_debug) {
1120 _dl_dprintf(_dl_debug_file, "\nINIT/FINI order and dependencies:\n");
1121 for (i = 0; i < nlist; i++) {
1122 struct init_fini_list *tmp;
1124 _dl_dprintf(_dl_debug_file, "lib: %s has deps:\n",
1125 init_fini_list[i]->libname);
1126 tmp = init_fini_list[i]->init_fini;
1127 for (; tmp; tmp = tmp->next)
1128 _dl_dprintf(_dl_debug_file, " %s ", tmp->tpnt->libname);
1129 _dl_dprintf(_dl_debug_file, "\n");
1132 #endif
1135 * If the program interpreter is not in the module chain, add it.
1136 * This will be required for dlopen to be able to access the internal
1137 * functions in the dynamic linker and to relocate the interpreter
1138 * again once all libs are loaded.
1140 if (!ldso_tpnt) {
1141 tpnt = add_ldso(tpnt, load_addr, ldso_mapaddr, auxvt, rpnt);
1142 tpnt->usage_count++;
1143 nscope_elem++;
1144 } else
1145 tpnt = ldso_tpnt;
1147 #ifdef RERELOCATE_LDSO
1148 /* Only rerelocate functions for now. */
1149 tpnt->init_flag = RELOCS_DONE;
1150 lpnt = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT]);
1151 # ifdef ALLOW_ZERO_PLTGOT
1152 if (tpnt->dynamic_info[DT_PLTGOT])
1153 # endif
1154 INIT_GOT(lpnt, tpnt);
1155 #else
1156 tpnt->init_flag = RELOCS_DONE | JMP_RELOCS_DONE;
1157 #endif
1158 tpnt = NULL;
1161 * Allocate the global scope array.
1163 scope_elem_list = (struct elf_resolve **) _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
1165 for (i = 0, tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next)
1166 scope_elem_list[i++] = tcurr;
1168 _dl_loaded_modules->symbol_scope.r_list = scope_elem_list;
1169 _dl_loaded_modules->symbol_scope.r_nlist = nscope_elem;
1171 * The symbol scope of the application, that is the first entry of the
1172 * _dl_loaded_modules list, is just the global scope to be used for the
1173 * symbol lookup.
1175 global_scope = &_dl_loaded_modules->symbol_scope;
1177 /* Build the local scope for each loaded modules. */
1178 local_scope = _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
1179 i = 1;
1180 for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
1181 unsigned int k;
1182 cnt = _dl_build_local_scope(local_scope, scope_elem_list[i++]);
1183 tcurr->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *));
1184 tcurr->symbol_scope.r_nlist = cnt;
1185 _dl_memcpy (tcurr->symbol_scope.r_list, local_scope, cnt * sizeof (struct elf_resolve *));
1186 /* Restoring the init_flag.*/
1187 for (k = 1; k < nscope_elem; k++)
1188 scope_elem_list[k]->init_flag &= ~DL_RESERVED;
1191 _dl_free(local_scope);
1193 #ifdef __LDSO_LDD_SUPPORT__
1194 /* Exit if LD_TRACE_LOADED_OBJECTS is on. */
1195 if (trace_loaded_objects && !_dl_trace_prelink)
1196 _dl_exit(0);
1197 #endif
1199 #if defined(USE_TLS) && USE_TLS
1200 /* We do not initialize any of the TLS functionality unless any of the
1201 * initial modules uses TLS. This makes dynamic loading of modules with
1202 * TLS impossible, but to support it requires either eagerly doing setup
1203 * now or lazily doing it later. Doing it now makes us incompatible with
1204 * an old kernel that can't perform TLS_INIT_TP, even if no TLS is ever
1205 * used. Trying to do it lazily is too hairy to try when there could be
1206 * multiple threads (from a non-TLS-using libpthread). */
1207 bool was_tls_init_tp_called = tls_init_tp_called;
1208 if (tcbp == NULL) {
1209 _dl_debug_early("Calling init_tls()!\n");
1210 tcbp = init_tls ();
1212 #endif
1213 #ifdef __UCLIBC_HAS_SSP__
1214 _dl_debug_early("Setting up SSP guards\n");
1215 /* Set up the stack checker's canary. */
1216 stack_chk_guard = _dl_setup_stack_chk_guard ();
1217 # ifdef THREAD_SET_STACK_GUARD
1218 THREAD_SET_STACK_GUARD (stack_chk_guard);
1219 # else
1220 __stack_chk_guard = stack_chk_guard;
1221 # endif
1222 #endif
1224 #ifdef __LDSO_PRELINK_SUPPORT__
1225 if (_dl_trace_prelink) {
1227 unsigned int nscope_trace = ldso_tpnt ? nscope_elem : (nscope_elem - 1);
1229 for (i = 0; i < nscope_trace; i++)
1230 trace_objects(scope_elem_list[i],
1231 _dl_get_last_path_component(scope_elem_list[i]->libname));
1233 if (_dl_verbose)
1234 /* Warn about undefined symbols. */
1235 if (_dl_symbol_tables)
1236 if (_dl_fixup(_dl_symbol_tables, global_scope, unlazy))
1237 _dl_exit(-1);
1238 _dl_exit(0);
1241 if (_dl_loaded_modules->dynamic_info[DT_GNU_LIBLIST_IDX]) {
1242 ElfW(Lib) *liblist, *liblistend;
1243 struct elf_resolve **r_list, **r_listend, *l;
1244 const char *strtab = (const char *)_dl_loaded_modules->dynamic_info[DT_STRTAB];
1246 _dl_assert (_dl_loaded_modules->dynamic_info[DT_GNU_LIBLISTSZ_IDX] != 0);
1247 liblist = (ElfW(Lib) *) _dl_loaded_modules->dynamic_info[DT_GNU_LIBLIST_IDX];
1248 liblistend = (ElfW(Lib) *)
1249 ((char *) liblist + _dl_loaded_modules->dynamic_info[DT_GNU_LIBLISTSZ_IDX]);
1250 r_list = _dl_loaded_modules->symbol_scope.r_list;
1251 r_listend = r_list + nscope_elem;
1253 for (; r_list < r_listend && liblist < liblistend; r_list++) {
1254 l = *r_list;
1256 if (l == _dl_loaded_modules)
1257 continue;
1259 /* If the library is not mapped where it should, fail. */
1260 if (l->loadaddr)
1261 break;
1263 /* Next, check if checksum matches. */
1264 if (l->dynamic_info[DT_CHECKSUM_IDX] == 0 ||
1265 l->dynamic_info[DT_CHECKSUM_IDX] != liblist->l_checksum)
1266 break;
1268 if (l->dynamic_info[DT_GNU_PRELINKED_IDX] == 0 ||
1269 (l->dynamic_info[DT_GNU_PRELINKED_IDX] != liblist->l_time_stamp))
1270 break;
1272 if (_dl_strcmp(strtab + liblist->l_name, _dl_get_last_path_component(l->libname)) != 0)
1273 break;
1275 ++liblist;
1279 if (r_list == r_listend && liblist == liblistend)
1280 prelinked = true;
1284 _dl_debug_early ("prelink checking: %s\n", prelinked ? "ok" : "failed");
1286 if (prelinked) {
1287 if (_dl_loaded_modules->dynamic_info[DT_GNU_CONFLICT_IDX]) {
1288 ELF_RELOC *conflict;
1289 unsigned long conflict_size;
1291 _dl_assert (_dl_loaded_modules->dynamic_info[DT_GNU_CONFLICTSZ_IDX] != 0);
1292 conflict = (ELF_RELOC *) _dl_loaded_modules->dynamic_info[DT_GNU_CONFLICT_IDX];
1293 conflict_size = _dl_loaded_modules->dynamic_info[DT_GNU_CONFLICTSZ_IDX];
1294 _dl_parse_relocation_information(_dl_symbol_tables, global_scope,
1295 (unsigned long) conflict, conflict_size);
1298 /* Mark all the objects so we know they have been already relocated. */
1299 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
1300 tpnt->init_flag |= RELOCS_DONE;
1301 if (tpnt->relro_size)
1302 _dl_protect_relro (tpnt);
1304 } else
1305 #endif
1309 _dl_debug_early("Beginning relocation fixups\n");
1311 #ifdef __mips__
1313 * Relocation of the GOT entries for MIPS have to be done
1314 * after all the libraries have been loaded.
1316 _dl_perform_mips_global_got_relocations(_dl_loaded_modules, !unlazy);
1317 #endif
1320 * OK, now all of the kids are tucked into bed in their proper
1321 * addresses. Now we go through and look for REL and RELA records that
1322 * indicate fixups to the GOT tables. We need to do this in reverse
1323 * order so that COPY directives work correctly.
1325 if (_dl_symbol_tables)
1326 if (_dl_fixup(_dl_symbol_tables, global_scope, unlazy))
1327 _dl_exit(-1);
1329 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
1330 if (tpnt->relro_size)
1331 _dl_protect_relro (tpnt);
1333 } /* not prelinked */
1335 #if defined(USE_TLS) && USE_TLS
1336 if (!was_tls_init_tp_called && _dl_tls_max_dtv_idx > 0)
1337 ++_dl_tls_generation;
1339 _dl_debug_early("Calling _dl_allocate_tls_init()!\n");
1341 /* Now that we have completed relocation, the initializer data
1342 for the TLS blocks has its final values and we can copy them
1343 into the main thread's TLS area, which we allocated above. */
1344 _dl_allocate_tls_init (tcbp);
1346 /* And finally install it for the main thread. If ld.so itself uses
1347 TLS we know the thread pointer was initialized earlier. */
1348 if (! tls_init_tp_called) {
1349 const char *lossage = (char *) TLS_INIT_TP (tcbp, USE___THREAD);
1350 if (__builtin_expect (lossage != NULL, 0)) {
1351 _dl_debug_early("cannot set up thread-local storage: %s\n", lossage);
1352 _dl_exit(30);
1355 #endif /* USE_TLS */
1357 /* OK, at this point things are pretty much ready to run. Now we need
1358 * to touch up a few items that are required, and then we can let the
1359 * user application have at it. Note that the dynamic linker itself
1360 * is not guaranteed to be fully dynamicly linked if we are using
1361 * ld.so.1, so we have to look up each symbol individually.
1364 _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", global_scope, NULL, 0, NULL);
1365 if (_dl_envp)
1366 *_dl_envp = (unsigned long) envp;
1368 #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
1370 unsigned int j;
1371 ElfW(Phdr) *myppnt;
1373 /* We had to set the protections of all pages to R/W for
1374 * dynamic linking. Set text pages back to R/O.
1376 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
1377 for (myppnt = tpnt->ppnt, j = 0; j < tpnt->n_phent; j++, myppnt++) {
1378 if (myppnt->p_type == PT_LOAD && !(myppnt->p_flags & PF_W) && tpnt->dynamic_info[DT_TEXTREL]) {
1379 _dl_mprotect((void *) (DL_RELOC_ADDR(tpnt->loadaddr, myppnt->p_vaddr) & PAGE_ALIGN),
1380 (myppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) myppnt->p_filesz, LXFLAGS(myppnt->p_flags));
1386 #endif
1387 /* Notify the debugger we have added some objects. */
1388 _dl_debug_addr->r_state = RT_ADD;
1389 _dl_debug_state();
1391 /* Run pre-initialization functions for the executable. */
1392 _dl_run_array_forward(_dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAY],
1393 _dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAYSZ],
1394 _dl_loaded_modules->loadaddr);
1396 /* Run initialization functions for loaded objects. For the
1397 main executable, they will be run from __uClibc_main. */
1398 for (i = nlist; i; --i) {
1399 tpnt = init_fini_list[i-1];
1400 tpnt->init_fini = NULL; /* Clear, since alloca was used */
1401 if (tpnt->init_flag & INIT_FUNCS_CALLED)
1402 continue;
1403 tpnt->init_flag |= INIT_FUNCS_CALLED;
1405 if (tpnt->dynamic_info[DT_INIT]) {
1406 void (*dl_elf_func) (void);
1408 dl_elf_func = (void (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_INIT]);
1410 _dl_if_debug_dprint("calling INIT: %s\n\n", tpnt->libname);
1412 DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
1415 _dl_run_init_array(tpnt);
1418 /* Find the real malloc function and make ldso functions use that from now on */
1419 _dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "malloc",
1420 global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1422 #if defined(USE_TLS) && USE_TLS
1423 /* Find the real functions and make ldso functions use them from now on */
1424 _dl_calloc_function = (void* (*)(size_t, size_t)) (intptr_t)
1425 _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1427 _dl_realloc_function = (void* (*)(void *, size_t)) (intptr_t)
1428 _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1430 _dl_free_function = (void (*)(void *)) (intptr_t)
1431 _dl_find_hash(__C_SYMBOL_PREFIX__ "free", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1433 _dl_memalign_function = (void* (*)(size_t, size_t)) (intptr_t)
1434 _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1436 #endif
1438 /* Notify the debugger that all objects are now mapped in. */
1439 _dl_debug_addr->r_state = RT_CONSISTENT;
1440 _dl_debug_state();
1442 #ifdef __LDSO_STANDALONE_SUPPORT__
1443 if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val)
1444 return (void *) app_tpnt->l_entry;
1445 else
1446 #endif
1447 return (void *) auxvt[AT_ENTRY].a_un.a_val;
1450 #include "dl-hash.c"
1451 #include "dl-elf.c"