OSDN Git Service

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