OSDN Git Service

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