OSDN Git Service

ldso: Add support for LD_WARN and LD_TRACE_PRELINKING
[uclinux-h8/uClibc.git] / ldso / ldso / ldso.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Program to load an ELF binary on a linux system, and run it
4  * after resolving ELF shared library symbols
5  *
6  * Copyright (C) 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
10  *
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.
19  *
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.
31  */
32
33 #include "ldso.h"
34 #include "unsecvars.h"
35
36 /* Pull in common debug code */
37 #include "dl-debug.c"
38
39 #define ALLOW_ZERO_PLTGOT
40
41 #if defined(USE_TLS) && USE_TLS
42 #include "dl-tls.c"
43 #endif
44
45 /* Pull in the value of _dl_progname */
46 #include LDSO_ELFINTERP
47
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 */
52 #endif
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;
59
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 #endif
65 static int _dl_secure = 1; /* Are we dealing with setuid stuff? */
66
67 #ifdef __SUPPORT_LD_DEBUG__
68 char *_dl_debug           = NULL;
69 char *_dl_debug_symbols   = NULL;
70 char *_dl_debug_move      = NULL;
71 char *_dl_debug_reloc     = NULL;
72 char *_dl_debug_detail    = NULL;
73 char *_dl_debug_nofixups  = NULL;
74 char *_dl_debug_bindings  = NULL;
75 int   _dl_debug_file      = 2;
76 #endif
77
78 #if defined (__LDSO_STANDALONE_SUPPORT__) && defined (__sh__)
79 /* Not hidden, needed for standalone execution. */
80 /*
81  * FIXME: align dl_start for SH to other archs so that we can keep this symbol
82  *        hidden and we don't need to handle in __uClibc_main
83  */
84
85 unsigned long _dl_skip_args = 0;
86 #else
87 unsigned long attribute_hidden _dl_skip_args = 0;
88 #endif
89
90 const char *_dl_progname = UCLIBC_LDSO;      /* The name of the executable being run */
91 #include "dl-startup.c"
92 #include "dl-symbols.c"
93 #include "dl-array.c"
94
95 /*
96  * This stub function is used by some debuggers.  The idea is that they
97  * can set an internal breakpoint on it, so that we are notified when the
98  * address mapping is changed in some way.
99  */
100 void _dl_debug_state(void);
101 rtld_hidden_proto(_dl_debug_state, noinline);
102 void _dl_debug_state(void)
103 {
104         /* Make sure GCC doesn't recognize this function as pure, to avoid
105          * having the calls optimized away.
106          */
107         __asm__("");
108 }
109 rtld_hidden_def(_dl_debug_state);
110
111 static unsigned char *_dl_malloc_addr = NULL;   /* Lets _dl_malloc use the already allocated memory page */
112 static unsigned char *_dl_mmap_zero   = NULL;   /* Also used by _dl_malloc */
113
114 static struct elf_resolve **init_fini_list;
115 static struct elf_resolve **scope_elem_list;
116 static unsigned int nlist; /* # items in init_fini_list */
117 extern void _start(void);
118
119 #ifdef __UCLIBC_HAS_SSP__
120 # include <dl-osinfo.h>
121 uintptr_t stack_chk_guard;
122 # ifndef THREAD_SET_STACK_GUARD
123 /* Only exported for architectures that don't store the stack guard canary
124  * in local thread area.  */
125 uintptr_t __stack_chk_guard attribute_relro;
126 #  ifdef __UCLIBC_HAS_SSP_COMPAT__
127 strong_alias(__stack_chk_guard,__guard)
128 #  endif
129 # elif __UCLIBC_HAS_SSP_COMPAT__
130 uintptr_t __guard attribute_relro;
131 # endif
132 #endif
133
134 char *_dl_getenv(const char *symbol, char **envp)
135 {
136         char *pnt;
137         const char *pnt1;
138
139         while ((pnt = *envp++)) {
140                 pnt1 = symbol;
141                 while (*pnt && *pnt == *pnt1)
142                         pnt1++, pnt++;
143                 if (!*pnt || *pnt != '=' || *pnt1)
144                         continue;
145                 return pnt + 1;
146         }
147         return 0;
148 }
149
150 void _dl_unsetenv(const char *symbol, char **envp)
151 {
152         char *pnt;
153         const char *pnt1;
154         char **newenvp = envp;
155
156         for (pnt = *envp; pnt; pnt = *++envp) {
157                 pnt1 = symbol;
158                 while (*pnt && *pnt == *pnt1)
159                         pnt1++, pnt++;
160                 if (!*pnt || *pnt != '=' || *pnt1)
161                         *newenvp++ = *envp;
162         }
163         *newenvp++ = *envp;
164         return;
165 }
166
167 static int _dl_suid_ok(void)
168 {
169         __kernel_uid_t uid, euid;
170         __kernel_gid_t gid, egid;
171
172         uid = _dl_getuid();
173         euid = _dl_geteuid();
174         gid = _dl_getgid();
175         egid = _dl_getegid();
176
177         if (uid == euid && gid == egid) {
178                 return 1;
179         }
180         return 0;
181 }
182
183 void *_dl_malloc(size_t size)
184 {
185         void *retval;
186
187 #if 0
188         _dl_debug_early("request for %d bytes\n", size);
189 #endif
190
191         if (_dl_malloc_function)
192                 return (*_dl_malloc_function) (size);
193
194         if (_dl_malloc_addr - _dl_mmap_zero + size > _dl_pagesize) {
195                 size_t rounded_size;
196
197                 /* Since the above assumes we get a full page even if
198                    we request less than that, make sure we request a
199                    full page, since uClinux may give us less than than
200                    a full page.  We might round even
201                    larger-than-a-page sizes, but we end up never
202                    reusing _dl_mmap_zero/_dl_malloc_addr in that case,
203                    so we don't do it.
204
205                    The actual page size doesn't really matter; as long
206                    as we're self-consistent here, we're safe.  */
207                 if (size < _dl_pagesize)
208                         rounded_size = (size + ADDR_ALIGN) & _dl_pagesize;
209                 else
210                         rounded_size = size;
211
212                 _dl_debug_early("mmapping more memory\n");
213                 _dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, rounded_size,
214                                 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZE, -1, 0);
215                 if (_dl_mmap_check_error(_dl_mmap_zero)) {
216                         _dl_dprintf(_dl_debug_file, "%s: mmap of a spare page failed!\n", _dl_progname);
217                         _dl_exit(20);
218                 }
219         }
220         retval = _dl_malloc_addr;
221         _dl_malloc_addr += size;
222
223         /*
224          * Align memory to DL_MALLOC_ALIGN byte boundary.  Some
225          * platforms require this, others simply get better
226          * performance.
227          */
228         _dl_malloc_addr = (unsigned char *) (((unsigned long) _dl_malloc_addr + DL_MALLOC_ALIGN - 1) & ~(DL_MALLOC_ALIGN - 1));
229         return retval;
230 }
231
232 static void *_dl_zalloc(size_t size)
233 {
234         void *p = _dl_malloc(size);
235         if (p)
236                 _dl_memset(p, 0, size);
237         return p;
238 }
239
240 void _dl_free(void *p)
241 {
242         if (_dl_free_function)
243                 (*_dl_free_function) (p);
244 }
245
246 #if defined(USE_TLS) && USE_TLS
247 void *_dl_memalign(size_t __boundary, size_t __size)
248 {
249         void *result;
250         int i = 0;
251         size_t delta;
252         size_t rounded = 0;
253
254         if (_dl_memalign_function)
255                 return (*_dl_memalign_function) (__boundary, __size);
256
257         while (rounded < __boundary) {
258                 rounded = (1 << i++);
259         }
260
261         delta = (((size_t) _dl_malloc_addr + __size) & (rounded - 1));
262
263         if ((result = _dl_malloc(rounded - delta)) == NULL)
264                 return result;
265
266         result = _dl_malloc(__size);
267
268         return result;
269 }
270 #endif
271
272 static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void)
273 {
274         unsigned int i;
275         struct elf_resolve * tpnt;
276
277         for (i = 0; i < nlist; ++i) {
278                 tpnt = init_fini_list[i];
279                 if (tpnt->init_flag & FINI_FUNCS_CALLED)
280                         continue;
281                 tpnt->init_flag |= FINI_FUNCS_CALLED;
282                 _dl_run_fini_array(tpnt);
283                 if (tpnt->dynamic_info[DT_FINI]) {
284                         void (*dl_elf_func) (void);
285
286                         dl_elf_func = (void (*)(void)) (intptr_t) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI]);
287                         _dl_if_debug_dprint("\ncalling FINI: %s\n\n", tpnt->libname);
288                         DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
289                 }
290         }
291 }
292
293 #ifdef __LDSO_PRELINK_SUPPORT__
294
295 static void trace_objects(struct elf_resolve *tpnt, char *str_name)
296 {
297         if (_dl_strcmp(_dl_trace_prelink, tpnt->libname) == 0)
298                 _dl_trace_prelink_map = tpnt;
299         if (tpnt->libtype == elf_executable) {
300 /* Main executeble */
301                 _dl_dprintf(1, "\t%s => %s (%x, %x)", tpnt->libname, tpnt->libname,
302                                         tpnt->mapaddr, DL_LOADADDR_BASE(tpnt->loadaddr));
303         } else {
304 /* Preloaded, Needed or interpreter */
305                 _dl_dprintf(1, "\t%s => %s (%x, %x)", str_name, tpnt->libname,
306                                         tpnt->mapaddr, DL_LOADADDR_BASE(tpnt->loadaddr));
307         }
308
309         if ((tpnt->libtype != program_interpreter) && (tpnt->l_tls_modid))
310                 _dl_dprintf (1, " TLS(%x, %x)\n", tpnt->l_tls_modid,
311                                         (size_t) tpnt->l_tls_offset);
312         else
313                 _dl_dprintf (1, "\n");
314 }
315
316 #endif
317
318 static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list,
319                                                                                 struct elf_resolve *map)
320 {
321         struct elf_resolve **p = list;
322         struct init_fini_list *q;
323
324         *p++ = map;
325         map->init_flag |= DL_RESERVED;
326         if (map->init_fini)
327                 for (q = map->init_fini; q; q = q->next)
328                         if (! (q->tpnt->init_flag & DL_RESERVED))
329                                 p += _dl_build_local_scope (p, q->tpnt);
330         return p - list;
331 }
332
333 void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
334                           ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv
335                           DL_GET_READY_TO_RUN_EXTRA_PARMS)
336 {
337         ElfW(Addr) app_mapaddr = 0;
338         ElfW(Phdr) *ppnt;
339         ElfW(Dyn) *dpnt;
340         char *lpntstr;
341         unsigned int i, cnt, k, nscope_elem;
342         int unlazy = 0, trace_loaded_objects = 0;
343         struct dyn_elf *rpnt;
344         struct elf_resolve *tcurr;
345         struct elf_resolve *tpnt1;
346         struct elf_resolve app_tpnt_tmp;
347         struct elf_resolve *app_tpnt = &app_tpnt_tmp;
348         struct r_debug *debug_addr;
349         unsigned long *lpnt;
350         unsigned long *_dl_envp;                /* The environment address */
351         ElfW(Addr) relro_addr = 0;
352         size_t relro_size = 0;
353         struct r_scope_elem *global_scope;
354         struct elf_resolve **local_scope;
355
356         struct stat st;
357 #if defined(USE_TLS) && USE_TLS
358         void *tcbp = NULL;
359 #endif
360
361         /* Wahoo!!! We managed to make a function call!  Get malloc
362          * setup so we can use _dl_dprintf() to print debug noise
363          * instead of the SEND_STDERR macros used in dl-startup.c */
364
365         _dl_memset(app_tpnt, 0, sizeof(*app_tpnt));
366
367         /* Store the page size for later use */
368         _dl_pagesize = (auxvt[AT_PAGESZ].a_un.a_val) ? (size_t) auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE;
369         /* Make it so _dl_malloc can use the page of memory we have already
370          * allocated.  We shouldn't need to grab any more memory.  This must
371          * be first since things like _dl_dprintf() use _dl_malloc()...
372          */
373         _dl_malloc_addr = (unsigned char *)_dl_pagesize;
374         _dl_mmap_zero = 0;
375
376         /* Wahoo!!! */
377         _dl_debug_early("Cool, ldso survived making function calls\n");
378
379         /* Now we have done the mandatory linking of some things.  We are now
380          * free to start using global variables, since these things have all
381          * been fixed up by now.  Still no function calls outside of this
382          * library, since the dynamic resolver is not yet ready.
383          */
384         if (argv[0]) {
385                 _dl_progname = argv[0];
386         }
387
388 #ifndef __LDSO_STANDALONE_SUPPORT__
389         if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
390                 _dl_dprintf(_dl_debug_file, "Standalone execution is not enabled\n");
391                 _dl_exit(1);
392         }
393 #endif
394
395         /* Start to build the tables of the modules that are required for
396          * this beast to run.  We start with the basic executable, and then
397          * go from there.  Eventually we will run across ourself, and we
398          * will need to properly deal with that as well.
399          */
400         rpnt = NULL;
401         if (_dl_getenv("LD_BIND_NOW", envp))
402                 unlazy = RTLD_NOW;
403
404         /* Now we need to figure out what kind of options are selected.
405          * Note that for SUID programs we ignore the settings in
406          * LD_LIBRARY_PATH.
407          */
408         if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && _dl_suid_ok()) ||
409             (auxvt[AT_UID].a_un.a_val != (size_t)-1 &&
410              auxvt[AT_UID].a_un.a_val == auxvt[AT_EUID].a_un.a_val &&
411              auxvt[AT_GID].a_un.a_val == auxvt[AT_EGID].a_un.a_val)) {
412                 _dl_secure = 0;
413 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
414                 _dl_preload = _dl_getenv("LD_PRELOAD", envp);
415 #endif
416                 _dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp);
417         } else {
418                 static const char unsecure_envvars[] =
419 #ifdef EXTRA_UNSECURE_ENVVARS
420                         EXTRA_UNSECURE_ENVVARS
421 #endif
422                         UNSECURE_ENVVARS;
423                 const char *nextp;
424                 _dl_secure = 1;
425
426                 nextp = unsecure_envvars;
427                 do {
428                         _dl_unsetenv (nextp, envp);
429                         /* We could use rawmemchr but this need not be fast.  */
430                         nextp = _dl_strchr(nextp, '\0') + 1;
431                 } while (*nextp != '\0');
432 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
433                 _dl_preload = NULL;
434 #endif
435                 _dl_library_path = NULL;
436                 /* SUID binaries can be exploited if they do LAZY relocation. */
437                 unlazy = RTLD_NOW;
438         }
439
440 #if defined(USE_TLS) && USE_TLS
441         _dl_error_catch_tsd = &_dl_initial_error_catch_tsd;
442         _dl_init_static_tls = &_dl_nothread_init_static_tls;
443 #endif
444
445 #ifdef __LDSO_STANDALONE_SUPPORT__
446         if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
447                 char *ptmp;
448                 unsigned int *aux_dat = (unsigned int *) argv;
449                 int argc = aux_dat[-1];
450
451                 tpnt->libname = argv[0];
452                 while (argc > 1)
453                         if (! _dl_strcmp (argv[1], "--library-path") && argc > 2) {
454                                 _dl_library_path = argv[2];
455                                 _dl_skip_args += 2;
456                                 argc -= 2;
457                                 argv += 2;
458                         } else
459                                 break;
460
461         /*
462          * If we have no further argument the program was called incorrectly.
463          * Grant the user some education.
464          */
465
466                 if (argc < 2) {
467                         _dl_dprintf(1, "\
468 Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\
469 You have invoked `ld.so', the helper program for shared library executables.\n\
470 This program usually lives in the file `/lib/ld.so', and special directives\n\
471 in executable files using ELF shared libraries tell the system's program\n\
472 loader to load the helper program from this file.  This helper program loads\n\
473 the shared libraries needed by the program executable, prepares the program\n\
474 to run, and runs it.  You may invoke this helper program directly from the\n\
475 command line to load and run an ELF executable file; this is like executing\n\
476 that file itself, but always uses this helper program from the file you\n\
477 specified, instead of the helper program file specified in the executable\n\
478 file you run.  This is mostly of use for maintainers to test new versions\n\
479 of this helper program; chances are you did not intend to run this program.\n\
480 \n\
481   --library-path PATH   use given PATH instead of content of the environment\n\
482                         variable LD_LIBRARY_PATH\n");
483                         _dl_exit(1);
484                 }
485
486                 ++_dl_skip_args;
487                 ++argv;
488                 _dl_progname = argv[0];
489
490                 _dl_symbol_tables = rpnt = _dl_zalloc(sizeof(struct dyn_elf));
491                 /*
492                  * It needs to load the _dl_progname and to map it
493                  * Usually it is the main application launched by means of the ld.so
494                  * but it could be also a shared object (when ld.so used for tracing)
495                  * We keep the misleading app_tpnt name to avoid variable pollution
496                  */
497                 app_tpnt = _dl_load_elf_shared_library(_dl_secure, &rpnt, _dl_progname);
498                 if (!app_tpnt) {
499                         _dl_dprintf(_dl_debug_file, "can't load '%s'\n", _dl_progname);
500                         _dl_exit(16);
501                 }
502                 /*
503                  * FIXME: it needs to properly handle a PIE executable
504                  * Usually for a main application, loadaddr is computed as difference
505                  * between auxvt entry points and phdr, so if it is not 0, that it is a
506                  * PIE executable. In this case instead we need to set the loadaddr to 0
507                  * because we are actually mapping the ELF for the main application by
508                  * ourselves. So the PIE case must be checked.
509                  */
510
511                 app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
512
513                 if (app_tpnt->libtype == elf_executable)
514                         app_tpnt->loadaddr = 0;
515
516                 /*
517                  * This is used by gdb to locate the chain of shared libraries that are
518                  * currently loaded.
519                  */
520                 debug_addr = _dl_zalloc(sizeof(struct r_debug));
521                 ppnt = (ElfW(Phdr) *)app_tpnt->ppnt;
522                 for (i = 0; i < app_tpnt->n_phent; i++, ppnt++) {
523                         if (ppnt->p_type == PT_DYNAMIC) {
524                                 dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
525                                 _dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr);
526                         }
527                 }
528
529                 /* Store the path where the shared lib loader was found
530                  * for later use
531                  */
532                 _dl_ldsopath = _dl_strdup(tpnt->libname);
533                 ptmp = _dl_strrchr(_dl_ldsopath, '/');
534                 if (ptmp != _dl_ldsopath)
535                         *ptmp = '\0';
536
537                 _dl_debug_early("Lib Loader: (%x) %s\n", (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname);
538         } else {
539 #endif
540
541         /* At this point we are now free to examine the user application,
542          * and figure out which libraries are supposed to be called.  Until
543          * we have this list, we will not be completely ready for dynamic
544          * linking.
545          */
546
547         /* Find the runtime load address of the main executable.  This may be
548          * different from what the ELF header says for ET_DYN/PIE executables.
549          */
550         {
551                 unsigned int idx;
552                 ElfW(Phdr) *phdr = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
553
554                 for (idx = 0; idx < auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++)
555                         if (phdr->p_type == PT_PHDR) {
556                                 DL_INIT_LOADADDR_PROG(app_tpnt->loadaddr, auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr);
557                                 break;
558                         }
559
560                 if (DL_LOADADDR_BASE(app_tpnt->loadaddr))
561                         _dl_debug_early("Position Independent Executable: "
562                                         "app_tpnt->loadaddr=%x\n", DL_LOADADDR_BASE(app_tpnt->loadaddr));
563         }
564
565         /*
566          * This is used by gdb to locate the chain of shared libraries that are
567          * currently loaded.
568          */
569         debug_addr = _dl_zalloc(sizeof(struct r_debug));
570
571         ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
572         for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
573                 if (ppnt->p_type == PT_GNU_RELRO) {
574                         relro_addr = ppnt->p_vaddr;
575                         relro_size = ppnt->p_memsz;
576                 }
577                 if (!app_mapaddr && (ppnt->p_type == PT_LOAD)) {
578                         app_mapaddr = DL_RELOC_ADDR (app_tpnt->loadaddr, ppnt->p_vaddr);
579                 }
580                 if (ppnt->p_type == PT_DYNAMIC) {
581                         dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
582                         _dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr);
583 #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
584                         /* Ugly, ugly.  We need to call mprotect to change the
585                          * protection of the text pages so that we can do the
586                          * dynamic linking.  We can set the protection back
587                          * again once we are done.
588                          */
589                         _dl_debug_early("calling mprotect on the application program\n");
590                         /* Now cover the application program. */
591                         if (app_tpnt->dynamic_info[DT_TEXTREL]) {
592                                 ElfW(Phdr) *ppnt_outer = ppnt;
593                                 ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
594                                 for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
595                                         if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))
596                                                 _dl_mprotect((void *) (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & PAGE_ALIGN),
597                                                              (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & ADDR_ALIGN) +
598                                                              (unsigned long) ppnt->p_filesz,
599                                                              PROT_READ | PROT_WRITE | PROT_EXEC);
600                                 }
601                                 ppnt = ppnt_outer;
602                         }
603 #else
604                         if (app_tpnt->dynamic_info[DT_TEXTREL]) {
605                                 _dl_dprintf(_dl_debug_file, "Can't modify application's text section; use the GCC option -fPIE for position-independent executables.\n");
606                                 _dl_exit(1);
607                         }
608 #endif
609
610 #ifndef ALLOW_ZERO_PLTGOT
611                         /* make sure it's really there. */
612                         if (app_tpnt->dynamic_info[DT_PLTGOT] == 0)
613                                 continue;
614 #endif
615                         /* OK, we have what we need - slip this one into the list. */
616                         app_tpnt = _dl_add_elf_hash_table(_dl_progname, app_tpnt->loadaddr,
617                                         app_tpnt->dynamic_info,
618                                         (unsigned long) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr),
619                                         ppnt->p_filesz);
620                         _dl_loaded_modules->libtype = elf_executable;
621                         _dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
622                         _dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val;
623                         _dl_symbol_tables = rpnt = _dl_zalloc(sizeof(struct dyn_elf));
624                         rpnt->dyn = _dl_loaded_modules;
625                         app_tpnt->mapaddr = app_mapaddr;
626                         app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
627                         app_tpnt->usage_count++;
628                         lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]);
629 #ifdef ALLOW_ZERO_PLTGOT
630                         if (lpnt)
631 #endif
632                                 INIT_GOT(lpnt, _dl_loaded_modules);
633                 }
634
635                 /* OK, fill this in - we did not have this before */
636                 if (ppnt->p_type == PT_INTERP) {
637                         tpnt->libname = (char *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
638 #ifdef __LDSO_SEARCH_INTERP_PATH__
639                         {
640                                 char *ptmp;
641                                 /* Store the path where the shared lib loader was found
642                                  * for later use
643                                  */
644                                 _dl_ldsopath = _dl_strdup(tpnt->libname);
645                                 ptmp = _dl_strrchr(_dl_ldsopath, '/');
646                                 if (ptmp != _dl_ldsopath)
647                                         *ptmp = '\0';
648                         }
649                         _dl_debug_early("Lib Loader: (%x) %s\n", (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname);
650 #endif
651                 }
652
653                 /* Discover any TLS sections if the target supports them. */
654                 if (ppnt->p_type == PT_TLS) {
655 #if defined(USE_TLS) && USE_TLS
656                         if (ppnt->p_memsz > 0) {
657                                 app_tpnt->l_tls_blocksize = ppnt->p_memsz;
658                                 app_tpnt->l_tls_align = ppnt->p_align;
659                                 if (ppnt->p_align == 0)
660                                         app_tpnt->l_tls_firstbyte_offset = 0;
661                                 else
662                                         app_tpnt->l_tls_firstbyte_offset =
663                                                 (ppnt->p_vaddr & (ppnt->p_align - 1));
664                                 app_tpnt->l_tls_initimage_size = ppnt->p_filesz;
665                                 app_tpnt->l_tls_initimage = (void *) ppnt->p_vaddr;
666
667                                 /* This image gets the ID one.  */
668                                 _dl_tls_max_dtv_idx = app_tpnt->l_tls_modid = 1;
669
670                         }
671                         _dl_debug_early("Found TLS header for appplication program\n");
672                         break;
673 #else
674                         _dl_dprintf(_dl_debug_file, "Program uses unsupported TLS data!\n");
675                         _dl_exit(1);
676 #endif
677                 }
678         }
679         app_tpnt->relro_addr = relro_addr;
680         app_tpnt->relro_size = relro_size;
681
682 #if defined(USE_TLS) && USE_TLS
683         /*
684          * Adjust the address of the TLS initialization image in
685          * case the executable is actually an ET_DYN object.
686          */
687         if (app_tpnt->l_tls_initimage != NULL) {
688                 unsigned int tmp = (unsigned int) app_tpnt->l_tls_initimage;
689                 app_tpnt->l_tls_initimage =
690                         (char *) app_tpnt->l_tls_initimage + app_tpnt->loadaddr;
691                 _dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n",
692                         tmp, app_tpnt->l_tls_initimage, app_tpnt->l_tls_initimage_size);
693         }
694 #endif
695
696 #ifdef __LDSO_STANDALONE_SUPPORT__
697         } /* ! ldso standalone mode */
698 #endif
699
700 #ifdef __SUPPORT_LD_DEBUG__
701         _dl_debug = _dl_getenv("LD_DEBUG", envp);
702         if (_dl_debug) {
703                 if (_dl_strstr(_dl_debug, "all")) {
704                         _dl_debug_detail = _dl_debug_move = _dl_debug_symbols
705                                 = _dl_debug_reloc = _dl_debug_bindings = _dl_debug_nofixups = (void*)1;
706                 } else {
707                         _dl_debug_detail   = _dl_strstr(_dl_debug, "detail");
708                         _dl_debug_move     = _dl_strstr(_dl_debug, "move");
709                         _dl_debug_symbols  = _dl_strstr(_dl_debug, "sym");
710                         _dl_debug_reloc    = _dl_strstr(_dl_debug, "reloc");
711                         _dl_debug_nofixups = _dl_strstr(_dl_debug, "nofix");
712                         _dl_debug_bindings = _dl_strstr(_dl_debug, "bind");
713                 }
714         }
715
716         {
717                 const char *dl_debug_output;
718
719                 dl_debug_output = _dl_getenv("LD_DEBUG_OUTPUT", envp);
720
721                 if (dl_debug_output) {
722                         char tmp[22], *tmp1, *filename;
723                         int len1, len2;
724
725                         _dl_memset(tmp, 0, sizeof(tmp));
726                         tmp1 = _dl_simple_ltoa( tmp, (unsigned long)_dl_getpid());
727
728                         len1 = _dl_strlen(dl_debug_output);
729                         len2 = _dl_strlen(tmp1);
730
731                         filename = _dl_malloc(len1 + len2 + 2);
732
733                         if (filename) {
734                                 _dl_strcpy (filename, dl_debug_output);
735                                 filename[len1] = '.';
736                                 _dl_strcpy (&filename[len1+1], tmp1);
737
738                                 _dl_debug_file = _dl_open(filename, O_WRONLY|O_CREAT, 0644);
739                                 if (_dl_debug_file < 0) {
740                                         _dl_debug_file = 2;
741                                         _dl_dprintf(_dl_debug_file, "can't open file: '%s'\n",filename);
742                                 }
743                         }
744                 }
745         }
746 #endif
747
748 #ifdef __LDSO_PRELINK_SUPPORT__
749 {
750         char *ld_warn = _dl_getenv ("LD_WARN", envp);
751
752         if (ld_warn && *ld_warn == '\0')
753                 _dl_verbose = false;
754 }
755         _dl_trace_prelink = _dl_getenv("LD_TRACE_PRELINKING", envp);
756 #endif
757
758         if (_dl_getenv("LD_TRACE_LOADED_OBJECTS", envp) != NULL) {
759                 trace_loaded_objects++;
760         }
761
762 #ifndef __LDSO_LDD_SUPPORT__
763         if (trace_loaded_objects) {
764                 _dl_dprintf(_dl_debug_file, "Use the ldd provided by uClibc\n");
765                 _dl_exit(1);
766         }
767 #endif
768
769         /*
770          * OK, fix one more thing - set up debug_addr so it will point
771          * to our chain.  Later we may need to fill in more fields, but this
772          * should be enough for now.
773          */
774         debug_addr->r_map = (struct link_map *) _dl_loaded_modules;
775         debug_addr->r_version = 1;
776         debug_addr->r_ldbase = (ElfW(Addr)) DL_LOADADDR_BASE(load_addr);
777         debug_addr->r_brk = (unsigned long) &_dl_debug_state;
778         _dl_debug_addr = debug_addr;
779
780         /* Do not notify the debugger until the interpreter is in the list */
781
782         /* OK, we now have the application in the list, and we have some
783          * basic stuff in place.  Now search through the list for other shared
784          * libraries that should be loaded, and insert them on the list in the
785          * correct order.
786          */
787
788         _dl_map_cache();
789
790 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
791         if (_dl_preload) {
792                 char c, *str, *str2;
793
794                 str = _dl_preload;
795                 while (*str == ':' || *str == ' ' || *str == '\t')
796                         str++;
797
798                 while (*str) {
799                         str2 = str;
800                         while (*str2 && *str2 != ':' && *str2 != ' ' && *str2 != '\t')
801                                 str2++;
802                         c = *str2;
803                         *str2 = '\0';
804
805                         if (!_dl_secure || _dl_strchr(str, '/') == NULL) {
806                                 _dl_if_debug_dprint("\tfile='%s';  needed by '%s'\n", str, _dl_progname);
807
808                                 tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str, trace_loaded_objects);
809                                 if (!tpnt1) {
810 #ifdef __LDSO_LDD_SUPPORT__
811                                         if (trace_loaded_objects || _dl_trace_prelink)
812                                                 _dl_dprintf(1, "\t%s => not found\n", str);
813                                         else
814 #endif
815                                         {
816                                                 _dl_dprintf(_dl_debug_file, "%s: can't load " "library '%s'\n", _dl_progname, str);
817                                                 _dl_exit(15);
818                                         }
819                                 } else {
820                                         tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
821
822                                         _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
823
824 #ifdef __LDSO_LDD_SUPPORT__
825                                         if (trace_loaded_objects && !_dl_trace_prelink &&
826                                             tpnt1->usage_count == 1) {
827                                                 /* This is a real hack to make
828                                                  * ldd not print the library
829                                                  * itself when run on a
830                                                  * library.
831                                                  */
832                                                 if (_dl_strcmp(_dl_progname, str) != 0)
833                                                         _dl_dprintf(1, "\t%s => %s (%x)\n", str, tpnt1->libname,
834                                                                     DL_LOADADDR_BASE(tpnt1->loadaddr));
835                                         }
836 #endif
837                                 }
838                         }
839
840                         *str2 = c;
841                         str = str2;
842                         while (*str == ':' || *str == ' ' || *str == '\t')
843                                 str++;
844                 }
845         }
846 #endif /* __LDSO_PRELOAD_ENV_SUPPORT__ */
847
848 #ifdef __LDSO_PRELOAD_FILE_SUPPORT__
849         do {
850                 char *preload;
851                 int fd;
852                 char c, *cp, *cp2;
853
854                 if (_dl_stat(LDSO_PRELOAD, &st) || st.st_size == 0) {
855                         break;
856                 }
857
858                 if ((fd = _dl_open(LDSO_PRELOAD, O_RDONLY, 0)) < 0) {
859                         _dl_dprintf(_dl_debug_file, "%s: can't open file '%s'\n",
860                                     _dl_progname, LDSO_PRELOAD);
861                         break;
862                 }
863
864                 preload = (caddr_t) _dl_mmap(0, st.st_size + 1,
865                                              PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
866                 _dl_close(fd);
867                 if (preload == (caddr_t) -1) {
868                         _dl_dprintf(_dl_debug_file, "%s:%i: can't map '%s'\n",
869                                     _dl_progname, __LINE__, LDSO_PRELOAD);
870                         break;
871                 }
872
873                 /* convert all separators and comments to spaces */
874                 for (cp = preload; *cp; /*nada */ ) {
875                         if (*cp == ':' || *cp == '\t' || *cp == '\n') {
876                                 *cp++ = ' ';
877                         } else if (*cp == '#') {
878                                 do {
879                                         *cp++ = ' ';
880                                 } while (*cp != '\n' && *cp != '\0');
881                         } else {
882                                 cp++;
883                         }
884                 }
885
886                 /* find start of first library */
887                 for (cp = preload; *cp && *cp == ' '; cp++)
888                         /*nada */ ;
889
890                 while (*cp) {
891                         /* find end of library */
892                         for (cp2 = cp; *cp && *cp != ' '; cp++)
893                                 /*nada */ ;
894                         c = *cp;
895                         *cp = '\0';
896
897                         _dl_if_debug_dprint("\tfile='%s';  needed by '%s'\n", cp2, _dl_progname);
898
899                         tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2, trace_loaded_objects);
900                         if (!tpnt1) {
901 # ifdef __LDSO_LDD_SUPPORT__
902                                 if (trace_loaded_objects || _dl_trace_prelink)
903                                         _dl_dprintf(1, "\t%s => not found\n", cp2);
904                                 else
905 # endif
906                                 {
907                                         _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, cp2);
908                                         _dl_exit(15);
909                                 }
910                         } else {
911                                 tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
912
913                                 _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
914
915 # ifdef __LDSO_LDD_SUPPORT__
916                                 if (trace_loaded_objects && !_dl_trace_prelink &&
917                                     tpnt1->usage_count == 1) {
918                                         _dl_dprintf(1, "\t%s => %s (%x)\n",
919                                                     cp2, tpnt1->libname,
920                                                     DL_LOADADDR_BASE(tpnt1->loadaddr));
921                                 }
922 # endif
923                         }
924
925                         /* find start of next library */
926                         *cp = c;
927                         for ( /*nada */ ; *cp && *cp == ' '; cp++)
928                                 /*nada */ ;
929                 }
930
931                 _dl_munmap(preload, st.st_size + 1);
932         } while (0);
933 #endif /* __LDSO_PRELOAD_FILE_SUPPORT__ */
934
935         nlist = 0;
936         for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) {
937                 ElfW(Dyn) *this_dpnt;
938
939                 nlist++;
940                 for (this_dpnt = (ElfW(Dyn) *) tcurr->dynamic_addr; this_dpnt->d_tag; this_dpnt++) {
941                         if (this_dpnt->d_tag == DT_NEEDED) {
942                                 char *name;
943                                 struct init_fini_list *tmp;
944
945                                 lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + this_dpnt->d_un.d_val);
946                                 name = _dl_get_last_path_component(lpntstr);
947                                 if (_dl_strcmp(name, UCLIBC_LDSO) == 0)
948                                         continue;
949
950                                 _dl_if_debug_dprint("\tfile='%s';  needed by '%s'\n", lpntstr, _dl_progname);
951
952                                 if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects))) {
953 #ifdef __LDSO_LDD_SUPPORT__
954                                         if (trace_loaded_objects || _dl_trace_prelink) {
955                                                 _dl_dprintf(1, "\t%s => not found\n", lpntstr);
956                                                 continue;
957                                         } else
958 #endif
959                                         {
960                                                 _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, lpntstr);
961                                                 _dl_exit(16);
962                                         }
963                                 }
964
965                                 tmp = alloca(sizeof(struct init_fini_list)); /* Allocates on stack, no need to free this memory */
966                                 tmp->tpnt = tpnt1;
967                                 tmp->next = tcurr->init_fini;
968                                 tcurr->init_fini = tmp;
969
970                                 tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
971
972                                 _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);
973
974 #ifdef __LDSO_LDD_SUPPORT__
975                                 if (trace_loaded_objects && !_dl_trace_prelink &&
976                                     tpnt1->usage_count == 1) {
977                                         _dl_dprintf(1, "\t%s => %s (%x)\n",
978                                                     lpntstr, tpnt1->libname,
979                                                     DL_LOADADDR_BASE(tpnt1->loadaddr));
980                                 }
981 #endif
982                         }
983                 }
984         }
985         _dl_unmap_cache();
986
987         /* Keep track of the number of elements in the global scope */
988         nscope_elem = nlist;
989
990         if (_dl_loaded_modules->libtype == elf_executable) {
991                 --nlist; /* Exclude the application. */
992                 tcurr = _dl_loaded_modules->next;
993         } else
994                 tcurr = _dl_loaded_modules;
995         init_fini_list = _dl_malloc(nlist * sizeof(struct elf_resolve *));
996         i = 0;
997         for (; tcurr; tcurr = tcurr->next)
998                 init_fini_list[i++] = tcurr;
999
1000         /* Sort the INIT/FINI list in dependency order. */
1001         for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
1002                 unsigned int j, k;
1003
1004                 for (j = 0; init_fini_list[j] != tcurr; ++j)
1005                         /* Empty */;
1006                 for (k = j + 1; k < nlist; ++k) {
1007                         struct init_fini_list *runp = init_fini_list[k]->init_fini;
1008
1009                         for (; runp; runp = runp->next) {
1010                                 if (runp->tpnt == tcurr) {
1011                                         struct elf_resolve *here = init_fini_list[k];
1012                                         _dl_if_debug_dprint("Move %s from pos %d to %d in INIT/FINI list\n", here->libname, k, j);
1013                                         for (i = (k - j); i; --i)
1014                                                 init_fini_list[i+j] = init_fini_list[i+j-1];
1015                                         init_fini_list[j] = here;
1016                                         ++j;
1017                                         break;
1018                                 }
1019                         }
1020                 }
1021         }
1022 #ifdef __SUPPORT_LD_DEBUG__
1023         if (_dl_debug) {
1024                 _dl_dprintf(_dl_debug_file, "\nINIT/FINI order and dependencies:\n");
1025                 for (i = 0; i < nlist; i++) {
1026                         struct init_fini_list *tmp;
1027
1028                         _dl_dprintf(_dl_debug_file, "lib: %s has deps:\n",
1029                                     init_fini_list[i]->libname);
1030                         tmp = init_fini_list[i]->init_fini;
1031                         for (; tmp; tmp = tmp->next)
1032                                 _dl_dprintf(_dl_debug_file, " %s ", tmp->tpnt->libname);
1033                         _dl_dprintf(_dl_debug_file, "\n");
1034                 }
1035         }
1036 #endif
1037
1038         /*
1039          * If the program interpreter is not in the module chain, add it.
1040          * This will be required for dlopen to be able to access the internal
1041          * functions in the dynamic linker and to relocate the interpreter
1042          * again once all libs are loaded.
1043          */
1044         if (tpnt) {
1045                 ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
1046                 ElfW(Phdr) *myppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(load_addr, epnt->e_phoff);
1047                 int j;
1048
1049                 tpnt = _dl_add_elf_hash_table(tpnt->libname, load_addr,
1050                                               tpnt->dynamic_info,
1051                                               (unsigned long)tpnt->dynamic_addr,
1052                                               0);
1053
1054                 if (_dl_stat(tpnt->libname, &st) >= 0) {
1055                         tpnt->st_dev = st.st_dev;
1056                         tpnt->st_ino = st.st_ino;
1057                 }
1058                 tpnt->n_phent = epnt->e_phnum;
1059                 tpnt->ppnt = myppnt;
1060                 for (j = 0; j < epnt->e_phnum; j++, myppnt++) {
1061                         if (myppnt->p_type ==  PT_GNU_RELRO) {
1062                                 tpnt->relro_addr = myppnt->p_vaddr;
1063                                 tpnt->relro_size = myppnt->p_memsz;
1064                                 break;
1065                         }
1066                 }
1067                 tpnt->libtype = program_interpreter;
1068                 tpnt->usage_count++;
1069                 nscope_elem++;
1070                 if (rpnt) {
1071                         rpnt->next = _dl_zalloc(sizeof(struct dyn_elf));
1072                         rpnt->next->prev = rpnt;
1073                         rpnt = rpnt->next;
1074                 } else {
1075                         rpnt = _dl_zalloc(sizeof(struct dyn_elf));
1076                 }
1077                 rpnt->dyn = tpnt;
1078                 tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */
1079
1080 #ifdef RERELOCATE_LDSO
1081                 /* Only rerelocate functions for now. */
1082                 tpnt->init_flag = RELOCS_DONE;
1083                 lpnt = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT]);
1084 # ifdef ALLOW_ZERO_PLTGOT
1085                 if (tpnt->dynamic_info[DT_PLTGOT])
1086 # endif
1087                         INIT_GOT(lpnt, tpnt);
1088 #else
1089                 tpnt->init_flag = RELOCS_DONE | JMP_RELOCS_DONE;
1090 #endif
1091                 tpnt = NULL;
1092         }
1093
1094         /*
1095          * Allocate the global scope array.
1096          */
1097         scope_elem_list = (struct elf_resolve **) _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
1098
1099         for (i = 0, tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next)
1100                 scope_elem_list[i++] = tcurr;
1101
1102         _dl_loaded_modules->symbol_scope.r_list = scope_elem_list;
1103         _dl_loaded_modules->symbol_scope.r_nlist = nscope_elem;
1104         /*
1105          * The symbol scope of the application, that is the first entry of the
1106          * _dl_loaded_modules list, is just the global scope to be used for the
1107          * symbol lookup.
1108          */
1109         global_scope = &_dl_loaded_modules->symbol_scope;
1110
1111         /* Build the local scope for each loaded modules. */
1112         local_scope = _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
1113         i = 1;
1114         for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
1115                 cnt = _dl_build_local_scope(local_scope, scope_elem_list[i++]);
1116                 tcurr->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *));
1117                 tcurr->symbol_scope.r_nlist = cnt;
1118                 _dl_memcpy (tcurr->symbol_scope.r_list, local_scope, cnt * sizeof (struct elf_resolve *));
1119                 /* Restoring the init_flag.*/
1120                 for (k = 1; k < nscope_elem; k++)
1121                         scope_elem_list[k]->init_flag &= ~DL_RESERVED;
1122         }
1123
1124         _dl_free(local_scope);
1125
1126 #ifdef __LDSO_LDD_SUPPORT__
1127         /* End of the line for ldd.... */
1128         if (trace_loaded_objects && !_dl_trace_prelink) {
1129                 _dl_dprintf(1, "\t%s => %s (%x)\n",
1130                             rpnt->dyn->libname + _dl_strlen(_dl_ldsopath) + 1,
1131                             rpnt->dyn->libname, DL_LOADADDR_BASE(rpnt->dyn->loadaddr));
1132                 _dl_exit(0);
1133         }
1134 #endif
1135
1136 #if defined(USE_TLS) && USE_TLS
1137         /* We do not initialize any of the TLS functionality unless any of the
1138          * initial modules uses TLS.  This makes dynamic loading of modules with
1139          * TLS impossible, but to support it requires either eagerly doing setup
1140          * now or lazily doing it later.  Doing it now makes us incompatible with
1141          * an old kernel that can't perform TLS_INIT_TP, even if no TLS is ever
1142          * used.  Trying to do it lazily is too hairy to try when there could be
1143          * multiple threads (from a non-TLS-using libpthread).  */
1144         bool was_tls_init_tp_called = tls_init_tp_called;
1145         if (tcbp == NULL) {
1146                 _dl_debug_early("Calling init_tls()!\n");
1147                 tcbp = init_tls ();
1148         }
1149 #endif
1150 #ifdef __UCLIBC_HAS_SSP__
1151         /* Set up the stack checker's canary.  */
1152         stack_chk_guard = _dl_setup_stack_chk_guard ();
1153 # ifdef THREAD_SET_STACK_GUARD
1154         THREAD_SET_STACK_GUARD (stack_chk_guard);
1155 #  ifdef __UCLIBC_HAS_SSP_COMPAT__
1156         __guard = stack_chk_guard;
1157 #  endif
1158 # else
1159         __stack_chk_guard = stack_chk_guard;
1160 # endif
1161 #endif
1162
1163
1164         /* FIXME: The glibc code doesn't trace the ldso when LD_TRACE_OBJECT is set,
1165          *        here has been trace to mantain the original one.
1166          *        Another difference Vs Glibc is the check to verify if an object is
1167          *        "statically linked" (only if LD_TRACE_OBJECT is on).
1168          */
1169
1170 #ifdef __LDSO_PRELINK_SUPPORT__
1171         if (_dl_trace_prelink) {
1172                 for (i = 0; i < nscope_elem; i++)
1173                         trace_objects(scope_elem_list[i],
1174                                 _dl_get_last_path_component(scope_elem_list[i]->libname));
1175
1176                 if (_dl_verbose)
1177                         /* Warn about undefined symbols. */
1178                         if (_dl_symbol_tables)
1179                                 if (_dl_fixup(_dl_symbol_tables, global_scope, unlazy))
1180                                         _dl_exit(-1);
1181                 _dl_exit(0);
1182         }
1183 #endif
1184
1185         _dl_debug_early("Beginning relocation fixups\n");
1186
1187 #ifdef __mips__
1188         /*
1189          * Relocation of the GOT entries for MIPS have to be done
1190          * after all the libraries have been loaded.
1191          */
1192         _dl_perform_mips_global_got_relocations(_dl_loaded_modules, !unlazy);
1193 #endif
1194
1195         /*
1196          * OK, now all of the kids are tucked into bed in their proper
1197          * addresses.  Now we go through and look for REL and RELA records that
1198          * indicate fixups to the GOT tables.  We need to do this in reverse
1199          * order so that COPY directives work correctly.
1200          */
1201         if (_dl_symbol_tables)
1202                 if (_dl_fixup(_dl_symbol_tables, global_scope, unlazy))
1203                         _dl_exit(-1);
1204
1205         for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
1206                 if (tpnt->relro_size)
1207                         _dl_protect_relro (tpnt);
1208         }
1209
1210 #if defined(USE_TLS) && USE_TLS
1211         if (!was_tls_init_tp_called && _dl_tls_max_dtv_idx > 0)
1212                 ++_dl_tls_generation;
1213
1214         _dl_debug_early("Calling _dl_allocate_tls_init()!\n");
1215
1216         /* Now that we have completed relocation, the initializer data
1217            for the TLS blocks has its final values and we can copy them
1218            into the main thread's TLS area, which we allocated above.  */
1219         _dl_allocate_tls_init (tcbp);
1220
1221         /* And finally install it for the main thread.  If ld.so itself uses
1222            TLS we know the thread pointer was initialized earlier.  */
1223         if (! tls_init_tp_called) {
1224                 const char *lossage = (char *) TLS_INIT_TP (tcbp, USE___THREAD);
1225                 if (__builtin_expect (lossage != NULL, 0)) {
1226                         _dl_debug_early("cannot set up thread-local storage: %s\n", lossage);
1227                         _dl_exit(30);
1228                 }
1229         }
1230 #endif /* USE_TLS */
1231
1232         /* OK, at this point things are pretty much ready to run.  Now we need
1233          * to touch up a few items that are required, and then we can let the
1234          * user application have at it.  Note that the dynamic linker itself
1235          * is not guaranteed to be fully dynamicly linked if we are using
1236          * ld.so.1, so we have to look up each symbol individually.
1237          */
1238
1239         _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", global_scope, NULL, NULL, 0, NULL);
1240         if (_dl_envp)
1241                 *_dl_envp = (unsigned long) envp;
1242
1243 #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
1244         {
1245                 unsigned int j;
1246                 ElfW(Phdr) *myppnt;
1247
1248                 /* We had to set the protections of all pages to R/W for
1249                  * dynamic linking.  Set text pages back to R/O.
1250                  */
1251                 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
1252                         for (myppnt = tpnt->ppnt, j = 0; j < tpnt->n_phent; j++, myppnt++) {
1253                                 if (myppnt->p_type == PT_LOAD && !(myppnt->p_flags & PF_W) && tpnt->dynamic_info[DT_TEXTREL]) {
1254                                         _dl_mprotect((void *) (DL_RELOC_ADDR(tpnt->loadaddr, myppnt->p_vaddr) & PAGE_ALIGN),
1255                                                         (myppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) myppnt->p_filesz, LXFLAGS(myppnt->p_flags));
1256                                 }
1257                         }
1258                 }
1259
1260         }
1261 #endif
1262         /* Notify the debugger we have added some objects. */
1263         _dl_debug_addr->r_state = RT_ADD;
1264         _dl_debug_state();
1265
1266         /* Run pre-initialization functions for the executable.  */
1267         _dl_run_array_forward(_dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAY],
1268                               _dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAYSZ],
1269                               _dl_loaded_modules->loadaddr);
1270
1271         /* Run initialization functions for loaded objects.  For the
1272            main executable, they will be run from __uClibc_main.  */
1273         for (i = nlist; i; --i) {
1274                 tpnt = init_fini_list[i-1];
1275                 tpnt->init_fini = NULL; /* Clear, since alloca was used */
1276                 if (tpnt->init_flag & INIT_FUNCS_CALLED)
1277                         continue;
1278                 tpnt->init_flag |= INIT_FUNCS_CALLED;
1279
1280                 if (tpnt->dynamic_info[DT_INIT]) {
1281                         void (*dl_elf_func) (void);
1282
1283                         dl_elf_func = (void (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_INIT]);
1284
1285                         _dl_if_debug_dprint("calling INIT: %s\n\n", tpnt->libname);
1286
1287                         DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void)));
1288                 }
1289
1290                 _dl_run_init_array(tpnt);
1291         }
1292
1293         /* Find the real malloc function and make ldso functions use that from now on */
1294         _dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "malloc",
1295                         global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1296
1297 #if defined(USE_TLS) && USE_TLS
1298         /* Find the real functions and make ldso functions use them from now on */
1299         _dl_calloc_function = (void* (*)(size_t, size_t)) (intptr_t)
1300                 _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1301
1302         _dl_realloc_function = (void* (*)(void *, size_t)) (intptr_t)
1303                 _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1304
1305         _dl_free_function = (void (*)(void *)) (intptr_t)
1306                 _dl_find_hash(__C_SYMBOL_PREFIX__ "free", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1307
1308         _dl_memalign_function = (void* (*)(size_t, size_t)) (intptr_t)
1309                 _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
1310
1311 #endif
1312
1313         /* Notify the debugger that all objects are now mapped in.  */
1314         _dl_debug_addr->r_state = RT_CONSISTENT;
1315         _dl_debug_state();
1316
1317 #ifdef __LDSO_STANDALONE_SUPPORT__
1318         if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val)
1319                 return (void *) app_tpnt->l_entry;
1320         else
1321 #endif
1322                 return (void *) auxvt[AT_ENTRY].a_un.a_val;
1323 }
1324
1325 #include "dl-hash.c"
1326 #include "dl-elf.c"