OSDN Git Service

- use proper macros
[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 == (caddr_t) - 1)
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, 0)) < 0) {
55                 _dl_cache_addr = (caddr_t) - 1; /* 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 = (caddr_t) - 1;
100         return -1;
101 }
102
103 int _dl_unmap_cache(void)
104 {
105         if (_dl_cache_addr == NULL || _dl_cache_addr == (caddr_t) - 1)
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 != (caddr_t) - 1) {
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,
280                                                                                                                  rpnt, strs + libent[i].liboffset)))
281                                 return tpnt1;
282                 }
283         }
284 #endif
285
286         /* Look for libraries wherever the shared library loader
287          * was installed */
288         _dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath);
289         if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt)) != NULL)
290         {
291                 return tpnt1;
292         }
293
294
295         /* Lastly, search the standard list of paths for the library.
296            This list must exactly match the list in uClibc/ldso/util/ldd.c */
297         _dl_if_debug_dprint("\tsearching full lib path list\n");
298         if ((tpnt1 = search_for_named_library(libname, secure,
299                                         UCLIBC_RUNTIME_PREFIX "lib:"
300                                         UCLIBC_RUNTIME_PREFIX "usr/lib"
301 #ifndef __LDSO_CACHE_SUPPORT__
302                                         ":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib"
303 #endif
304                                         , rpnt)
305                 ) != NULL)
306         {
307                 return tpnt1;
308         }
309
310 goof:
311         /* Well, we shot our wad on that one.  All we can do now is punt */
312         if (_dl_internal_error_number)
313                 _dl_error_number = _dl_internal_error_number;
314         else
315                 _dl_error_number = LD_ERROR_NOFILE;
316         _dl_if_debug_dprint("Bummer: could not find '%s'!\n", libname);
317         return NULL;
318 }
319
320
321 /*
322  * Read one ELF library into memory, mmap it into the correct locations and
323  * add the symbol info to the symbol chain.  Perform any relocations that
324  * are required.
325  */
326
327 struct elf_resolve *_dl_load_elf_shared_library(int secure,
328         struct dyn_elf **rpnt, char *libname)
329 {
330         ElfW(Ehdr) *epnt;
331         unsigned long dynamic_addr = 0;
332         ElfW(Dyn) *dpnt;
333         struct elf_resolve *tpnt;
334         ElfW(Phdr) *ppnt;
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         DL_LOADADDR_TYPE lib_loadaddr;
345         DL_INIT_LOADADDR_EXTRA_DECLS
346
347         libaddr = 0;
348         infile = _dl_open(libname, O_RDONLY, 0);
349         if (infile < 0) {
350                 _dl_internal_error_number = LD_ERROR_NOFILE;
351                 return NULL;
352         }
353
354         if (_dl_fstat(infile, &st) < 0) {
355                 _dl_internal_error_number = LD_ERROR_NOFILE;
356                 _dl_close(infile);
357                 return NULL;
358         }
359         /* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD),
360            we don't load the library if it isn't setuid. */
361         if (secure)
362                 if (!(st.st_mode & S_ISUID)) {
363                         _dl_close(infile);
364                         return NULL;
365                 }
366
367         /* Check if file is already loaded */
368         for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
369                 if (tpnt->st_dev == st.st_dev && tpnt->st_ino == st.st_ino) {
370                         /* Already loaded */
371                         tpnt->usage_count++;
372                         _dl_close(infile);
373                         return tpnt;
374                 }
375         }
376         header = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
377                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
378         if (_dl_mmap_check_error(header)) {
379                 _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
380                 _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
381                 _dl_close(infile);
382                 return NULL;
383         }
384
385         _dl_read(infile, header, _dl_pagesize);
386         epnt = (ElfW(Ehdr) *) (intptr_t) header;
387         if (epnt->e_ident[0] != 0x7f ||
388                         epnt->e_ident[1] != 'E' ||
389                         epnt->e_ident[2] != 'L' ||
390                         epnt->e_ident[3] != 'F')
391         {
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) || (epnt->e_machine != MAGIC1
401 #ifdef MAGIC2
402                                 && epnt->e_machine != MAGIC2
403 #endif
404                                 ))
405         {
406                 _dl_internal_error_number =
407                         (epnt->e_type != ET_DYN ? LD_ERROR_NOTDYN : LD_ERROR_NOTMAGIC);
408                 _dl_dprintf(2, "%s: '%s' is not an ELF executable for " ELF_TARGET
409                                 "\n", _dl_progname, libname);
410                 _dl_close(infile);
411                 _dl_munmap(header, _dl_pagesize);
412                 return NULL;
413         }
414
415         ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
416
417         piclib = 1;
418         for (i = 0; i < epnt->e_phnum; i++) {
419
420                 if (ppnt->p_type == PT_DYNAMIC) {
421                         if (dynamic_addr)
422                                 _dl_dprintf(2, "%s: '%s' has more than one dynamic section\n",
423                                                 _dl_progname, libname);
424                         dynamic_addr = ppnt->p_vaddr;
425                 }
426
427                 if (ppnt->p_type == PT_LOAD) {
428                         /* See if this is a PIC library. */
429                         if (i == 0 && ppnt->p_vaddr > 0x1000000) {
430                                 piclib = 0;
431                                 minvma = ppnt->p_vaddr;
432                         }
433                         if (piclib && ppnt->p_vaddr < minvma) {
434                                 minvma = ppnt->p_vaddr;
435                         }
436                         if (((unsigned long) ppnt->p_vaddr + ppnt->p_memsz) > maxvma) {
437                                 maxvma = ppnt->p_vaddr + ppnt->p_memsz;
438                         }
439                 }
440                 ppnt++;
441         }
442
443         DL_CHECK_LIB_TYPE (epnt, piclib, _dl_progname, libname);
444
445         maxvma = (maxvma + ADDR_ALIGN) & PAGE_ALIGN;
446         minvma = minvma & ~0xffffU;
447
448         flags = MAP_PRIVATE /*| MAP_DENYWRITE */ ;
449         if (!piclib)
450                 flags |= MAP_FIXED;
451
452         if (piclib == 0 || piclib == 1) {
453                 status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma),
454                                 maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0);
455                 if (_dl_mmap_check_error(status)) {
456                         _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
457                         _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
458                         _dl_close(infile);
459                         _dl_munmap(header, _dl_pagesize);
460                         return NULL;
461                 }
462                 libaddr = (unsigned long) status;
463                 flags |= MAP_FIXED;
464         }
465
466         /* Get the memory to store the library */
467         ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
468
469         DL_INIT_LOADADDR(lib_loadaddr, libaddr, ppnt, epnt->e_phnum);
470
471         for (i = 0; i < epnt->e_phnum; i++) {
472                 if (DL_IS_SPECIAL_SEGMENT (epnt, ppnt)) {
473                         char *addr;
474
475                         addr = DL_MAP_SEGMENT (epnt, ppnt, infile, flags);
476                         if (addr == NULL)
477                                 goto cant_map;
478
479                         DL_INIT_LOADADDR_HDR (lib_loadaddr, addr, ppnt);
480                         ppnt++;
481                         continue;
482                 }
483                 if (ppnt->p_type == PT_GNU_RELRO) {
484                         relro_addr = ppnt->p_vaddr;
485                         relro_size = ppnt->p_memsz;
486                 }
487                 if (ppnt->p_type == PT_LOAD) {
488                         char *tryaddr;
489                         ssize_t size;
490
491                         /* See if this is a PIC library. */
492                         if (i == 0 && ppnt->p_vaddr > 0x1000000) {
493                                 piclib = 0;
494                                 /* flags |= MAP_FIXED; */
495                         }
496
497                         if (ppnt->p_flags & PF_W) {
498                                 unsigned long map_size;
499                                 char *cpnt;
500                                 char *piclib2map = 0;
501
502                                 if (piclib == 2 &&
503                                     /* We might be able to avoid this
504                                        call if memsz doesn't require
505                                        an additional page, but this
506                                        would require mmap to always
507                                        return page-aligned addresses
508                                        and a whole number of pages
509                                        allocated.  Unfortunately on
510                                        uClinux may return misaligned
511                                        addresses and may allocate
512                                        partial pages, so we may end up
513                                        doing unnecessary mmap calls.
514
515                                        This is what we could do if we
516                                        knew mmap would always return
517                                        aligned pages:
518
519                                     ((ppnt->p_vaddr + ppnt->p_filesz
520                                       + ADDR_ALIGN)
521                                      & PAGE_ALIGN)
522                                     < ppnt->p_vaddr + ppnt->p_memsz)
523
524                                        Instead, we have to do this:  */
525                                     ppnt->p_filesz < ppnt->p_memsz)
526                                   {
527                                     piclib2map = (char *)
528                                       _dl_mmap(0, (ppnt->p_vaddr & ADDR_ALIGN)
529                                                + ppnt->p_memsz,
530                                                LXFLAGS(ppnt->p_flags),
531                                                flags | MAP_ANONYMOUS, -1, 0);
532                                     if (_dl_mmap_check_error(piclib2map))
533                                       goto cant_map;
534                                     DL_INIT_LOADADDR_HDR
535                                       (lib_loadaddr, piclib2map
536                                        + (ppnt->p_vaddr & ADDR_ALIGN), ppnt);
537                                   }
538
539                                 tryaddr = piclib == 2 ? piclib2map
540                                   : ((char*) (piclib ? libaddr : 0) +
541                                      (ppnt->p_vaddr & PAGE_ALIGN));
542
543                                 size = (ppnt->p_vaddr & ADDR_ALIGN)
544                                   + ppnt->p_filesz;
545
546                                 /* For !MMU, mmap to fixed address will fail.
547                                    So instead of desperately call mmap and fail,
548                                    we set status to MAP_FAILED to save a call
549                                    to mmap ().  */
550 #ifndef __ARCH_USE_MMU__
551                                 if (piclib2map == 0)
552 #endif
553                                   status = (char *) _dl_mmap
554                                     (tryaddr, size, LXFLAGS(ppnt->p_flags),
555                                      flags | (piclib2map ? MAP_FIXED : 0),
556                                      infile, ppnt->p_offset & OFFS_ALIGN);
557 #ifndef __ARCH_USE_MMU__
558                                 else
559                                   status = MAP_FAILED;
560 #endif
561 #ifdef _DL_PREAD
562                                 if (_dl_mmap_check_error(status) && piclib2map
563                                     && (_DL_PREAD (infile, tryaddr, size,
564                                                    ppnt->p_offset & OFFS_ALIGN)
565                                         == size))
566                                   status = tryaddr;
567 #endif
568                                 if (_dl_mmap_check_error(status)
569                                     || (tryaddr && tryaddr != status)) {
570                                 cant_map:
571                                         _dl_dprintf(2, "%s:%i: can't map '%s'\n",
572                                                         _dl_progname, __LINE__, libname);
573                                         _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
574                                         DL_LOADADDR_UNMAP (lib_loadaddr, maxvma - minvma);
575                                         _dl_close(infile);
576                                         _dl_munmap(header, _dl_pagesize);
577                                         return NULL;
578                                 }
579
580                                 if (! piclib2map) {
581                                   DL_INIT_LOADADDR_HDR
582                                     (lib_loadaddr, status
583                                      + (ppnt->p_vaddr & ADDR_ALIGN), ppnt);
584                                 }
585                                 /* Now we want to allocate and
586                                    zero-out any data from the end of
587                                    the region we mapped in from the
588                                    file (filesz) to the end of the
589                                    loadable segment (memsz).  We may
590                                    need additional pages for memsz,
591                                    that we map in below, and we can
592                                    count on the kernel to zero them
593                                    out, but we have to zero out stuff
594                                    in the last page that we mapped in
595                                    from the file.  However, we can't
596                                    assume to have actually obtained
597                                    full pages from the kernel, since
598                                    we didn't ask for them, and uClibc
599                                    may not give us full pages for
600                                    small allocations.  So only zero
601                                    out up to memsz or the end of the
602                                    page, whichever comes first.  */
603
604                                 /* CPNT is the beginning of the memsz
605                                    portion not backed by filesz.  */
606                                 cpnt = (char *) (status + size);
607
608                                 /* MAP_SIZE is the address of the
609                                    beginning of the next page.  */
610                                 map_size = (ppnt->p_vaddr + ppnt->p_filesz
611                                             + ADDR_ALIGN) & PAGE_ALIGN;
612
613 #ifndef MIN
614 # define MIN(a,b) ((a) < (b) ? (a) : (b))
615 #endif
616                                 _dl_memset (cpnt, 0,
617                                             MIN (map_size
618                                                  - (ppnt->p_vaddr
619                                                     + ppnt->p_filesz),
620                                                  ppnt->p_memsz
621                                                  - ppnt->p_filesz));
622
623                                 if (map_size < ppnt->p_vaddr + ppnt->p_memsz
624                                     && !piclib2map) {
625                                         tryaddr = map_size + (char*)(piclib ? libaddr : 0);
626                                         status = (char *) _dl_mmap(tryaddr,
627                                                 ppnt->p_vaddr + ppnt->p_memsz - map_size,
628                                                 LXFLAGS(ppnt->p_flags), flags | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
629                                         if (_dl_mmap_check_error(status)
630                                             || tryaddr != status)
631                                                 goto cant_map;
632                                 }
633                         } else {
634                                 tryaddr = (piclib == 2 ? 0
635                                            : (char *) (ppnt->p_vaddr & PAGE_ALIGN)
636                                            + (piclib ? libaddr : 0));
637                                 size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
638                                 status = (char *) _dl_mmap
639                                            (tryaddr, size, LXFLAGS(ppnt->p_flags),
640                                             flags | (piclib == 2 ? MAP_EXECUTABLE
641                                                      | MAP_DENYWRITE : 0),
642                                             infile, ppnt->p_offset & OFFS_ALIGN);
643                                 if (_dl_mmap_check_error(status)
644                                     || (tryaddr && tryaddr != status))
645                                   goto cant_map;
646                                 DL_INIT_LOADADDR_HDR
647                                   (lib_loadaddr, status
648                                    + (ppnt->p_vaddr & ADDR_ALIGN), ppnt);
649                         }
650
651                         /* if (libaddr == 0 && piclib) {
652                            libaddr = (unsigned long) status;
653                            flags |= MAP_FIXED;
654                            } */
655                 }
656                 ppnt++;
657         }
658         _dl_close(infile);
659
660         /* For a non-PIC library, the addresses are all absolute */
661         if (piclib) {
662                 dynamic_addr = (unsigned long) DL_RELOC_ADDR(lib_loadaddr, dynamic_addr);
663         }
664
665         /*
666          * OK, the ELF library is now loaded into VM in the correct locations
667          * The next step is to go through and do the dynamic linking (if needed).
668          */
669
670         /* Start by scanning the dynamic section to get all of the pointers */
671
672         if (!dynamic_addr) {
673                 _dl_internal_error_number = LD_ERROR_NODYNAMIC;
674                 _dl_dprintf(2, "%s: '%s' is missing a dynamic section\n",
675                                 _dl_progname, libname);
676                 _dl_munmap(header, _dl_pagesize);
677                 return NULL;
678         }
679
680         dpnt = (ElfW(Dyn) *) dynamic_addr;
681         _dl_memset(dynamic_info, 0, sizeof(dynamic_info));
682         _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr);
683         /* If the TEXTREL is set, this means that we need to make the pages
684            writable before we perform relocations.  Do this now. They get set
685            back again later. */
686
687         if (dynamic_info[DT_TEXTREL]) {
688 #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
689                 ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
690                 for (i = 0; i < epnt->e_phnum; i++, ppnt++) {
691                         if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))
692                                 _dl_mprotect((void *) ((piclib ? libaddr : 0) +
693                                                         (ppnt->p_vaddr & PAGE_ALIGN)),
694                                                 (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,
695                                                 PROT_READ | PROT_WRITE | PROT_EXEC);
696                 }
697 #else
698                 _dl_dprintf(_dl_debug_file, "Can't modify %s's text section. Use GCC option -fPIC for shared objects, please.\n",libname);
699                 _dl_exit(1);
700 #endif
701         }
702
703         tpnt = _dl_add_elf_hash_table(libname, lib_loadaddr, dynamic_info,
704                         dynamic_addr, 0);
705         tpnt->relro_addr = relro_addr;
706         tpnt->relro_size = relro_size;
707         tpnt->st_dev = st.st_dev;
708         tpnt->st_ino = st.st_ino;
709         tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(tpnt->loadaddr, epnt->e_phoff);
710         tpnt->n_phent = epnt->e_phnum;
711
712         /*
713          * Add this object into the symbol chain
714          */
715         if (*rpnt) {
716                 (*rpnt)->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
717                 _dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf));
718                 (*rpnt)->next->prev = (*rpnt);
719                 *rpnt = (*rpnt)->next;
720         }
721 #ifndef SHARED
722         /* When statically linked, the first time we dlopen a DSO
723          * the *rpnt is NULL, so we need to allocate memory for it,
724          * and initialize the _dl_symbol_table.
725          */
726         else {
727                 *rpnt = _dl_symbol_tables = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
728                 _dl_memset(*rpnt, 0, sizeof(struct dyn_elf));
729         }
730 #endif
731         (*rpnt)->dyn = tpnt;
732         tpnt->symbol_scope = _dl_symbol_tables;
733         tpnt->usage_count++;
734         tpnt->libtype = elf_lib;
735
736         /*
737          * OK, the next thing we need to do is to insert the dynamic linker into
738          * the proper entry in the GOT so that the PLT symbols can be properly
739          * resolved.
740          */
741
742         lpnt = (unsigned long *) dynamic_info[DT_PLTGOT];
743
744         if (lpnt) {
745                 lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT]);
746                 INIT_GOT(lpnt, tpnt);
747         }
748
749         _dl_if_debug_dprint("\n\tfile='%s';  generating link map\n", libname);
750         _dl_if_debug_dprint("\t\tdynamic: %x  base: %x\n", dynamic_addr, DL_LOADADDR_BASE(lib_loadaddr));
751         _dl_if_debug_dprint("\t\t  entry: %x  phdr: %x  phnum: %x\n\n",
752                         DL_RELOC_ADDR(lib_loadaddr, epnt->e_entry), tpnt->ppnt, tpnt->n_phent);
753
754         _dl_munmap(header, _dl_pagesize);
755
756         return tpnt;
757 }
758
759 /* now_flag must be RTLD_NOW or zero */
760 int _dl_fixup(struct dyn_elf *rpnt, int now_flag)
761 {
762         int goof = 0;
763         struct elf_resolve *tpnt;
764         ElfW(Word) reloc_size, relative_count;
765         ElfW(Addr) reloc_addr;
766
767         if (rpnt->next)
768                 goof = _dl_fixup(rpnt->next, now_flag);
769         if (goof)
770                 return goof;
771         tpnt = rpnt->dyn;
772
773         if (!(tpnt->init_flag & RELOCS_DONE))
774                 _dl_if_debug_dprint("relocation processing: %s\n", tpnt->libname);
775
776         if (unlikely(tpnt->dynamic_info[UNSUPPORTED_RELOC_TYPE])) {
777                 _dl_if_debug_dprint("%s: can't handle %s relocation records\n",
778                                 _dl_progname, UNSUPPORTED_RELOC_STR);
779                 goof++;
780                 return goof;
781         }
782
783         reloc_size = tpnt->dynamic_info[DT_RELOC_TABLE_SIZE];
784 /* On some machines, notably SPARC & PPC, DT_REL* includes DT_JMPREL in its
785    range.  Note that according to the ELF spec, this is completely legal! */
786 #ifdef ELF_MACHINE_PLTREL_OVERLAP
787         reloc_size -= tpnt->dynamic_info [DT_PLTRELSZ];
788 #endif
789         if (tpnt->dynamic_info[DT_RELOC_TABLE_ADDR] &&
790             !(tpnt->init_flag & RELOCS_DONE)) {
791                 reloc_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR];
792                 relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
793                 if (relative_count) { /* Optimize the XX_RELATIVE relocations if possible */
794                         reloc_size -= relative_count * sizeof(ELF_RELOC);
795                         elf_machine_relative(tpnt->loadaddr, reloc_addr, relative_count);
796                         reloc_addr += relative_count * sizeof(ELF_RELOC);
797                 }
798                 goof += _dl_parse_relocation_information(rpnt,
799                                 reloc_addr,
800                                 reloc_size);
801                 tpnt->init_flag |= RELOCS_DONE;
802         }
803         if (tpnt->dynamic_info[DT_BIND_NOW])
804                 now_flag = RTLD_NOW;
805         if (tpnt->dynamic_info[DT_JMPREL] &&
806             (!(tpnt->init_flag & JMP_RELOCS_DONE) ||
807              (now_flag && !(tpnt->rtld_flags & now_flag)))) {
808                 tpnt->rtld_flags |= now_flag;
809                 if (!(tpnt->rtld_flags & RTLD_NOW)) {
810                         _dl_parse_lazy_relocation_information(rpnt,
811                                         tpnt->dynamic_info[DT_JMPREL],
812                                         tpnt->dynamic_info [DT_PLTRELSZ]);
813                 } else {
814                         goof += _dl_parse_relocation_information(rpnt,
815                                         tpnt->dynamic_info[DT_JMPREL],
816                                         tpnt->dynamic_info[DT_PLTRELSZ]);
817                 }
818                 tpnt->init_flag |= JMP_RELOCS_DONE;
819         }
820         return goof;
821 }
822
823 /* Minimal printf which handles only %s, %d, and %x */
824 void _dl_dprintf(int fd, const char *fmt, ...)
825 {
826 #if __WORDSIZE > 32
827         long int num;
828 #else
829         int num;
830 #endif
831         va_list args;
832         char *start, *ptr, *string;
833         static char *buf;
834
835         if (!fmt)
836                 return;
837
838         buf = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
839                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
840         if (_dl_mmap_check_error(buf)) {
841                 _dl_write(fd, "mmap of a spare page failed!\n", 29);
842                 _dl_exit(20);
843         }
844
845         start = ptr = buf;
846
847         if (_dl_strlen(fmt) >= (_dl_pagesize - 1)) {
848                 _dl_write(fd, "overflow\n", 11);
849                 _dl_exit(20);
850         }
851
852         _dl_strcpy(buf, fmt);
853         va_start(args, fmt);
854
855         while (start) {
856                 while (*ptr != '%' && *ptr) {
857                         ptr++;
858                 }
859
860                 if (*ptr == '%') {
861                         *ptr++ = '\0';
862                         _dl_write(fd, start, _dl_strlen(start));
863
864                         switch (*ptr++) {
865                                 case 's':
866                                         string = va_arg(args, char *);
867
868                                         if (!string)
869                                                 _dl_write(fd, "(null)", 6);
870                                         else
871                                                 _dl_write(fd, string, _dl_strlen(string));
872                                         break;
873
874                                 case 'i':
875                                 case 'd':
876                                         {
877                                                 char tmp[22];
878 #if __WORDSIZE > 32
879                                                 num = va_arg(args, long int);
880 #else
881                                                 num = va_arg(args, int);
882 #endif
883                                                 string = _dl_simple_ltoa(tmp, num);
884                                                 _dl_write(fd, string, _dl_strlen(string));
885                                                 break;
886                                         }
887                                 case 'x':
888                                 case 'X':
889                                         {
890                                                 char tmp[22];
891 #if __WORDSIZE > 32
892                                                 num = va_arg(args, long int);
893 #else
894                                                 num = va_arg(args, int);
895 #endif
896                                                 string = _dl_simple_ltoahex(tmp, num);
897                                                 _dl_write(fd, string, _dl_strlen(string));
898                                                 break;
899                                         }
900                                 default:
901                                         _dl_write(fd, "(null)", 6);
902                                         break;
903                         }
904
905                         start = ptr;
906                 } else {
907                         _dl_write(fd, start, _dl_strlen(start));
908                         start = NULL;
909                 }
910         }
911         _dl_munmap(buf, _dl_pagesize);
912         return;
913 }
914
915 char *_dl_strdup(const char *string)
916 {
917         char *retval;
918         int len;
919
920         len = _dl_strlen(string);
921         retval = _dl_malloc(len + 1);
922         _dl_strcpy(retval, string);
923         return retval;
924 }
925
926 void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
927                             void *debug_addr, DL_LOADADDR_TYPE load_off)
928 {
929         __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off);
930 }