]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-elf.c
Inital import
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / 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 { (void)tpnt;
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, 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         int i, flags, piclib, infile;
341         ElfW(Addr) relro_addr = 0;
342         size_t relro_size = 0;
343         struct stat st;
344         uint32_t *p32;
345         DL_LOADADDR_TYPE lib_loadaddr;
346         DL_INIT_LOADADDR_EXTRA_DECLS
347
348         libaddr = 0;
349         infile = _dl_open(libname, O_RDONLY, 0);
350         if (infile < 0) {
351                 _dl_internal_error_number = LD_ERROR_NOFILE;
352                 return NULL;
353         }
354
355         if (_dl_fstat(infile, &st) < 0) {
356                 _dl_internal_error_number = LD_ERROR_NOFILE;
357                 _dl_close(infile);
358                 return NULL;
359         }
360         /* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD),
361            we don't load the library if it isn't setuid. */
362         if (secure) {
363                 if (!(st.st_mode & S_ISUID)) {
364                         _dl_close(infile);
365                         return NULL;
366                 }
367         }
368
369         /* Check if file is already loaded */
370         for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
371 #ifndef __NOT_FOR_L4__
372                 if (_dl_cap_equal(tpnt->st_dev, st.st_dev)) {
373 #else
374                 if (tpnt->st_dev == st.st_dev && tpnt->st_ino == st.st_ino) {
375 #endif
376                         /* Already loaded */
377                         tpnt->usage_count++;
378                         _dl_close(infile);
379                         return tpnt;
380                 }
381         }
382         header = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
383                         MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZE, -1, 0);
384         if (_dl_mmap_check_error(header)) {
385                 _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
386                 _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
387                 _dl_close(infile);
388                 return NULL;
389         }
390
391         _dl_read(infile, header, _dl_pagesize);
392         epnt = (ElfW(Ehdr) *) (intptr_t) header;
393         p32 = (uint32_t*)&epnt->e_ident;
394         if (*p32 != ELFMAG_U32) {
395                 _dl_dprintf(2, "%s: '%s' is not an ELF file\n", _dl_progname,
396                                 libname);
397                 _dl_internal_error_number = LD_ERROR_NOTELF;
398                 _dl_close(infile);
399                 _dl_munmap(header, _dl_pagesize);
400                 return NULL;
401         }
402
403         if ((epnt->e_type != ET_DYN) || (epnt->e_machine != MAGIC1
404 #ifdef MAGIC2
405                                 && epnt->e_machine != MAGIC2
406 #endif
407                                 ))
408         {
409                 _dl_internal_error_number =
410                         (epnt->e_type != ET_DYN ? LD_ERROR_NOTDYN : LD_ERROR_NOTMAGIC);
411                 _dl_dprintf(2, "%s: '%s' is not an ELF executable for " ELF_TARGET
412                                 "\n", _dl_progname, libname);
413                 _dl_close(infile);
414                 _dl_munmap(header, _dl_pagesize);
415                 return NULL;
416         }
417
418         ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
419
420         piclib = 1;
421         for (i = 0; i < epnt->e_phnum; i++) {
422
423                 if (ppnt->p_type == PT_DYNAMIC) {
424                         if (dynamic_addr)
425                                 _dl_dprintf(2, "%s: '%s' has more than one dynamic section\n",
426                                                 _dl_progname, libname);
427                         dynamic_addr = ppnt->p_vaddr;
428                 }
429
430                 if (ppnt->p_type == PT_LOAD) {
431                         /* See if this is a PIC library. */
432                         if (i == 0 && ppnt->p_vaddr > 0x1000000) {
433                                 piclib = 0;
434                                 minvma = ppnt->p_vaddr;
435                         }
436                         if (piclib && ppnt->p_vaddr < minvma) {
437                                 minvma = ppnt->p_vaddr;
438                         }
439                         if (((unsigned long) ppnt->p_vaddr + ppnt->p_memsz) > maxvma) {
440                                 maxvma = ppnt->p_vaddr + ppnt->p_memsz;
441                         }
442                 }
443                 if (ppnt->p_type == PT_TLS) {
444 #if defined(USE_TLS) && USE_TLS
445                         if (ppnt->p_memsz == 0)
446                                 /* Nothing to do for an empty segment.  */
447                                 continue;
448                         else
449                                 /* Save for after 'tpnt' is actually allocated. */
450                                 tlsppnt = ppnt;
451 #else
452                         /*
453                          * Yup, the user was an idiot and tried to sneak in a library with
454                          * TLS in it and we don't support it. Let's fall on our own sword
455                          * and scream at the luser while we die.
456                          */
457                         _dl_dprintf(2, "%s: '%s' library contains unsupported TLS\n",
458                                 _dl_progname, libname);
459                         _dl_internal_error_number = LD_ERROR_TLS_FAILED;
460                         _dl_close(infile);
461                         _dl_munmap(header, _dl_pagesize);
462                         return NULL;
463 #endif
464                 }
465                 ppnt++;
466         }
467
468         DL_CHECK_LIB_TYPE (epnt, piclib, _dl_progname, libname);
469
470         maxvma = (maxvma + ADDR_ALIGN) & PAGE_ALIGN;
471         minvma = minvma & ~0xffffU;
472
473         flags = MAP_PRIVATE /*| MAP_DENYWRITE */ ;
474         if (!piclib)
475                 flags |= MAP_FIXED;
476
477         if (piclib == 0 || piclib == 1) {
478 #ifdef __NOT_FOR_L4__
479                 status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma),
480                                 maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0);
481 #else
482                 status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma),
483                                 maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS | 0x1000000, -1, 0);
484 #endif
485                 if (_dl_mmap_check_error(status)) {
486                         _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
487                         _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
488                         _dl_close(infile);
489                         _dl_munmap(header, _dl_pagesize);
490                         return NULL;
491                 }
492                 libaddr = (unsigned long) status;
493                 flags |= MAP_FIXED;
494         }
495
496         /* Get the memory to store the library */
497         ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
498
499         DL_INIT_LOADADDR(lib_loadaddr, libaddr, ppnt, epnt->e_phnum);
500
501         for (i = 0; i < epnt->e_phnum; i++) {
502                 if (DL_IS_SPECIAL_SEGMENT (epnt, ppnt)) {
503                         char *addr;
504
505                         addr = DL_MAP_SEGMENT (epnt, ppnt, infile, flags);
506                         if (addr == NULL)
507                                 goto cant_map;
508
509                         DL_INIT_LOADADDR_HDR (lib_loadaddr, addr, ppnt);
510                         ppnt++;
511                         continue;
512                 }
513                 if (ppnt->p_type == PT_GNU_RELRO) {
514                         relro_addr = ppnt->p_vaddr;
515                         relro_size = ppnt->p_memsz;
516                 }
517                 if (ppnt->p_type == PT_LOAD) {
518                         char *tryaddr;
519                         ssize_t size;
520
521                         /* See if this is a PIC library. */
522                         if (i == 0 && ppnt->p_vaddr > 0x1000000) {
523                                 piclib = 0;
524                                 /* flags |= MAP_FIXED; */
525                         }
526
527                         if (ppnt->p_flags & PF_W) {
528                                 unsigned long map_size;
529                                 char *cpnt;
530                                 char *piclib2map = 0;
531
532                                 if (piclib == 2 &&
533                                     /* We might be able to avoid this
534                                        call if memsz doesn't require
535                                        an additional page, but this
536                                        would require mmap to always
537                                        return page-aligned addresses
538                                        and a whole number of pages
539                                        allocated.  Unfortunately on
540                                        uClinux may return misaligned
541                                        addresses and may allocate
542                                        partial pages, so we may end up
543                                        doing unnecessary mmap calls.
544
545                                        This is what we could do if we
546                                        knew mmap would always return
547                                        aligned pages:
548
549                                     ((ppnt->p_vaddr + ppnt->p_filesz
550                                       + ADDR_ALIGN)
551                                      & PAGE_ALIGN)
552                                     < ppnt->p_vaddr + ppnt->p_memsz)
553
554                                        Instead, we have to do this:  */
555                                     ppnt->p_filesz < ppnt->p_memsz)
556                                   {
557                                     piclib2map = (char *)
558                                       _dl_mmap(0, (ppnt->p_vaddr & ADDR_ALIGN)
559                                                + ppnt->p_memsz,
560                                                LXFLAGS(ppnt->p_flags),
561                                                flags | MAP_ANONYMOUS, -1, 0);
562                                     if (_dl_mmap_check_error(piclib2map))
563                                       goto cant_map;
564                                     DL_INIT_LOADADDR_HDR
565                                       (lib_loadaddr, piclib2map
566                                        + (ppnt->p_vaddr & ADDR_ALIGN), ppnt);
567                                   }
568
569                                 tryaddr = piclib == 2 ? piclib2map
570                                   : ((char*) (piclib ? libaddr : 0) +
571                                      (ppnt->p_vaddr & PAGE_ALIGN));
572
573                                 size = (ppnt->p_vaddr & ADDR_ALIGN)
574                                   + ppnt->p_filesz;
575
576                                 /* For !MMU, mmap to fixed address will fail.
577                                    So instead of desperately call mmap and fail,
578                                    we set status to MAP_FAILED to save a call
579                                    to mmap ().  */
580 #ifndef __ARCH_USE_MMU__
581                                 if (piclib2map == 0)
582 #endif
583                                   status = (char *) _dl_mmap
584                                     (tryaddr, size, LXFLAGS(ppnt->p_flags),
585                                      flags | (piclib2map ? MAP_FIXED : 0),
586                                      infile, ppnt->p_offset & OFFS_ALIGN);
587 #ifndef __ARCH_USE_MMU__
588                                 else
589                                   status = MAP_FAILED;
590 #endif
591 #ifdef _DL_PREAD
592                                 if (_dl_mmap_check_error(status) && piclib2map
593                                     && (_DL_PREAD (infile, tryaddr, size,
594                                                    ppnt->p_offset & OFFS_ALIGN)
595                                         == size))
596                                   status = tryaddr;
597 #endif
598                                 if (_dl_mmap_check_error(status)
599                                     || (tryaddr && tryaddr != status)) {
600                                 cant_map:
601                                         _dl_dprintf(2, "%s:%i: can't map '%s'\n",
602                                                         _dl_progname, __LINE__, libname);
603                                         _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
604                                         DL_LOADADDR_UNMAP (lib_loadaddr, maxvma - minvma);
605                                         _dl_close(infile);
606                                         _dl_munmap(header, _dl_pagesize);
607                                         return NULL;
608                                 }
609
610                                 if (! piclib2map) {
611                                   DL_INIT_LOADADDR_HDR
612                                     (lib_loadaddr, status
613                                      + (ppnt->p_vaddr & ADDR_ALIGN), ppnt);
614                                 }
615                                 /* Now we want to allocate and
616                                    zero-out any data from the end of
617                                    the region we mapped in from the
618                                    file (filesz) to the end of the
619                                    loadable segment (memsz).  We may
620                                    need additional pages for memsz,
621                                    that we map in below, and we can
622                                    count on the kernel to zero them
623                                    out, but we have to zero out stuff
624                                    in the last page that we mapped in
625                                    from the file.  However, we can't
626                                    assume to have actually obtained
627                                    full pages from the kernel, since
628                                    we didn't ask for them, and uClibc
629                                    may not give us full pages for
630                                    small allocations.  So only zero
631                                    out up to memsz or the end of the
632                                    page, whichever comes first.  */
633
634                                 /* CPNT is the beginning of the memsz
635                                    portion not backed by filesz.  */
636                                 cpnt = (char *) (status + size);
637
638                                 /* MAP_SIZE is the address of the
639                                    beginning of the next page.  */
640                                 map_size = (ppnt->p_vaddr + ppnt->p_filesz
641                                             + ADDR_ALIGN) & PAGE_ALIGN;
642
643 #ifndef MIN
644 # define MIN(a,b) ((a) < (b) ? (a) : (b))
645 #endif
646                                 _dl_memset (cpnt, 0,
647                                             MIN (map_size
648                                                  - (ppnt->p_vaddr
649                                                     + ppnt->p_filesz),
650                                                  ppnt->p_memsz
651                                                  - ppnt->p_filesz));
652
653                                 if (map_size < ppnt->p_vaddr + ppnt->p_memsz
654                                     && !piclib2map) {
655                                         tryaddr = map_size + (char*)(piclib ? libaddr : 0);
656                                         status = (char *) _dl_mmap(tryaddr,
657                                                 ppnt->p_vaddr + ppnt->p_memsz - map_size,
658                                                 LXFLAGS(ppnt->p_flags), flags | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
659                                         if (_dl_mmap_check_error(status)
660                                             || tryaddr != status)
661                                                 goto cant_map;
662                                 }
663                         } else {
664                                 tryaddr = (piclib == 2 ? 0
665                                            : (char *) (ppnt->p_vaddr & PAGE_ALIGN)
666                                            + (piclib ? libaddr : 0));
667                                 size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
668                                 status = (char *) _dl_mmap
669                                            (tryaddr, size, LXFLAGS(ppnt->p_flags),
670                                             flags | (piclib == 2 ? MAP_EXECUTABLE
671                                                      | MAP_DENYWRITE : 0),
672                                             infile, ppnt->p_offset & OFFS_ALIGN);
673                                 if (_dl_mmap_check_error(status)
674                                     || (tryaddr && tryaddr != status))
675                                   goto cant_map;
676                                 DL_INIT_LOADADDR_HDR
677                                   (lib_loadaddr, status
678                                    + (ppnt->p_vaddr & ADDR_ALIGN), ppnt);
679                         }
680
681                         /* if (libaddr == 0 && piclib) {
682                            libaddr = (unsigned long) status;
683                            flags |= MAP_FIXED;
684                            } */
685                 }
686                 ppnt++;
687         }
688         _dl_close(infile);
689
690         /* For a non-PIC library, the addresses are all absolute */
691         if (piclib) {
692                 dynamic_addr = (unsigned long) DL_RELOC_ADDR(lib_loadaddr, dynamic_addr);
693         }
694
695         /*
696          * OK, the ELF library is now loaded into VM in the correct locations
697          * The next step is to go through and do the dynamic linking (if needed).
698          */
699
700         /* Start by scanning the dynamic section to get all of the pointers */
701
702         if (!dynamic_addr) {
703                 _dl_internal_error_number = LD_ERROR_NODYNAMIC;
704                 _dl_dprintf(2, "%s: '%s' is missing a dynamic section\n",
705                                 _dl_progname, libname);
706                 _dl_munmap(header, _dl_pagesize);
707                 return NULL;
708         }
709
710         dpnt = (ElfW(Dyn) *) dynamic_addr;
711         _dl_memset(dynamic_info, 0, sizeof(dynamic_info));
712         _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr);
713         /* If the TEXTREL is set, this means that we need to make the pages
714            writable before we perform relocations.  Do this now. They get set
715            back again later. */
716
717         if (dynamic_info[DT_TEXTREL]) {
718 #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
719                 ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
720                 for (i = 0; i < epnt->e_phnum; i++, ppnt++) {
721                         if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) {
722                                 _dl_mprotect((void *) ((piclib ? libaddr : 0) +
723                                                         (ppnt->p_vaddr & PAGE_ALIGN)),
724                                                 (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,
725                                                 PROT_READ | PROT_WRITE | PROT_EXEC);
726                         }
727                 }
728 #else
729                 _dl_dprintf(_dl_debug_file, "Can't modify %s's text section."
730                         " Use GCC option -fPIC for shared objects, please.\n",
731                         libname);
732                 _dl_exit(1);
733 #endif
734         }
735
736         tpnt = _dl_add_elf_hash_table(libname, lib_loadaddr, dynamic_info,
737                         dynamic_addr, 0);
738         tpnt->relro_addr = relro_addr;
739         tpnt->relro_size = relro_size;
740         tpnt->st_dev = st.st_dev;
741         tpnt->st_ino = st.st_ino;
742         tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(tpnt->loadaddr, epnt->e_phoff);
743         tpnt->n_phent = epnt->e_phnum;
744
745 #if defined(USE_TLS) && USE_TLS
746         if (tlsppnt) {
747                 _dl_debug_early("Found TLS header for %s\n", libname);
748 #if NO_TLS_OFFSET != 0
749                 tpnt->l_tls_offset = NO_TLS_OFFSET;
750 #endif
751                 tpnt->l_tls_blocksize = tlsppnt->p_memsz;
752                 tpnt->l_tls_align = tlsppnt->p_align;
753                 if (tlsppnt->p_align == 0)
754                         tpnt->l_tls_firstbyte_offset = 0;
755                 else
756                         tpnt->l_tls_firstbyte_offset = tlsppnt->p_vaddr &
757                                 (tlsppnt->p_align - 1);
758                 tpnt->l_tls_initimage_size = tlsppnt->p_filesz;
759                 tpnt->l_tls_initimage = (void *) tlsppnt->p_vaddr;
760
761                 /* Assign the next available module ID.  */
762                 tpnt->l_tls_modid = _dl_next_tls_modid ();
763
764                 /* We know the load address, so add it to the offset. */
765                 if (tpnt->l_tls_initimage != NULL)
766                 {
767                         unsigned int tmp = (unsigned int) tpnt->l_tls_initimage;
768                         tpnt->l_tls_initimage = (char *) tlsppnt->p_vaddr + tpnt->loadaddr;
769                         _dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n", tmp, tpnt->l_tls_initimage, tpnt->l_tls_initimage_size);
770                         tmp = 0;
771                 }
772         }
773 #endif
774
775         /*
776          * Add this object into the symbol chain
777          */
778         if (*rpnt) {
779                 (*rpnt)->next = _dl_malloc(sizeof(struct dyn_elf));
780                 _dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf));
781                 (*rpnt)->next->prev = (*rpnt);
782                 *rpnt = (*rpnt)->next;
783         }
784 #ifndef SHARED
785         /* When statically linked, the first time we dlopen a DSO
786          * the *rpnt is NULL, so we need to allocate memory for it,
787          * and initialize the _dl_symbol_table.
788          */
789         else {
790                 *rpnt = _dl_symbol_tables = _dl_malloc(sizeof(struct dyn_elf));
791                 _dl_memset(*rpnt, 0, sizeof(struct dyn_elf));
792         }
793 #endif
794         (*rpnt)->dyn = tpnt;
795         tpnt->symbol_scope = _dl_symbol_tables;
796         tpnt->usage_count++;
797         tpnt->libtype = elf_lib;
798
799         /*
800          * OK, the next thing we need to do is to insert the dynamic linker into
801          * the proper entry in the GOT so that the PLT symbols can be properly
802          * resolved.
803          */
804
805         lpnt = (unsigned long *) dynamic_info[DT_PLTGOT];
806
807         if (lpnt) {
808                 lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT]);
809                 INIT_GOT(lpnt, tpnt);
810         }
811
812         _dl_if_debug_dprint("\n\tfile='%s';  generating link map\n", libname);
813         _dl_if_debug_dprint("\t\tdynamic: %x  base: %x\n", dynamic_addr, DL_LOADADDR_BASE(lib_loadaddr));
814         _dl_if_debug_dprint("\t\t  entry: %x  phdr: %x  phnum: %x\n\n",
815                         DL_RELOC_ADDR(lib_loadaddr, epnt->e_entry), tpnt->ppnt, tpnt->n_phent);
816
817         _dl_munmap(header, _dl_pagesize);
818
819         return tpnt;
820 }
821
822 /* now_flag must be RTLD_NOW or zero */
823 int _dl_fixup(struct dyn_elf *rpnt, int now_flag)
824 {
825         int goof = 0;
826         struct elf_resolve *tpnt;
827         ElfW(Word) reloc_size, relative_count;
828         ElfW(Addr) reloc_addr;
829
830         if (rpnt->next)
831                 goof = _dl_fixup(rpnt->next, now_flag);
832         if (goof)
833                 return goof;
834         tpnt = rpnt->dyn;
835
836         if (!(tpnt->init_flag & RELOCS_DONE))
837                 _dl_if_debug_dprint("relocation processing: %s\n", tpnt->libname);
838
839         if (unlikely(tpnt->dynamic_info[UNSUPPORTED_RELOC_TYPE])) {
840                 _dl_if_debug_dprint("%s: can't handle %s relocation records\n",
841                                 _dl_progname, UNSUPPORTED_RELOC_STR);
842                 goof++;
843                 return goof;
844         }
845
846         reloc_size = tpnt->dynamic_info[DT_RELOC_TABLE_SIZE];
847 /* On some machines, notably SPARC & PPC, DT_REL* includes DT_JMPREL in its
848    range.  Note that according to the ELF spec, this is completely legal! */
849 #ifdef ELF_MACHINE_PLTREL_OVERLAP
850         reloc_size -= tpnt->dynamic_info [DT_PLTRELSZ];
851 #endif
852         if (tpnt->dynamic_info[DT_RELOC_TABLE_ADDR] &&
853             !(tpnt->init_flag & RELOCS_DONE)) {
854                 reloc_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR];
855                 relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
856                 if (relative_count) { /* Optimize the XX_RELATIVE relocations if possible */
857                         reloc_size -= relative_count * sizeof(ELF_RELOC);
858                         elf_machine_relative(tpnt->loadaddr, reloc_addr, relative_count);
859                         reloc_addr += relative_count * sizeof(ELF_RELOC);
860                 }
861                 goof += _dl_parse_relocation_information(rpnt,
862                                 reloc_addr,
863                                 reloc_size);
864                 tpnt->init_flag |= RELOCS_DONE;
865         }
866         if (tpnt->dynamic_info[DT_BIND_NOW])
867                 now_flag = RTLD_NOW;
868         if (tpnt->dynamic_info[DT_JMPREL] &&
869             (!(tpnt->init_flag & JMP_RELOCS_DONE) ||
870              (now_flag && !(tpnt->rtld_flags & now_flag)))) {
871                 tpnt->rtld_flags |= now_flag;
872                 if (!(tpnt->rtld_flags & RTLD_NOW)) {
873                         _dl_parse_lazy_relocation_information(rpnt,
874                                         tpnt->dynamic_info[DT_JMPREL],
875                                         tpnt->dynamic_info [DT_PLTRELSZ]);
876                 } else {
877                         goof += _dl_parse_relocation_information(rpnt,
878                                         tpnt->dynamic_info[DT_JMPREL],
879                                         tpnt->dynamic_info[DT_PLTRELSZ]);
880                 }
881                 tpnt->init_flag |= JMP_RELOCS_DONE;
882         }
883
884 #if 0
885 /* _dl_add_to_slotinfo is called by init_tls() for initial DSO
886    or by dlopen() for dynamically loaded DSO. */
887 #if defined(USE_TLS) && USE_TLS
888         /* Add object to slot information data if necessasy. */
889         if (tpnt->l_tls_blocksize != 0 && tls_init_tp_called)
890                 _dl_add_to_slotinfo ((struct link_map *) tpnt);
891 #endif
892 #endif
893         return goof;
894 }
895 #ifndef NOT_FOR_L4
896 #include <l4/sys/utcb.h>
897 #endif
898
899 /* Minimal printf which handles only %s, %d, and %x */
900 void _dl_dprintf(int fd, const char *fmt, ...)
901 {
902 #if __WORDSIZE > 32
903         long int num;
904 #else
905         int num;
906 #endif
907         va_list args;
908         char *start, *ptr, *string;
909         char *buf;
910
911         if (!fmt)
912                 return;
913
914 #ifndef NOT_FOR_L4
915         l4_msg_regs_t store_mr;
916         l4_buf_regs_t store_br;
917         l4_msg_regs_t *mr = l4_utcb_mr();
918         l4_buf_regs_t *br = l4_utcb_br();
919
920         _dl_memcpy(&store_mr, mr, sizeof(store_mr));
921         _dl_memcpy(&store_br, br, sizeof(store_br));
922 #endif
923
924         buf = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
925                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
926         if (_dl_mmap_check_error(buf)) {
927                 _dl_write(fd, "mmap of a spare page failed!\n", 29);
928                 _dl_exit(20);
929         }
930
931         start = ptr = buf;
932
933         if (_dl_strlen(fmt) >= (_dl_pagesize - 1)) {
934                 _dl_write(fd, "overflow\n", 11);
935                 _dl_exit(20);
936         }
937
938         _dl_strcpy(buf, fmt);
939         va_start(args, fmt);
940
941         while (start) {
942                 while (*ptr != '%' && *ptr) {
943                         ptr++;
944                 }
945
946                 if (*ptr == '%') {
947                         *ptr++ = '\0';
948                         _dl_write(fd, start, _dl_strlen(start));
949
950                         switch (*ptr++) {
951                                 case 's':
952                                         string = va_arg(args, char *);
953
954                                         if (!string)
955                                                 _dl_write(fd, "(null)", 6);
956                                         else
957                                                 _dl_write(fd, string, _dl_strlen(string));
958                                         break;
959
960                                 case 'i':
961                                 case 'd':
962                                         {
963                                                 char tmp[22];
964 #if __WORDSIZE > 32
965                                                 num = va_arg(args, long int);
966 #else
967                                                 num = va_arg(args, int);
968 #endif
969                                                 string = _dl_simple_ltoa(tmp, num);
970                                                 _dl_write(fd, string, _dl_strlen(string));
971                                                 break;
972                                         }
973                                 case 'x':
974                                 case 'X':
975                                         {
976                                                 char tmp[22];
977 #if __WORDSIZE > 32
978                                                 num = va_arg(args, long int);
979 #else
980                                                 num = va_arg(args, int);
981 #endif
982                                                 string = _dl_simple_ltoahex(tmp, num);
983                                                 _dl_write(fd, string, _dl_strlen(string));
984                                                 break;
985                                         }
986                                 default:
987                                         _dl_write(fd, "(null)", 6);
988                                         break;
989                         }
990
991                         start = ptr;
992                 } else {
993                         _dl_write(fd, start, _dl_strlen(start));
994                         start = NULL;
995                 }
996         }
997         _dl_munmap(buf, _dl_pagesize);
998 #ifndef NOT_FOR_L4
999         _dl_memcpy(mr, &store_mr, sizeof(store_mr));
1000         _dl_memcpy(br, &store_br, sizeof(store_br));
1001 #endif
1002         return;
1003 }
1004
1005 char *_dl_strdup(const char *string)
1006 {
1007         char *retval;
1008         int len;
1009
1010         len = _dl_strlen(string);
1011         retval = _dl_malloc(len + 1);
1012         _dl_strcpy(retval, string);
1013         return retval;
1014 }
1015
1016 void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
1017                             void *debug_addr, DL_LOADADDR_TYPE load_off)
1018 {
1019         __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off);
1020 }