OSDN Git Service

Merge remote-tracking branch 'origin/master' into prelink
[uclinux-h8/uClibc.git] / ldso / ldso / dl-elf.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * This file contains the helper routines to load an ELF shared
4  * library into memory and add the symbol table info to the chain.
5  *
6  * Copyright (C) 2000-2006 by Erik Andersen <andersen@codepoet.org>
7  * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
8  *                              David Engel, Hongjiu Lu and Mitch D'Souza
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. The name of the above contributors may not be
16  *    used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31
32
33 #include "ldso.h"
34
35 #ifdef __LDSO_CACHE_SUPPORT__
36
37 static caddr_t _dl_cache_addr = NULL;
38 static size_t _dl_cache_size = 0;
39
40 int _dl_map_cache(void)
41 {
42         int fd;
43         struct stat st;
44         header_t *header;
45         libentry_t *libent;
46         int i, strtabsize;
47
48         if (_dl_cache_addr == MAP_FAILED)
49                 return -1;
50         else if (_dl_cache_addr != NULL)
51                 return 0;
52
53         if (_dl_stat(LDSO_CACHE, &st)
54             || (fd = _dl_open(LDSO_CACHE, O_RDONLY|O_CLOEXEC, 0)) < 0) {
55                 _dl_cache_addr = MAP_FAILED;    /* so we won't try again */
56                 return -1;
57         }
58
59         _dl_cache_size = st.st_size;
60         _dl_cache_addr = _dl_mmap(0, _dl_cache_size, PROT_READ, LDSO_CACHE_MMAP_FLAGS, fd, 0);
61         _dl_close(fd);
62         if (_dl_mmap_check_error(_dl_cache_addr)) {
63                 _dl_dprintf(2, "%s:%i: can't map '%s'\n",
64                                 _dl_progname, __LINE__, LDSO_CACHE);
65                 return -1;
66         }
67
68         header = (header_t *) _dl_cache_addr;
69
70         if (_dl_cache_size < sizeof(header_t) ||
71                         _dl_memcmp(header->magic, LDSO_CACHE_MAGIC, LDSO_CACHE_MAGIC_LEN)
72                         || _dl_memcmp(header->version, LDSO_CACHE_VER, LDSO_CACHE_VER_LEN)
73                         || _dl_cache_size <
74                         (sizeof(header_t) + header->nlibs * sizeof(libentry_t))
75                         || _dl_cache_addr[_dl_cache_size - 1] != '\0')
76         {
77                 _dl_dprintf(2, "%s: cache '%s' is corrupt\n", _dl_progname,
78                                 LDSO_CACHE);
79                 goto fail;
80         }
81
82         strtabsize = _dl_cache_size - sizeof(header_t) -
83                 header->nlibs * sizeof(libentry_t);
84         libent = (libentry_t *) & header[1];
85
86         for (i = 0; i < header->nlibs; i++) {
87                 if (libent[i].sooffset >= strtabsize ||
88                                 libent[i].liboffset >= strtabsize)
89                 {
90                         _dl_dprintf(2, "%s: cache '%s' is corrupt\n", _dl_progname, LDSO_CACHE);
91                         goto fail;
92                 }
93         }
94
95         return 0;
96
97 fail:
98         _dl_munmap(_dl_cache_addr, _dl_cache_size);
99         _dl_cache_addr = MAP_FAILED;
100         return -1;
101 }
102
103 int _dl_unmap_cache(void)
104 {
105         if (_dl_cache_addr == NULL || _dl_cache_addr == MAP_FAILED)
106                 return -1;
107
108 #if 1
109         _dl_munmap(_dl_cache_addr, _dl_cache_size);
110         _dl_cache_addr = NULL;
111 #endif
112
113         return 0;
114 }
115 #endif
116
117
118 void
119 _dl_protect_relro (struct elf_resolve *l)
120 {
121         ElfW(Addr) base = (ElfW(Addr)) DL_RELOC_ADDR(l->loadaddr, l->relro_addr);
122         ElfW(Addr) start = (base & PAGE_ALIGN);
123         ElfW(Addr) end = ((base + l->relro_size) & PAGE_ALIGN);
124         _dl_if_debug_dprint("RELRO protecting %s:  start:%x, end:%x\n", l->libname, start, end);
125         if (start != end &&
126             _dl_mprotect ((void *) start, end - start, PROT_READ) < 0) {
127                 _dl_dprintf(2, "%s: cannot apply additional memory protection after relocation", l->libname);
128                 _dl_exit(0);
129         }
130 }
131
132 /* This function's behavior must exactly match that
133  * in uClibc/ldso/util/ldd.c */
134 static struct elf_resolve *
135 search_for_named_library(const char *name, int secure, const char *path_list,
136         struct dyn_elf **rpnt)
137 {
138         char *path, *path_n, *mylibname;
139         struct elf_resolve *tpnt;
140         int done;
141
142         if (path_list==NULL)
143                 return NULL;
144
145         /* We need a writable copy of this string, but we don't
146          * need this allocated permanently since we don't want
147          * to leak memory, so use alloca to put path on the stack */
148         done = _dl_strlen(path_list);
149         path = alloca(done + 1);
150
151         /* another bit of local storage */
152         mylibname = alloca(2050);
153
154         _dl_memcpy(path, path_list, done+1);
155
156         /* Unlike ldd.c, don't bother to eliminate double //s */
157
158         /* Replace colons with zeros in path_list */
159         /* : at the beginning or end of path maps to CWD */
160         /* :: anywhere maps CWD */
161         /* "" maps to CWD */
162         done = 0;
163         path_n = path;
164         do {
165                 if (*path == 0) {
166                         *path = ':';
167                         done = 1;
168                 }
169                 if (*path == ':') {
170                         *path = 0;
171                         if (*path_n)
172                                 _dl_strcpy(mylibname, path_n);
173                         else
174                                 _dl_strcpy(mylibname, "."); /* Assume current dir if empty path */
175                         _dl_strcat(mylibname, "/");
176                         _dl_strcat(mylibname, name);
177                         if ((tpnt = _dl_load_elf_shared_library(secure, rpnt, mylibname)) != NULL)
178                                 return tpnt;
179                         path_n = path+1;
180                 }
181                 path++;
182         } while (!done);
183         return NULL;
184 }
185
186 /* Used to return error codes back to dlopen et. al.  */
187 unsigned long _dl_error_number;
188 unsigned long _dl_internal_error_number;
189
190 struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
191         struct elf_resolve *tpnt, char *full_libname, int attribute_unused trace_loaded_objects)
192 {
193         char *pnt;
194         struct elf_resolve *tpnt1;
195         char *libname;
196
197         _dl_internal_error_number = 0;
198         libname = full_libname;
199
200         /* quick hack to ensure mylibname buffer doesn't overflow.  don't
201            allow full_libname or any directory to be longer than 1024. */
202         if (_dl_strlen(full_libname) > 1024)
203                 goto goof;
204
205         /* Skip over any initial initial './' and '/' stuff to
206          * get the short form libname with no path garbage */
207         pnt = _dl_strrchr(libname, '/');
208         if (pnt) {
209                 libname = pnt + 1;
210         }
211
212         _dl_if_debug_dprint("\tfind library='%s'; searching\n", libname);
213         /* If the filename has any '/', try it straight and leave it at that.
214            For IBCS2 compatibility under linux, we substitute the string
215            /usr/i486-sysv4/lib for /usr/lib in library names. */
216
217         if (libname != full_libname) {
218                 _dl_if_debug_dprint("\ttrying file='%s'\n", full_libname);
219                 tpnt1 = _dl_load_elf_shared_library(secure, rpnt, full_libname);
220                 if (tpnt1) {
221                         return tpnt1;
222                 }
223         }
224
225         /*
226          * The ABI specifies that RPATH is searched before LD_LIBRARY_PATH or
227          * the default path of /usr/lib.  Check in rpath directories.
228          */
229 #ifdef __LDSO_RUNPATH__
230         pnt = (tpnt ? (char *) tpnt->dynamic_info[DT_RPATH] : NULL);
231         if (pnt) {
232                 pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
233                 _dl_if_debug_dprint("\tsearching RPATH='%s'\n", pnt);
234                 if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL)
235                         return tpnt1;
236         }
237 #endif
238
239         /* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */
240         if (_dl_library_path) {
241                 _dl_if_debug_dprint("\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path);
242                 if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL)
243                 {
244                         return tpnt1;
245                 }
246         }
247
248         /*
249          * The ABI specifies that RUNPATH is searched after LD_LIBRARY_PATH.
250          */
251 #ifdef __LDSO_RUNPATH__
252         pnt = (tpnt ? (char *)tpnt->dynamic_info[DT_RUNPATH] : NULL);
253         if (pnt) {
254                 pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
255                 _dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt);
256                 if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL)
257                         return tpnt1;
258         }
259 #endif
260
261         /*
262          * Where should the cache be searched?  There is no such concept in the
263          * ABI, so we have some flexibility here.  For now, search it before
264          * the hard coded paths that follow (i.e before /lib and /usr/lib).
265          */
266 #ifdef __LDSO_CACHE_SUPPORT__
267         if (_dl_cache_addr != NULL && _dl_cache_addr != MAP_FAILED) {
268                 int i;
269                 header_t *header = (header_t *) _dl_cache_addr;
270                 libentry_t *libent = (libentry_t *) & header[1];
271                 char *strs = (char *) &libent[header->nlibs];
272
273                 _dl_if_debug_dprint("\tsearching cache='%s'\n", LDSO_CACHE);
274                 for (i = 0; i < header->nlibs; i++) {
275                         if ((libent[i].flags == LIB_ELF
276                              || libent[i].flags == LIB_ELF_LIBC0
277                              || libent[i].flags == LIB_ELF_LIBC5)
278                          && _dl_strcmp(libname, strs + libent[i].sooffset) == 0
279                          && (tpnt1 = _dl_load_elf_shared_library(secure, rpnt, strs + libent[i].liboffset))
280                         ) {
281                                 return tpnt1;
282                         }
283                 }
284         }
285 #endif
286
287         /* Look for libraries wherever the shared library loader
288          * was installed */
289         _dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath);
290         tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt);
291         if (tpnt1 != NULL)
292                 return tpnt1;
293
294         /* Lastly, search the standard list of paths for the library.
295            This list must exactly match the list in uClibc/ldso/util/ldd.c */
296         _dl_if_debug_dprint("\tsearching full lib path list\n");
297         tpnt1 = search_for_named_library(libname, secure,
298                                         UCLIBC_RUNTIME_PREFIX "lib:"
299                                         UCLIBC_RUNTIME_PREFIX "usr/lib"
300 #ifndef __LDSO_CACHE_SUPPORT__
301                                         ":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib"
302 #endif
303                                         , rpnt);
304         if (tpnt1 != NULL)
305                 return tpnt1;
306
307 goof:
308         /* Well, we shot our wad on that one.  All we can do now is punt */
309         if (_dl_internal_error_number)
310                 _dl_error_number = _dl_internal_error_number;
311         else
312                 _dl_error_number = LD_ERROR_NOFILE;
313         _dl_if_debug_dprint("Bummer: could not find '%s'!\n", libname);
314         return NULL;
315 }
316
317
318 /*
319  * Read one ELF library into memory, mmap it into the correct locations and
320  * add the symbol info to the symbol chain.  Perform any relocations that
321  * are required.
322  */
323
324 struct elf_resolve *_dl_load_elf_shared_library(int secure,
325         struct dyn_elf **rpnt, const char *libname)
326 {
327         ElfW(Ehdr) *epnt;
328         unsigned long dynamic_addr = 0;
329         ElfW(Dyn) *dpnt;
330         struct elf_resolve *tpnt;
331         ElfW(Phdr) *ppnt;
332 #if defined(USE_TLS) && USE_TLS
333         ElfW(Phdr) *tlsppnt = NULL;
334 #endif
335         char *status, *header;
336         unsigned long dynamic_info[DYNAMIC_SIZE];
337         unsigned long *lpnt;
338         unsigned long libaddr;
339         unsigned long minvma = 0xffffffff, maxvma = 0;
340         unsigned int rtld_flags;
341         int i, flags, piclib, infile;
342         ElfW(Addr) relro_addr = 0;
343         size_t relro_size = 0;
344         struct stat st;
345         uint32_t *p32;
346         DL_LOADADDR_TYPE lib_loadaddr = 0;
347         DL_INIT_LOADADDR_EXTRA_DECLS
348
349         libaddr = 0;
350         infile = _dl_open(libname, O_RDONLY, 0);
351         if (infile < 0) {
352                 _dl_internal_error_number = LD_ERROR_NOFILE;
353                 return NULL;
354         }
355
356         if (_dl_fstat(infile, &st) < 0) {
357                 _dl_internal_error_number = LD_ERROR_NOFILE;
358                 _dl_close(infile);
359                 return NULL;
360         }
361         /* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD),
362            we don't load the library if it isn't setuid. */
363         if (secure) {
364                 if (!(st.st_mode & S_ISUID)) {
365                         _dl_close(infile);
366                         return NULL;
367                 }
368         }
369
370         /* Check if file is already loaded */
371         for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
372                 if (tpnt->st_dev == st.st_dev && tpnt->st_ino == st.st_ino) {
373                         /* Already loaded */
374                         tpnt->usage_count++;
375                         _dl_close(infile);
376                         return tpnt;
377                 }
378         }
379         header = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
380                         MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZE, -1, 0);
381         if (_dl_mmap_check_error(header)) {
382                 _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
383                 _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
384                 _dl_close(infile);
385                 return NULL;
386         }
387
388         _dl_read(infile, header, _dl_pagesize);
389         epnt = (ElfW(Ehdr) *) (intptr_t) header;
390         p32 = (uint32_t*)&epnt->e_ident;
391         if (*p32 != ELFMAG_U32) {
392                 _dl_dprintf(2, "%s: '%s' is not an ELF file\n", _dl_progname,
393                                 libname);
394                 _dl_internal_error_number = LD_ERROR_NOTELF;
395                 _dl_close(infile);
396                 _dl_munmap(header, _dl_pagesize);
397                 return NULL;
398         }
399
400         if ((epnt->e_type != ET_DYN
401 #ifdef __LDSO_STANDALONE_SUPPORT__
402                 && epnt->e_type != ET_EXEC
403 #endif
404                 ) || (epnt->e_machine != MAGIC1
405 #ifdef MAGIC2
406                                 && epnt->e_machine != MAGIC2
407 #endif
408                         ))
409         {
410                 _dl_internal_error_number =
411                         (epnt->e_type != ET_DYN ? LD_ERROR_NOTDYN : LD_ERROR_NOTMAGIC);
412                 _dl_dprintf(2, "%s: '%s' is not an ELF executable for " ELF_TARGET
413                                 "\n", _dl_progname, libname);
414                 _dl_close(infile);
415                 _dl_munmap(header, _dl_pagesize);
416                 return NULL;
417         }
418
419         ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
420
421         piclib = 1;
422         for (i = 0; i < epnt->e_phnum; i++) {
423
424                 if (ppnt->p_type == PT_DYNAMIC) {
425                         if (dynamic_addr)
426                                 _dl_dprintf(2, "%s: '%s' has more than one dynamic section\n",
427                                                 _dl_progname, libname);
428                         dynamic_addr = ppnt->p_vaddr;
429                 }
430
431                 if (ppnt->p_type == PT_LOAD) {
432                         /* See if this is a PIC library. */
433                         if (minvma == 0xffffffff && ppnt->p_vaddr > 0x1000000) {
434                                 piclib = 0;
435                                 minvma = ppnt->p_vaddr;
436                         }
437                         if (piclib && ppnt->p_vaddr < minvma) {
438                                 minvma = ppnt->p_vaddr;
439                         }
440                         if (((unsigned long) ppnt->p_vaddr + ppnt->p_memsz) > maxvma) {
441                                 maxvma = ppnt->p_vaddr + ppnt->p_memsz;
442                         }
443                 }
444                 if (ppnt->p_type == PT_TLS) {
445 #if defined(USE_TLS) && USE_TLS
446                         if (ppnt->p_memsz == 0)
447                                 /* Nothing to do for an empty segment.  */
448                                 continue;
449                         else
450                                 /* Save for after 'tpnt' is actually allocated. */
451                                 tlsppnt = ppnt;
452 #else
453                         /*
454                          * Yup, the user was an idiot and tried to sneak in a library with
455                          * TLS in it and we don't support it. Let's fall on our own sword
456                          * and scream at the luser while we die.
457                          */
458                         _dl_dprintf(2, "%s: '%s' library contains unsupported TLS\n",
459                                 _dl_progname, libname);
460                         _dl_internal_error_number = LD_ERROR_TLS_FAILED;
461                         _dl_close(infile);
462                         _dl_munmap(header, _dl_pagesize);
463                         return NULL;
464 #endif
465                 }
466                 ppnt++;
467         }
468
469 #ifdef __LDSO_STANDALONE_SUPPORT__
470         if (epnt->e_type == ET_EXEC)
471                 piclib = 0;
472 #endif
473
474         DL_CHECK_LIB_TYPE (epnt, piclib, _dl_progname, libname);
475
476         maxvma = (maxvma + ADDR_ALIGN) & PAGE_ALIGN;
477         minvma = minvma & ~ADDR_ALIGN;
478
479         flags = MAP_PRIVATE /*| MAP_DENYWRITE */ ;
480
481         if (piclib == 0 || piclib == 1) {
482                 status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma),
483                                 maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0);
484                 if (_dl_mmap_check_error(status)) {
485                         _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
486                         _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
487                         _dl_close(infile);
488                         _dl_munmap(header, _dl_pagesize);
489                         return NULL;
490                 }
491                 libaddr = (unsigned long) status;
492                 flags |= MAP_FIXED;
493         }
494
495         /* Get the memory to store the library */
496         ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
497
498         DL_INIT_LOADADDR(lib_loadaddr, libaddr - minvma, ppnt, epnt->e_phnum);
499
500         for (i = 0; i < epnt->e_phnum; i++) {
501                 if (DL_IS_SPECIAL_SEGMENT (epnt, ppnt)) {
502                         char *addr;
503
504                         addr = DL_MAP_SEGMENT (epnt, ppnt, infile, flags);
505                         if (addr == NULL)
506                                 goto cant_map;
507
508                         DL_INIT_LOADADDR_HDR (lib_loadaddr, addr, ppnt);
509                         ppnt++;
510                         continue;
511                 }
512                 if (ppnt->p_type == PT_GNU_RELRO) {
513                         relro_addr = ppnt->p_vaddr;
514                         relro_size = ppnt->p_memsz;
515                 }
516                 if (ppnt->p_type == PT_LOAD) {
517                         char *tryaddr;
518                         ssize_t size;
519
520                         if (ppnt->p_flags & PF_W) {
521                                 unsigned long map_size;
522                                 char *cpnt;
523                                 char *piclib2map = 0;
524
525                                 if (piclib == 2 &&
526                                     /* We might be able to avoid this
527                                        call if memsz doesn't require
528                                        an additional page, but this
529                                        would require mmap to always
530                                        return page-aligned addresses
531                                        and a whole number of pages
532                                        allocated.  Unfortunately on
533                                        uClinux may return misaligned
534                                        addresses and may allocate
535                                        partial pages, so we may end up
536                                        doing unnecessary mmap calls.
537
538                                        This is what we could do if we
539                                        knew mmap would always return
540                                        aligned pages:
541
542                                     ((ppnt->p_vaddr + ppnt->p_filesz
543                                       + ADDR_ALIGN)
544                                      & PAGE_ALIGN)
545                                     < ppnt->p_vaddr + ppnt->p_memsz)
546
547                                        Instead, we have to do this:  */
548                                     ppnt->p_filesz < ppnt->p_memsz)
549                                   {
550                                     piclib2map = (char *)
551                                       _dl_mmap(0, (ppnt->p_vaddr & ADDR_ALIGN)
552                                                + ppnt->p_memsz,
553                                                LXFLAGS(ppnt->p_flags),
554                                                flags | MAP_ANONYMOUS, -1, 0);
555                                     if (_dl_mmap_check_error(piclib2map))
556                                       goto cant_map;
557                                     DL_INIT_LOADADDR_HDR
558                                       (lib_loadaddr, piclib2map
559                                        + (ppnt->p_vaddr & ADDR_ALIGN), ppnt);
560                                   }
561
562                                 tryaddr = piclib == 2 ? piclib2map
563                                   : ((char*) (piclib ? libaddr : lib_loadaddr) +
564                                      (ppnt->p_vaddr & PAGE_ALIGN));
565
566                                 size = (ppnt->p_vaddr & ADDR_ALIGN)
567                                   + ppnt->p_filesz;
568
569                                 /* For !MMU, mmap to fixed address will fail.
570                                    So instead of desperately call mmap and fail,
571                                    we set status to MAP_FAILED to save a call
572                                    to mmap ().  */
573 #ifndef __ARCH_USE_MMU__
574                                 if (piclib2map == 0)
575 #endif
576                                   status = (char *) _dl_mmap
577                                     (tryaddr, size, LXFLAGS(ppnt->p_flags),
578                                      flags | (piclib2map ? MAP_FIXED : 0),
579                                      infile, ppnt->p_offset & OFFS_ALIGN);
580 #ifndef __ARCH_USE_MMU__
581                                 else
582                                   status = MAP_FAILED;
583 #endif
584 #ifdef _DL_PREAD
585                                 if (_dl_mmap_check_error(status) && piclib2map
586                                     && (_DL_PREAD (infile, tryaddr, size,
587                                                    ppnt->p_offset & OFFS_ALIGN)
588                                         == size))
589                                   status = tryaddr;
590 #endif
591                                 if (_dl_mmap_check_error(status)
592                                     || (tryaddr && tryaddr != status)) {
593                                 cant_map:
594                                         _dl_dprintf(2, "%s:%i: can't map '%s'\n",
595                                                         _dl_progname, __LINE__, libname);
596                                         _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
597                                         DL_LOADADDR_UNMAP (lib_loadaddr, maxvma - minvma);
598                                         _dl_close(infile);
599                                         _dl_munmap(header, _dl_pagesize);
600                                         return NULL;
601                                 }
602
603                                 if (! piclib2map) {
604                                   DL_INIT_LOADADDR_HDR
605                                     (lib_loadaddr, status
606                                      + (ppnt->p_vaddr & ADDR_ALIGN), ppnt);
607                                 }
608                                 /* Now we want to allocate and
609                                    zero-out any data from the end of
610                                    the region we mapped in from the
611                                    file (filesz) to the end of the
612                                    loadable segment (memsz).  We may
613                                    need additional pages for memsz,
614                                    that we map in below, and we can
615                                    count on the kernel to zero them
616                                    out, but we have to zero out stuff
617                                    in the last page that we mapped in
618                                    from the file.  However, we can't
619                                    assume to have actually obtained
620                                    full pages from the kernel, since
621                                    we didn't ask for them, and uClibc
622                                    may not give us full pages for
623                                    small allocations.  So only zero
624                                    out up to memsz or the end of the
625                                    page, whichever comes first.  */
626
627                                 /* CPNT is the beginning of the memsz
628                                    portion not backed by filesz.  */
629                                 cpnt = (char *) (status + size);
630
631                                 /* MAP_SIZE is the address of the
632                                    beginning of the next page.  */
633                                 map_size = (ppnt->p_vaddr + ppnt->p_filesz
634                                             + ADDR_ALIGN) & PAGE_ALIGN;
635
636 #ifndef MIN
637 # define MIN(a,b) ((a) < (b) ? (a) : (b))
638 #endif
639                                 _dl_memset (cpnt, 0,
640                                             MIN (map_size
641                                                  - (ppnt->p_vaddr
642                                                     + ppnt->p_filesz),
643                                                  ppnt->p_memsz
644                                                  - ppnt->p_filesz));
645
646                                 if (map_size < ppnt->p_vaddr + ppnt->p_memsz
647                                     && !piclib2map) {
648                                         tryaddr = map_size + (char*)(piclib ? libaddr : lib_loadaddr);
649                                         status = (char *) _dl_mmap(tryaddr,
650                                                 ppnt->p_vaddr + ppnt->p_memsz - map_size,
651                                                 LXFLAGS(ppnt->p_flags), flags | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
652                                         if (_dl_mmap_check_error(status)
653                                             || tryaddr != status)
654                                                 goto cant_map;
655                                 }
656                         } else {
657                                 tryaddr = (piclib == 2 ? 0
658                                            : (char *) (ppnt->p_vaddr & PAGE_ALIGN)
659                                            + (piclib ? libaddr : lib_loadaddr));
660                                 size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
661                                 status = (char *) _dl_mmap
662                                            (tryaddr, size, LXFLAGS(ppnt->p_flags),
663                                             flags | (piclib == 2 ? MAP_EXECUTABLE
664                                                      | MAP_DENYWRITE : 0),
665                                             infile, ppnt->p_offset & OFFS_ALIGN);
666                                 if (_dl_mmap_check_error(status)
667                                     || (tryaddr && tryaddr != status))
668                                   goto cant_map;
669                                 DL_INIT_LOADADDR_HDR
670                                   (lib_loadaddr, status
671                                    + (ppnt->p_vaddr & ADDR_ALIGN), ppnt);
672                         }
673
674                         /* if (libaddr == 0 && piclib) {
675                            libaddr = (unsigned long) status;
676                            flags |= MAP_FIXED;
677                            } */
678                 }
679                 ppnt++;
680         }
681         _dl_close(infile);
682
683         /*
684          * The dynamic_addr must be take into acount lib_loadaddr value, to note
685          * it is zero when the SO has been mapped to the elf's physical addr
686          */
687         if (lib_loadaddr) {
688                 dynamic_addr = (unsigned long) DL_RELOC_ADDR(lib_loadaddr, dynamic_addr);
689         }
690
691         /*
692          * OK, the ELF library is now loaded into VM in the correct locations
693          * The next step is to go through and do the dynamic linking (if needed).
694          */
695
696         /* Start by scanning the dynamic section to get all of the pointers */
697
698         if (!dynamic_addr) {
699                 _dl_internal_error_number = LD_ERROR_NODYNAMIC;
700                 _dl_dprintf(2, "%s: '%s' is missing a dynamic section\n",
701                                 _dl_progname, libname);
702                 _dl_munmap(header, _dl_pagesize);
703                 return NULL;
704         }
705
706         dpnt = (ElfW(Dyn) *) dynamic_addr;
707         _dl_memset(dynamic_info, 0, sizeof(dynamic_info));
708         rtld_flags = _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr);
709         /* If the TEXTREL is set, this means that we need to make the pages
710            writable before we perform relocations.  Do this now. They get set
711            back again later. */
712
713         if (dynamic_info[DT_TEXTREL]) {
714 #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
715                 ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
716                 for (i = 0; i < epnt->e_phnum; i++, ppnt++) {
717                         if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) {
718                                 _dl_mprotect((void *) ((piclib ? libaddr : lib_loadaddr) +
719                                                         (ppnt->p_vaddr & PAGE_ALIGN)),
720                                                 (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,
721                                                 PROT_READ | PROT_WRITE | PROT_EXEC);
722                         }
723                 }
724 #else
725                 _dl_dprintf(_dl_debug_file, "Can't modify %s's text section."
726                         " Use GCC option -fPIC for shared objects, please.\n",
727                         libname);
728                 _dl_exit(1);
729 #endif
730         }
731
732         tpnt = _dl_add_elf_hash_table(libname, lib_loadaddr, dynamic_info,
733                         dynamic_addr, 0);
734         tpnt->mapaddr = libaddr;
735         tpnt->relro_addr = relro_addr;
736         tpnt->relro_size = relro_size;
737         tpnt->st_dev = st.st_dev;
738         tpnt->st_ino = st.st_ino;
739         tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(tpnt->mapaddr, epnt->e_phoff);
740         tpnt->n_phent = epnt->e_phnum;
741         tpnt->rtld_flags |= rtld_flags;
742 #ifdef __LDSO_STANDALONE_SUPPORT__
743         tpnt->l_entry = epnt->e_entry;
744 #endif
745
746 #if defined(USE_TLS) && USE_TLS
747         if (tlsppnt) {
748                 _dl_debug_early("Found TLS header for %s\n", libname);
749 # if NO_TLS_OFFSET != 0
750                 tpnt->l_tls_offset = NO_TLS_OFFSET;
751 # endif
752                 tpnt->l_tls_blocksize = tlsppnt->p_memsz;
753                 tpnt->l_tls_align = tlsppnt->p_align;
754                 if (tlsppnt->p_align == 0)
755                         tpnt->l_tls_firstbyte_offset = 0;
756                 else
757                         tpnt->l_tls_firstbyte_offset = tlsppnt->p_vaddr &
758                                 (tlsppnt->p_align - 1);
759                 tpnt->l_tls_initimage_size = tlsppnt->p_filesz;
760                 tpnt->l_tls_initimage = (void *) tlsppnt->p_vaddr;
761
762                 /* Assign the next available module ID.  */
763                 tpnt->l_tls_modid = _dl_next_tls_modid ();
764
765                 /* We know the load address, so add it to the offset. */
766 #ifdef __LDSO_STANDALONE_SUPPORT__
767                 if ((tpnt->l_tls_initimage != NULL) && piclib)
768 #else
769                 if (tpnt->l_tls_initimage != NULL)
770 #endif
771                 {
772 # ifdef __SUPPORT_LD_DEBUG_EARLY__
773                         unsigned int tmp = (unsigned int) tpnt->l_tls_initimage;
774                         tpnt->l_tls_initimage = (char *) tlsppnt->p_vaddr + tpnt->loadaddr;
775                         _dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n", tmp, tpnt->l_tls_initimage, tpnt->l_tls_initimage_size);
776                         tmp = 0;
777 # else
778                         tpnt->l_tls_initimage = (char *) tlsppnt->p_vaddr + tpnt->loadaddr;
779 # endif
780                 }
781         }
782 #endif
783
784         /*
785          * Add this object into the symbol chain
786          */
787         if (*rpnt
788 #ifdef __LDSO_STANDALONE_SUPPORT__
789                 /* Do not create a new chain entry for the main executable */
790                 && (*rpnt)->dyn
791 #endif
792                 ) {
793                 (*rpnt)->next = _dl_malloc(sizeof(struct dyn_elf));
794                 _dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf));
795                 (*rpnt)->next->prev = (*rpnt);
796                 *rpnt = (*rpnt)->next;
797         }
798 #ifndef SHARED
799         /* When statically linked, the first time we dlopen a DSO
800          * the *rpnt is NULL, so we need to allocate memory for it,
801          * and initialize the _dl_symbol_table.
802          */
803         else {
804                 *rpnt = _dl_symbol_tables = _dl_malloc(sizeof(struct dyn_elf));
805                 _dl_memset(*rpnt, 0, sizeof(struct dyn_elf));
806         }
807 #endif
808         (*rpnt)->dyn = tpnt;
809         tpnt->usage_count++;
810 #ifdef __LDSO_STANDALONE_SUPPORT__
811         tpnt->libtype = (epnt->e_type == ET_DYN) ? elf_lib : elf_executable;
812 #else
813         tpnt->libtype = elf_lib;
814 #endif
815
816         /*
817          * OK, the next thing we need to do is to insert the dynamic linker into
818          * the proper entry in the GOT so that the PLT symbols can be properly
819          * resolved.
820          */
821
822         lpnt = (unsigned long *) dynamic_info[DT_PLTGOT];
823
824         if (lpnt) {
825                 lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT]);
826                 INIT_GOT(lpnt, tpnt);
827         }
828
829 #ifdef __DSBT__
830         /* Handle DSBT initialization */
831         {
832                 struct elf_resolve *t, *ref = NULL;
833                 int idx = tpnt->loadaddr.map->dsbt_index;
834                 unsigned *dsbt = tpnt->loadaddr.map->dsbt_table;
835
836                 if (idx == 0) {
837                         /* This DSO has not been assigned an index */
838                         _dl_dprintf(2, "%s: '%s' is missing a dsbt index assignment!\n",
839                                     _dl_progname, libname);
840                         _dl_exit(1);
841                 }
842
843                 /*
844                  * Setup dsbt slot for this module in dsbt of all modules.
845                  */
846                 for (t = _dl_loaded_modules; t; t = t->next) {
847                         /* find a dsbt table from another module */
848                         if (ref == NULL && t != tpnt) {
849                                 ref = t;
850
851                                 /* make sure index is not already used */
852                                 if (t->loadaddr.map->dsbt_table[idx]) {
853                                         struct elf_resolve *dup;
854                                         char *dup_name;
855
856                                         for (dup = _dl_loaded_modules; dup; dup = dup->next)
857                                                 if (dup != tpnt && dup->loadaddr.map->dsbt_index == idx)
858                                                         break;
859                                         if (dup)
860                                                 dup_name = dup->libname;
861                                         else if (idx == 1)
862                                                 dup_name = "runtime linker";
863                                         else
864                                                 dup_name = "unknown library";
865                                         _dl_dprintf(2, "%s: '%s' dsbt index %d already used by %s!\n",
866                                                     _dl_progname, libname, idx, dup_name);
867                                         _dl_exit(1);
868                                 }
869                         }
870                         t->loadaddr.map->dsbt_table[idx] = (unsigned)dsbt;
871                 }
872                 if (ref)
873                         _dl_memcpy(dsbt, ref->loadaddr.map->dsbt_table,
874                                    tpnt->loadaddr.map->dsbt_size * sizeof(unsigned *));
875         }
876 #endif
877         _dl_if_debug_dprint("\n\tfile='%s';  generating link map\n", libname);
878         _dl_if_debug_dprint("\t\tdynamic: %x  base: %x\n", dynamic_addr, DL_LOADADDR_BASE(lib_loadaddr));
879         _dl_if_debug_dprint("\t\t  entry: %x  phdr: %x  phnum: %x\n\n",
880                         DL_RELOC_ADDR(lib_loadaddr, epnt->e_entry), tpnt->ppnt, tpnt->n_phent);
881
882         _dl_munmap(header, _dl_pagesize);
883
884         return tpnt;
885 }
886
887 /* now_flag must be RTLD_NOW or zero */
888 int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int now_flag)
889 {
890         int goof = 0;
891         struct elf_resolve *tpnt;
892         ElfW(Word) reloc_size, relative_count;
893         ElfW(Addr) reloc_addr;
894
895         if (rpnt->next)
896                 goof = _dl_fixup(rpnt->next, scope, now_flag);
897         if (goof)
898                 return goof;
899         tpnt = rpnt->dyn;
900
901         if (!(tpnt->init_flag & RELOCS_DONE))
902                 _dl_if_debug_dprint("relocation processing: %s\n", tpnt->libname);
903
904         if (unlikely(tpnt->dynamic_info[UNSUPPORTED_RELOC_TYPE])) {
905                 _dl_if_debug_dprint("%s: can't handle %s relocation records\n",
906                                 _dl_progname, UNSUPPORTED_RELOC_STR);
907                 goof++;
908                 return goof;
909         }
910
911         reloc_size = tpnt->dynamic_info[DT_RELOC_TABLE_SIZE];
912 /* On some machines, notably SPARC & PPC, DT_REL* includes DT_JMPREL in its
913    range.  Note that according to the ELF spec, this is completely legal! */
914 #ifdef ELF_MACHINE_PLTREL_OVERLAP
915         reloc_size -= tpnt->dynamic_info [DT_PLTRELSZ];
916 #endif
917         if (tpnt->dynamic_info[DT_RELOC_TABLE_ADDR] &&
918             !(tpnt->init_flag & RELOCS_DONE)) {
919                 reloc_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR];
920                 relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
921                 if (relative_count) { /* Optimize the XX_RELATIVE relocations if possible */
922                         reloc_size -= relative_count * sizeof(ELF_RELOC);
923                         if (tpnt->loadaddr
924 #ifdef __LDSO_PRELINK_SUPPORT__
925                                 || (!tpnt->dynamic_info[DT_GNU_PRELINKED_IDX])
926 #endif
927                                 )
928                                 elf_machine_relative(tpnt->loadaddr, reloc_addr, relative_count);
929                         reloc_addr += relative_count * sizeof(ELF_RELOC);
930                 }
931                 goof += _dl_parse_relocation_information(rpnt, scope,
932                                 reloc_addr,
933                                 reloc_size);
934                 tpnt->init_flag |= RELOCS_DONE;
935         }
936         if (tpnt->dynamic_info[DT_BIND_NOW])
937                 now_flag = RTLD_NOW;
938         if (tpnt->dynamic_info[DT_JMPREL] &&
939             (!(tpnt->init_flag & JMP_RELOCS_DONE) ||
940              (now_flag && !(tpnt->rtld_flags & now_flag)))) {
941                 tpnt->rtld_flags |= now_flag;
942                 if (!(tpnt->rtld_flags & RTLD_NOW)) {
943                         _dl_parse_lazy_relocation_information(rpnt,
944                                         tpnt->dynamic_info[DT_JMPREL],
945                                         tpnt->dynamic_info [DT_PLTRELSZ]);
946                 } else {
947                         goof += _dl_parse_relocation_information(rpnt, scope,
948                                         tpnt->dynamic_info[DT_JMPREL],
949                                         tpnt->dynamic_info[DT_PLTRELSZ]);
950                 }
951                 tpnt->init_flag |= JMP_RELOCS_DONE;
952         }
953
954 #if 0
955 /* _dl_add_to_slotinfo is called by init_tls() for initial DSO
956    or by dlopen() for dynamically loaded DSO. */
957 #if defined(USE_TLS) && USE_TLS
958         /* Add object to slot information data if necessasy. */
959         if (tpnt->l_tls_blocksize != 0 && tls_init_tp_called)
960                 _dl_add_to_slotinfo ((struct link_map *) tpnt);
961 #endif
962 #endif
963         return goof;
964 }
965
966 /* Minimal printf which handles only %s, %d, and %x */
967 void _dl_dprintf(int fd, const char *fmt, ...)
968 {
969 #if __WORDSIZE > 32
970         long int num;
971 #else
972         int num;
973 #endif
974         va_list args;
975         char *start, *ptr, *string;
976         char *buf;
977
978         if (!fmt)
979                 return;
980
981         buf = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
982                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
983         if (_dl_mmap_check_error(buf)) {
984                 _dl_write(fd, "mmap of a spare page failed!\n", 29);
985                 _dl_exit(20);
986         }
987
988         start = ptr = buf;
989
990         if (_dl_strlen(fmt) >= (_dl_pagesize - 1)) {
991                 _dl_write(fd, "overflow\n", 11);
992                 _dl_exit(20);
993         }
994
995         _dl_strcpy(buf, fmt);
996         va_start(args, fmt);
997
998         while (start) {
999                 while (*ptr != '%' && *ptr) {
1000                         ptr++;
1001                 }
1002
1003                 if (*ptr == '%') {
1004                         *ptr++ = '\0';
1005                         _dl_write(fd, start, _dl_strlen(start));
1006
1007                         switch (*ptr++) {
1008                                 case 's':
1009                                         string = va_arg(args, char *);
1010
1011                                         if (!string)
1012                                                 _dl_write(fd, "(null)", 6);
1013                                         else
1014                                                 _dl_write(fd, string, _dl_strlen(string));
1015                                         break;
1016
1017                                 case 'i':
1018                                 case 'd':
1019                                         {
1020                                                 char tmp[22];
1021 #if __WORDSIZE > 32
1022                                                 num = va_arg(args, long int);
1023 #else
1024                                                 num = va_arg(args, int);
1025 #endif
1026                                                 string = _dl_simple_ltoa(tmp, num);
1027                                                 _dl_write(fd, string, _dl_strlen(string));
1028                                                 break;
1029                                         }
1030                                 case 'x':
1031                                 case 'X':
1032                                         {
1033                                                 char tmp[22];
1034 #if __WORDSIZE > 32
1035                                                 num = va_arg(args, long int);
1036 #else
1037                                                 num = va_arg(args, int);
1038 #endif
1039                                                 string = _dl_simple_ltoahex(tmp, num);
1040                                                 _dl_write(fd, string, _dl_strlen(string));
1041                                                 break;
1042                                         }
1043                                 default:
1044                                         _dl_write(fd, "(null)", 6);
1045                                         break;
1046                         }
1047
1048                         start = ptr;
1049                 } else {
1050                         _dl_write(fd, start, _dl_strlen(start));
1051                         start = NULL;
1052                 }
1053         }
1054         _dl_munmap(buf, _dl_pagesize);
1055         return;
1056 }
1057
1058 char *_dl_strdup(const char *string)
1059 {
1060         char *retval;
1061         int len;
1062
1063         len = _dl_strlen(string);
1064         retval = _dl_malloc(len + 1);
1065         _dl_strcpy(retval, string);
1066         return retval;
1067 }
1068
1069 unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
1070                                     void *debug_addr, DL_LOADADDR_TYPE load_off)
1071 {
1072         return __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off);
1073 }