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 #ifdef __LDSO_LD_LIBRARY_PATH__
50 char *_dl_library_path = NULL; /* Where we look for libraries */
52 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
53 char *_dl_preload = NULL; /* Things to be loaded before the libs */
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;
67 static 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;
81 void **_dl_ldso_dsbt = NULL;
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"
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.
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;
123 # ifdef __UCLIBC_HAS_SSP_COMPAT__
124 uintptr_t __guard attribute_relro;
128 #ifdef __LDSO_SEARCH_INTERP_PATH__
129 const char *_dl_ldsopath = NULL; /* Location of the shared lib loader */
131 static void _dl_ldsopath_init(struct elf_resolve *tpnt)
133 char *ldsopath, *ptmp;
136 * Store the path where the shared lib loader was found for later use.
137 * Note that this logic isn't bullet proof when it comes to relative
138 * paths: if you use "./lib/ldso.so", and then the app does chdir()
139 * followed by dlopen(), the old ldso path won't get searched. But
140 * that is a fairly pathological use case, so if you don't like that,
141 * then set a full path to your interp and be done :P.
143 ldsopath = _dl_strdup(tpnt->libname);
144 ptmp = _dl_strrchr(ldsopath, '/');
146 * If there is no "/", then set the path to "", and the code
147 * later on will take this to implicitly mean "search $PWD".
153 _dl_ldsopath = ldsopath;
154 _dl_debug_early("Lib Loader: (%x) %s: using path: %s\n",
155 (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname,
159 #define _dl_ldsopath_init(tpnt)
162 char *_dl_getenv(const char *symbol, char **envp)
167 while ((pnt = *envp++)) {
169 while (*pnt && *pnt == *pnt1)
171 if (!*pnt || *pnt != '=' || *pnt1)
178 void _dl_unsetenv(const char *symbol, char **envp)
182 char **newenvp = envp;
184 for (pnt = *envp; pnt; pnt = *++envp) {
186 while (*pnt && *pnt == *pnt1)
188 if (!*pnt || *pnt != '=' || *pnt1)
195 static int _dl_suid_ok(void)
197 __kernel_uid_t uid, euid;
198 __kernel_gid_t gid, egid;
201 euid = _dl_geteuid();
203 egid = _dl_getegid();
205 if (uid == euid && gid == egid) {
211 void *_dl_malloc(size_t size)
216 _dl_debug_early("request for %d bytes\n", size);
219 if (_dl_malloc_function)
220 return (*_dl_malloc_function) (size);
222 if (_dl_malloc_addr - _dl_mmap_zero + size > _dl_pagesize) {
225 /* Since the above assumes we get a full page even if
226 we request less than that, make sure we request a
227 full page, since uClinux may give us less than than
228 a full page. We might round even
229 larger-than-a-page sizes, but we end up never
230 reusing _dl_mmap_zero/_dl_malloc_addr in that case,
233 The actual page size doesn't really matter; as long
234 as we're self-consistent here, we're safe. */
235 if (size < _dl_pagesize)
236 rounded_size = (size + ADDR_ALIGN) & _dl_pagesize;
240 _dl_debug_early("mmapping more memory\n");
241 _dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, rounded_size,
242 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZE, -1, 0);
243 if (_dl_mmap_check_error(_dl_mmap_zero)) {
244 _dl_dprintf(_dl_debug_file, "%s: mmap of a spare page failed!\n", _dl_progname);
248 retval = _dl_malloc_addr;
249 _dl_malloc_addr += size;
252 * Align memory to DL_MALLOC_ALIGN byte boundary. Some
253 * platforms require this, others simply get better
256 _dl_malloc_addr = (unsigned char *) (((unsigned long) _dl_malloc_addr + DL_MALLOC_ALIGN - 1) & ~(DL_MALLOC_ALIGN - 1));
260 static void *_dl_zalloc(size_t size)
262 void *p = _dl_malloc(size);
264 _dl_memset(p, 0, size);
268 void _dl_free(void *p)
270 if (_dl_free_function)
271 (*_dl_free_function) (p);
274 #if defined(USE_TLS) && USE_TLS
275 void *_dl_memalign(size_t __boundary, size_t __size)
282 if (_dl_memalign_function)
283 return (*_dl_memalign_function) (__boundary, __size);
285 while (rounded < __boundary) {
286 rounded = (1 << i++);
289 delta = (((size_t) _dl_malloc_addr + __size) & (rounded - 1));
291 if ((result = _dl_malloc(rounded - delta)) == NULL)
294 result = _dl_malloc(__size);
300 static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void)
303 struct elf_resolve * tpnt;
305 for (i = 0; i < nlist; ++i) {
306 tpnt = init_fini_list[i];
307 if (tpnt->init_flag & FINI_FUNCS_CALLED)
309 tpnt->init_flag |= FINI_FUNCS_CALLED;
310 _dl_run_fini_array(tpnt);
311 if (tpnt->dynamic_info[DT_FINI]) {
312 void (*dl_elf_func) (void);
314 dl_elf_func = (void (*)(void)) (intptr_t) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI]);
315 _dl_if_debug_dprint("\ncalling FINI: %s\n\n", tpnt->libname);
316 DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
321 #ifdef __LDSO_PRELINK_SUPPORT__
322 static void trace_objects(struct elf_resolve *tpnt, char *str_name)
324 if (_dl_strcmp(_dl_trace_prelink, tpnt->libname) == 0)
325 _dl_trace_prelink_map = tpnt;
326 if (tpnt->libtype == elf_executable) {
327 /* Main executeble */
328 _dl_dprintf(1, "\t%s => %s (%x, %x)", tpnt->libname, tpnt->libname,
329 tpnt->mapaddr, DL_LOADADDR_BASE(tpnt->loadaddr));
331 /* Preloaded, Needed or interpreter */
332 _dl_dprintf(1, "\t%s => %s (%x, %x)", str_name, tpnt->libname,
333 tpnt->mapaddr, DL_LOADADDR_BASE(tpnt->loadaddr));
336 #if defined USE_TLS && USE_TLS
337 if ((tpnt->libtype != program_interpreter) && (tpnt->l_tls_modid))
338 _dl_dprintf (1, " TLS(%x, %x)\n", tpnt->l_tls_modid,
339 (size_t) tpnt->l_tls_offset);
342 _dl_dprintf (1, "\n");
346 static struct elf_resolve * add_ldso(struct elf_resolve *tpnt,
347 DL_LOADADDR_TYPE load_addr,
348 ElfW(Addr) ldso_mapaddr,
349 ElfW(auxv_t) auxvt[AT_EGID + 1],
350 struct dyn_elf *rpnt)
352 ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
353 ElfW(Phdr) *myppnt = (ElfW(Phdr) *)
354 DL_RELOC_ADDR(DL_GET_RUN_ADDR(load_addr, ldso_mapaddr),
359 tpnt = _dl_add_elf_hash_table(tpnt->libname, tpnt->loadaddr,
360 tpnt->dynamic_info, (unsigned long)tpnt->dynamic_addr,
363 tpnt->mapaddr = ldso_mapaddr;
364 if (_dl_stat(tpnt->libname, &st) >= 0) {
365 tpnt->st_dev = st.st_dev;
366 tpnt->st_ino = st.st_ino;
368 tpnt->n_phent = epnt->e_phnum;
370 for (j = 0; j < epnt->e_phnum; j++, myppnt++) {
371 if (myppnt->p_type == PT_GNU_RELRO) {
372 tpnt->relro_addr = myppnt->p_vaddr;
373 tpnt->relro_size = myppnt->p_memsz;
377 tpnt->libtype = program_interpreter;
379 rpnt->next = _dl_zalloc(sizeof(struct dyn_elf));
380 rpnt->next->prev = rpnt;
383 rpnt = _dl_zalloc(sizeof(struct dyn_elf));
386 tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */
391 static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list,
392 struct elf_resolve *map)
394 struct elf_resolve **p = list;
395 struct init_fini_list *q;
398 map->init_flag |= DL_RESERVED;
400 for (q = map->init_fini; q; q = q->next)
401 if (! (q->tpnt->init_flag & DL_RESERVED))
402 p += _dl_build_local_scope (p, q->tpnt);
406 void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
407 ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv
408 DL_GET_READY_TO_RUN_EXTRA_PARMS)
410 ElfW(Addr) app_mapaddr = 0, ldso_mapaddr = 0;
414 unsigned int i, cnt, nscope_elem;
415 int unlazy = 0, trace_loaded_objects = 0;
416 struct dyn_elf *rpnt;
417 struct elf_resolve *tcurr;
418 struct elf_resolve *tpnt1;
419 struct elf_resolve *ldso_tpnt = NULL;
420 struct elf_resolve app_tpnt_tmp;
421 struct elf_resolve *app_tpnt = &app_tpnt_tmp;
422 struct r_debug *debug_addr;
424 unsigned long *_dl_envp; /* The environment address */
425 ElfW(Addr) relro_addr = 0;
426 size_t relro_size = 0;
427 struct r_scope_elem *global_scope;
428 struct elf_resolve **local_scope;
430 #if defined(USE_TLS) && USE_TLS
434 /* Wahoo!!! We managed to make a function call! Get malloc
435 * setup so we can use _dl_dprintf() to print debug noise
436 * instead of the SEND_STDERR macros used in dl-startup.c */
438 _dl_memset(app_tpnt, 0, sizeof(*app_tpnt));
440 /* Store the page size for later use */
441 _dl_pagesize = (auxvt[AT_PAGESZ].a_un.a_val) ? (size_t) auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE;
442 /* Make it so _dl_malloc can use the page of memory we have already
443 * allocated. We shouldn't need to grab any more memory. This must
444 * be first since things like _dl_dprintf() use _dl_malloc()...
446 _dl_malloc_addr = (unsigned char *)_dl_pagesize;
450 _dl_debug_early("Cool, ldso survived making function calls\n");
452 /* Now we have done the mandatory linking of some things. We are now
453 * free to start using global variables, since these things have all
454 * been fixed up by now. Still no function calls outside of this
455 * library, since the dynamic resolver is not yet ready.
458 _dl_progname = argv[0];
462 _dl_ldso_dsbt = (void *)tpnt->dynamic_info[DT_DSBT_BASE_IDX];
463 _dl_ldso_dsbt[tpnt->dynamic_info[DT_DSBT_INDEX_IDX]] = _dl_ldso_dsbt;
466 #ifndef __LDSO_STANDALONE_SUPPORT__
467 if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
468 _dl_dprintf(_dl_debug_file, "Standalone execution is not enabled\n");
473 /* Start to build the tables of the modules that are required for
474 * this beast to run. We start with the basic executable, and then
475 * go from there. Eventually we will run across ourself, and we
476 * will need to properly deal with that as well.
479 if (_dl_getenv("LD_BIND_NOW", envp))
482 /* Now we need to figure out what kind of options are selected.
483 * Note that for SUID programs we ignore the settings in
486 if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && _dl_suid_ok()) ||
487 (auxvt[AT_UID].a_un.a_val != (size_t)-1 &&
488 auxvt[AT_UID].a_un.a_val == auxvt[AT_EUID].a_un.a_val &&
489 auxvt[AT_GID].a_un.a_val == auxvt[AT_EGID].a_un.a_val)) {
491 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
492 _dl_preload = _dl_getenv("LD_PRELOAD", envp);
494 #ifdef __LDSO_LD_LIBRARY_PATH__
495 _dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp);
498 static const char unsecure_envvars[] =
499 #ifdef EXTRA_UNSECURE_ENVVARS
500 EXTRA_UNSECURE_ENVVARS
506 nextp = unsecure_envvars;
508 _dl_unsetenv (nextp, envp);
509 /* We could use rawmemchr but this need not be fast. */
510 nextp = _dl_strchr(nextp, '\0') + 1;
511 } while (*nextp != '\0');
512 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
515 #ifdef __LDSO_LD_LIBRARY_PATH__
516 _dl_library_path = NULL;
518 /* SUID binaries can be exploited if they do LAZY relocation. */
522 #if defined(USE_TLS) && USE_TLS
523 _dl_error_catch_tsd = &_dl_initial_error_catch_tsd;
524 _dl_init_static_tls = &_dl_nothread_init_static_tls;
527 #ifdef __LDSO_STANDALONE_SUPPORT__
528 if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
529 unsigned int *aux_dat = (unsigned int *) argv;
530 int argc = aux_dat[-1];
532 tpnt->libname = argv[0];
534 if (! _dl_strcmp (argv[1], "--library-path") && argc > 2) {
535 #ifdef __LDSO_LD_LIBRARY_PATH__
536 _dl_library_path = argv[2];
545 * If we have no further argument the program was called incorrectly.
546 * Grant the user some education.
551 Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\
552 You have invoked `ld.so', the helper program for shared library executables.\n\
553 This program usually lives in the file `/lib/ld.so', and special directives\n\
554 in executable files using ELF shared libraries tell the system's program\n\
555 loader to load the helper program from this file. This helper program loads\n\
556 the shared libraries needed by the program executable, prepares the program\n\
557 to run, and runs it. You may invoke this helper program directly from the\n\
558 command line to load and run an ELF executable file; this is like executing\n\
559 that file itself, but always uses this helper program from the file you\n\
560 specified, instead of the helper program file specified in the executable\n\
561 file you run. This is mostly of use for maintainers to test new versions\n\
562 of this helper program; chances are you did not intend to run this program.\n\
564 --library-path PATH use given PATH instead of content of the environment\n\
565 variable LD_LIBRARY_PATH\n");
571 _dl_progname = argv[0];
573 _dl_symbol_tables = rpnt = _dl_zalloc(sizeof(struct dyn_elf));
575 * It needs to load the _dl_progname and to map it
576 * Usually it is the main application launched by means of the ld.so
577 * but it could be also a shared object (when ld.so used for tracing)
578 * We keep the misleading app_tpnt name to avoid variable pollution
580 app_tpnt = _dl_load_elf_shared_library(_dl_secure, &rpnt, _dl_progname);
582 _dl_dprintf(_dl_debug_file, "can't load '%s'\n", _dl_progname);
586 * FIXME: it needs to properly handle a PIE executable
587 * Usually for a main application, loadaddr is computed as difference
588 * between auxvt entry points and phdr, so if it is not 0, that it is a
589 * PIE executable. In this case instead we need to set the loadaddr to 0
590 * because we are actually mapping the ELF for the main application by
591 * ourselves. So the PIE case must be checked.
594 app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
597 * This is used by gdb to locate the chain of shared libraries that are
600 debug_addr = _dl_zalloc(sizeof(struct r_debug));
601 ppnt = (ElfW(Phdr) *)app_tpnt->ppnt;
602 for (i = 0; i < app_tpnt->n_phent; i++, ppnt++) {
603 if (ppnt->p_type == PT_DYNAMIC) {
604 dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
605 _dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr);
609 _dl_ldsopath_init(tpnt);
613 /* At this point we are now free to examine the user application,
614 * and figure out which libraries are supposed to be called. Until
615 * we have this list, we will not be completely ready for dynamic
619 /* Find the runtime load address of the main executable. This may be
620 * different from what the ELF header says for ET_DYN/PIE executables.
624 ElfW(Phdr) *phdr = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
626 for (idx = 0; idx < auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++)
627 if (phdr->p_type == PT_PHDR) {
628 DL_INIT_LOADADDR_PROG(app_tpnt->loadaddr, auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr);
632 if (DL_LOADADDR_BASE(app_tpnt->loadaddr))
633 _dl_debug_early("Position Independent Executable: "
634 "app_tpnt->loadaddr=%x\n", DL_LOADADDR_BASE(app_tpnt->loadaddr));
638 * This is used by gdb to locate the chain of shared libraries that are
641 debug_addr = _dl_zalloc(sizeof(struct r_debug));
643 ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
644 for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
645 if (ppnt->p_type == PT_GNU_RELRO) {
646 relro_addr = ppnt->p_vaddr;
647 relro_size = ppnt->p_memsz;
649 if (!app_mapaddr && (ppnt->p_type == PT_LOAD)) {
650 app_mapaddr = DL_RELOC_ADDR (app_tpnt->loadaddr, ppnt->p_vaddr);
652 if (ppnt->p_type == PT_DYNAMIC) {
653 dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
654 _dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr);
655 #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
656 /* Ugly, ugly. We need to call mprotect to change the
657 * protection of the text pages so that we can do the
658 * dynamic linking. We can set the protection back
659 * again once we are done.
661 _dl_debug_early("calling mprotect on the application program\n");
662 /* Now cover the application program. */
663 if (app_tpnt->dynamic_info[DT_TEXTREL]) {
664 ElfW(Phdr) *ppnt_outer = ppnt;
665 ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
666 for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
667 if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))
668 _dl_mprotect((void *) (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & PAGE_ALIGN),
669 (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & ADDR_ALIGN) +
670 (unsigned long) ppnt->p_filesz,
671 PROT_READ | PROT_WRITE | PROT_EXEC);
676 if (app_tpnt->dynamic_info[DT_TEXTREL]) {
677 _dl_dprintf(_dl_debug_file, "Can't modify application's text section; use the GCC option -fPIE for position-independent executables.\n");
682 #ifndef ALLOW_ZERO_PLTGOT
683 /* make sure it's really there. */
684 if (app_tpnt->dynamic_info[DT_PLTGOT] == 0)
687 /* OK, we have what we need - slip this one into the list. */
688 app_tpnt = _dl_add_elf_hash_table(_dl_progname, app_tpnt->loadaddr,
689 app_tpnt->dynamic_info,
690 (unsigned long) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr),
692 _dl_loaded_modules->libtype = elf_executable;
693 _dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
694 _dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val;
695 _dl_symbol_tables = rpnt = _dl_zalloc(sizeof(struct dyn_elf));
696 rpnt->dyn = _dl_loaded_modules;
697 app_tpnt->mapaddr = app_mapaddr;
698 app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
699 app_tpnt->usage_count++;
701 _dl_ldso_dsbt[0] = app_tpnt->dsbt_table;
702 _dl_memcpy(app_tpnt->dsbt_table, _dl_ldso_dsbt,
703 app_tpnt->dsbt_size * sizeof(tpnt->dsbt_table[0]));
705 lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]);
706 #ifdef ALLOW_ZERO_PLTGOT
709 INIT_GOT(lpnt, _dl_loaded_modules);
712 /* OK, fill this in - we did not have this before */
713 if (ppnt->p_type == PT_INTERP) {
714 tpnt->libname = (char *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
716 _dl_ldsopath_init(tpnt);
719 /* Discover any TLS sections if the target supports them. */
720 if (ppnt->p_type == PT_TLS) {
721 #if defined(USE_TLS) && USE_TLS
722 if (ppnt->p_memsz > 0) {
723 app_tpnt->l_tls_blocksize = ppnt->p_memsz;
724 app_tpnt->l_tls_align = ppnt->p_align;
725 if (ppnt->p_align == 0)
726 app_tpnt->l_tls_firstbyte_offset = 0;
728 app_tpnt->l_tls_firstbyte_offset =
729 (ppnt->p_vaddr & (ppnt->p_align - 1));
730 app_tpnt->l_tls_initimage_size = ppnt->p_filesz;
731 app_tpnt->l_tls_initimage = (void *) ppnt->p_vaddr;
733 /* This image gets the ID one. */
734 _dl_tls_max_dtv_idx = app_tpnt->l_tls_modid = 1;
737 _dl_debug_early("Found TLS header for application program\n");
740 _dl_dprintf(_dl_debug_file, "Program uses unsupported TLS data!\n");
745 app_tpnt->relro_addr = relro_addr;
746 app_tpnt->relro_size = relro_size;
748 #if defined(USE_TLS) && USE_TLS
750 * Adjust the address of the TLS initialization image in
751 * case the executable is actually an ET_DYN object.
753 if (app_tpnt->l_tls_initimage != NULL) {
754 unsigned int tmp = (unsigned int) app_tpnt->l_tls_initimage;
755 app_tpnt->l_tls_initimage =
756 (char *) app_tpnt->l_tls_initimage + app_tpnt->loadaddr;
757 _dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n",
758 tmp, app_tpnt->l_tls_initimage, app_tpnt->l_tls_initimage_size);
762 #ifdef __LDSO_STANDALONE_SUPPORT__
763 } /* ! ldso standalone mode */
766 #ifdef __SUPPORT_LD_DEBUG__
767 _dl_debug = _dl_getenv("LD_DEBUG", envp);
769 if (_dl_strstr(_dl_debug, "all")) {
770 _dl_debug_detail = _dl_debug_move = _dl_debug_symbols
771 = _dl_debug_reloc = _dl_debug_bindings = _dl_debug_nofixups = (void*)1;
773 _dl_debug_detail = _dl_strstr(_dl_debug, "detail");
774 _dl_debug_move = _dl_strstr(_dl_debug, "move");
775 _dl_debug_symbols = _dl_strstr(_dl_debug, "sym");
776 _dl_debug_reloc = _dl_strstr(_dl_debug, "reloc");
777 _dl_debug_nofixups = _dl_strstr(_dl_debug, "nofix");
778 _dl_debug_bindings = _dl_strstr(_dl_debug, "bind");
783 const char *dl_debug_output;
785 dl_debug_output = _dl_getenv("LD_DEBUG_OUTPUT", envp);
787 if (dl_debug_output) {
788 char tmp[22], *tmp1, *filename;
791 _dl_memset(tmp, 0, sizeof(tmp));
792 tmp1 = _dl_simple_ltoa( tmp, (unsigned long)_dl_getpid());
794 len1 = _dl_strlen(dl_debug_output);
795 len2 = _dl_strlen(tmp1);
797 filename = _dl_malloc(len1 + len2 + 2);
800 _dl_strcpy (filename, dl_debug_output);
801 filename[len1] = '.';
802 _dl_strcpy (&filename[len1+1], tmp1);
804 _dl_debug_file = _dl_open(filename, O_WRONLY|O_CREAT, 0644);
805 if (_dl_debug_file < 0) {
807 _dl_dprintf(_dl_debug_file, "can't open file: '%s'\n",filename);
814 #ifdef __LDSO_PRELINK_SUPPORT__
816 char *ld_warn = _dl_getenv ("LD_WARN", envp);
818 if (ld_warn && *ld_warn == '\0')
821 _dl_trace_prelink = _dl_getenv("LD_TRACE_PRELINKING", envp);
824 if (_dl_getenv("LD_TRACE_LOADED_OBJECTS", envp) != NULL) {
825 trace_loaded_objects++;
828 #ifndef __LDSO_LDD_SUPPORT__
829 if (trace_loaded_objects) {
830 _dl_dprintf(_dl_debug_file, "Use the ldd provided by uClibc\n");
835 ldso_mapaddr = (ElfW(Addr)) auxvt[AT_BASE].a_un.a_val;
837 * OK, fix one more thing - set up debug_addr so it will point
838 * to our chain. Later we may need to fill in more fields, but this
839 * should be enough for now.
841 debug_addr->r_map = (struct link_map *) _dl_loaded_modules;
842 debug_addr->r_version = 1;
843 debug_addr->r_ldbase = (ElfW(Addr))
844 DL_LOADADDR_BASE(DL_GET_RUN_ADDR(load_addr, ldso_mapaddr));
845 debug_addr->r_brk = (unsigned long) &_dl_debug_state;
846 _dl_debug_addr = debug_addr;
848 /* Do not notify the debugger until the interpreter is in the list */
850 /* OK, we now have the application in the list, and we have some
851 * basic stuff in place. Now search through the list for other shared
852 * libraries that should be loaded, and insert them on the list in the
858 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
863 while (*str == ':' || *str == ' ' || *str == '\t')
868 while (*str2 && *str2 != ':' && *str2 != ' ' && *str2 != '\t')
873 if (!_dl_secure || _dl_strchr(str, '/') == NULL) {
874 _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", str, _dl_progname);
876 tpnt1 = _dl_load_shared_library(
877 _dl_secure ? DL_RESOLVE_SECURE : 0,
878 &rpnt, NULL, str, trace_loaded_objects);
880 #ifdef __LDSO_LDD_SUPPORT__
881 if (trace_loaded_objects || _dl_trace_prelink)
882 _dl_dprintf(1, "\t%s => not found\n", str);
886 _dl_dprintf(_dl_debug_file, "%s: can't load " "library '%s'\n", _dl_progname, str);
890 tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
892 _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
894 #ifdef __LDSO_LDD_SUPPORT__
895 if (trace_loaded_objects && !_dl_trace_prelink &&
896 tpnt1->usage_count == 1) {
897 /* This is a real hack to make
898 * ldd not print the library
899 * itself when run on a
902 if (_dl_strcmp(_dl_progname, str) != 0)
903 _dl_dprintf(1, "\t%s => %s (%x)\n", str, tpnt1->libname,
904 DL_LOADADDR_BASE(tpnt1->loadaddr));
912 while (*str == ':' || *str == ' ' || *str == '\t')
916 #endif /* __LDSO_PRELOAD_ENV_SUPPORT__ */
918 #ifdef __LDSO_PRELOAD_FILE_SUPPORT__
925 if (_dl_stat(LDSO_PRELOAD, &st) || st.st_size == 0) {
929 if ((fd = _dl_open(LDSO_PRELOAD, O_RDONLY, 0)) < 0) {
930 _dl_dprintf(_dl_debug_file, "%s: can't open file '%s'\n",
931 _dl_progname, LDSO_PRELOAD);
935 preload = (caddr_t) _dl_mmap(0, st.st_size + 1,
936 PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
938 if (preload == (caddr_t) -1) {
939 _dl_dprintf(_dl_debug_file, "%s:%i: can't map '%s'\n",
940 _dl_progname, __LINE__, LDSO_PRELOAD);
944 /* convert all separators and comments to spaces */
945 for (cp = preload; *cp; /*nada */ ) {
946 if (*cp == ':' || *cp == '\t' || *cp == '\n') {
948 } else if (*cp == '#') {
951 } while (*cp != '\n' && *cp != '\0');
957 /* find start of first library */
958 for (cp = preload; *cp && *cp == ' '; cp++)
962 /* find end of library */
963 for (cp2 = cp; *cp && *cp != ' '; cp++)
968 _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", cp2, _dl_progname);
970 tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2, trace_loaded_objects);
972 # ifdef __LDSO_LDD_SUPPORT__
973 if (trace_loaded_objects || _dl_trace_prelink)
974 _dl_dprintf(1, "\t%s => not found\n", cp2);
978 _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, cp2);
982 tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
984 _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
986 # ifdef __LDSO_LDD_SUPPORT__
987 if (trace_loaded_objects && !_dl_trace_prelink &&
988 tpnt1->usage_count == 1) {
989 _dl_dprintf(1, "\t%s => %s (%x)\n",
991 DL_LOADADDR_BASE(tpnt1->loadaddr));
996 /* find start of next library */
998 for ( /*nada */ ; *cp && *cp == ' '; cp++)
1002 _dl_munmap(preload, st.st_size + 1);
1004 #endif /* __LDSO_PRELOAD_FILE_SUPPORT__ */
1007 for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) {
1008 ElfW(Dyn) *this_dpnt;
1011 for (this_dpnt = (ElfW(Dyn) *) tcurr->dynamic_addr; this_dpnt->d_tag; this_dpnt++) {
1012 if (this_dpnt->d_tag == DT_NEEDED) {
1014 struct init_fini_list *tmp;
1016 lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + this_dpnt->d_un.d_val);
1017 name = _dl_get_last_path_component(lpntstr);
1018 _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", lpntstr, _dl_progname);
1020 if (_dl_strcmp(name, UCLIBC_LDSO) == 0) {
1022 /* Insert the ld.so only once */
1023 ldso_tpnt = add_ldso(tpnt, load_addr,
1024 ldso_mapaddr, auxvt, rpnt);
1026 ldso_tpnt->usage_count++;
1029 tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects);
1032 #ifdef __LDSO_LDD_SUPPORT__
1033 if (trace_loaded_objects || _dl_trace_prelink) {
1034 _dl_dprintf(1, "\t%s => not found\n", lpntstr);
1039 _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, lpntstr);
1044 tmp = alloca(sizeof(struct init_fini_list)); /* Allocates on stack, no need to free this memory */
1046 tmp->next = tcurr->init_fini;
1047 tcurr->init_fini = tmp;
1049 tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
1051 _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
1053 #ifdef __LDSO_LDD_SUPPORT__
1054 if (trace_loaded_objects && !_dl_trace_prelink &&
1055 tpnt1->usage_count == 1) {
1056 _dl_dprintf(1, "\t%s => %s (%x)\n",
1057 lpntstr, tpnt1->libname,
1058 DL_LOADADDR_BASE(tpnt1->loadaddr));
1066 /* Keep track of the number of elements in the global scope */
1067 nscope_elem = nlist;
1069 if (_dl_loaded_modules->libtype == elf_executable) {
1070 --nlist; /* Exclude the application. */
1071 tcurr = _dl_loaded_modules->next;
1073 tcurr = _dl_loaded_modules;
1074 init_fini_list = _dl_malloc(nlist * sizeof(struct elf_resolve *));
1076 for (; tcurr; tcurr = tcurr->next)
1077 init_fini_list[i++] = tcurr;
1079 /* Sort the INIT/FINI list in dependency order. */
1080 for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
1083 for (j = 0; init_fini_list[j] != tcurr; ++j)
1085 for (k = j + 1; k < nlist; ++k) {
1086 struct init_fini_list *runp = init_fini_list[k]->init_fini;
1088 for (; runp; runp = runp->next) {
1089 if (runp->tpnt == tcurr) {
1090 struct elf_resolve *here = init_fini_list[k];
1091 _dl_if_debug_dprint("Move %s from pos %d to %d in INIT/FINI list\n", here->libname, k, j);
1092 for (i = (k - j); i; --i)
1093 init_fini_list[i+j] = init_fini_list[i+j-1];
1094 init_fini_list[j] = here;
1101 #ifdef __SUPPORT_LD_DEBUG__
1103 _dl_dprintf(_dl_debug_file, "\nINIT/FINI order and dependencies:\n");
1104 for (i = 0; i < nlist; i++) {
1105 struct init_fini_list *tmp;
1107 _dl_dprintf(_dl_debug_file, "lib: %s has deps:\n",
1108 init_fini_list[i]->libname);
1109 tmp = init_fini_list[i]->init_fini;
1110 for (; tmp; tmp = tmp->next)
1111 _dl_dprintf(_dl_debug_file, " %s ", tmp->tpnt->libname);
1112 _dl_dprintf(_dl_debug_file, "\n");
1118 * If the program interpreter is not in the module chain, add it.
1119 * This will be required for dlopen to be able to access the internal
1120 * functions in the dynamic linker and to relocate the interpreter
1121 * again once all libs are loaded.
1124 tpnt = add_ldso(tpnt, load_addr, ldso_mapaddr, auxvt, rpnt);
1125 tpnt->usage_count++;
1130 #ifdef RERELOCATE_LDSO
1131 /* Only rerelocate functions for now. */
1132 tpnt->init_flag = RELOCS_DONE;
1133 lpnt = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT]);
1134 # ifdef ALLOW_ZERO_PLTGOT
1135 if (tpnt->dynamic_info[DT_PLTGOT])
1137 INIT_GOT(lpnt, tpnt);
1139 tpnt->init_flag = RELOCS_DONE | JMP_RELOCS_DONE;
1144 * Allocate the global scope array.
1146 scope_elem_list = (struct elf_resolve **) _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
1148 for (i = 0, tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next)
1149 scope_elem_list[i++] = tcurr;
1151 _dl_loaded_modules->symbol_scope.r_list = scope_elem_list;
1152 _dl_loaded_modules->symbol_scope.r_nlist = nscope_elem;
1154 * The symbol scope of the application, that is the first entry of the
1155 * _dl_loaded_modules list, is just the global scope to be used for the
1158 global_scope = &_dl_loaded_modules->symbol_scope;
1160 /* Build the local scope for each loaded modules. */
1161 local_scope = _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
1163 for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
1165 cnt = _dl_build_local_scope(local_scope, scope_elem_list[i++]);
1166 tcurr->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *));
1167 tcurr->symbol_scope.r_nlist = cnt;
1168 _dl_memcpy (tcurr->symbol_scope.r_list, local_scope, cnt * sizeof (struct elf_resolve *));
1169 /* Restoring the init_flag.*/
1170 for (k = 1; k < nscope_elem; k++)
1171 scope_elem_list[k]->init_flag &= ~DL_RESERVED;
1174 _dl_free(local_scope);
1176 #ifdef __LDSO_LDD_SUPPORT__
1177 /* Exit if LD_TRACE_LOADED_OBJECTS is on. */
1178 if (trace_loaded_objects && !_dl_trace_prelink)
1182 #if defined(USE_TLS) && USE_TLS
1183 /* We do not initialize any of the TLS functionality unless any of the
1184 * initial modules uses TLS. This makes dynamic loading of modules with
1185 * TLS impossible, but to support it requires either eagerly doing setup
1186 * now or lazily doing it later. Doing it now makes us incompatible with
1187 * an old kernel that can't perform TLS_INIT_TP, even if no TLS is ever
1188 * used. Trying to do it lazily is too hairy to try when there could be
1189 * multiple threads (from a non-TLS-using libpthread). */
1190 bool was_tls_init_tp_called = tls_init_tp_called;
1192 _dl_debug_early("Calling init_tls()!\n");
1196 #ifdef __UCLIBC_HAS_SSP__
1197 /* Set up the stack checker's canary. */
1198 stack_chk_guard = _dl_setup_stack_chk_guard ();
1199 # ifdef THREAD_SET_STACK_GUARD
1200 THREAD_SET_STACK_GUARD (stack_chk_guard);
1202 __stack_chk_guard = stack_chk_guard;
1204 # ifdef __UCLIBC_HAS_SSP_COMPAT__
1205 __guard = stack_chk_guard;
1209 #ifdef __LDSO_PRELINK_SUPPORT__
1210 if (_dl_trace_prelink) {
1212 unsigned int nscope_trace = ldso_tpnt ? nscope_elem : (nscope_elem - 1);
1214 for (i = 0; i < nscope_trace; i++)
1215 trace_objects(scope_elem_list[i],
1216 _dl_get_last_path_component(scope_elem_list[i]->libname));
1219 /* Warn about undefined symbols. */
1220 if (_dl_symbol_tables)
1221 if (_dl_fixup(_dl_symbol_tables, global_scope, unlazy))
1226 if (_dl_loaded_modules->dynamic_info[DT_GNU_LIBLIST_IDX]) {
1227 ElfW(Lib) *liblist, *liblistend;
1228 struct elf_resolve **r_list, **r_listend, *l;
1229 const char *strtab = (const char *)_dl_loaded_modules->dynamic_info[DT_STRTAB];
1231 _dl_assert (_dl_loaded_modules->dynamic_info[DT_GNU_LIBLISTSZ_IDX] != 0);
1232 liblist = (ElfW(Lib) *) _dl_loaded_modules->dynamic_info[DT_GNU_LIBLIST_IDX];
1233 liblistend = (ElfW(Lib) *)
1234 ((char *) liblist + _dl_loaded_modules->dynamic_info[DT_GNU_LIBLISTSZ_IDX]);
1235 r_list = _dl_loaded_modules->symbol_scope.r_list;
1236 r_listend = r_list + nscope_elem;
1238 for (; r_list < r_listend && liblist < liblistend; r_list++) {
1241 if (l == _dl_loaded_modules)
1244 /* If the library is not mapped where it should, fail. */
1248 /* Next, check if checksum matches. */
1249 if (l->dynamic_info[DT_CHECKSUM_IDX] == 0 ||
1250 l->dynamic_info[DT_CHECKSUM_IDX] != liblist->l_checksum)
1253 if (l->dynamic_info[DT_GNU_PRELINKED_IDX] == 0 ||
1254 (l->dynamic_info[DT_GNU_PRELINKED_IDX] != liblist->l_time_stamp))
1257 if (_dl_strcmp(strtab + liblist->l_name, _dl_get_last_path_component(l->libname)) != 0)
1264 if (r_list == r_listend && liblist == liblistend)
1269 _dl_debug_early ("\nprelink checking: %s\n", prelinked ? "ok" : "failed");
1272 if (_dl_loaded_modules->dynamic_info[DT_GNU_CONFLICT_IDX]) {
1273 ELF_RELOC *conflict;
1274 unsigned long conflict_size;
1276 _dl_assert (_dl_loaded_modules->dynamic_info[DT_GNU_CONFLICTSZ_IDX] != 0);
1277 conflict = (ELF_RELOC *) _dl_loaded_modules->dynamic_info[DT_GNU_CONFLICT_IDX];
1278 conflict_size = _dl_loaded_modules->dynamic_info[DT_GNU_CONFLICTSZ_IDX];
1279 _dl_parse_relocation_information(_dl_symbol_tables, global_scope,
1280 (unsigned long) conflict, conflict_size);
1283 /* Mark all the objects so we know they have been already relocated. */
1284 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
1285 tpnt->init_flag |= RELOCS_DONE;
1286 if (tpnt->relro_size)
1287 _dl_protect_relro (tpnt);
1294 _dl_debug_early("Beginning relocation fixups\n");
1298 * Relocation of the GOT entries for MIPS have to be done
1299 * after all the libraries have been loaded.
1301 _dl_perform_mips_global_got_relocations(_dl_loaded_modules, !unlazy);
1305 * OK, now all of the kids are tucked into bed in their proper
1306 * addresses. Now we go through and look for REL and RELA records that
1307 * indicate fixups to the GOT tables. We need to do this in reverse
1308 * order so that COPY directives work correctly.
1310 if (_dl_symbol_tables)
1311 if (_dl_fixup(_dl_symbol_tables, global_scope, unlazy))
1314 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
1315 if (tpnt->relro_size)
1316 _dl_protect_relro (tpnt);
1318 } /* not prelinked */
1320 #if defined(USE_TLS) && USE_TLS
1321 if (!was_tls_init_tp_called && _dl_tls_max_dtv_idx > 0)
1322 ++_dl_tls_generation;
1324 _dl_debug_early("Calling _dl_allocate_tls_init()!\n");
1326 /* Now that we have completed relocation, the initializer data
1327 for the TLS blocks has its final values and we can copy them
1328 into the main thread's TLS area, which we allocated above. */
1329 _dl_allocate_tls_init (tcbp);
1331 /* And finally install it for the main thread. If ld.so itself uses
1332 TLS we know the thread pointer was initialized earlier. */
1333 if (! tls_init_tp_called) {
1334 const char *lossage = (char *) TLS_INIT_TP (tcbp, USE___THREAD);
1335 if (__builtin_expect (lossage != NULL, 0)) {
1336 _dl_debug_early("cannot set up thread-local storage: %s\n", lossage);
1340 #endif /* USE_TLS */
1342 /* OK, at this point things are pretty much ready to run. Now we need
1343 * to touch up a few items that are required, and then we can let the
1344 * user application have at it. Note that the dynamic linker itself
1345 * is not guaranteed to be fully dynamicly linked if we are using
1346 * ld.so.1, so we have to look up each symbol individually.
1349 _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", global_scope, NULL, 0, NULL);
1351 *_dl_envp = (unsigned long) envp;
1353 #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
1358 /* We had to set the protections of all pages to R/W for
1359 * dynamic linking. Set text pages back to R/O.
1361 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
1362 for (myppnt = tpnt->ppnt, j = 0; j < tpnt->n_phent; j++, myppnt++) {
1363 if (myppnt->p_type == PT_LOAD && !(myppnt->p_flags & PF_W) && tpnt->dynamic_info[DT_TEXTREL]) {
1364 _dl_mprotect((void *) (DL_RELOC_ADDR(tpnt->loadaddr, myppnt->p_vaddr) & PAGE_ALIGN),
1365 (myppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) myppnt->p_filesz, LXFLAGS(myppnt->p_flags));
1372 /* Notify the debugger we have added some objects. */
1373 _dl_debug_addr->r_state = RT_ADD;
1376 /* Run pre-initialization functions for the executable. */
1377 _dl_run_array_forward(_dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAY],
1378 _dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAYSZ],
1379 _dl_loaded_modules->loadaddr);
1381 /* Run initialization functions for loaded objects. For the
1382 main executable, they will be run from __uClibc_main. */
1383 for (i = nlist; i; --i) {
1384 tpnt = init_fini_list[i-1];
1385 tpnt->init_fini = NULL; /* Clear, since alloca was used */
1386 if (tpnt->init_flag & INIT_FUNCS_CALLED)
1388 tpnt->init_flag |= INIT_FUNCS_CALLED;
1390 if (tpnt->dynamic_info[DT_INIT]) {
1391 void (*dl_elf_func) (void);
1393 dl_elf_func = (void (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_INIT]);
1395 _dl_if_debug_dprint("calling INIT: %s\n\n", tpnt->libname);
1397 DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
1400 _dl_run_init_array(tpnt);
1403 /* Find the real malloc function and make ldso functions use that from now on */
1404 _dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "malloc",
1405 global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1407 #if defined(USE_TLS) && USE_TLS
1408 /* Find the real functions and make ldso functions use them from now on */
1409 _dl_calloc_function = (void* (*)(size_t, size_t)) (intptr_t)
1410 _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1412 _dl_realloc_function = (void* (*)(void *, size_t)) (intptr_t)
1413 _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1415 _dl_free_function = (void (*)(void *)) (intptr_t)
1416 _dl_find_hash(__C_SYMBOL_PREFIX__ "free", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1418 _dl_memalign_function = (void* (*)(size_t, size_t)) (intptr_t)
1419 _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1423 /* Notify the debugger that all objects are now mapped in. */
1424 _dl_debug_addr->r_state = RT_CONSISTENT;
1427 #ifdef __LDSO_STANDALONE_SUPPORT__
1428 if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val)
1429 return (void *) app_tpnt->l_entry;
1432 return (void *) auxvt[AT_ENTRY].a_un.a_val;
1435 #include "dl-hash.c"