OSDN Git Service

Be extra careful to memset the correct size, not the size of some random
[uclinux-h8/uClibc.git] / ldso / ldso / ldso.c
1 /* vi: set sw=4 ts=4: */
2 /* Program to load an ELF binary on a linux system, and run it
3  * after resolving ELF shared library symbols
4  *
5  * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, 
6  *                              David Engel, Hongjiu Lu and Mitch D'Souza
7  * Copyright (C) 2001-2002, Erik Andersen
8  *
9  * All rights reserved.
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 // Support a list of library preloads in /etc/ld.so.preload
34 //#define SUPPORT_LDSO_PRELOAD_FILE
35
36
37 /* Disclaimer:  I have never seen any AT&T source code for SVr4, nor have
38    I ever taken any courses on internals.  This program was developed using
39    information available through the book "UNIX SYSTEM V RELEASE 4,
40    Programmers guide: Ansi C and Programming Support Tools", which did
41    a more than adequate job of explaining everything required to get this
42    working. */
43
44 /*
45  * The main trick with this program is that initially, we ourselves are
46  * not dynamicly linked.  This means that we cannot access any global
47  * variables or call any functions.  No globals initially, since the
48  * Global Offset Table (GOT) is initialized by the linker assuming a
49  * virtual address of 0, and no function calls initially since the
50  * Procedure Linkage Table (PLT) is not yet initialized.
51  *
52  * There are additional initial restrictions - we cannot use large
53  * switch statements, since the compiler generates tables of addresses
54  * and jumps through them.  We can use inline functions, because these
55  * do not transfer control to a new address, but they must be static so
56  * that they are not exported from the modules.  We cannot use normal
57  * syscall stubs, because these all reference the errno global variable
58  * which is not yet initialized.  We can use all of the local stack
59  * variables that we want.
60  *
61  * Life is further complicated by the fact that initially we do not
62  * want to do a complete dynamic linking.  We want to allow the user to
63  * supply new functions to override symbols (i.e. weak symbols and/or
64  * LD_PRELOAD).  So initially, we only perform relocations for
65  * variables that start with "_dl_" since ANSI specifies that the user
66  * is not supposed to redefine any of these variables.
67  *
68  * Fortunately, the linker itself leaves a few clues lying around, and
69  * when the kernel starts the image, there are a few further clues.
70  * First of all, there is Auxiliary Vector Table information sitting on
71  * which is provided to us by the kernel, and which includes
72  * information about the load address that the program interpreter was
73  * loaded at, the number of sections, the address the application was
74  * loaded at and so forth.  Here this information is stored in the
75  * array auxvt.  For details see linux/fs/binfmt_elf.c where it calls
76  * NEW_AUX_ENT() a bunch of time....
77  *
78  * Next, we need to find the GOT.  On most arches there is a register
79  * pointing to the GOT, but just in case (and for new ports) I've added
80  * some (slow) C code to locate the GOT for you. 
81  *
82  * This code was originally written for SVr4, and there the kernel
83  * would load all text pages R/O, so they needed to call mprotect a
84  * zillion times to mark all text pages as writable so dynamic linking
85  * would succeed.  Then when they were done, they would change the
86  * protections for all the pages back again.  Well, under Linux
87  * everything is loaded writable (since Linux does copy on write
88  * anyways) so all the mprotect stuff has been disabled.
89  *
90  * Initially, we do not have access to _dl_malloc since we can't yet
91  * make function calls, so we mmap one page to use as scratch space.
92  * Later on, when we can call _dl_malloc we reuse this this memory.
93  * This is also beneficial, since we do not want to use the same memory
94  * pool as malloc anyway - esp if the user redefines malloc to do
95  * something funky.
96  *
97  * Our first task is to perform a minimal linking so that we can call
98  * other portions of the dynamic linker.  Once we have done this, we
99  * then build the list of modules that the application requires, using
100  * LD_LIBRARY_PATH if this is not a suid program (/usr/lib otherwise).
101  * Once this is done, we can do the dynamic linking as required, and we
102  * must omit the things we did to get the dynamic linker up and running
103  * in the first place.  After we have done this, we just have a few
104  * housekeeping chores and we can transfer control to the user's
105  * application.
106  */
107
108 #include "ld_syscall.h"
109 #include "linuxelf.h"
110 #include "ld_hash.h"
111 #include "ld_string.h"
112 #include "dlfcn.h"
113 #include "../config.h"
114
115 #define ALLOW_ZERO_PLTGOT
116
117 /*  Some arches may need to override this in boot1_arch.h */
118 #define     ELFMAGIC    ELFMAG
119
120 /* This is a poor man's malloc, used prior to resolving our internal poor man's malloc */
121 #define LD_MALLOC(SIZE) ((void *) (malloc_buffer += SIZE, malloc_buffer - SIZE)) ;  REALIGN();
122 /*
123  * Make sure that the malloc buffer is aligned on 4 byte boundary.  For 64 bit
124  * platforms we may need to increase this to 8, but this is good enough for
125  * now.  This is typically called after LD_MALLOC.
126  */
127 #define REALIGN() malloc_buffer = (char *) (((unsigned long) malloc_buffer + 3) & ~(3))
128
129 char *_dl_library_path = 0;             /* Where we look for libraries */
130 char *_dl_preload = 0;                  /* Things to be loaded before the libs. */
131 char *_dl_ldsopath = 0;
132 static char *_dl_not_lazy = 0;
133 #ifdef __SUPPORT_LD_DEBUG__
134 static char *_dl_debug  = 0;
135 static char *_dl_debug_symbols = 0;
136 static char *_dl_debug_move    = 0;
137 static char *_dl_debug_reloc   = 0;
138 static char *_dl_debug_detail  = 0;
139 static char *_dl_debug_nofixups  = 0;
140 static char *_dl_debug_bindings  = 0;
141 static int   _dl_debug_file = 2;
142 #else
143 #define _dl_debug_file 2
144 #endif
145 static char *_dl_malloc_addr, *_dl_mmap_zero;
146
147 static char *_dl_trace_loaded_objects = 0;
148 static int (*_dl_elf_main) (int, char **, char **);
149 static int (*_dl_elf_init) (void);
150 struct r_debug *_dl_debug_addr = NULL;
151 unsigned long *_dl_brkp;
152 unsigned long *_dl_envp;
153 int _dl_fixup(struct elf_resolve *tpnt);
154 void _dl_debug_state(void);
155 char *_dl_get_last_path_component(char *path);
156 static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt, 
157                 unsigned long load_addr, unsigned long *hash_addr, Elf32_auxv_t auxvt[AT_EGID + 1], 
158                 char **envp, struct r_debug *debug_addr);
159 #include "boot1_arch.h"
160 #include "ldso.h"                               /* Pull in the name of ld.so */
161
162
163 /* When we enter this piece of code, the program stack looks like this:
164         argc            argument counter (integer)
165         argv[0]         program name (pointer)
166         argv[1...N]     program args (pointers)
167         argv[argc-1]    end of args (integer)
168                 NULL
169         env[0...N]      environment variables (pointers)
170         NULL
171                 auxvt[0...N]   Auxiliary Vector Table elements (mixed types)
172 */
173
174 #ifdef __SUPPORT_LD_DEBUG_EARLY__
175 /* Debugging is especially tricky on PowerPC, since string literals
176  * require relocations.  Thus, you can't use _dl_dprintf() for
177  * anything until the bootstrap relocations are finished. */
178 static inline void hexprint(unsigned long x)
179 {
180         int i;
181         char c;
182
183         for (i = 0; i < 8; i++) {
184                 c = ((x >> 28) + '0');
185                 if (c > '9')
186                         c += 'a' - '9' - 1;
187                 _dl_write(1, &c, 1);
188                 x <<= 4;
189         }
190         c = '\n';
191         _dl_write(1, &c, 1);
192 }
193 #endif
194
195 LD_BOOT(unsigned long args) __attribute__ ((unused));
196
197 LD_BOOT(unsigned long args)
198 {
199         unsigned int argc;
200         char **argv, **envp;
201         unsigned long load_addr;
202         unsigned long *got;
203         unsigned long *aux_dat;
204         int goof = 0;
205         elfhdr *header;
206         struct elf_resolve *tpnt;
207         struct elf_resolve *app_tpnt;
208         Elf32_auxv_t auxvt[AT_EGID + 1];
209         unsigned char *malloc_buffer, *mmap_zero;
210         Elf32_Dyn *dpnt;
211         unsigned long *hash_addr;
212         struct r_debug *debug_addr = NULL;
213         int indx;
214         int status;
215
216
217         /* WARNING! -- we cannot make _any_ funtion calls until we have
218          * taken care of fixing up our own relocations.  Making static
219          * inline calls is ok, but _no_ function calls.  Not yet
220          * anyways. */
221
222         /* First obtain the information on the stack that tells us more about
223            what binary is loaded, where it is loaded, etc, etc */
224         GET_ARGV(aux_dat, args);
225 #if defined (__arm__) || defined (__mips__)
226         aux_dat += 1;
227 #endif
228         argc = *(aux_dat - 1);
229         argv = (char **) aux_dat;
230         aux_dat += argc;                        /* Skip over the argv pointers */
231         aux_dat++;                                      /* Skip over NULL at end of argv */
232         envp = (char **) aux_dat;
233         while (*aux_dat)
234                 aux_dat++;                              /* Skip over the envp pointers */
235         aux_dat++;                                      /* Skip over NULL at end of envp */
236
237         /* Place -1 here as a checkpoint.  We later check if it was changed
238          * when we read in the auxvt */
239         auxvt[AT_UID].a_type = -1;
240
241         /* The junk on the stack immediately following the environment is  
242          * the Auxiliary Vector Table.  Read out the elements of the auxvt,
243          * sort and store them in auxvt for later use. */
244         while (*aux_dat) {
245                 Elf32_auxv_t *auxv_entry = (Elf32_auxv_t *) aux_dat;
246
247                 if (auxv_entry->a_type <= AT_EGID) {
248                         _dl_memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(Elf32_auxv_t));
249                 }
250                 aux_dat += 2;
251         }
252
253         /* locate the ELF header.   We need this done as soon as possible 
254          * (esp since SEND_STDERR() needs this on some platforms... */
255         load_addr = auxvt[AT_BASE].a_un.a_val;
256         header = (elfhdr *) auxvt[AT_BASE].a_un.a_ptr;
257
258         /* Check the ELF header to make sure everything looks ok.  */
259         if (!header || header->e_ident[EI_CLASS] != ELFCLASS32 ||
260                 header->e_ident[EI_VERSION] != EV_CURRENT
261 #if !defined(__powerpc__) && !defined(__mips__) && !defined(__sh__)
262                 || _dl_strncmp((void *) header, ELFMAGIC, SELFMAG) != 0
263 #else
264                 || header->e_ident[EI_MAG0] != ELFMAG0
265                 || header->e_ident[EI_MAG1] != ELFMAG1
266                 || header->e_ident[EI_MAG2] != ELFMAG2
267                 || header->e_ident[EI_MAG3] != ELFMAG3
268 #endif
269                 ) {
270                 SEND_STDERR("Invalid ELF header\n");
271                 _dl_exit(0);
272         }
273 #ifdef __SUPPORT_LD_DEBUG_EARLY__
274         SEND_STDERR("ELF header=");
275         SEND_ADDRESS_STDERR(load_addr, 1);
276 #endif
277
278
279         /* Locate the global offset table.  Since this code must be PIC  
280          * we can take advantage of the magic offset register, if we
281          * happen to know what that is for this architecture.  If not,
282          * we can always read stuff out of the ELF file to find it... */
283 #if defined(__i386__)
284   __asm__("\tmovl %%ebx,%0\n\t":"=a"(got));
285 #elif defined(__m68k__)
286   __asm__("movel %%a5,%0":"=g"(got))
287 #elif defined(__sparc__)
288   __asm__("\tmov %%l7,%0\n\t":"=r"(got))
289 #elif defined(__arm__)
290   __asm__("\tmov %0, r10\n\t":"=r"(got));
291 #elif defined(__powerpc__)
292   __asm__("\tbl _GLOBAL_OFFSET_TABLE_-4@local\n\t":"=l"(got));
293 #elif defined(__mips__)
294   __asm__("\tmove %0, $28\n\tsubu %0,%0,0x7ff0\n\t":"=r"(got));
295 #elif defined(__sh__)
296   __asm__(
297 "       mov.l    1f, %0\n"
298 "       mova     1f, r0\n"
299 "       bra      2f\n"
300 "       add r0,  %0\n"
301 "       .balign  4\n"
302 "1:     .long    _GLOBAL_OFFSET_TABLE_\n"
303 "2:" : "=r" (got) : : "r0");
304 #elif defined(__cris__)
305   __asm__("\tmove.d $pc,%0\n\tsub.d .:GOTOFF,%0\n\t":"=r"(got));
306 #else
307         /* Do things the slow way in C */
308         {
309                 unsigned long tx_reloc;
310                 Elf32_Dyn *dynamic = NULL;
311                 Elf32_Shdr *shdr;
312                 Elf32_Phdr *pt_load;
313
314 #ifdef __SUPPORT_LD_DEBUG_EARLY__
315                 SEND_STDERR("Finding the GOT using C code to read the ELF file\n");
316 #endif
317                 /* Find where the dynamic linking information section is hiding */
318                 shdr = (Elf32_Shdr *) (header->e_shoff + (char *) header);
319                 for (indx = header->e_shnum; --indx >= 0; ++shdr) {
320                         if (shdr->sh_type == SHT_DYNAMIC) {
321                                 goto found_dynamic;
322                         }
323                 }
324                 SEND_STDERR("missing dynamic linking information section \n");
325                 _dl_exit(0);
326
327           found_dynamic:
328                 dynamic = (Elf32_Dyn *) (shdr->sh_offset + (char *) header);
329
330                 /* Find where PT_LOAD is hiding */
331                 pt_load = (Elf32_Phdr *) (header->e_phoff + (char *) header);
332                 for (indx = header->e_phnum; --indx >= 0; ++pt_load) {
333                         if (pt_load->p_type == PT_LOAD) {
334                                 goto found_pt_load;
335                         }
336                 }
337                 SEND_STDERR("missing loadable program segment\n");
338                 _dl_exit(0);
339
340           found_pt_load:
341                 /* Now (finally) find where DT_PLTGOT is hiding */
342                 tx_reloc = pt_load->p_vaddr - pt_load->p_offset;
343                 for (; DT_NULL != dynamic->d_tag; ++dynamic) {
344                         if (dynamic->d_tag == DT_PLTGOT) {
345                                 goto found_got;
346                         }
347                 }
348                 SEND_STDERR("missing global offset table\n");
349                 _dl_exit(0);
350
351           found_got:
352                 got = (unsigned long *) (dynamic->d_un.d_val - tx_reloc +
353                                 (char *) header);
354         }
355 #endif
356
357         /* Now, finally, fix up the location of the dynamic stuff */
358         dpnt = (Elf32_Dyn *) (*got + load_addr);
359 #ifdef __SUPPORT_LD_DEBUG_EARLY__
360         SEND_STDERR("First Dynamic section entry=");
361         SEND_ADDRESS_STDERR(dpnt, 1);
362 #endif
363
364
365         /* Call mmap to get a page of writable memory that can be used 
366          * for _dl_malloc throughout the shared lib loader. */
367         mmap_zero = malloc_buffer = _dl_mmap((void *) 0, 4096, 
368                         PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
369         if (_dl_mmap_check_error(mmap_zero)) {
370                 SEND_STDERR("dl_boot: mmap of a spare page failed!\n");
371                 _dl_exit(13);
372         }
373
374         tpnt = LD_MALLOC(sizeof(struct elf_resolve));
375         _dl_memset(tpnt, 0, sizeof(struct elf_resolve));
376         app_tpnt = LD_MALLOC(sizeof(struct elf_resolve));
377         _dl_memset(app_tpnt, 0, sizeof(struct elf_resolve));
378
379         /*
380          * This is used by gdb to locate the chain of shared libraries that are currently loaded.
381          */
382         debug_addr = LD_MALLOC(sizeof(struct r_debug));
383         _dl_memset(debug_addr, 0, sizeof(struct r_debug));
384
385         /* OK, that was easy.  Next scan the DYNAMIC section of the image.
386            We are only doing ourself right now - we will have to do the rest later */
387 #ifdef __SUPPORT_LD_DEBUG_EARLY__
388         SEND_STDERR("scanning DYNAMIC section\n");
389 #endif
390         while (dpnt->d_tag) {
391 #if defined(__mips__)
392                 if (dpnt->d_tag == DT_MIPS_GOTSYM)
393                         tpnt->mips_gotsym = (unsigned long) dpnt->d_un.d_val;
394                 if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
395                         tpnt->mips_local_gotno = (unsigned long) dpnt->d_un.d_val;
396                 if (dpnt->d_tag == DT_MIPS_SYMTABNO)
397                         tpnt->mips_symtabno = (unsigned long) dpnt->d_un.d_val;
398 #endif
399                 if (dpnt->d_tag < 24) {
400                         tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
401                         if (dpnt->d_tag == DT_TEXTREL) {
402                                 tpnt->dynamic_info[DT_TEXTREL] = 1;
403                         }
404                 }
405                 dpnt++;
406         }
407
408         {
409                 elf_phdr *ppnt;
410                 int i;
411
412                 ppnt = (elf_phdr *) auxvt[AT_PHDR].a_un.a_ptr;
413                 for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++)
414                         if (ppnt->p_type == PT_DYNAMIC) {
415                                 dpnt = (Elf32_Dyn *) ppnt->p_vaddr;
416                                 while (dpnt->d_tag) {
417 #if defined(__mips__)
418                                         if (dpnt->d_tag == DT_MIPS_GOTSYM)
419                                                 app_tpnt->mips_gotsym =
420                                                         (unsigned long) dpnt->d_un.d_val;
421                                         if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
422                                                 app_tpnt->mips_local_gotno =
423                                                         (unsigned long) dpnt->d_un.d_val;
424                                         if (dpnt->d_tag == DT_MIPS_SYMTABNO)
425                                                 app_tpnt->mips_symtabno =
426                                                         (unsigned long) dpnt->d_un.d_val;
427 #endif
428                                         if (dpnt->d_tag > DT_JMPREL) {
429                                                 dpnt++;
430                                                 continue;
431                                         }
432                                         app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
433 #if !defined(__mips__)
434                                         if (dpnt->d_tag == DT_DEBUG) {
435                                                 dpnt->d_un.d_val = (unsigned long) debug_addr;
436                                         }
437 #else
438 #warning "Debugging threads on mips won't work till someone fixes this..."
439 #endif
440                                         if (dpnt->d_tag == DT_TEXTREL)
441                                                 app_tpnt->dynamic_info[DT_TEXTREL] = 1;
442                                         dpnt++;
443                                 }
444                         }
445         }
446
447 #ifdef __SUPPORT_LD_DEBUG_EARLY__
448         SEND_STDERR("done scanning DYNAMIC section\n");
449 #endif
450
451         /* Get some more of the information that we will need to dynamicly link
452            this module to itself */
453
454         hash_addr = (unsigned long *) (tpnt->dynamic_info[DT_HASH] + load_addr);
455         tpnt->nbucket = *hash_addr++;
456         tpnt->nchain = *hash_addr++;
457         tpnt->elf_buckets = hash_addr;
458         hash_addr += tpnt->nbucket;
459
460 #ifdef __SUPPORT_LD_DEBUG_EARLY__
461         SEND_STDERR("done grabbing link information\n");
462 #endif
463
464 #ifndef FORCE_SHAREABLE_TEXT_SEGMENTS
465         /* Ugly, ugly.  We need to call mprotect to change the protection of
466            the text pages so that we can do the dynamic linking.  We can set the
467            protection back again once we are done */
468
469         {
470                 elf_phdr *ppnt;
471                 int i;
472
473 #ifdef __SUPPORT_LD_DEBUG_EARLY__
474                 SEND_STDERR("calling mprotect on the shared library/dynamic linker\n");
475 #endif
476
477                 /* First cover the shared library/dynamic linker. */
478                 if (tpnt->dynamic_info[DT_TEXTREL]) {
479                         header = (elfhdr *) auxvt[AT_BASE].a_un.a_ptr;
480                         ppnt = (elf_phdr *) ((int)auxvt[AT_BASE].a_un.a_ptr + 
481                                         header->e_phoff);
482                         for (i = 0; i < header->e_phnum; i++, ppnt++) {
483                                 if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) {
484                                         _dl_mprotect((void *) (load_addr + (ppnt->p_vaddr & PAGE_ALIGN)), 
485                                                         (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz, 
486                                                         PROT_READ | PROT_WRITE | PROT_EXEC);
487                                 }
488                         }
489                 }
490
491 #ifdef __SUPPORT_LD_DEBUG_EARLY__
492                 SEND_STDERR("calling mprotect on the application program\n");
493 #endif
494                 /* Now cover the application program. */
495                 if (app_tpnt->dynamic_info[DT_TEXTREL]) {
496                         ppnt = (elf_phdr *) auxvt[AT_PHDR].a_un.a_ptr;
497                         for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
498                                 if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))
499                                         _dl_mprotect((void *) (ppnt->p_vaddr & PAGE_ALIGN),
500                                                                  (ppnt->p_vaddr & ADDR_ALIGN) +
501                                                                  (unsigned long) ppnt->p_filesz,
502                                                                  PROT_READ | PROT_WRITE | PROT_EXEC);
503                         }
504                 }
505         }
506 #endif
507         
508 #if defined(__mips__)
509 #ifdef __SUPPORT_LD_DEBUG_EARLY__
510         SEND_STDERR("About to do MIPS specific GOT bootstrap\n");
511 #endif
512         /* For MIPS we have to do stuff to the GOT before we do relocations.  */
513         PERFORM_BOOTSTRAP_GOT(got);
514 #endif
515
516         /* OK, now do the relocations.  We do not do a lazy binding here, so
517            that once we are done, we have considerably more flexibility. */
518 #ifdef __SUPPORT_LD_DEBUG_EARLY__
519         SEND_STDERR("About to do library loader relocations\n");
520 #endif
521
522         goof = 0;
523         for (indx = 0; indx < 2; indx++) {
524                 unsigned int i;
525                 ELF_RELOC *rpnt;
526                 unsigned long *reloc_addr;
527                 unsigned long symbol_addr;
528                 int symtab_index;
529                 unsigned long rel_addr, rel_size;
530
531
532 #ifdef ELF_USES_RELOCA
533                 rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] : tpnt->
534                          dynamic_info[DT_RELA]);
535                 rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] : tpnt->
536                          dynamic_info[DT_RELASZ]);
537 #else
538                 rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] : tpnt->
539                          dynamic_info[DT_REL]);
540                 rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] : tpnt->
541                          dynamic_info[DT_RELSZ]);
542 #endif
543
544                 if (!rel_addr)
545                         continue;
546
547                 /* Now parse the relocation information */
548                 rpnt = (ELF_RELOC *) (rel_addr + load_addr);
549                 for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) {
550                         reloc_addr = (unsigned long *) (load_addr + (unsigned long) rpnt->r_offset);
551                         symtab_index = ELF32_R_SYM(rpnt->r_info);
552                         symbol_addr = 0;
553                         if (symtab_index) {
554                                 char *strtab;
555                                 Elf32_Sym *symtab;
556
557                                 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + load_addr);
558                                 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + load_addr);
559
560                                 /* We only do a partial dynamic linking right now.  The user
561                                    is not supposed to redefine any symbols that start with
562                                    a '_', so we can do this with confidence. */
563                                 if (!_dl_symbol(strtab + symtab[symtab_index].st_name))
564                                         continue;
565                                 symbol_addr = load_addr + symtab[symtab_index].st_value;
566
567                                 if (!symbol_addr) {
568                                         /* This will segfault - you cannot call a function until
569                                          * we have finished the relocations.
570                                          */
571                                         SEND_STDERR("ELF dynamic loader - unable to self-bootstrap - symbol ");
572                                         SEND_STDERR(strtab + symtab[symtab_index].st_name);
573                                         SEND_STDERR(" undefined.\n");
574                                         goof++;
575                                 }
576 #ifdef __SUPPORT_LD_DEBUG_EARLY__
577                                 SEND_STDERR("About to fixup symbol: ");
578                                 SEND_STDERR(strtab + symtab[symtab_index].st_name);
579                                 SEND_STDERR("\n");
580 #endif  
581                         }
582                         /*
583                          * Use this machine-specific macro to perform the actual relocation.
584                          */
585                         PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr);
586                 }
587         }
588
589         if (goof) {
590                 _dl_exit(14);
591         }
592 #ifdef __SUPPORT_LD_DEBUG_EARLY__
593         /* Wahoo!!! */
594         _dl_dprintf(_dl_debug_file, "Done relocating library loader, so we can now\n\tuse globals and make function calls!\n");
595 #endif
596
597         if (argv[0]) {
598                 _dl_progname = argv[0];
599         }
600
601         /* Start to build the tables of the modules that are required for
602          * this beast to run.  We start with the basic executable, and then
603          * go from there.  Eventually we will run across ourself, and we
604          * will need to properly deal with that as well. */
605
606         /* Make it so _dl_malloc can use the page of memory we have already
607          * allocated, so we shouldn't need to grab any more memory */
608         _dl_malloc_addr = malloc_buffer;
609         _dl_mmap_zero = mmap_zero;
610
611
612
613         /* Now we have done the mandatory linking of some things.  We are now
614            free to start using global variables, since these things have all been
615            fixed up by now.  Still no function calls outside of this library ,
616            since the dynamic resolver is not yet ready. */
617         _dl_get_ready_to_run(tpnt, app_tpnt, load_addr, hash_addr, auxvt, envp, debug_addr);
618
619
620         /* Notify the debugger that all objects are now mapped in.  */
621         _dl_debug_addr->r_state = RT_CONSISTENT;
622         _dl_debug_state();
623
624
625         /* OK we are done here.  Turn out the lights, and lock up. */
626         _dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_fcn;
627
628         /*
629          * Transfer control to the application.
630          */
631         status = 0;                                     /* Used on x86, but not on other arches */
632 #if defined (__SUPPORT_LD_DEBUG__)
633         if(_dl_debug) _dl_dprintf(_dl_debug_file,"\ntransfering control: %s\n\n", _dl_progname);        
634 #endif    
635         START();
636 }
637
638 #if defined (__SUPPORT_LD_DEBUG__)
639 static void debug_fini (int status, void *arg)
640 {
641         (void)status;
642         _dl_dprintf(_dl_debug_file,"\ncalling fini: %s\n\n", (const char*)arg);
643 }
644 #endif    
645
646 static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt, 
647                 unsigned long load_addr, unsigned long *hash_addr, Elf32_auxv_t auxvt[AT_EGID + 1], 
648                 char **envp, struct r_debug *debug_addr)
649 {
650         elf_phdr *ppnt;
651         char *lpntstr;
652         int i, _dl_secure, goof = 0;
653         struct dyn_elf *rpnt;
654         struct elf_resolve *tcurr;
655         struct elf_resolve *tpnt1;
656         unsigned long brk_addr, *lpnt;
657         int (*_dl_atexit) (void *);
658 #if defined (__SUPPORT_LD_DEBUG__)
659         int (*_dl_on_exit) (void (*FUNCTION)(int STATUS, void *ARG),void*);
660 #endif
661
662         /* Now we have done the mandatory linking of some things.  We are now
663            free to start using global variables, since these things have all been
664            fixed up by now.  Still no function calls outside of this library ,
665            since the dynamic resolver is not yet ready. */
666         lpnt = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT] + load_addr);
667
668         tpnt->chains = hash_addr;
669         tpnt->next = 0;
670         tpnt->libname = 0;
671         tpnt->libtype = program_interpreter;
672         tpnt->loadaddr = (char *) load_addr;
673
674 #ifdef ALLOW_ZERO_PLTGOT
675         if (tpnt->dynamic_info[DT_PLTGOT])
676 #endif
677         {
678                 INIT_GOT(lpnt, tpnt);
679 #ifdef __SUPPORT_LD_DEBUG_EARLY__
680                 _dl_dprintf(_dl_debug_file, "GOT found at %x\n", lpnt);
681 #endif
682         }
683
684         /* OK, this was a big step, now we need to scan all of the user images
685            and load them properly. */
686
687         {
688                 elfhdr *epnt;
689                 elf_phdr *myppnt;
690                 int j;
691
692                 epnt = (elfhdr *) auxvt[AT_BASE].a_un.a_ptr;
693                 tpnt->n_phent = epnt->e_phnum;
694                 tpnt->ppnt = myppnt = (elf_phdr *) (load_addr + epnt->e_phoff);
695                 for (j = 0; j < epnt->e_phnum; j++, myppnt++) {
696                         if (myppnt->p_type == PT_DYNAMIC) {
697                                 tpnt->dynamic_addr = myppnt->p_vaddr + load_addr;
698 #if defined(__mips__)
699                                 {
700                                         int k = 1;
701                                         Elf32_Dyn *dpnt = (Elf32_Dyn *) tpnt->dynamic_addr;
702
703                                         while(dpnt->d_tag) {
704                                                 dpnt++;
705                                                 k++;
706                                         }
707                                         tpnt->dynamic_size = k * sizeof(Elf32_Dyn);
708                                 }
709 #else
710                                 tpnt->dynamic_size = myppnt->p_filesz;
711 #endif
712                         }
713                 }
714         }
715
716         brk_addr = 0;
717         rpnt = NULL;
718
719         /* At this point we are now free to examine the user application,
720            and figure out which libraries are supposed to be called.  Until
721            we have this list, we will not be completely ready for dynamic linking */
722
723         ppnt = (elf_phdr *) auxvt[AT_PHDR].a_un.a_ptr;
724         for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
725                 if (ppnt->p_type == PT_LOAD) {
726                         if (ppnt->p_vaddr + ppnt->p_memsz > brk_addr)
727                                 brk_addr = ppnt->p_vaddr + ppnt->p_memsz;
728                 }
729                 if (ppnt->p_type == PT_DYNAMIC) {
730 #ifndef ALLOW_ZERO_PLTGOT
731                         /* make sure it's really there. */
732                         if (app_tpnt->dynamic_info[DT_PLTGOT] == 0)
733                                 continue;
734 #endif
735                         /* OK, we have what we need - slip this one into the list. */
736 #if defined(__mips__)
737                         {
738                                 int i = 1;
739                                 Elf32_Dyn *dpnt = (Elf32_Dyn *) tpnt->dynamic_addr;
740
741                                 while(dpnt->d_tag) {
742                                         dpnt++;
743                                         i++;
744                                 }
745                                 app_tpnt = _dl_add_elf_hash_table("", 0, 
746                                         app_tpnt->dynamic_info, ppnt->p_vaddr,
747                                         (i * sizeof(Elf32_Dyn)));
748                         }
749 #else
750                         app_tpnt = _dl_add_elf_hash_table("", 0, 
751                                         app_tpnt->dynamic_info, ppnt->p_vaddr, ppnt->p_filesz);
752 #endif
753                         _dl_loaded_modules->libtype = elf_executable;
754                         _dl_loaded_modules->ppnt = (elf_phdr *) auxvt[AT_PHDR].a_un.a_ptr;
755                         _dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val;
756                         _dl_symbol_tables = rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
757                         _dl_memset(rpnt, 0, sizeof(struct dyn_elf));
758                         rpnt->dyn = _dl_loaded_modules;
759                         app_tpnt->usage_count++;
760                         app_tpnt->symbol_scope = _dl_symbol_tables;
761                         lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]);
762 #ifdef ALLOW_ZERO_PLTGOT
763                         if (lpnt)
764 #endif
765                                 INIT_GOT(lpnt, _dl_loaded_modules);
766                 }
767
768                 /* OK, fill this in - we did not have this before */
769                 if (ppnt->p_type == PT_INTERP) {        
770                         int readsize = 0;
771                         char *pnt, *pnt1, buf[1024];
772                         tpnt->libname = _dl_strdup((char *) ppnt->p_offset +
773                                         (auxvt[AT_PHDR].a_un.a_val & PAGE_ALIGN));
774                         
775                         /* Determine if the shared lib loader is a symlink */
776                         _dl_memset(buf, 0, sizeof(buf));
777                         readsize = _dl_readlink(tpnt->libname, buf, sizeof(buf));
778                         if (readsize > 0 && readsize < (int)(sizeof(buf)-1)) {
779                                 pnt1 = _dl_strrchr(buf, '/');
780                                 if (pnt1 && buf != pnt1) {
781 #ifdef __SUPPORT_LD_DEBUG_EARLY__
782                                         _dl_dprintf(_dl_debug_file, "changing tpnt->libname from '%s' to '%s'\n", tpnt->libname, buf);
783 #endif
784                                         tpnt->libname = _dl_strdup(buf);
785                                 }
786                         }
787
788                         /* Store the path where the shared lib loader was found for 
789                          * later use */
790                         pnt = _dl_strdup(tpnt->libname);
791                         pnt1 = _dl_strrchr(pnt, '/');
792                         if (pnt != pnt1) {
793                                 *pnt1 = '\0';
794                                 _dl_ldsopath = pnt;
795                         } else {
796                                 _dl_ldsopath = tpnt->libname;
797                         }
798 #ifdef __SUPPORT_LD_DEBUG_EARLY__
799                         _dl_dprintf(_dl_debug_file, "Lib Loader:\t(%x) %s\n", tpnt->loadaddr, tpnt->libname);
800 #endif
801                 }
802         }
803
804
805         /* Now we need to figure out what kind of options are selected.
806            Note that for SUID programs we ignore the settings in LD_LIBRARY_PATH */
807         {
808                 _dl_not_lazy = _dl_getenv("LD_BIND_NOW", envp);
809
810                 if ((auxvt[AT_UID].a_un.a_val == -1 && _dl_suid_ok()) ||
811                                 (auxvt[AT_UID].a_un.a_val != -1 && 
812                                  auxvt[AT_UID].a_un.a_val == auxvt[AT_EUID].a_un.a_val
813                                  && auxvt[AT_GID].a_un.a_val== auxvt[AT_EGID].a_un.a_val)) {
814                         _dl_secure = 0;
815                         _dl_preload = _dl_getenv("LD_PRELOAD", envp);
816                         _dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp);
817                 } else {
818                         _dl_secure = 1;
819                         _dl_preload = _dl_getenv("LD_PRELOAD", envp);
820                         _dl_unsetenv("LD_AOUT_PRELOAD", envp);
821                         _dl_unsetenv("LD_LIBRARY_PATH", envp);
822                         _dl_unsetenv("LD_AOUT_LIBRARY_PATH", envp);
823                         _dl_library_path = NULL;
824                 }
825         }
826
827 #ifdef __SUPPORT_LD_DEBUG__
828         _dl_debug    = _dl_getenv("LD_DEBUG", envp);
829         if (_dl_debug)
830         {
831           if (_dl_strstr(_dl_debug, "all")) {
832                 _dl_debug_detail = _dl_debug_move = _dl_debug_symbols
833                         = _dl_debug_reloc = _dl_debug_bindings = _dl_debug_nofixups = _dl_strstr(_dl_debug, "all");
834           }
835           else {
836                 _dl_debug_detail   = _dl_strstr(_dl_debug, "detail");
837                 _dl_debug_move     = _dl_strstr(_dl_debug, "move");
838                 _dl_debug_symbols  = _dl_strstr(_dl_debug, "sym");
839                 _dl_debug_reloc    = _dl_strstr(_dl_debug, "reloc");
840                 _dl_debug_nofixups = _dl_strstr(_dl_debug, "nofix");
841                 _dl_debug_bindings = _dl_strstr(_dl_debug, "bind");
842           }
843         }
844         {
845           const char *dl_debug_output;
846           
847           dl_debug_output = _dl_getenv("LD_DEBUG_OUTPUT", envp);
848
849           if (dl_debug_output)
850           {
851             char tmp[22], *tmp1, *filename;
852             int len1, len2;
853             
854             _dl_memset(tmp, 0, sizeof(tmp));
855             tmp1=_dl_simple_ltoa( tmp, (unsigned long)_dl_getpid());
856
857             len1 = _dl_strlen(dl_debug_output);
858             len2 = _dl_strlen(tmp1);
859
860             filename = _dl_malloc(len1+len2+2);
861
862             if (filename)
863             {
864               _dl_strcpy (filename, dl_debug_output);
865               filename[len1] = '.';
866               _dl_strcpy (&filename[len1+1], tmp1);
867
868               _dl_debug_file= _dl_open (filename, O_WRONLY|O_CREAT);
869               if (_dl_debug_file<0)
870               {
871                 _dl_debug_file = 2;
872                 _dl_dprintf (2, "can't open file: '%s'\n",filename);
873               }
874             }
875           }
876         }
877         
878         
879 #endif  
880         _dl_trace_loaded_objects = _dl_getenv("LD_TRACE_LOADED_OBJECTS", envp);
881 #ifndef __LDSO_LDD_SUPPORT__
882         if (_dl_trace_loaded_objects) {
883                 _dl_dprintf(_dl_debug_file, "Use the ldd provided by uClibc\n");
884                 _dl_exit(1);
885         }
886 #endif
887
888         /*
889          * OK, fix one more thing - set up debug_addr so it will point
890          * to our chain.  Later we may need to fill in more fields, but this
891          * should be enough for now.
892          */
893         debug_addr->r_map = (struct link_map *) _dl_loaded_modules;
894         debug_addr->r_version = 1;
895         debug_addr->r_ldbase = load_addr;
896         debug_addr->r_brk = (unsigned long) &_dl_debug_state;
897         _dl_debug_addr = debug_addr;
898
899         /* Notify the debugger we are in a consistant state */
900         _dl_debug_addr->r_state = RT_CONSISTENT;
901         _dl_debug_state();
902
903         /* OK, we now have the application in the list, and we have some
904            basic stuff in place.  Now search through the list for other shared
905            libraries that should be loaded, and insert them on the list in the
906            correct order. */
907
908 #ifdef USE_CACHE
909         _dl_map_cache();
910 #endif
911
912
913         if (_dl_preload) 
914         {
915                 char c, *str, *str2;
916
917                 str = _dl_preload;
918                 while (*str == ':' || *str == ' ' || *str == '\t')
919                         str++;
920                 while (*str) 
921                 {
922                         str2 = str;
923                         while (*str2 && *str2 != ':' && *str2 != ' ' && *str2 != '\t')
924                                 str2++;
925                         c = *str2;
926                         *str2 = '\0';
927                         if (!_dl_secure || _dl_strchr(str, '/') == NULL) 
928                         {
929                                 tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str);
930                                 if (!tpnt1) {
931 #ifdef __LDSO_LDD_SUPPORT__
932                                         if (_dl_trace_loaded_objects)
933                                                 _dl_dprintf(1, "\t%s => not found\n", str);
934                                         else 
935 #endif
936                                         {
937                                                 _dl_dprintf(2, "%s: can't load " "library '%s'\n", _dl_progname, str);
938                                                 _dl_exit(15);
939                                         }
940                                 } else {
941 #ifdef __SUPPORT_LD_DEBUG_EARLY__
942                                         _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
943 #endif
944 #ifdef __LDSO_LDD_SUPPORT__
945                                         if (_dl_trace_loaded_objects && tpnt1->usage_count==1) {
946                                                 /* this is a real hack to make ldd not print 
947                                                  * the library itself when run on a library. */
948                                                 if (_dl_strcmp(_dl_progname, str) != 0)
949                                                         _dl_dprintf(1, "\t%s => %s (%x)\n", str, tpnt1->libname, 
950                                                                         (unsigned) tpnt1->loadaddr);
951                                         }
952 #endif
953                                 }
954                         }
955                         *str2 = c;
956                         str = str2;
957                         while (*str == ':' || *str == ' ' || *str == '\t')
958                                 str++;
959                 }
960         }
961
962 #ifdef SUPPORT_LDSO_PRELOAD_FILE
963         {
964                 int fd;
965                 struct stat st;
966                 char *preload;
967                 if (!_dl_stat(LDSO_PRELOAD, &st) && st.st_size > 0) {
968                         if ((fd = _dl_open(LDSO_PRELOAD, O_RDONLY)) < 0) {
969                                 _dl_dprintf(2, "%s: can't open file '%s'\n", 
970                                                 _dl_progname, LDSO_PRELOAD);
971                         } else {
972                                 preload = (caddr_t) _dl_mmap(0, st.st_size + 1, 
973                                                 PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
974                                 _dl_close(fd);
975                                 if (preload == (caddr_t) - 1) {
976                                         _dl_dprintf(2, "%s: can't map file '%s'\n", 
977                                                         _dl_progname, LDSO_PRELOAD);
978                                 } else {
979                                         char c, *cp, *cp2;
980
981                                         /* convert all separators and comments to spaces */
982                                         for (cp = preload; *cp; /*nada */ ) {
983                                                 if (*cp == ':' || *cp == '\t' || *cp == '\n') {
984                                                         *cp++ = ' ';
985                                                 } else if (*cp == '#') {
986                                                         do
987                                                                 *cp++ = ' ';
988                                                         while (*cp != '\n' && *cp != '\0');
989                                                 } else {
990                                                         cp++;
991                                                 }
992                                         }
993
994                                         /* find start of first library */
995                                         for (cp = preload; *cp && *cp == ' '; cp++)
996                                                 /*nada */ ;
997
998                                         while (*cp) {
999                                                 /* find end of library */
1000                                                 for (cp2 = cp; *cp && *cp != ' '; cp++)
1001                                                         /*nada */ ;
1002                                                 c = *cp;
1003                                                 *cp = '\0';
1004
1005                                                 tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2);
1006                                                 if (!tpnt1) {
1007 #ifdef __LDSO_LDD_SUPPORT__
1008                                                         if (_dl_trace_loaded_objects)
1009                                                                 _dl_dprintf(1, "\t%s => not found\n", cp2);
1010                                                         else 
1011 #endif
1012                                                         {
1013                                                                 _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, cp2);
1014                                                                 _dl_exit(15);
1015                                                         }
1016                                                 } else {
1017 #ifdef __SUPPORT_LD_DEBUG_EARLY__
1018                                                         _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
1019 #endif
1020 #ifdef __LDSO_LDD_SUPPORT__
1021                                                         if (_dl_trace_loaded_objects && tpnt1->usage_count==1) {
1022                                                                 _dl_dprintf(1, "\t%s => %s (%x)\n", cp2, 
1023                                                                                 tpnt1->libname, (unsigned) tpnt1->loadaddr);
1024                                                         }
1025 #endif
1026                                                 }
1027
1028                                                 /* find start of next library */
1029                                                 *cp = c;
1030                                                 for ( /*nada */ ; *cp && *cp == ' '; cp++)
1031                                                         /*nada */ ;
1032                                         }
1033
1034                                         _dl_munmap(preload, st.st_size + 1);
1035                                 }
1036                         }
1037                 }
1038         }
1039 #endif
1040
1041         for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) {
1042                 Elf32_Dyn *dpnt;
1043                 for (dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag;
1044                                 dpnt++) {
1045                         if (dpnt->d_tag == DT_NEEDED) {
1046                                 lpntstr = tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] +
1047                                         dpnt->d_un.d_val;
1048                                 if (_dl_strcmp(lpntstr, "libc.so.6") == 0) {
1049                                         char *name, *msg;
1050                                         name = tcurr->libname;
1051                                         while(*name == '/')
1052                                                 name++;
1053                                         if (_dl_trace_loaded_objects) {
1054                                                 msg = "WARNING"; 
1055                                         } else {
1056                                                 msg = "ERROR"; 
1057                                         }
1058                                         _dl_dprintf(2, "\t%s: %s is linked with GNU libc!\n", msg, --name);
1059                                         /* If all we are doing is ldd, then we don't need to freak out... */
1060                                         if (_dl_trace_loaded_objects) {
1061                                                 continue;
1062                                         }
1063                                         /* Time to freak out.  Make sure glibc linked libraries are not loaded */
1064                                         _dl_exit(150);
1065                                 }
1066                                 if (tpnt && _dl_strcmp(lpntstr, _dl_get_last_path_component(tpnt->libname)) == 0) 
1067                                 {
1068                                         struct elf_resolve *ttmp;
1069
1070 #ifdef __LDSO_LDD_SUPPORT__
1071                                         if (_dl_trace_loaded_objects && tpnt->usage_count==1) {
1072                                                 char *name;
1073                                                 name = tpnt->libname;
1074                                                 while(*name == '/')
1075                                                         name++;
1076                                                 _dl_dprintf(1, "\t%s => %s (%x)\n", 
1077                                                                 lpntstr, --name, (unsigned) tpnt->loadaddr);
1078                                         }
1079 #endif
1080                                         ttmp = _dl_loaded_modules;
1081                                         while (ttmp->next)
1082                                                 ttmp = ttmp->next;
1083                                         ttmp->next = tpnt;
1084                                         tpnt->prev = ttmp;
1085                                         tpnt->next = NULL;
1086                                         rpnt->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
1087                                         _dl_memset(rpnt->next, 0, sizeof(struct dyn_elf));
1088                                         rpnt->next->prev = rpnt;
1089                                         rpnt = rpnt->next;
1090                                         rpnt->dyn = tpnt;
1091                                         tpnt->usage_count++;
1092                                         tpnt->symbol_scope = _dl_symbol_tables;
1093                                         tpnt = NULL;
1094                                         continue;
1095                                 }
1096                                 if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr)))
1097                                 {
1098 #ifdef __LDSO_LDD_SUPPORT__
1099                                         if (_dl_trace_loaded_objects)
1100                                                 _dl_dprintf(1, "\t%s => not found\n", lpntstr);
1101                                         else 
1102 #endif
1103                                         {
1104                                                 _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, lpntstr);
1105                                                 _dl_exit(16);
1106                                         }
1107                                 } else {
1108 #ifdef __SUPPORT_LD_DEBUG_EARLY__
1109                                         _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
1110 #endif
1111 #ifdef __LDSO_LDD_SUPPORT__
1112                                         if (_dl_trace_loaded_objects && tpnt1->usage_count==1) {
1113                                                 char *name;
1114                                                 name = tpnt1->libname;
1115                                                 while(*name == '/')
1116                                                         name++;
1117                                                 _dl_dprintf(1, "\t%s => %s (%x)\n", lpntstr, --name, 
1118                                                                 (unsigned) tpnt1->loadaddr);
1119                                         }
1120 #endif
1121                                 }
1122                         }
1123                 }
1124         }
1125
1126
1127 #ifdef USE_CACHE
1128         _dl_unmap_cache();
1129 #endif
1130
1131         /*
1132          * If the program interpreter is not in the module chain, add it.  This will
1133          * be required for dlopen to be able to access the internal functions in the 
1134          * dynamic linker.
1135          */
1136         if (tpnt) {
1137                 tcurr = _dl_loaded_modules;
1138                 if (tcurr)
1139                         while (tcurr->next)
1140                                 tcurr = tcurr->next;
1141                 tpnt->next = NULL;
1142                 tpnt->usage_count++;
1143
1144                 if (tcurr) {
1145                         tcurr->next = tpnt;
1146                         tpnt->prev = tcurr;
1147                 } else {
1148                         _dl_loaded_modules = tpnt;
1149                         tpnt->prev = NULL;
1150                 }
1151                 if (rpnt) {
1152                         rpnt->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
1153                         _dl_memset(rpnt->next, 0, sizeof(struct dyn_elf));
1154                         rpnt->next->prev = rpnt;
1155                         rpnt = rpnt->next;
1156                 } else {
1157                         rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
1158                         _dl_memset(rpnt, 0, sizeof(struct dyn_elf));
1159                 }
1160                 rpnt->dyn = tpnt;
1161                 tpnt = NULL;
1162         }
1163
1164 #ifdef __LDSO_LDD_SUPPORT__
1165         /* End of the line for ldd.... */
1166         if (_dl_trace_loaded_objects) {
1167                 _dl_dprintf(1, "\t%s => %s (%x)\n", rpnt->dyn->libname + (_dl_strlen(_dl_ldsopath)) + 1, 
1168                                 rpnt->dyn->libname, rpnt->dyn->loadaddr);  
1169                 _dl_exit(0);
1170         }
1171 #endif
1172
1173
1174 #ifdef __mips__
1175         /*
1176          * Relocation of the GOT entries for MIPS have to be done
1177          * after all the libraries have been loaded.
1178          */
1179         _dl_perform_mips_global_got_relocations(_dl_loaded_modules);
1180 #endif
1181
1182 #ifdef __SUPPORT_LD_DEBUG_EARLY__
1183         _dl_dprintf(_dl_debug_file, "Beginning relocation fixups\n");
1184 #endif
1185         /*
1186          * OK, now all of the kids are tucked into bed in their proper addresses.
1187          * Now we go through and look for REL and RELA records that indicate fixups
1188          * to the GOT tables.  We need to do this in reverse order so that COPY
1189          * directives work correctly */
1190         goof = _dl_loaded_modules ? _dl_fixup(_dl_loaded_modules) : 0;
1191
1192
1193         /* Some flavors of SVr4 do not generate the R_*_COPY directive,
1194            and we have to manually search for entries that require fixups. 
1195            Solaris gets this one right, from what I understand.  */
1196
1197 #ifdef __SUPPORT_LD_DEBUG_EARLY__
1198         _dl_dprintf(_dl_debug_file, "Beginning copy fixups\n");
1199 #endif
1200         if (_dl_symbol_tables)
1201                 goof += _dl_copy_fixups(_dl_symbol_tables);
1202
1203         /* OK, at this point things are pretty much ready to run.  Now we
1204            need to touch up a few items that are required, and then
1205            we can let the user application have at it.  Note that
1206            the dynamic linker itself is not guaranteed to be fully
1207            dynamicly linked if we are using ld.so.1, so we have to look
1208            up each symbol individually. */
1209
1210
1211         _dl_brkp = (unsigned long *) (intptr_t) _dl_find_hash("___brk_addr", NULL, NULL, symbolrel);
1212         
1213         if (_dl_brkp) {
1214                 *_dl_brkp = brk_addr;
1215         }
1216         _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash("__environ", NULL, NULL, symbolrel);
1217
1218         if (_dl_envp) {
1219                 *_dl_envp = (unsigned long) envp;
1220         }
1221
1222 #ifndef FORCE_SHAREABLE_TEXT_SEGMENTS
1223         {
1224                 unsigned int j;
1225                 elf_phdr *myppnt;
1226
1227                 /* We had to set the protections of all pages to R/W for dynamic linking.
1228                    Set text pages back to R/O */
1229                 for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
1230                         for (myppnt = tpnt->ppnt, j = 0; j < tpnt->n_phent; j++, myppnt++) {
1231                                 if (myppnt->p_type == PT_LOAD && !(myppnt->p_flags & PF_W) && tpnt->dynamic_info[DT_TEXTREL]) {
1232                                         _dl_mprotect((void *) (tpnt->loadaddr + (myppnt->p_vaddr & PAGE_ALIGN)), 
1233                                                         (myppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) myppnt->p_filesz, LXFLAGS(myppnt->p_flags));
1234                                 }
1235                         }
1236                 }
1237
1238         }
1239 #endif
1240         _dl_atexit = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", NULL, NULL, symbolrel);
1241 #if defined (__SUPPORT_LD_DEBUG__)
1242         _dl_on_exit = (int (*)(void (*)(int, void *),void*)) 
1243                 (intptr_t) _dl_find_hash("on_exit", NULL, NULL, symbolrel);
1244 #endif
1245
1246         /* Notify the debugger we have added some objects. */
1247         _dl_debug_addr->r_state = RT_ADD;
1248         _dl_debug_state();
1249
1250         for (rpnt = _dl_symbol_tables; rpnt!=NULL&& rpnt->next!=NULL; rpnt=rpnt->next)
1251           ;
1252           
1253         for (;rpnt!=NULL; rpnt=rpnt->prev)
1254         {
1255                 tpnt = rpnt->dyn;
1256
1257                 if (tpnt->libtype == program_interpreter)
1258                         continue;
1259
1260                 /* Apparently crt0/1 for the application is responsible for handling this.
1261                  * We only need to run the init/fini for shared libraries
1262                  */
1263                 if (tpnt->libtype == elf_executable)
1264                         break;      /* at this point all shared libs are initialized !! */
1265
1266                 if (tpnt->init_flag & INIT_FUNCS_CALLED)
1267                         continue;
1268                 tpnt->init_flag |= INIT_FUNCS_CALLED;
1269
1270                 if (tpnt->dynamic_info[DT_INIT]) {
1271                         _dl_elf_init = (int (*)(void)) (intptr_t) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]);
1272                           
1273 #if defined (__SUPPORT_LD_DEBUG__)
1274                         if(_dl_debug) _dl_dprintf(_dl_debug_file,"\ncalling init: %s\n\n", tpnt->libname);      
1275 #endif    
1276                         (*_dl_elf_init) ();
1277                 }
1278                 if (_dl_atexit && tpnt->dynamic_info[DT_FINI]) {
1279                         (*_dl_atexit) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
1280 #if defined (__SUPPORT_LD_DEBUG__)
1281                         if(_dl_debug && _dl_on_exit)
1282                         {
1283                                 (*_dl_on_exit)(debug_fini, tpnt->libname);
1284                         }
1285 #endif
1286                 }
1287 #if defined (__SUPPORT_LD_DEBUG__)
1288                 else {
1289                         if (!_dl_atexit)
1290                                 _dl_dprintf(_dl_debug_file, "%s: The address of atexit () is 0x0.\n", tpnt->libname);
1291 #if 0
1292                         if (!tpnt->dynamic_info[DT_FINI])
1293                                 _dl_dprintf(_dl_debug_file, "%s: Invalid .fini section.\n", tpnt->libname);
1294 #endif
1295                 }
1296 #endif
1297         }
1298 }
1299
1300 /*
1301  * This stub function is used by some debuggers.  The idea is that they
1302  * can set an internal breakpoint on it, so that we are notified when the
1303  * address mapping is changed in some way.
1304  */
1305 void _dl_debug_state(void)
1306 {
1307 }
1308
1309 int _dl_fixup(struct elf_resolve *tpnt)
1310 {
1311         int goof = 0;
1312
1313         if (tpnt->next)
1314                 goof += _dl_fixup(tpnt->next);
1315 #if defined (__SUPPORT_LD_DEBUG__)
1316         if(_dl_debug) _dl_dprintf(_dl_debug_file,"\nrelocation processing: %s", tpnt->libname); 
1317 #endif    
1318         
1319         if (tpnt->dynamic_info[DT_REL]) {
1320 #ifdef ELF_USES_RELOCA
1321                 _dl_dprintf(2, "%s: can't handle REL relocation records\n",
1322                                         _dl_progname);
1323                 _dl_exit(17);
1324 #else
1325                 if (tpnt->init_flag & RELOCS_DONE)
1326                         return goof;
1327                 tpnt->init_flag |= RELOCS_DONE;
1328                 goof += _dl_parse_relocation_information(tpnt, tpnt->dynamic_info[DT_REL], 
1329                                 tpnt->dynamic_info[DT_RELSZ], 0);
1330 #endif
1331         }
1332         if (tpnt->dynamic_info[DT_RELA]) {
1333 #ifdef ELF_USES_RELOCA
1334                 if (tpnt->init_flag & RELOCS_DONE)
1335                         return goof;
1336                 tpnt->init_flag |= RELOCS_DONE;
1337                 goof += _dl_parse_relocation_information(tpnt, tpnt->dynamic_info[DT_RELA], 
1338                                 tpnt->dynamic_info[DT_RELASZ], 0);
1339 #else
1340                 _dl_dprintf(2, "%s: can't handle RELA relocation records\n",
1341                                         _dl_progname);
1342                 _dl_exit(18);
1343 #endif
1344         }
1345         if (tpnt->dynamic_info[DT_JMPREL]) {
1346                 if (tpnt->init_flag & JMP_RELOCS_DONE)
1347                         return goof;
1348                 tpnt->init_flag |= JMP_RELOCS_DONE;
1349                 if (!_dl_not_lazy || *_dl_not_lazy == 0)
1350                         _dl_parse_lazy_relocation_information(tpnt, tpnt->dynamic_info[DT_JMPREL], 
1351                                         tpnt->dynamic_info [DT_PLTRELSZ], 0);
1352                 else
1353                         goof += _dl_parse_relocation_information(tpnt, tpnt->dynamic_info[DT_JMPREL], 
1354                                         tpnt->dynamic_info[DT_PLTRELSZ], 0);
1355         }
1356 #if defined (__SUPPORT_LD_DEBUG__)
1357         if(_dl_debug) {
1358                 _dl_dprintf(_dl_debug_file,"\nrelocation processing: %s", tpnt->libname);     
1359                 _dl_dprintf(_dl_debug_file,"; finished\n\n");
1360         }
1361 #endif    
1362         return goof;
1363 }
1364
1365 char *_dl_getenv(const char *symbol, char **envp)
1366 {
1367         char *pnt;
1368         const char *pnt1;
1369
1370         while ((pnt = *envp++)) {
1371                 pnt1 = symbol;
1372                 while (*pnt && *pnt == *pnt1)
1373                         pnt1++, pnt++;
1374                 if (!*pnt || *pnt != '=' || *pnt1)
1375                         continue;
1376                 return pnt + 1;
1377         }
1378         return 0;
1379 }
1380
1381 void _dl_unsetenv(const char *symbol, char **envp)
1382 {
1383         char *pnt;
1384         const char *pnt1;
1385         char **newenvp = envp;
1386
1387         for (pnt = *envp; pnt; pnt = *++envp) {
1388                 pnt1 = symbol;
1389                 while (*pnt && *pnt == *pnt1)
1390                         pnt1++, pnt++;
1391                 if (!*pnt || *pnt != '=' || *pnt1)
1392                         *newenvp++ = *envp;
1393         }
1394         *newenvp++ = *envp;
1395         return;
1396 }
1397
1398 #include "hash.c"
1399 #include "readelflib1.c"