OSDN Git Service

Merge remote-tracking branch 'origin/master' into prelink
[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, const 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 = 0;
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
516 #ifdef __LDSO_STANDALONE_SUPPORT__
517                 && epnt->e_type != ET_EXEC
518 #endif
519                 ) || (epnt->e_machine != MAGIC1
520 #ifdef MAGIC2
521                                 && epnt->e_machine != MAGIC2
522 #endif
523                         ))
524         {
525                 _dl_internal_error_number =
526                         (epnt->e_type != ET_DYN ? LD_ERROR_NOTDYN : LD_ERROR_NOTMAGIC);
527                 _dl_dprintf(2, "%s: '%s' is not an ELF executable for " ELF_TARGET
528                                 "\n", _dl_progname, libname);
529                 _dl_close(infile);
530                 _dl_munmap(header, _dl_pagesize);
531                 return NULL;
532         }
533
534         ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
535
536         piclib = 1;
537         for (i = 0; i < epnt->e_phnum; i++) {
538
539                 if (ppnt->p_type == PT_DYNAMIC) {
540                         if (dynamic_addr)
541                                 _dl_dprintf(2, "%s: '%s' has more than one dynamic section\n",
542                                                 _dl_progname, libname);
543                         dynamic_addr = ppnt->p_vaddr;
544                 }
545
546                 if (ppnt->p_type == PT_LOAD) {
547                         /* See if this is a PIC library. */
548                         if (minvma == 0xffffffff && ppnt->p_vaddr > 0x1000000) {
549                                 piclib = 0;
550                                 minvma = ppnt->p_vaddr;
551                         }
552                         if (piclib && ppnt->p_vaddr < minvma) {
553                                 minvma = ppnt->p_vaddr;
554                         }
555                         if (((unsigned long) ppnt->p_vaddr + ppnt->p_memsz) > maxvma) {
556                                 maxvma = ppnt->p_vaddr + ppnt->p_memsz;
557                         }
558                 }
559                 if (ppnt->p_type == PT_TLS) {
560 #if defined(USE_TLS) && USE_TLS
561                         if (ppnt->p_memsz == 0)
562                                 /* Nothing to do for an empty segment.  */
563                                 continue;
564                         else
565                                 /* Save for after 'tpnt' is actually allocated. */
566                                 tlsppnt = ppnt;
567 #else
568                         /*
569                          * Yup, the user was an idiot and tried to sneak in a library with
570                          * TLS in it and we don't support it. Let's fall on our own sword
571                          * and scream at the luser while we die.
572                          */
573                         _dl_dprintf(2, "%s: '%s' library contains unsupported TLS\n",
574                                 _dl_progname, libname);
575                         _dl_internal_error_number = LD_ERROR_TLS_FAILED;
576                         _dl_close(infile);
577                         _dl_munmap(header, _dl_pagesize);
578                         return NULL;
579 #endif
580                 }
581                 ppnt++;
582         }
583
584 #ifdef __LDSO_STANDALONE_SUPPORT__
585         if (epnt->e_type == ET_EXEC)
586                 piclib = 0;
587 #endif
588
589         DL_CHECK_LIB_TYPE (epnt, piclib, _dl_progname, libname);
590
591         maxvma = (maxvma + ADDR_ALIGN) & PAGE_ALIGN;
592         minvma = minvma & ~ADDR_ALIGN;
593
594         flags = MAP_PRIVATE /*| MAP_DENYWRITE */ ;
595
596         if (piclib == 0 || piclib == 1) {
597                 status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma),
598                                 maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0);
599                 if (_dl_mmap_check_error(status)) {
600                 cant_map:
601                         _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
602                         _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
603                         _dl_close(infile);
604                         _dl_munmap(header, _dl_pagesize);
605                         return NULL;
606                 }
607                 libaddr = (unsigned long) status;
608                 flags |= MAP_FIXED;
609         }
610
611         /* Get the memory to store the library */
612         ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
613
614         DL_INIT_LOADADDR(lib_loadaddr, libaddr - minvma, ppnt, epnt->e_phnum);
615
616         for (i = 0; i < epnt->e_phnum; i++) {
617                 if (DL_IS_SPECIAL_SEGMENT (epnt, ppnt)) {
618                         char *addr;
619
620                         addr = DL_MAP_SEGMENT (epnt, ppnt, infile, flags);
621                         if (addr == NULL) {
622                         cant_map1:
623                                 DL_LOADADDR_UNMAP (lib_loadaddr, maxvma - minvma);
624                                 goto cant_map;
625                         }
626
627                         DL_INIT_LOADADDR_HDR (lib_loadaddr, addr, ppnt);
628                         ppnt++;
629                         continue;
630                 }
631                 if (ppnt->p_type == PT_GNU_RELRO) {
632                         relro_addr = ppnt->p_vaddr;
633                         relro_size = ppnt->p_memsz;
634                 }
635                 if (ppnt->p_type == PT_LOAD) {
636                         char *tryaddr;
637                         ssize_t size;
638
639                         if (ppnt->p_flags & PF_W) {
640                                 status = map_writeable (infile, ppnt, piclib, flags, libaddr);
641                                 if (status == NULL)
642                                         goto cant_map1;
643                         } else {
644                                 tryaddr = (piclib == 2 ? 0
645                                            : (char *) (ppnt->p_vaddr & PAGE_ALIGN)
646                                            + (piclib ? libaddr : lib_loadaddr));
647                                 size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
648                                 status = (char *) _dl_mmap
649                                            (tryaddr, size, LXFLAGS(ppnt->p_flags),
650                                             flags | (piclib == 2 ? MAP_EXECUTABLE
651                                                      | MAP_DENYWRITE : 0),
652                                             infile, ppnt->p_offset & OFFS_ALIGN);
653                                 if (_dl_mmap_check_error(status)
654                                     || (tryaddr && tryaddr != status))
655                                   goto cant_map1;
656                         }
657                         DL_INIT_LOADADDR_HDR(lib_loadaddr,
658                                              status + (ppnt->p_vaddr & ADDR_ALIGN),
659                                              ppnt);
660
661                         /* if (libaddr == 0 && piclib) {
662                            libaddr = (unsigned long) status;
663                            flags |= MAP_FIXED;
664                            } */
665                 }
666                 ppnt++;
667         }
668
669         /*
670          * The dynamic_addr must be take into acount lib_loadaddr value, to note
671          * it is zero when the SO has been mapped to the elf's physical addr
672          */
673         if (lib_loadaddr) {
674                 dynamic_addr = (unsigned long) DL_RELOC_ADDR(lib_loadaddr, dynamic_addr);
675         }
676
677         /*
678          * OK, the ELF library is now loaded into VM in the correct locations
679          * The next step is to go through and do the dynamic linking (if needed).
680          */
681
682         /* Start by scanning the dynamic section to get all of the pointers */
683
684         if (!dynamic_addr) {
685                 _dl_internal_error_number = LD_ERROR_NODYNAMIC;
686                 _dl_dprintf(2, "%s: '%s' is missing a dynamic section\n",
687                                 _dl_progname, libname);
688                 _dl_munmap(header, _dl_pagesize);
689                 _dl_close(infile);
690                 return NULL;
691         }
692
693         dpnt = (ElfW(Dyn) *) dynamic_addr;
694         _dl_memset(dynamic_info, 0, sizeof(dynamic_info));
695         rtld_flags = _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr);
696         /* If the TEXTREL is set, this means that we need to make the pages
697            writable before we perform relocations.  Do this now. They get set
698            back again later. */
699
700         if (dynamic_info[DT_TEXTREL]) {
701 #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
702                 ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
703                 for (i = 0; i < epnt->e_phnum; i++, ppnt++) {
704                         if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) {
705 #ifdef __ARCH_USE_MMU__
706                                 _dl_mprotect((void *) ((piclib ? libaddr : lib_loadaddr) +
707                                                         (ppnt->p_vaddr & PAGE_ALIGN)),
708                                                 (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,
709                                                 PROT_READ | PROT_WRITE | PROT_EXEC);
710 #else
711                                 void *new_addr;
712                                 new_addr = map_writeable (infile, ppnt, piclib, flags, libaddr);
713                                 if (!new_addr) {
714                                         _dl_dprintf(_dl_debug_file, "Can't modify %s's text section.",
715                                                     libname);
716                                         _dl_exit(1);
717                                 }
718                                 DL_UPDATE_LOADADDR_HDR(lib_loadaddr,
719                                                        new_addr + (ppnt->p_vaddr & ADDR_ALIGN),
720                                                        ppnt);
721                                 /* This has invalidated all pointers into the previously readonly segment.
722                                    Update any them to point into the remapped segment.  */
723                                 _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr);
724 #endif
725                         }
726                 }
727 #else
728                 _dl_dprintf(_dl_debug_file, "Can't modify %s's text section."
729                         " Use GCC option -fPIC for shared objects, please.\n",
730                         libname);
731                 _dl_exit(1);
732 #endif
733         }
734
735         _dl_close(infile);
736
737         tpnt = _dl_add_elf_hash_table(libname, lib_loadaddr, dynamic_info,
738                         dynamic_addr, 0);
739         tpnt->mapaddr = libaddr;
740         tpnt->relro_addr = relro_addr;
741         tpnt->relro_size = relro_size;
742         tpnt->st_dev = st.st_dev;
743         tpnt->st_ino = st.st_ino;
744         tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(tpnt->mapaddr, epnt->e_phoff);
745         tpnt->n_phent = epnt->e_phnum;
746         tpnt->rtld_flags |= rtld_flags;
747 #ifdef __LDSO_STANDALONE_SUPPORT__
748         tpnt->l_entry = epnt->e_entry;
749 #endif
750
751 #if defined(USE_TLS) && USE_TLS
752         if (tlsppnt) {
753                 _dl_debug_early("Found TLS header for %s\n", libname);
754 # if NO_TLS_OFFSET != 0
755                 tpnt->l_tls_offset = NO_TLS_OFFSET;
756 # endif
757                 tpnt->l_tls_blocksize = tlsppnt->p_memsz;
758                 tpnt->l_tls_align = tlsppnt->p_align;
759                 if (tlsppnt->p_align == 0)
760                         tpnt->l_tls_firstbyte_offset = 0;
761                 else
762                         tpnt->l_tls_firstbyte_offset = tlsppnt->p_vaddr &
763                                 (tlsppnt->p_align - 1);
764                 tpnt->l_tls_initimage_size = tlsppnt->p_filesz;
765                 tpnt->l_tls_initimage = (void *) tlsppnt->p_vaddr;
766
767                 /* Assign the next available module ID.  */
768                 tpnt->l_tls_modid = _dl_next_tls_modid ();
769
770                 /* We know the load address, so add it to the offset. */
771 #ifdef __LDSO_STANDALONE_SUPPORT__
772                 if ((tpnt->l_tls_initimage != NULL) && piclib)
773 #else
774                 if (tpnt->l_tls_initimage != NULL)
775 #endif
776                 {
777 # ifdef __SUPPORT_LD_DEBUG_EARLY__
778                         unsigned int tmp = (unsigned int) tpnt->l_tls_initimage;
779                         tpnt->l_tls_initimage = (char *) tlsppnt->p_vaddr + tpnt->loadaddr;
780                         _dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n", tmp, tpnt->l_tls_initimage, tpnt->l_tls_initimage_size);
781                         tmp = 0;
782 # else
783                         tpnt->l_tls_initimage = (char *) tlsppnt->p_vaddr + tpnt->loadaddr;
784 # endif
785                 }
786         }
787 #endif
788
789         /*
790          * Add this object into the symbol chain
791          */
792         if (*rpnt
793 #ifdef __LDSO_STANDALONE_SUPPORT__
794                 /* Do not create a new chain entry for the main executable */
795                 && (*rpnt)->dyn
796 #endif
797                 ) {
798                 (*rpnt)->next = _dl_malloc(sizeof(struct dyn_elf));
799                 _dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf));
800                 (*rpnt)->next->prev = (*rpnt);
801                 *rpnt = (*rpnt)->next;
802         }
803 #ifndef SHARED
804         /* When statically linked, the first time we dlopen a DSO
805          * the *rpnt is NULL, so we need to allocate memory for it,
806          * and initialize the _dl_symbol_table.
807          */
808         else {
809                 *rpnt = _dl_symbol_tables = _dl_malloc(sizeof(struct dyn_elf));
810                 _dl_memset(*rpnt, 0, sizeof(struct dyn_elf));
811         }
812 #endif
813         (*rpnt)->dyn = tpnt;
814         tpnt->usage_count++;
815 #ifdef __LDSO_STANDALONE_SUPPORT__
816         tpnt->libtype = (epnt->e_type == ET_DYN) ? elf_lib : elf_executable;
817 #else
818         tpnt->libtype = elf_lib;
819 #endif
820
821         /*
822          * OK, the next thing we need to do is to insert the dynamic linker into
823          * the proper entry in the GOT so that the PLT symbols can be properly
824          * resolved.
825          */
826
827         lpnt = (unsigned long *) dynamic_info[DT_PLTGOT];
828
829         if (lpnt) {
830                 lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT]);
831                 INIT_GOT(lpnt, tpnt);
832         }
833
834 #ifdef __DSBT__
835         /* Handle DSBT initialization */
836         {
837                 struct elf_resolve *t, *ref;
838                 int idx = tpnt->loadaddr.map->dsbt_index;
839                 unsigned *dsbt = tpnt->loadaddr.map->dsbt_table;
840
841                 if (idx == 0) {
842                         if (!dynamic_info[DT_TEXTREL]) {
843                                 /* This DSO has not been assigned an index. */
844                                 _dl_dprintf(2, "%s: '%s' is missing a dsbt index assignment!\n",
845                                             _dl_progname, libname);
846                                 _dl_exit(1);
847                         }
848                         /* Find a dsbt table from another module. */
849                         ref = NULL;
850                         for (t = _dl_loaded_modules; t; t = t->next) {
851                                 if (ref == NULL && t != tpnt) {
852                                         ref = t;
853                                         break;
854                                 }
855                         }
856                         idx = tpnt->loadaddr.map->dsbt_size;
857                         while (idx-- > 0)
858                                 if (!ref || ref->loadaddr.map->dsbt_table[idx] == NULL)
859                                         break;
860                         if (idx <= 0) {
861                                 _dl_dprintf(2, "%s: '%s' caused DSBT table overflow!\n",
862                                             _dl_progname, libname);
863                                 _dl_exit(1);
864                         }
865                         _dl_if_debug_dprint("\n\tfile='%s';  assigned index %d\n",
866                                             libname, idx);
867                         tpnt->loadaddr.map->dsbt_index = idx;
868
869                 }
870
871                 /*
872                  * Setup dsbt slot for this module in dsbt of all modules.
873                  */
874                 ref = NULL;
875                 for (t = _dl_loaded_modules; t; t = t->next) {
876                         /* find a dsbt table from another module */
877                         if (ref == NULL && t != tpnt) {
878                                 ref = t;
879
880                                 /* make sure index is not already used */
881                                 if (t->loadaddr.map->dsbt_table[idx]) {
882                                         struct elf_resolve *dup;
883                                         char *dup_name;
884
885                                         for (dup = _dl_loaded_modules; dup; dup = dup->next)
886                                                 if (dup != tpnt && dup->loadaddr.map->dsbt_index == idx)
887                                                         break;
888                                         if (dup)
889                                                 dup_name = dup->libname;
890                                         else if (idx == 1)
891                                                 dup_name = "runtime linker";
892                                         else
893                                                 dup_name = "unknown library";
894                                         _dl_dprintf(2, "%s: '%s' dsbt index %d already used by %s!\n",
895                                                     _dl_progname, libname, idx, dup_name);
896                                         _dl_exit(1);
897                                 }
898                         }
899                         t->loadaddr.map->dsbt_table[idx] = (unsigned)dsbt;
900                 }
901                 if (ref)
902                         _dl_memcpy(dsbt, ref->loadaddr.map->dsbt_table,
903                                    tpnt->loadaddr.map->dsbt_size * sizeof(unsigned *));
904         }
905 #endif
906         _dl_if_debug_dprint("\n\tfile='%s';  generating link map\n", libname);
907         _dl_if_debug_dprint("\t\tdynamic: %x  base: %x\n", dynamic_addr, DL_LOADADDR_BASE(lib_loadaddr));
908         _dl_if_debug_dprint("\t\t  entry: %x  phdr: %x  phnum: %x\n\n",
909                         DL_RELOC_ADDR(lib_loadaddr, epnt->e_entry), tpnt->ppnt, tpnt->n_phent);
910
911         _dl_munmap(header, _dl_pagesize);
912
913         return tpnt;
914 }
915
916 /* now_flag must be RTLD_NOW or zero */
917 int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int now_flag)
918 {
919         int goof = 0;
920         struct elf_resolve *tpnt;
921         ElfW(Word) reloc_size, relative_count;
922         ElfW(Addr) reloc_addr;
923
924         if (rpnt->next)
925                 goof = _dl_fixup(rpnt->next, scope, now_flag);
926         if (goof)
927                 return goof;
928         tpnt = rpnt->dyn;
929
930         if (!(tpnt->init_flag & RELOCS_DONE))
931                 _dl_if_debug_dprint("relocation processing: %s\n", tpnt->libname);
932
933         if (unlikely(tpnt->dynamic_info[UNSUPPORTED_RELOC_TYPE])) {
934                 _dl_if_debug_dprint("%s: can't handle %s relocation records\n",
935                                 _dl_progname, UNSUPPORTED_RELOC_STR);
936                 goof++;
937                 return goof;
938         }
939
940         reloc_size = tpnt->dynamic_info[DT_RELOC_TABLE_SIZE];
941 /* On some machines, notably SPARC & PPC, DT_REL* includes DT_JMPREL in its
942    range.  Note that according to the ELF spec, this is completely legal! */
943 #ifdef ELF_MACHINE_PLTREL_OVERLAP
944         reloc_size -= tpnt->dynamic_info [DT_PLTRELSZ];
945 #endif
946         if (tpnt->dynamic_info[DT_RELOC_TABLE_ADDR] &&
947             !(tpnt->init_flag & RELOCS_DONE)) {
948                 reloc_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR];
949                 relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
950                 if (relative_count) { /* Optimize the XX_RELATIVE relocations if possible */
951                         reloc_size -= relative_count * sizeof(ELF_RELOC);
952                         if (tpnt->loadaddr
953 #ifdef __LDSO_PRELINK_SUPPORT__
954                                 || (!tpnt->dynamic_info[DT_GNU_PRELINKED_IDX])
955 #endif
956                                 )
957                                 elf_machine_relative(tpnt->loadaddr, reloc_addr, relative_count);
958                         reloc_addr += relative_count * sizeof(ELF_RELOC);
959                 }
960                 goof += _dl_parse_relocation_information(rpnt, scope,
961                                 reloc_addr,
962                                 reloc_size);
963                 tpnt->init_flag |= RELOCS_DONE;
964         }
965         if (tpnt->dynamic_info[DT_BIND_NOW])
966                 now_flag = RTLD_NOW;
967         if (tpnt->dynamic_info[DT_JMPREL] &&
968             (!(tpnt->init_flag & JMP_RELOCS_DONE) ||
969              (now_flag && !(tpnt->rtld_flags & now_flag)))) {
970                 tpnt->rtld_flags |= now_flag;
971                 if (!(tpnt->rtld_flags & RTLD_NOW)) {
972                         _dl_parse_lazy_relocation_information(rpnt,
973                                         tpnt->dynamic_info[DT_JMPREL],
974                                         tpnt->dynamic_info [DT_PLTRELSZ]);
975                 } else {
976                         goof += _dl_parse_relocation_information(rpnt, scope,
977                                         tpnt->dynamic_info[DT_JMPREL],
978                                         tpnt->dynamic_info[DT_PLTRELSZ]);
979                 }
980                 tpnt->init_flag |= JMP_RELOCS_DONE;
981         }
982
983 #if 0
984 /* _dl_add_to_slotinfo is called by init_tls() for initial DSO
985    or by dlopen() for dynamically loaded DSO. */
986 #if defined(USE_TLS) && USE_TLS
987         /* Add object to slot information data if necessasy. */
988         if (tpnt->l_tls_blocksize != 0 && tls_init_tp_called)
989                 _dl_add_to_slotinfo ((struct link_map *) tpnt);
990 #endif
991 #endif
992         return goof;
993 }
994
995 /* Minimal printf which handles only %s, %d, and %x */
996 void _dl_dprintf(int fd, const char *fmt, ...)
997 {
998 #if __WORDSIZE > 32
999         long int num;
1000 #else
1001         int num;
1002 #endif
1003         va_list args;
1004         char *start, *ptr, *string;
1005         char *buf;
1006
1007         if (!fmt)
1008                 return;
1009
1010         buf = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
1011                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1012         if (_dl_mmap_check_error(buf)) {
1013                 _dl_write(fd, "mmap of a spare page failed!\n", 29);
1014                 _dl_exit(20);
1015         }
1016
1017         start = ptr = buf;
1018
1019         if (_dl_strlen(fmt) >= (_dl_pagesize - 1)) {
1020                 _dl_write(fd, "overflow\n", 11);
1021                 _dl_exit(20);
1022         }
1023
1024         _dl_strcpy(buf, fmt);
1025         va_start(args, fmt);
1026
1027         while (start) {
1028                 while (*ptr != '%' && *ptr) {
1029                         ptr++;
1030                 }
1031
1032                 if (*ptr == '%') {
1033                         *ptr++ = '\0';
1034                         _dl_write(fd, start, _dl_strlen(start));
1035
1036                         switch (*ptr++) {
1037                                 case 's':
1038                                         string = va_arg(args, char *);
1039
1040                                         if (!string)
1041                                                 _dl_write(fd, "(null)", 6);
1042                                         else
1043                                                 _dl_write(fd, string, _dl_strlen(string));
1044                                         break;
1045
1046                                 case 'i':
1047                                 case 'd':
1048                                         {
1049                                                 char tmp[22];
1050 #if __WORDSIZE > 32
1051                                                 num = va_arg(args, long int);
1052 #else
1053                                                 num = va_arg(args, int);
1054 #endif
1055                                                 string = _dl_simple_ltoa(tmp, num);
1056                                                 _dl_write(fd, string, _dl_strlen(string));
1057                                                 break;
1058                                         }
1059                                 case 'x':
1060                                 case 'X':
1061                                         {
1062                                                 char tmp[22];
1063 #if __WORDSIZE > 32
1064                                                 num = va_arg(args, long int);
1065 #else
1066                                                 num = va_arg(args, int);
1067 #endif
1068                                                 string = _dl_simple_ltoahex(tmp, num);
1069                                                 _dl_write(fd, string, _dl_strlen(string));
1070                                                 break;
1071                                         }
1072                                 default:
1073                                         _dl_write(fd, "(null)", 6);
1074                                         break;
1075                         }
1076
1077                         start = ptr;
1078                 } else {
1079                         _dl_write(fd, start, _dl_strlen(start));
1080                         start = NULL;
1081                 }
1082         }
1083         _dl_munmap(buf, _dl_pagesize);
1084         return;
1085 }
1086
1087 char *_dl_strdup(const char *string)
1088 {
1089         char *retval;
1090         int len;
1091
1092         len = _dl_strlen(string);
1093         retval = _dl_malloc(len + 1);
1094         _dl_strcpy(retval, string);
1095         return retval;
1096 }
1097
1098 unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
1099                                     void *debug_addr, DL_LOADADDR_TYPE load_off)
1100 {
1101         return __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off);
1102 }