OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [ldso/] [ldso/] [ldso.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.