OSDN Git Service

Fix nommu handling of DT_TEXTREL
[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 = NULL;
815                 int idx = tpnt->loadaddr.map->dsbt_index;
816                 unsigned *dsbt = tpnt->loadaddr.map->dsbt_table;
817
818                 if (idx == 0) {
819                         /* This DSO has not been assigned an index */
820                         _dl_dprintf(2, "%s: '%s' is missing a dsbt index assignment!\n",
821                                     _dl_progname, libname);
822                         _dl_exit(1);
823                 }
824
825                 /*
826                  * Setup dsbt slot for this module in dsbt of all modules.
827                  */
828                 for (t = _dl_loaded_modules; t; t = t->next) {
829                         /* find a dsbt table from another module */
830                         if (ref == NULL && t != tpnt) {
831                                 ref = t;
832
833                                 /* make sure index is not already used */
834                                 if (t->loadaddr.map->dsbt_table[idx]) {
835                                         struct elf_resolve *dup;
836                                         char *dup_name;
837
838                                         for (dup = _dl_loaded_modules; dup; dup = dup->next)
839                                                 if (dup != tpnt && dup->loadaddr.map->dsbt_index == idx)
840                                                         break;
841                                         if (dup)
842                                                 dup_name = dup->libname;
843                                         else if (idx == 1)
844                                                 dup_name = "runtime linker";
845                                         else
846                                                 dup_name = "unknown library";
847                                         _dl_dprintf(2, "%s: '%s' dsbt index %d already used by %s!\n",
848                                                     _dl_progname, libname, idx, dup_name);
849                                         _dl_exit(1);
850                                 }
851                         }
852                         t->loadaddr.map->dsbt_table[idx] = (unsigned)dsbt;
853                 }
854                 if (ref)
855                         _dl_memcpy(dsbt, ref->loadaddr.map->dsbt_table,
856                                    tpnt->loadaddr.map->dsbt_size * sizeof(unsigned *));
857         }
858 #endif
859         _dl_if_debug_dprint("\n\tfile='%s';  generating link map\n", libname);
860         _dl_if_debug_dprint("\t\tdynamic: %x  base: %x\n", dynamic_addr, DL_LOADADDR_BASE(lib_loadaddr));
861         _dl_if_debug_dprint("\t\t  entry: %x  phdr: %x  phnum: %x\n\n",
862                         DL_RELOC_ADDR(lib_loadaddr, epnt->e_entry), tpnt->ppnt, tpnt->n_phent);
863
864         _dl_munmap(header, _dl_pagesize);
865
866         return tpnt;
867 }
868
869 /* now_flag must be RTLD_NOW or zero */
870 int _dl_fixup(struct dyn_elf *rpnt, int now_flag)
871 {
872         int goof = 0;
873         struct elf_resolve *tpnt;
874         ElfW(Word) reloc_size, relative_count;
875         ElfW(Addr) reloc_addr;
876
877         if (rpnt->next)
878                 goof = _dl_fixup(rpnt->next, now_flag);
879         if (goof)
880                 return goof;
881         tpnt = rpnt->dyn;
882
883         if (!(tpnt->init_flag & RELOCS_DONE))
884                 _dl_if_debug_dprint("relocation processing: %s\n", tpnt->libname);
885
886         if (unlikely(tpnt->dynamic_info[UNSUPPORTED_RELOC_TYPE])) {
887                 _dl_if_debug_dprint("%s: can't handle %s relocation records\n",
888                                 _dl_progname, UNSUPPORTED_RELOC_STR);
889                 goof++;
890                 return goof;
891         }
892
893         reloc_size = tpnt->dynamic_info[DT_RELOC_TABLE_SIZE];
894 /* On some machines, notably SPARC & PPC, DT_REL* includes DT_JMPREL in its
895    range.  Note that according to the ELF spec, this is completely legal! */
896 #ifdef ELF_MACHINE_PLTREL_OVERLAP
897         reloc_size -= tpnt->dynamic_info [DT_PLTRELSZ];
898 #endif
899         if (tpnt->dynamic_info[DT_RELOC_TABLE_ADDR] &&
900             !(tpnt->init_flag & RELOCS_DONE)) {
901                 reloc_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR];
902                 relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
903                 if (relative_count) { /* Optimize the XX_RELATIVE relocations if possible */
904                         reloc_size -= relative_count * sizeof(ELF_RELOC);
905                         elf_machine_relative(tpnt->loadaddr, reloc_addr, relative_count);
906                         reloc_addr += relative_count * sizeof(ELF_RELOC);
907                 }
908                 goof += _dl_parse_relocation_information(rpnt,
909                                 reloc_addr,
910                                 reloc_size);
911                 tpnt->init_flag |= RELOCS_DONE;
912         }
913         if (tpnt->dynamic_info[DT_BIND_NOW])
914                 now_flag = RTLD_NOW;
915         if (tpnt->dynamic_info[DT_JMPREL] &&
916             (!(tpnt->init_flag & JMP_RELOCS_DONE) ||
917              (now_flag && !(tpnt->rtld_flags & now_flag)))) {
918                 tpnt->rtld_flags |= now_flag;
919                 if (!(tpnt->rtld_flags & RTLD_NOW)) {
920                         _dl_parse_lazy_relocation_information(rpnt,
921                                         tpnt->dynamic_info[DT_JMPREL],
922                                         tpnt->dynamic_info [DT_PLTRELSZ]);
923                 } else {
924                         goof += _dl_parse_relocation_information(rpnt,
925                                         tpnt->dynamic_info[DT_JMPREL],
926                                         tpnt->dynamic_info[DT_PLTRELSZ]);
927                 }
928                 tpnt->init_flag |= JMP_RELOCS_DONE;
929         }
930
931 #if 0
932 /* _dl_add_to_slotinfo is called by init_tls() for initial DSO
933    or by dlopen() for dynamically loaded DSO. */
934 #if defined(USE_TLS) && USE_TLS
935         /* Add object to slot information data if necessasy. */
936         if (tpnt->l_tls_blocksize != 0 && tls_init_tp_called)
937                 _dl_add_to_slotinfo ((struct link_map *) tpnt);
938 #endif
939 #endif
940         return goof;
941 }
942
943 /* Minimal printf which handles only %s, %d, and %x */
944 void _dl_dprintf(int fd, const char *fmt, ...)
945 {
946 #if __WORDSIZE > 32
947         long int num;
948 #else
949         int num;
950 #endif
951         va_list args;
952         char *start, *ptr, *string;
953         char *buf;
954
955         if (!fmt)
956                 return;
957
958         buf = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
959                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
960         if (_dl_mmap_check_error(buf)) {
961                 _dl_write(fd, "mmap of a spare page failed!\n", 29);
962                 _dl_exit(20);
963         }
964
965         start = ptr = buf;
966
967         if (_dl_strlen(fmt) >= (_dl_pagesize - 1)) {
968                 _dl_write(fd, "overflow\n", 11);
969                 _dl_exit(20);
970         }
971
972         _dl_strcpy(buf, fmt);
973         va_start(args, fmt);
974
975         while (start) {
976                 while (*ptr != '%' && *ptr) {
977                         ptr++;
978                 }
979
980                 if (*ptr == '%') {
981                         *ptr++ = '\0';
982                         _dl_write(fd, start, _dl_strlen(start));
983
984                         switch (*ptr++) {
985                                 case 's':
986                                         string = va_arg(args, char *);
987
988                                         if (!string)
989                                                 _dl_write(fd, "(null)", 6);
990                                         else
991                                                 _dl_write(fd, string, _dl_strlen(string));
992                                         break;
993
994                                 case 'i':
995                                 case 'd':
996                                         {
997                                                 char tmp[22];
998 #if __WORDSIZE > 32
999                                                 num = va_arg(args, long int);
1000 #else
1001                                                 num = va_arg(args, int);
1002 #endif
1003                                                 string = _dl_simple_ltoa(tmp, num);
1004                                                 _dl_write(fd, string, _dl_strlen(string));
1005                                                 break;
1006                                         }
1007                                 case 'x':
1008                                 case 'X':
1009                                         {
1010                                                 char tmp[22];
1011 #if __WORDSIZE > 32
1012                                                 num = va_arg(args, long int);
1013 #else
1014                                                 num = va_arg(args, int);
1015 #endif
1016                                                 string = _dl_simple_ltoahex(tmp, num);
1017                                                 _dl_write(fd, string, _dl_strlen(string));
1018                                                 break;
1019                                         }
1020                                 default:
1021                                         _dl_write(fd, "(null)", 6);
1022                                         break;
1023                         }
1024
1025                         start = ptr;
1026                 } else {
1027                         _dl_write(fd, start, _dl_strlen(start));
1028                         start = NULL;
1029                 }
1030         }
1031         _dl_munmap(buf, _dl_pagesize);
1032         return;
1033 }
1034
1035 char *_dl_strdup(const char *string)
1036 {
1037         char *retval;
1038         int len;
1039
1040         len = _dl_strlen(string);
1041         retval = _dl_malloc(len + 1);
1042         _dl_strcpy(retval, string);
1043         return retval;
1044 }
1045
1046 unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
1047                                     void *debug_addr, DL_LOADADDR_TYPE load_off)
1048 {
1049         return __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off);
1050 }