1 /* vi: set sw=4 ts=4: */
3 * Program to load an ELF binary on a linux system, and run it
4 * after resolving ELF shared library symbols
6 * Copyright (C) 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
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
34 #include "unsecvars.h"
36 /* Pull in common debug code */
39 #define ALLOW_ZERO_PLTGOT
41 #if defined(USE_TLS) && USE_TLS
45 /* Pull in the value of _dl_progname */
46 #include LDSO_ELFINTERP
48 /* Global variables used within the shared library loader */
49 char *_dl_library_path = NULL; /* Where we look for libraries */
50 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
51 char *_dl_preload = NULL; /* Things to be loaded before the libs */
53 char *_dl_ldsopath = NULL; /* Location of the shared lib loader */
54 int _dl_errno = 0; /* We can't use the real errno in ldso */
55 size_t _dl_pagesize = 0; /* Store the page size for use later */
56 struct r_debug *_dl_debug_addr = NULL; /* Used to communicate with the gdb debugger */
57 void *(*_dl_malloc_function) (size_t size) = NULL;
58 void (*_dl_free_function) (void *p) = NULL;
60 #ifdef __LDSO_PRELINK_SUPPORT__
61 char *_dl_trace_prelink = NULL; /* Library for prelinking trace */
62 struct elf_resolve *_dl_trace_prelink_map = NULL; /* Library module for prelinking trace */
63 bool _dl_verbose = true; /* On by default */
64 bool prelinked = false;
66 static int _dl_secure = 1; /* Are we dealing with setuid stuff? */
68 #ifdef __SUPPORT_LD_DEBUG__
69 char *_dl_debug = NULL;
70 char *_dl_debug_symbols = NULL;
71 char *_dl_debug_move = NULL;
72 char *_dl_debug_reloc = NULL;
73 char *_dl_debug_detail = NULL;
74 char *_dl_debug_nofixups = NULL;
75 char *_dl_debug_bindings = NULL;
76 int _dl_debug_file = 2;
79 #if defined (__LDSO_STANDALONE_SUPPORT__) && defined (__sh__)
80 /* Not hidden, needed for standalone execution. */
82 * FIXME: align dl_start for SH to other archs so that we can keep this symbol
83 * hidden and we don't need to handle in __uClibc_main
86 unsigned long _dl_skip_args = 0;
88 unsigned long attribute_hidden _dl_skip_args = 0;
91 const char *_dl_progname = UCLIBC_LDSO; /* The name of the executable being run */
92 #include "dl-startup.c"
93 #include "dl-symbols.c"
97 * This stub function is used by some debuggers. The idea is that they
98 * can set an internal breakpoint on it, so that we are notified when the
99 * address mapping is changed in some way.
101 void _dl_debug_state(void);
102 rtld_hidden_proto(_dl_debug_state, noinline);
103 void _dl_debug_state(void)
105 /* Make sure GCC doesn't recognize this function as pure, to avoid
106 * having the calls optimized away.
110 rtld_hidden_def(_dl_debug_state);
112 static unsigned char *_dl_malloc_addr = NULL; /* Lets _dl_malloc use the already allocated memory page */
113 static unsigned char *_dl_mmap_zero = NULL; /* Also used by _dl_malloc */
115 static struct elf_resolve **init_fini_list;
116 static struct elf_resolve **scope_elem_list;
117 static unsigned int nlist; /* # items in init_fini_list */
118 extern void _start(void);
120 #ifdef __UCLIBC_HAS_SSP__
121 # include <dl-osinfo.h>
122 static uintptr_t stack_chk_guard;
123 # ifndef THREAD_SET_STACK_GUARD
124 /* Only exported for architectures that don't store the stack guard canary
125 * in local thread area. */
126 uintptr_t __stack_chk_guard attribute_relro;
128 # ifdef __UCLIBC_HAS_SSP_COMPAT__
129 uintptr_t __guard attribute_relro;
133 char *_dl_getenv(const char *symbol, char **envp)
138 while ((pnt = *envp++)) {
140 while (*pnt && *pnt == *pnt1)
142 if (!*pnt || *pnt != '=' || *pnt1)
149 void _dl_unsetenv(const char *symbol, char **envp)
153 char **newenvp = envp;
155 for (pnt = *envp; pnt; pnt = *++envp) {
157 while (*pnt && *pnt == *pnt1)
159 if (!*pnt || *pnt != '=' || *pnt1)
166 static int _dl_suid_ok(void)
168 __kernel_uid_t uid, euid;
169 __kernel_gid_t gid, egid;
172 euid = _dl_geteuid();
174 egid = _dl_getegid();
176 if (uid == euid && gid == egid) {
182 void *_dl_malloc(size_t size)
187 _dl_debug_early("request for %d bytes\n", size);
190 if (_dl_malloc_function)
191 return (*_dl_malloc_function) (size);
193 if (_dl_malloc_addr - _dl_mmap_zero + size > _dl_pagesize) {
196 /* Since the above assumes we get a full page even if
197 we request less than that, make sure we request a
198 full page, since uClinux may give us less than than
199 a full page. We might round even
200 larger-than-a-page sizes, but we end up never
201 reusing _dl_mmap_zero/_dl_malloc_addr in that case,
204 The actual page size doesn't really matter; as long
205 as we're self-consistent here, we're safe. */
206 if (size < _dl_pagesize)
207 rounded_size = (size + ADDR_ALIGN) & _dl_pagesize;
211 _dl_debug_early("mmapping more memory\n");
212 _dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, rounded_size,
213 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZE, -1, 0);
214 if (_dl_mmap_check_error(_dl_mmap_zero)) {
215 _dl_dprintf(_dl_debug_file, "%s: mmap of a spare page failed!\n", _dl_progname);
219 retval = _dl_malloc_addr;
220 _dl_malloc_addr += size;
223 * Align memory to DL_MALLOC_ALIGN byte boundary. Some
224 * platforms require this, others simply get better
227 _dl_malloc_addr = (unsigned char *) (((unsigned long) _dl_malloc_addr + DL_MALLOC_ALIGN - 1) & ~(DL_MALLOC_ALIGN - 1));
231 static void *_dl_zalloc(size_t size)
233 void *p = _dl_malloc(size);
235 _dl_memset(p, 0, size);
239 void _dl_free(void *p)
241 if (_dl_free_function)
242 (*_dl_free_function) (p);
245 #if defined(USE_TLS) && USE_TLS
246 void *_dl_memalign(size_t __boundary, size_t __size)
253 if (_dl_memalign_function)
254 return (*_dl_memalign_function) (__boundary, __size);
256 while (rounded < __boundary) {
257 rounded = (1 << i++);
260 delta = (((size_t) _dl_malloc_addr + __size) & (rounded - 1));
262 if ((result = _dl_malloc(rounded - delta)) == NULL)
265 result = _dl_malloc(__size);
271 static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void)
274 struct elf_resolve * tpnt;
276 for (i = 0; i < nlist; ++i) {
277 tpnt = init_fini_list[i];
278 if (tpnt->init_flag & FINI_FUNCS_CALLED)
280 tpnt->init_flag |= FINI_FUNCS_CALLED;
281 _dl_run_fini_array(tpnt);
282 if (tpnt->dynamic_info[DT_FINI]) {
283 void (*dl_elf_func) (void);
285 dl_elf_func = (void (*)(void)) (intptr_t) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI]);
286 _dl_if_debug_dprint("\ncalling FINI: %s\n\n", tpnt->libname);
287 DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
292 #ifdef __LDSO_PRELINK_SUPPORT__
293 static void trace_objects(struct elf_resolve *tpnt, char *str_name)
295 if (_dl_strcmp(_dl_trace_prelink, tpnt->libname) == 0)
296 _dl_trace_prelink_map = tpnt;
297 if (tpnt->libtype == elf_executable) {
298 /* Main executeble */
299 _dl_dprintf(1, "\t%s => %s (%x, %x)", tpnt->libname, tpnt->libname,
300 tpnt->mapaddr, DL_LOADADDR_BASE(tpnt->loadaddr));
302 /* Preloaded, Needed or interpreter */
303 _dl_dprintf(1, "\t%s => %s (%x, %x)", str_name, tpnt->libname,
304 tpnt->mapaddr, DL_LOADADDR_BASE(tpnt->loadaddr));
307 if ((tpnt->libtype != program_interpreter) && (tpnt->l_tls_modid))
308 _dl_dprintf (1, " TLS(%x, %x)\n", tpnt->l_tls_modid,
309 (size_t) tpnt->l_tls_offset);
311 _dl_dprintf (1, "\n");
315 static struct elf_resolve * add_ldso(struct elf_resolve *tpnt,
316 DL_LOADADDR_TYPE load_addr,
317 ElfW(auxv_t) auxvt[AT_EGID + 1],
318 struct dyn_elf *rpnt)
320 ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
321 ElfW(Phdr) *myppnt = (ElfW(Phdr) *)
322 DL_RELOC_ADDR(load_addr, epnt->e_phoff);
326 tpnt = _dl_add_elf_hash_table(tpnt->libname, tpnt->loadaddr,
327 tpnt->dynamic_info, (unsigned long)tpnt->dynamic_addr,
330 tpnt->mapaddr = load_addr;
331 if (_dl_stat(tpnt->libname, &st) >= 0) {
332 tpnt->st_dev = st.st_dev;
333 tpnt->st_ino = st.st_ino;
335 tpnt->n_phent = epnt->e_phnum;
337 for (j = 0; j < epnt->e_phnum; j++, myppnt++) {
338 if (myppnt->p_type == PT_GNU_RELRO) {
339 tpnt->relro_addr = myppnt->p_vaddr;
340 tpnt->relro_size = myppnt->p_memsz;
344 tpnt->libtype = program_interpreter;
346 rpnt->next = _dl_zalloc(sizeof(struct dyn_elf));
347 rpnt->next->prev = rpnt;
350 rpnt = _dl_zalloc(sizeof(struct dyn_elf));
353 tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */
358 static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list,
359 struct elf_resolve *map)
361 struct elf_resolve **p = list;
362 struct init_fini_list *q;
365 map->init_flag |= DL_RESERVED;
367 for (q = map->init_fini; q; q = q->next)
368 if (! (q->tpnt->init_flag & DL_RESERVED))
369 p += _dl_build_local_scope (p, q->tpnt);
373 void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
374 ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv
375 DL_GET_READY_TO_RUN_EXTRA_PARMS)
377 ElfW(Addr) app_mapaddr = 0;
381 unsigned int i, cnt, nscope_elem;
382 int unlazy = 0, trace_loaded_objects = 0;
383 struct dyn_elf *rpnt;
384 struct elf_resolve *tcurr;
385 struct elf_resolve *tpnt1;
386 struct elf_resolve *ldso_tpnt = NULL;
387 struct elf_resolve app_tpnt_tmp;
388 struct elf_resolve *app_tpnt = &app_tpnt_tmp;
389 struct r_debug *debug_addr;
391 unsigned long *_dl_envp; /* The environment address */
392 ElfW(Addr) relro_addr = 0;
393 size_t relro_size = 0;
394 struct r_scope_elem *global_scope;
395 struct elf_resolve **local_scope;
397 #if defined(USE_TLS) && USE_TLS
401 /* Wahoo!!! We managed to make a function call! Get malloc
402 * setup so we can use _dl_dprintf() to print debug noise
403 * instead of the SEND_STDERR macros used in dl-startup.c */
405 _dl_memset(app_tpnt, 0, sizeof(*app_tpnt));
407 /* Store the page size for later use */
408 _dl_pagesize = (auxvt[AT_PAGESZ].a_un.a_val) ? (size_t) auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE;
409 /* Make it so _dl_malloc can use the page of memory we have already
410 * allocated. We shouldn't need to grab any more memory. This must
411 * be first since things like _dl_dprintf() use _dl_malloc()...
413 _dl_malloc_addr = (unsigned char *)_dl_pagesize;
417 _dl_debug_early("Cool, ldso survived making function calls\n");
419 /* Now we have done the mandatory linking of some things. We are now
420 * free to start using global variables, since these things have all
421 * been fixed up by now. Still no function calls outside of this
422 * library, since the dynamic resolver is not yet ready.
425 _dl_progname = argv[0];
428 #ifndef __LDSO_STANDALONE_SUPPORT__
429 if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
430 _dl_dprintf(_dl_debug_file, "Standalone execution is not enabled\n");
435 /* Start to build the tables of the modules that are required for
436 * this beast to run. We start with the basic executable, and then
437 * go from there. Eventually we will run across ourself, and we
438 * will need to properly deal with that as well.
441 if (_dl_getenv("LD_BIND_NOW", envp))
444 /* Now we need to figure out what kind of options are selected.
445 * Note that for SUID programs we ignore the settings in
448 if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && _dl_suid_ok()) ||
449 (auxvt[AT_UID].a_un.a_val != (size_t)-1 &&
450 auxvt[AT_UID].a_un.a_val == auxvt[AT_EUID].a_un.a_val &&
451 auxvt[AT_GID].a_un.a_val == auxvt[AT_EGID].a_un.a_val)) {
453 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
454 _dl_preload = _dl_getenv("LD_PRELOAD", envp);
456 _dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp);
458 static const char unsecure_envvars[] =
459 #ifdef EXTRA_UNSECURE_ENVVARS
460 EXTRA_UNSECURE_ENVVARS
466 nextp = unsecure_envvars;
468 _dl_unsetenv (nextp, envp);
469 /* We could use rawmemchr but this need not be fast. */
470 nextp = _dl_strchr(nextp, '\0') + 1;
471 } while (*nextp != '\0');
472 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
475 _dl_library_path = NULL;
476 /* SUID binaries can be exploited if they do LAZY relocation. */
480 #if defined(USE_TLS) && USE_TLS
481 _dl_error_catch_tsd = &_dl_initial_error_catch_tsd;
482 _dl_init_static_tls = &_dl_nothread_init_static_tls;
485 #ifdef __LDSO_STANDALONE_SUPPORT__
486 if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
488 unsigned int *aux_dat = (unsigned int *) argv;
489 int argc = aux_dat[-1];
491 tpnt->libname = argv[0];
493 if (! _dl_strcmp (argv[1], "--library-path") && argc > 2) {
494 _dl_library_path = argv[2];
502 * If we have no further argument the program was called incorrectly.
503 * Grant the user some education.
508 Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\
509 You have invoked `ld.so', the helper program for shared library executables.\n\
510 This program usually lives in the file `/lib/ld.so', and special directives\n\
511 in executable files using ELF shared libraries tell the system's program\n\
512 loader to load the helper program from this file. This helper program loads\n\
513 the shared libraries needed by the program executable, prepares the program\n\
514 to run, and runs it. You may invoke this helper program directly from the\n\
515 command line to load and run an ELF executable file; this is like executing\n\
516 that file itself, but always uses this helper program from the file you\n\
517 specified, instead of the helper program file specified in the executable\n\
518 file you run. This is mostly of use for maintainers to test new versions\n\
519 of this helper program; chances are you did not intend to run this program.\n\
521 --library-path PATH use given PATH instead of content of the environment\n\
522 variable LD_LIBRARY_PATH\n");
528 _dl_progname = argv[0];
530 _dl_symbol_tables = rpnt = _dl_zalloc(sizeof(struct dyn_elf));
532 * It needs to load the _dl_progname and to map it
533 * Usually it is the main application launched by means of the ld.so
534 * but it could be also a shared object (when ld.so used for tracing)
535 * We keep the misleading app_tpnt name to avoid variable pollution
537 app_tpnt = _dl_load_elf_shared_library(_dl_secure, &rpnt, _dl_progname);
539 _dl_dprintf(_dl_debug_file, "can't load '%s'\n", _dl_progname);
543 * FIXME: it needs to properly handle a PIE executable
544 * Usually for a main application, loadaddr is computed as difference
545 * between auxvt entry points and phdr, so if it is not 0, that it is a
546 * PIE executable. In this case instead we need to set the loadaddr to 0
547 * because we are actually mapping the ELF for the main application by
548 * ourselves. So the PIE case must be checked.
551 app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
554 * This is used by gdb to locate the chain of shared libraries that are
557 debug_addr = _dl_zalloc(sizeof(struct r_debug));
558 ppnt = (ElfW(Phdr) *)app_tpnt->ppnt;
559 for (i = 0; i < app_tpnt->n_phent; i++, ppnt++) {
560 if (ppnt->p_type == PT_DYNAMIC) {
561 dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
562 _dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr);
566 /* Store the path where the shared lib loader was found
569 _dl_ldsopath = _dl_strdup(tpnt->libname);
570 ptmp = _dl_strrchr(_dl_ldsopath, '/');
571 if (ptmp != _dl_ldsopath)
574 _dl_debug_early("Lib Loader: (%x) %s\n", (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname);
578 /* At this point we are now free to examine the user application,
579 * and figure out which libraries are supposed to be called. Until
580 * we have this list, we will not be completely ready for dynamic
584 /* Find the runtime load address of the main executable. This may be
585 * different from what the ELF header says for ET_DYN/PIE executables.
589 ElfW(Phdr) *phdr = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
591 for (idx = 0; idx < auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++)
592 if (phdr->p_type == PT_PHDR) {
593 DL_INIT_LOADADDR_PROG(app_tpnt->loadaddr, auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr);
597 if (DL_LOADADDR_BASE(app_tpnt->loadaddr))
598 _dl_debug_early("Position Independent Executable: "
599 "app_tpnt->loadaddr=%x\n", DL_LOADADDR_BASE(app_tpnt->loadaddr));
603 * This is used by gdb to locate the chain of shared libraries that are
606 debug_addr = _dl_zalloc(sizeof(struct r_debug));
608 ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
609 for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
610 if (ppnt->p_type == PT_GNU_RELRO) {
611 relro_addr = ppnt->p_vaddr;
612 relro_size = ppnt->p_memsz;
614 if (!app_mapaddr && (ppnt->p_type == PT_LOAD)) {
615 app_mapaddr = DL_RELOC_ADDR (app_tpnt->loadaddr, ppnt->p_vaddr);
617 if (ppnt->p_type == PT_DYNAMIC) {
618 dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
619 _dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr);
620 #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
621 /* Ugly, ugly. We need to call mprotect to change the
622 * protection of the text pages so that we can do the
623 * dynamic linking. We can set the protection back
624 * again once we are done.
626 _dl_debug_early("calling mprotect on the application program\n");
627 /* Now cover the application program. */
628 if (app_tpnt->dynamic_info[DT_TEXTREL]) {
629 ElfW(Phdr) *ppnt_outer = ppnt;
630 ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
631 for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
632 if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))
633 _dl_mprotect((void *) (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & PAGE_ALIGN),
634 (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & ADDR_ALIGN) +
635 (unsigned long) ppnt->p_filesz,
636 PROT_READ | PROT_WRITE | PROT_EXEC);
641 if (app_tpnt->dynamic_info[DT_TEXTREL]) {
642 _dl_dprintf(_dl_debug_file, "Can't modify application's text section; use the GCC option -fPIE for position-independent executables.\n");
647 #ifndef ALLOW_ZERO_PLTGOT
648 /* make sure it's really there. */
649 if (app_tpnt->dynamic_info[DT_PLTGOT] == 0)
652 /* OK, we have what we need - slip this one into the list. */
653 app_tpnt = _dl_add_elf_hash_table(_dl_progname, app_tpnt->loadaddr,
654 app_tpnt->dynamic_info,
655 (unsigned long) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr),
657 _dl_loaded_modules->libtype = elf_executable;
658 _dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
659 _dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val;
660 _dl_symbol_tables = rpnt = _dl_zalloc(sizeof(struct dyn_elf));
661 rpnt->dyn = _dl_loaded_modules;
662 app_tpnt->mapaddr = app_mapaddr;
663 app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
664 app_tpnt->usage_count++;
665 lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]);
666 #ifdef ALLOW_ZERO_PLTGOT
669 INIT_GOT(lpnt, _dl_loaded_modules);
672 /* OK, fill this in - we did not have this before */
673 if (ppnt->p_type == PT_INTERP) {
674 tpnt->libname = (char *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
675 #ifdef __LDSO_SEARCH_INTERP_PATH__
678 /* Store the path where the shared lib loader was found
681 _dl_ldsopath = _dl_strdup(tpnt->libname);
682 ptmp = _dl_strrchr(_dl_ldsopath, '/');
683 if (ptmp != _dl_ldsopath)
686 _dl_debug_early("Lib Loader: (%x) %s\n", (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname);
690 /* Discover any TLS sections if the target supports them. */
691 if (ppnt->p_type == PT_TLS) {
692 #if defined(USE_TLS) && USE_TLS
693 if (ppnt->p_memsz > 0) {
694 app_tpnt->l_tls_blocksize = ppnt->p_memsz;
695 app_tpnt->l_tls_align = ppnt->p_align;
696 if (ppnt->p_align == 0)
697 app_tpnt->l_tls_firstbyte_offset = 0;
699 app_tpnt->l_tls_firstbyte_offset =
700 (ppnt->p_vaddr & (ppnt->p_align - 1));
701 app_tpnt->l_tls_initimage_size = ppnt->p_filesz;
702 app_tpnt->l_tls_initimage = (void *) ppnt->p_vaddr;
704 /* This image gets the ID one. */
705 _dl_tls_max_dtv_idx = app_tpnt->l_tls_modid = 1;
708 _dl_debug_early("Found TLS header for appplication program\n");
711 _dl_dprintf(_dl_debug_file, "Program uses unsupported TLS data!\n");
716 app_tpnt->relro_addr = relro_addr;
717 app_tpnt->relro_size = relro_size;
719 #if defined(USE_TLS) && USE_TLS
721 * Adjust the address of the TLS initialization image in
722 * case the executable is actually an ET_DYN object.
724 if (app_tpnt->l_tls_initimage != NULL) {
725 unsigned int tmp = (unsigned int) app_tpnt->l_tls_initimage;
726 app_tpnt->l_tls_initimage =
727 (char *) app_tpnt->l_tls_initimage + app_tpnt->loadaddr;
728 _dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n",
729 tmp, app_tpnt->l_tls_initimage, app_tpnt->l_tls_initimage_size);
733 #ifdef __LDSO_STANDALONE_SUPPORT__
734 } /* ! ldso standalone mode */
737 #ifdef __SUPPORT_LD_DEBUG__
738 _dl_debug = _dl_getenv("LD_DEBUG", envp);
740 if (_dl_strstr(_dl_debug, "all")) {
741 _dl_debug_detail = _dl_debug_move = _dl_debug_symbols
742 = _dl_debug_reloc = _dl_debug_bindings = _dl_debug_nofixups = (void*)1;
744 _dl_debug_detail = _dl_strstr(_dl_debug, "detail");
745 _dl_debug_move = _dl_strstr(_dl_debug, "move");
746 _dl_debug_symbols = _dl_strstr(_dl_debug, "sym");
747 _dl_debug_reloc = _dl_strstr(_dl_debug, "reloc");
748 _dl_debug_nofixups = _dl_strstr(_dl_debug, "nofix");
749 _dl_debug_bindings = _dl_strstr(_dl_debug, "bind");
754 const char *dl_debug_output;
756 dl_debug_output = _dl_getenv("LD_DEBUG_OUTPUT", envp);
758 if (dl_debug_output) {
759 char tmp[22], *tmp1, *filename;
762 _dl_memset(tmp, 0, sizeof(tmp));
763 tmp1 = _dl_simple_ltoa( tmp, (unsigned long)_dl_getpid());
765 len1 = _dl_strlen(dl_debug_output);
766 len2 = _dl_strlen(tmp1);
768 filename = _dl_malloc(len1 + len2 + 2);
771 _dl_strcpy (filename, dl_debug_output);
772 filename[len1] = '.';
773 _dl_strcpy (&filename[len1+1], tmp1);
775 _dl_debug_file = _dl_open(filename, O_WRONLY|O_CREAT, 0644);
776 if (_dl_debug_file < 0) {
778 _dl_dprintf(_dl_debug_file, "can't open file: '%s'\n",filename);
785 #ifdef __LDSO_PRELINK_SUPPORT__
787 char *ld_warn = _dl_getenv ("LD_WARN", envp);
789 if (ld_warn && *ld_warn == '\0')
792 _dl_trace_prelink = _dl_getenv("LD_TRACE_PRELINKING", envp);
795 if (_dl_getenv("LD_TRACE_LOADED_OBJECTS", envp) != NULL) {
796 trace_loaded_objects++;
799 #ifndef __LDSO_LDD_SUPPORT__
800 if (trace_loaded_objects) {
801 _dl_dprintf(_dl_debug_file, "Use the ldd provided by uClibc\n");
807 * OK, fix one more thing - set up debug_addr so it will point
808 * to our chain. Later we may need to fill in more fields, but this
809 * should be enough for now.
811 debug_addr->r_map = (struct link_map *) _dl_loaded_modules;
812 debug_addr->r_version = 1;
813 debug_addr->r_ldbase = (ElfW(Addr)) DL_LOADADDR_BASE(load_addr);
814 debug_addr->r_brk = (unsigned long) &_dl_debug_state;
815 _dl_debug_addr = debug_addr;
817 /* Do not notify the debugger until the interpreter is in the list */
819 /* OK, we now have the application in the list, and we have some
820 * basic stuff in place. Now search through the list for other shared
821 * libraries that should be loaded, and insert them on the list in the
827 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
832 while (*str == ':' || *str == ' ' || *str == '\t')
837 while (*str2 && *str2 != ':' && *str2 != ' ' && *str2 != '\t')
842 if (!_dl_secure || _dl_strchr(str, '/') == NULL) {
843 _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", str, _dl_progname);
845 tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str, trace_loaded_objects);
847 #ifdef __LDSO_LDD_SUPPORT__
848 if (trace_loaded_objects || _dl_trace_prelink)
849 _dl_dprintf(1, "\t%s => not found\n", str);
853 _dl_dprintf(_dl_debug_file, "%s: can't load " "library '%s'\n", _dl_progname, str);
857 tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
859 _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
861 #ifdef __LDSO_LDD_SUPPORT__
862 if (trace_loaded_objects && !_dl_trace_prelink &&
863 tpnt1->usage_count == 1) {
864 /* This is a real hack to make
865 * ldd not print the library
866 * itself when run on a
869 if (_dl_strcmp(_dl_progname, str) != 0)
870 _dl_dprintf(1, "\t%s => %s (%x)\n", str, tpnt1->libname,
871 DL_LOADADDR_BASE(tpnt1->loadaddr));
879 while (*str == ':' || *str == ' ' || *str == '\t')
883 #endif /* __LDSO_PRELOAD_ENV_SUPPORT__ */
885 #ifdef __LDSO_PRELOAD_FILE_SUPPORT__
891 if (_dl_stat(LDSO_PRELOAD, &st) || st.st_size == 0) {
895 if ((fd = _dl_open(LDSO_PRELOAD, O_RDONLY, 0)) < 0) {
896 _dl_dprintf(_dl_debug_file, "%s: can't open file '%s'\n",
897 _dl_progname, LDSO_PRELOAD);
901 preload = (caddr_t) _dl_mmap(0, st.st_size + 1,
902 PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
904 if (preload == (caddr_t) -1) {
905 _dl_dprintf(_dl_debug_file, "%s:%i: can't map '%s'\n",
906 _dl_progname, __LINE__, LDSO_PRELOAD);
910 /* convert all separators and comments to spaces */
911 for (cp = preload; *cp; /*nada */ ) {
912 if (*cp == ':' || *cp == '\t' || *cp == '\n') {
914 } else if (*cp == '#') {
917 } while (*cp != '\n' && *cp != '\0');
923 /* find start of first library */
924 for (cp = preload; *cp && *cp == ' '; cp++)
928 /* find end of library */
929 for (cp2 = cp; *cp && *cp != ' '; cp++)
934 _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", cp2, _dl_progname);
936 tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2, trace_loaded_objects);
938 # ifdef __LDSO_LDD_SUPPORT__
939 if (trace_loaded_objects || _dl_trace_prelink)
940 _dl_dprintf(1, "\t%s => not found\n", cp2);
944 _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, cp2);
948 tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
950 _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
952 # ifdef __LDSO_LDD_SUPPORT__
953 if (trace_loaded_objects && !_dl_trace_prelink &&
954 tpnt1->usage_count == 1) {
955 _dl_dprintf(1, "\t%s => %s (%x)\n",
957 DL_LOADADDR_BASE(tpnt1->loadaddr));
962 /* find start of next library */
964 for ( /*nada */ ; *cp && *cp == ' '; cp++)
968 _dl_munmap(preload, st.st_size + 1);
970 #endif /* __LDSO_PRELOAD_FILE_SUPPORT__ */
973 for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) {
974 ElfW(Dyn) *this_dpnt;
977 for (this_dpnt = (ElfW(Dyn) *) tcurr->dynamic_addr; this_dpnt->d_tag; this_dpnt++) {
978 if (this_dpnt->d_tag == DT_NEEDED) {
980 struct init_fini_list *tmp;
982 lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + this_dpnt->d_un.d_val);
983 name = _dl_get_last_path_component(lpntstr);
984 _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", lpntstr, _dl_progname);
986 if (_dl_strcmp(name, UCLIBC_LDSO) == 0) {
988 /* Insert the ld.so only once */
989 ldso_tpnt = add_ldso(tpnt, load_addr, auxvt, rpnt);
991 ldso_tpnt->usage_count++;
994 tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects);
997 #ifdef __LDSO_LDD_SUPPORT__
998 if (trace_loaded_objects || _dl_trace_prelink) {
999 _dl_dprintf(1, "\t%s => not found\n", lpntstr);
1004 _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, lpntstr);
1009 tmp = alloca(sizeof(struct init_fini_list)); /* Allocates on stack, no need to free this memory */
1011 tmp->next = tcurr->init_fini;
1012 tcurr->init_fini = tmp;
1014 tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
1016 _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
1018 #ifdef __LDSO_LDD_SUPPORT__
1019 if (trace_loaded_objects && !_dl_trace_prelink &&
1020 tpnt1->usage_count == 1) {
1021 _dl_dprintf(1, "\t%s => %s (%x)\n",
1022 lpntstr, tpnt1->libname,
1023 DL_LOADADDR_BASE(tpnt1->loadaddr));
1031 /* Keep track of the number of elements in the global scope */
1032 nscope_elem = nlist;
1034 if (_dl_loaded_modules->libtype == elf_executable) {
1035 --nlist; /* Exclude the application. */
1036 tcurr = _dl_loaded_modules->next;
1038 tcurr = _dl_loaded_modules;
1039 init_fini_list = _dl_malloc(nlist * sizeof(struct elf_resolve *));
1041 for (; tcurr; tcurr = tcurr->next)
1042 init_fini_list[i++] = tcurr;
1044 /* Sort the INIT/FINI list in dependency order. */
1045 for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
1048 for (j = 0; init_fini_list[j] != tcurr; ++j)
1050 for (k = j + 1; k < nlist; ++k) {
1051 struct init_fini_list *runp = init_fini_list[k]->init_fini;
1053 for (; runp; runp = runp->next) {
1054 if (runp->tpnt == tcurr) {
1055 struct elf_resolve *here = init_fini_list[k];
1056 _dl_if_debug_dprint("Move %s from pos %d to %d in INIT/FINI list\n", here->libname, k, j);
1057 for (i = (k - j); i; --i)
1058 init_fini_list[i+j] = init_fini_list[i+j-1];
1059 init_fini_list[j] = here;
1066 #ifdef __SUPPORT_LD_DEBUG__
1068 _dl_dprintf(_dl_debug_file, "\nINIT/FINI order and dependencies:\n");
1069 for (i = 0; i < nlist; i++) {
1070 struct init_fini_list *tmp;
1072 _dl_dprintf(_dl_debug_file, "lib: %s has deps:\n",
1073 init_fini_list[i]->libname);
1074 tmp = init_fini_list[i]->init_fini;
1075 for (; tmp; tmp = tmp->next)
1076 _dl_dprintf(_dl_debug_file, " %s ", tmp->tpnt->libname);
1077 _dl_dprintf(_dl_debug_file, "\n");
1083 * If the program interpreter is not in the module chain, add it.
1084 * This will be required for dlopen to be able to access the internal
1085 * functions in the dynamic linker and to relocate the interpreter
1086 * again once all libs are loaded.
1089 tpnt = add_ldso(tpnt, load_addr, auxvt, rpnt);
1090 tpnt->usage_count++;
1095 #ifdef RERELOCATE_LDSO
1096 /* Only rerelocate functions for now. */
1097 tpnt->init_flag = RELOCS_DONE;
1098 lpnt = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT]);
1099 # ifdef ALLOW_ZERO_PLTGOT
1100 if (tpnt->dynamic_info[DT_PLTGOT])
1102 INIT_GOT(lpnt, tpnt);
1104 tpnt->init_flag = RELOCS_DONE | JMP_RELOCS_DONE;
1109 * Allocate the global scope array.
1111 scope_elem_list = (struct elf_resolve **) _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
1113 for (i = 0, tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next)
1114 scope_elem_list[i++] = tcurr;
1116 _dl_loaded_modules->symbol_scope.r_list = scope_elem_list;
1117 _dl_loaded_modules->symbol_scope.r_nlist = nscope_elem;
1119 * The symbol scope of the application, that is the first entry of the
1120 * _dl_loaded_modules list, is just the global scope to be used for the
1123 global_scope = &_dl_loaded_modules->symbol_scope;
1125 /* Build the local scope for each loaded modules. */
1126 local_scope = _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
1128 for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
1130 cnt = _dl_build_local_scope(local_scope, scope_elem_list[i++]);
1131 tcurr->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *));
1132 tcurr->symbol_scope.r_nlist = cnt;
1133 _dl_memcpy (tcurr->symbol_scope.r_list, local_scope, cnt * sizeof (struct elf_resolve *));
1134 /* Restoring the init_flag.*/
1135 for (k = 1; k < nscope_elem; k++)
1136 scope_elem_list[k]->init_flag &= ~DL_RESERVED;
1139 _dl_free(local_scope);
1141 #ifdef __LDSO_LDD_SUPPORT__
1142 /* Exit if LD_TRACE_LOADED_OBJECTS is on. */
1143 if (trace_loaded_objects && !_dl_trace_prelink)
1147 #if defined(USE_TLS) && USE_TLS
1148 /* We do not initialize any of the TLS functionality unless any of the
1149 * initial modules uses TLS. This makes dynamic loading of modules with
1150 * TLS impossible, but to support it requires either eagerly doing setup
1151 * now or lazily doing it later. Doing it now makes us incompatible with
1152 * an old kernel that can't perform TLS_INIT_TP, even if no TLS is ever
1153 * used. Trying to do it lazily is too hairy to try when there could be
1154 * multiple threads (from a non-TLS-using libpthread). */
1155 bool was_tls_init_tp_called = tls_init_tp_called;
1157 _dl_debug_early("Calling init_tls()!\n");
1161 #ifdef __UCLIBC_HAS_SSP__
1162 /* Set up the stack checker's canary. */
1163 stack_chk_guard = _dl_setup_stack_chk_guard ();
1164 # ifdef THREAD_SET_STACK_GUARD
1165 THREAD_SET_STACK_GUARD (stack_chk_guard);
1167 __stack_chk_guard = stack_chk_guard;
1169 # ifdef __UCLIBC_HAS_SSP_COMPAT__
1170 __guard = stack_chk_guard;
1174 #ifdef __LDSO_PRELINK_SUPPORT__
1175 if (_dl_trace_prelink) {
1177 unsigned int nscope_trace = ldso_tpnt ? nscope_elem : (nscope_elem - 1);
1179 for (i = 0; i < nscope_trace; i++)
1180 trace_objects(scope_elem_list[i],
1181 _dl_get_last_path_component(scope_elem_list[i]->libname));
1184 /* Warn about undefined symbols. */
1185 if (_dl_symbol_tables)
1186 if (_dl_fixup(_dl_symbol_tables, global_scope, unlazy))
1191 if (_dl_loaded_modules->dynamic_info[DT_GNU_LIBLIST_IDX]) {
1192 ElfW(Lib) *liblist, *liblistend;
1193 struct elf_resolve **r_list, **r_listend, *l;
1194 const char *strtab = (const char *)_dl_loaded_modules->dynamic_info[DT_STRTAB];
1196 _dl_assert (_dl_loaded_modules->dynamic_info[DT_GNU_LIBLISTSZ_IDX] != 0);
1197 liblist = (ElfW(Lib) *) _dl_loaded_modules->dynamic_info[DT_GNU_LIBLIST_IDX];
1198 liblistend = (ElfW(Lib) *)
1199 ((char *) liblist + _dl_loaded_modules->dynamic_info[DT_GNU_LIBLISTSZ_IDX]);
1200 r_list = _dl_loaded_modules->symbol_scope.r_list;
1201 r_listend = r_list + nscope_elem;
1203 for (; r_list < r_listend && liblist < liblistend; r_list++) {
1206 if (l == _dl_loaded_modules)
1209 /* If the library is not mapped where it should, fail. */
1213 /* Next, check if checksum matches. */
1214 if (l->dynamic_info[DT_CHECKSUM_IDX] == 0 ||
1215 l->dynamic_info[DT_CHECKSUM_IDX] != liblist->l_checksum)
1218 if (l->dynamic_info[DT_GNU_PRELINKED_IDX] == 0 ||
1219 (l->dynamic_info[DT_GNU_PRELINKED_IDX] != liblist->l_time_stamp))
1222 if (_dl_strcmp(strtab + liblist->l_name, _dl_get_last_path_component(l->libname)) != 0)
1229 if (r_list == r_listend && liblist == liblistend)
1234 _dl_debug_early ("\nprelink checking: %s\n", prelinked ? "ok" : "failed");
1237 if (_dl_loaded_modules->dynamic_info[DT_GNU_CONFLICT_IDX]) {
1238 ELF_RELOC *conflict;
1239 unsigned long conflict_size;
1241 _dl_assert (_dl_loaded_modules->dynamic_info[DT_GNU_CONFLICTSZ_IDX] != 0);
1242 conflict = (ELF_RELOC *) _dl_loaded_modules->dynamic_info[DT_GNU_CONFLICT_IDX];
1243 conflict_size = _dl_loaded_modules->dynamic_info[DT_GNU_CONFLICTSZ_IDX];
1244 _dl_parse_relocation_information(_dl_symbol_tables, global_scope,
1245 (unsigned long) conflict, conflict_size);
1248 /* Mark all the objects so we know they have been already relocated. */
1249 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
1250 tpnt->init_flag |= RELOCS_DONE;
1251 if (tpnt->relro_size)
1252 _dl_protect_relro (tpnt);
1259 _dl_debug_early("Beginning relocation fixups\n");
1263 * Relocation of the GOT entries for MIPS have to be done
1264 * after all the libraries have been loaded.
1266 _dl_perform_mips_global_got_relocations(_dl_loaded_modules, !unlazy);
1270 * OK, now all of the kids are tucked into bed in their proper
1271 * addresses. Now we go through and look for REL and RELA records that
1272 * indicate fixups to the GOT tables. We need to do this in reverse
1273 * order so that COPY directives work correctly.
1275 if (_dl_symbol_tables)
1276 if (_dl_fixup(_dl_symbol_tables, global_scope, unlazy))
1279 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
1280 if (tpnt->relro_size)
1281 _dl_protect_relro (tpnt);
1283 } /* not prelinked */
1285 #if defined(USE_TLS) && USE_TLS
1286 if (!was_tls_init_tp_called && _dl_tls_max_dtv_idx > 0)
1287 ++_dl_tls_generation;
1289 _dl_debug_early("Calling _dl_allocate_tls_init()!\n");
1291 /* Now that we have completed relocation, the initializer data
1292 for the TLS blocks has its final values and we can copy them
1293 into the main thread's TLS area, which we allocated above. */
1294 _dl_allocate_tls_init (tcbp);
1296 /* And finally install it for the main thread. If ld.so itself uses
1297 TLS we know the thread pointer was initialized earlier. */
1298 if (! tls_init_tp_called) {
1299 const char *lossage = (char *) TLS_INIT_TP (tcbp, USE___THREAD);
1300 if (__builtin_expect (lossage != NULL, 0)) {
1301 _dl_debug_early("cannot set up thread-local storage: %s\n", lossage);
1305 #endif /* USE_TLS */
1307 /* OK, at this point things are pretty much ready to run. Now we need
1308 * to touch up a few items that are required, and then we can let the
1309 * user application have at it. Note that the dynamic linker itself
1310 * is not guaranteed to be fully dynamicly linked if we are using
1311 * ld.so.1, so we have to look up each symbol individually.
1314 _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", global_scope, NULL, 0, NULL);
1316 *_dl_envp = (unsigned long) envp;
1318 #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
1323 /* We had to set the protections of all pages to R/W for
1324 * dynamic linking. Set text pages back to R/O.
1326 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
1327 for (myppnt = tpnt->ppnt, j = 0; j < tpnt->n_phent; j++, myppnt++) {
1328 if (myppnt->p_type == PT_LOAD && !(myppnt->p_flags & PF_W) && tpnt->dynamic_info[DT_TEXTREL]) {
1329 _dl_mprotect((void *) (DL_RELOC_ADDR(tpnt->loadaddr, myppnt->p_vaddr) & PAGE_ALIGN),
1330 (myppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) myppnt->p_filesz, LXFLAGS(myppnt->p_flags));
1337 /* Notify the debugger we have added some objects. */
1338 _dl_debug_addr->r_state = RT_ADD;
1341 /* Run pre-initialization functions for the executable. */
1342 _dl_run_array_forward(_dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAY],
1343 _dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAYSZ],
1344 _dl_loaded_modules->loadaddr);
1346 /* Run initialization functions for loaded objects. For the
1347 main executable, they will be run from __uClibc_main. */
1348 for (i = nlist; i; --i) {
1349 tpnt = init_fini_list[i-1];
1350 tpnt->init_fini = NULL; /* Clear, since alloca was used */
1351 if (tpnt->init_flag & INIT_FUNCS_CALLED)
1353 tpnt->init_flag |= INIT_FUNCS_CALLED;
1355 if (tpnt->dynamic_info[DT_INIT]) {
1356 void (*dl_elf_func) (void);
1358 dl_elf_func = (void (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_INIT]);
1360 _dl_if_debug_dprint("calling INIT: %s\n\n", tpnt->libname);
1362 DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
1365 _dl_run_init_array(tpnt);
1368 /* Find the real malloc function and make ldso functions use that from now on */
1369 _dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "malloc",
1370 global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1372 #if defined(USE_TLS) && USE_TLS
1373 /* Find the real functions and make ldso functions use them from now on */
1374 _dl_calloc_function = (void* (*)(size_t, size_t)) (intptr_t)
1375 _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1377 _dl_realloc_function = (void* (*)(void *, size_t)) (intptr_t)
1378 _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1380 _dl_free_function = (void (*)(void *)) (intptr_t)
1381 _dl_find_hash(__C_SYMBOL_PREFIX__ "free", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1383 _dl_memalign_function = (void* (*)(size_t, size_t)) (intptr_t)
1384 _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1388 /* Notify the debugger that all objects are now mapped in. */
1389 _dl_debug_addr->r_state = RT_CONSISTENT;
1392 #ifdef __LDSO_STANDALONE_SUPPORT__
1393 if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val)
1394 return (void *) app_tpnt->l_entry;
1397 return (void *) auxvt[AT_ENTRY].a_un.a_val;
1400 #include "dl-hash.c"