OSDN Git Service

1b06bc1724f3175780bed624e76592bc63221c7e
[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, unsigned rflags, 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 #ifdef __LDSO_SAFE_RUNPATH__
178                         if (*mylibname == '/')
179 #endif
180                                 if ((tpnt = _dl_load_elf_shared_library(rflags, rpnt, mylibname)) != NULL)
181                                         return tpnt;
182                         path_n = path+1;
183                 }
184                 path++;
185         } while (!done);
186         return NULL;
187 }
188
189 /* Used to return error codes back to dlopen et. al.  */
190 unsigned long _dl_error_number;
191 unsigned long _dl_internal_error_number;
192
193 struct elf_resolve *_dl_load_shared_library(unsigned rflags, struct dyn_elf **rpnt,
194         struct elf_resolve *tpnt, char *full_libname, int attribute_unused trace_loaded_objects)
195 {
196         char *pnt;
197         struct elf_resolve *tpnt1;
198         char *libname;
199
200         _dl_internal_error_number = 0;
201         libname = full_libname;
202
203         /* quick hack to ensure mylibname buffer doesn't overflow.  don't
204            allow full_libname or any directory to be longer than 1024. */
205         if (_dl_strlen(full_libname) > 1024)
206                 goto goof;
207
208         /* Skip over any initial initial './' and '/' stuff to
209          * get the short form libname with no path garbage */
210         pnt = _dl_strrchr(libname, '/');
211         if (pnt) {
212                 libname = pnt + 1;
213         }
214
215         _dl_if_debug_dprint("\tfind library='%s'; searching\n", libname);
216         /* If the filename has any '/', try it straight and leave it at that.
217            For IBCS2 compatibility under linux, we substitute the string
218            /usr/i486-sysv4/lib for /usr/lib in library names. */
219
220         if (libname != full_libname) {
221                 _dl_if_debug_dprint("\ttrying file='%s'\n", full_libname);
222                 tpnt1 = _dl_load_elf_shared_library(rflags, rpnt, full_libname);
223                 if (tpnt1) {
224                         return tpnt1;
225                 }
226         }
227
228         /*
229          * The ABI specifies that RPATH is searched before LD_LIBRARY_PATH or
230          * the default path of /usr/lib.  Check in rpath directories.
231          */
232 #ifdef __LDSO_RUNPATH__
233         pnt = (tpnt ? (char *) tpnt->dynamic_info[DT_RPATH] : NULL);
234         if (pnt) {
235                 pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
236                 _dl_if_debug_dprint("\tsearching RPATH='%s'\n", pnt);
237                 if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt)) != NULL)
238                         return tpnt1;
239         }
240 #endif
241
242 #ifdef __LDSO_LD_LIBRARY_PATH__
243         /* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */
244         if (_dl_library_path) {
245                 _dl_if_debug_dprint("\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path);
246                 if ((tpnt1 = search_for_named_library(libname, rflags, _dl_library_path, rpnt)) != NULL)
247                 {
248                         return tpnt1;
249                 }
250         }
251 #endif
252         /*
253          * The ABI specifies that RUNPATH is searched after LD_LIBRARY_PATH.
254          */
255 #ifdef __LDSO_RUNPATH__
256         pnt = (tpnt ? (char *)tpnt->dynamic_info[DT_RUNPATH] : NULL);
257         if (pnt) {
258                 pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
259                 _dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt);
260                 if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt)) != NULL)
261                         return tpnt1;
262         }
263 #endif
264
265         /*
266          * Where should the cache be searched?  There is no such concept in the
267          * ABI, so we have some flexibility here.  For now, search it before
268          * the hard coded paths that follow (i.e before /lib and /usr/lib).
269          */
270 #ifdef __LDSO_CACHE_SUPPORT__
271         if (_dl_cache_addr != NULL && _dl_cache_addr != MAP_FAILED) {
272                 int i;
273                 header_t *header = (header_t *) _dl_cache_addr;
274                 libentry_t *libent = (libentry_t *) & header[1];
275                 char *strs = (char *) &libent[header->nlibs];
276
277                 _dl_if_debug_dprint("\tsearching cache='%s'\n", LDSO_CACHE);
278                 for (i = 0; i < header->nlibs; i++) {
279                         if ((libent[i].flags == LIB_ELF
280                              || libent[i].flags == LIB_ELF_LIBC0
281                              || libent[i].flags == LIB_ELF_LIBC5)
282                          && _dl_strcmp(libname, strs + libent[i].sooffset) == 0
283                          && (tpnt1 = _dl_load_elf_shared_library(rflags, rpnt, strs + libent[i].liboffset))
284                         ) {
285                                 return tpnt1;
286                         }
287                 }
288         }
289 #endif
290 #if defined SHARED && defined __LDSO_SEARCH_INTERP_PATH__
291         /* Look for libraries wherever the shared library loader
292          * was installed */
293         _dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath);
294         tpnt1 = search_for_named_library(libname, rflags, _dl_ldsopath, rpnt);
295         if (tpnt1 != NULL)
296                 return tpnt1;
297 #endif
298         /* Lastly, search the standard list of paths for the library.
299            This list must exactly match the list in uClibc/ldso/util/ldd.c */
300         _dl_if_debug_dprint("\tsearching full lib path list\n");
301         tpnt1 = search_for_named_library(libname, rflags,
302                                         UCLIBC_RUNTIME_PREFIX "lib:"
303                                         UCLIBC_RUNTIME_PREFIX "usr/lib"
304 #ifndef __LDSO_CACHE_SUPPORT__
305                                         ":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib"
306 #endif
307                                         , rpnt);
308         if (tpnt1 != NULL)
309                 return tpnt1;
310
311 goof:
312         /* Well, we shot our wad on that one.  All we can do now is punt */
313         if (_dl_internal_error_number)
314                 _dl_error_number = _dl_internal_error_number;
315         else
316                 _dl_error_number = LD_ERROR_NOFILE;
317         _dl_if_debug_dprint("Bummer: could not find '%s'!\n", libname);
318         return NULL;
319 }
320
321 /* Define the _dl_library_offset for the architectures that need it */
322 DL_DEF_LIB_OFFSET;
323
324 /*
325  * Make a writeable mapping of a segment, regardless of whether PF_W is
326  * set or not.
327  */
328 static void *
329 map_writeable (int infile, ElfW(Phdr) *ppnt, int piclib, int flags,
330                unsigned long libaddr)
331 {
332         int prot_flags = ppnt->p_flags | PF_W;
333         char *status, *retval;
334         char *tryaddr;
335         ssize_t size;
336         unsigned long map_size;
337         char *cpnt;
338         char *piclib2map = NULL;
339
340         if (piclib == 2 &&
341             /* We might be able to avoid this call if memsz doesn't
342                require an additional page, but this would require mmap
343                to always return page-aligned addresses and a whole
344                number of pages allocated.  Unfortunately on uClinux
345                may return misaligned addresses and may allocate
346                partial pages, so we may end up doing unnecessary mmap
347                calls.
348
349                This is what we could do if we knew mmap would always
350                return aligned pages:
351
352                ((ppnt->p_vaddr + ppnt->p_filesz + ADDR_ALIGN) &
353                PAGE_ALIGN) < ppnt->p_vaddr + ppnt->p_memsz)
354
355                Instead, we have to do this:  */
356             ppnt->p_filesz < ppnt->p_memsz)
357         {
358                 piclib2map = (char *)
359                         _dl_mmap(0, (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_memsz,
360                                  LXFLAGS(prot_flags), flags | MAP_ANONYMOUS, -1, 0);
361                 if (_dl_mmap_check_error(piclib2map))
362                         return 0;
363         }
364
365         tryaddr = piclib == 2 ? piclib2map
366                 : ((char *) (piclib ? libaddr : DL_GET_LIB_OFFSET()) +
367                    (ppnt->p_vaddr & PAGE_ALIGN));
368
369         size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
370
371         /* For !MMU, mmap to fixed address will fail.
372            So instead of desperately call mmap and fail,
373            we set status to MAP_FAILED to save a call
374            to mmap ().  */
375 #ifndef __ARCH_USE_MMU__
376         if (piclib2map == 0)
377 #endif
378                 status = (char *) _dl_mmap
379                         (tryaddr, size, LXFLAGS(prot_flags),
380                          flags | (piclib2map ? MAP_FIXED : 0),
381                          infile, ppnt->p_offset & OFFS_ALIGN);
382 #ifndef __ARCH_USE_MMU__
383         else
384                 status = MAP_FAILED;
385 #endif
386 #ifdef _DL_PREAD
387         if (_dl_mmap_check_error(status) && piclib2map
388             && (_DL_PREAD (infile, tryaddr, size,
389                            ppnt->p_offset & OFFS_ALIGN) == size))
390                 status = tryaddr;
391 #endif
392         if (_dl_mmap_check_error(status) || (tryaddr && tryaddr != status))
393                 return 0;
394
395         if (piclib2map)
396                 retval = piclib2map;
397         else
398                 retval = status;
399
400         /* Now we want to allocate and zero-out any data from the end
401            of the region we mapped in from the file (filesz) to the
402            end of the loadable segment (memsz).  We may need
403            additional pages for memsz, that we map in below, and we
404            can count on the kernel to zero them out, but we have to
405            zero out stuff in the last page that we mapped in from the
406            file.  However, we can't assume to have actually obtained
407            full pages from the kernel, since we didn't ask for them,
408            and uClibc may not give us full pages for small
409            allocations.  So only zero out up to memsz or the end of
410            the page, whichever comes first.  */
411
412         /* CPNT is the beginning of the memsz portion not backed by
413            filesz.  */
414         cpnt = (char *) (status + size);
415
416         /* MAP_SIZE is the address of the
417            beginning of the next page.  */
418         map_size = (ppnt->p_vaddr + ppnt->p_filesz
419                     + ADDR_ALIGN) & PAGE_ALIGN;
420
421         _dl_memset (cpnt, 0,
422                     MIN (map_size
423                          - (ppnt->p_vaddr
424                             + ppnt->p_filesz),
425                          ppnt->p_memsz
426                          - ppnt->p_filesz));
427
428         if (map_size < ppnt->p_vaddr + ppnt->p_memsz && !piclib2map) {
429                 tryaddr = map_size + (char*)(piclib ? libaddr : 0);
430                 status = (char *) _dl_mmap(tryaddr,
431                                            ppnt->p_vaddr + ppnt->p_memsz - map_size,
432                                            LXFLAGS(prot_flags),
433                                            flags | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
434                 if (_dl_mmap_check_error(status) || tryaddr != status)
435                         return NULL;
436         }
437         return retval;
438 }
439
440 /*
441  * Read one ELF library into memory, mmap it into the correct locations and
442  * add the symbol info to the symbol chain.  Perform any relocations that
443  * are required.
444  */
445
446 struct elf_resolve *_dl_load_elf_shared_library(unsigned rflags,
447         struct dyn_elf **rpnt, const char *libname)
448 {
449         ElfW(Ehdr) *epnt;
450         unsigned long dynamic_addr = 0;
451         ElfW(Dyn) *dpnt;
452         struct elf_resolve *tpnt;
453         ElfW(Phdr) *ppnt;
454 #if defined(USE_TLS) && USE_TLS
455         ElfW(Phdr) *tlsppnt = NULL;
456 #endif
457         char *status, *header;
458         unsigned long dynamic_info[DYNAMIC_SIZE];
459         unsigned long *lpnt;
460         unsigned long libaddr;
461         unsigned long minvma = 0xffffffff, maxvma = 0;
462         unsigned int rtld_flags;
463         int i, flags, piclib, infile;
464         ElfW(Addr) relro_addr = 0;
465         size_t relro_size = 0;
466         struct stat st;
467         uint32_t *p32;
468         DL_LOADADDR_TYPE lib_loadaddr;
469         DL_INIT_LOADADDR_EXTRA_DECLS
470
471         libaddr = 0;
472         infile = _dl_open(libname, O_RDONLY, 0);
473         if (infile < 0) {
474                 _dl_internal_error_number = LD_ERROR_NOFILE;
475                 return NULL;
476         }
477
478         if (_dl_fstat(infile, &st) < 0) {
479                 _dl_internal_error_number = LD_ERROR_NOFILE;
480                 _dl_close(infile);
481                 return NULL;
482         }
483         /* If we are in secure mode (i.e. a setuid/gid binary using LD_PRELOAD),
484            we don't load the library if it isn't setuid. */
485         if (rflags & DL_RESOLVE_SECURE) {
486                 if (!(st.st_mode & S_ISUID)) {
487                         _dl_close(infile);
488                         return NULL;
489                 }
490         }
491
492         /* Check if file is already loaded */
493         for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
494                 if (tpnt->st_dev == st.st_dev && tpnt->st_ino == st.st_ino) {
495                         /* Already loaded */
496                         tpnt->usage_count++;
497                         _dl_close(infile);
498                         return tpnt;
499                 }
500         }
501         if (rflags & DL_RESOLVE_NOLOAD) {
502                 _dl_close(infile);
503                 return NULL;
504         }
505         header = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
506                         MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZED, -1, 0);
507         if (_dl_mmap_check_error(header)) {
508                 _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
509                 _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
510                 _dl_close(infile);
511                 return NULL;
512         }
513
514         _dl_read(infile, header, _dl_pagesize);
515         epnt = (ElfW(Ehdr) *) (intptr_t) header;
516         p32 = (uint32_t*)&epnt->e_ident;
517         if (*p32 != ELFMAG_U32) {
518                 _dl_dprintf(2, "%s: '%s' is not an ELF file\n", _dl_progname,
519                                 libname);
520                 _dl_internal_error_number = LD_ERROR_NOTELF;
521                 _dl_close(infile);
522                 _dl_munmap(header, _dl_pagesize);
523                 return NULL;
524         }
525
526         if ((epnt->e_type != ET_DYN
527 #ifdef __LDSO_STANDALONE_SUPPORT__
528                 && epnt->e_type != ET_EXEC
529 #endif
530                 ) || (epnt->e_machine != MAGIC1
531 #ifdef MAGIC2
532                                 && epnt->e_machine != MAGIC2
533 #endif
534                         ))
535         {
536                 _dl_internal_error_number =
537                         (epnt->e_type != ET_DYN ? LD_ERROR_NOTDYN : LD_ERROR_NOTMAGIC);
538                 _dl_dprintf(2, "%s: '%s' is not an ELF executable for " ELF_TARGET
539                                 "\n", _dl_progname, libname);
540                 _dl_close(infile);
541                 _dl_munmap(header, _dl_pagesize);
542                 return NULL;
543         }
544
545         ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
546
547         piclib = 1;
548         for (i = 0; i < epnt->e_phnum; i++) {
549
550                 if (ppnt->p_type == PT_DYNAMIC) {
551                         if (dynamic_addr)
552                                 _dl_dprintf(2, "%s: '%s' has more than one dynamic section\n",
553                                                 _dl_progname, libname);
554                         dynamic_addr = ppnt->p_vaddr;
555                 }
556
557                 if (ppnt->p_type == PT_LOAD) {
558                         /* See if this is a PIC library. */
559                         if (minvma == 0xffffffff && ppnt->p_vaddr > 0x1000000) {
560                                 piclib = 0;
561                                 minvma = ppnt->p_vaddr;
562                         }
563                         if (piclib && ppnt->p_vaddr < minvma) {
564                                 minvma = ppnt->p_vaddr;
565                         }
566                         if (((unsigned long) ppnt->p_vaddr + ppnt->p_memsz) > maxvma) {
567                                 maxvma = ppnt->p_vaddr + ppnt->p_memsz;
568                         }
569                 }
570                 if (ppnt->p_type == PT_TLS) {
571 #if defined(USE_TLS) && USE_TLS
572                         if (ppnt->p_memsz == 0)
573                                 /* Nothing to do for an empty segment.  */
574                                 continue;
575                         else
576                                 /* Save for after 'tpnt' is actually allocated. */
577                                 tlsppnt = ppnt;
578 #else
579                         /*
580                          * Yup, the user was an idiot and tried to sneak in a library with
581                          * TLS in it and we don't support it. Let's fall on our own sword
582                          * and scream at the luser while we die.
583                          */
584                         _dl_dprintf(2, "%s: '%s' library contains unsupported TLS\n",
585                                 _dl_progname, libname);
586                         _dl_internal_error_number = LD_ERROR_TLS_FAILED;
587                         _dl_close(infile);
588                         _dl_munmap(header, _dl_pagesize);
589                         return NULL;
590 #endif
591                 }
592                 ppnt++;
593         }
594
595 #ifdef __LDSO_STANDALONE_SUPPORT__
596         if (epnt->e_type == ET_EXEC)
597                 piclib = 0;
598 #endif
599
600         DL_CHECK_LIB_TYPE (epnt, piclib, _dl_progname, libname);
601
602         maxvma = (maxvma + ADDR_ALIGN) & PAGE_ALIGN;
603         minvma = minvma & ~ADDR_ALIGN;
604
605         flags = MAP_PRIVATE /*| MAP_DENYWRITE */ ;
606
607         if (piclib == 0 || piclib == 1) {
608                 status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma),
609                                 maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0);
610                 if (_dl_mmap_check_error(status)) {
611                 cant_map:
612                         _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
613                         _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
614                         _dl_close(infile);
615                         _dl_munmap(header, _dl_pagesize);
616                         return NULL;
617                 }
618                 libaddr = (unsigned long) status;
619                 flags |= MAP_FIXED;
620         }
621
622         /* Get the memory to store the library */
623         ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
624
625         DL_INIT_LOADADDR(lib_loadaddr, libaddr - minvma, ppnt, epnt->e_phnum);
626         /* Set _dl_library_offset to lib_loadaddr or 0. */
627         DL_SET_LIB_OFFSET(lib_loadaddr);
628
629         for (i = 0; i < epnt->e_phnum; i++) {
630                 if (DL_IS_SPECIAL_SEGMENT (epnt, ppnt)) {
631                         char *addr;
632
633                         addr = DL_MAP_SEGMENT (epnt, ppnt, infile, flags);
634                         if (addr == NULL) {
635                         cant_map1:
636                                 DL_LOADADDR_UNMAP (lib_loadaddr, maxvma - minvma);
637                                 goto cant_map;
638                         }
639
640                         DL_INIT_LOADADDR_HDR (lib_loadaddr, addr, ppnt);
641                         ppnt++;
642                         continue;
643                 }
644                 if (ppnt->p_type == PT_GNU_RELRO) {
645                         relro_addr = ppnt->p_vaddr;
646                         relro_size = ppnt->p_memsz;
647                 }
648                 if (ppnt->p_type == PT_LOAD) {
649                         char *tryaddr;
650                         ssize_t size;
651
652                         if (ppnt->p_flags & PF_W) {
653                                 status = map_writeable (infile, ppnt, piclib, flags, libaddr);
654                                 if (status == NULL)
655                                         goto cant_map1;
656                         } else {
657                                 tryaddr = (piclib == 2 ? 0
658                                            : (char *) (ppnt->p_vaddr & PAGE_ALIGN)
659                                            + (piclib ? libaddr : DL_GET_LIB_OFFSET()));
660                                 size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
661                                 status = (char *) _dl_mmap
662                                            (tryaddr, size, LXFLAGS(ppnt->p_flags),
663                                             flags | (piclib == 2 ? MAP_EXECUTABLE
664                                                      | MAP_DENYWRITE : 0),
665                                             infile, ppnt->p_offset & OFFS_ALIGN);
666                                 if (_dl_mmap_check_error(status)
667                                     || (tryaddr && tryaddr != status))
668                                   goto cant_map1;
669                         }
670                         DL_INIT_LOADADDR_HDR(lib_loadaddr,
671                                              status + (ppnt->p_vaddr & ADDR_ALIGN),
672                                              ppnt);
673
674                         /* if (libaddr == 0 && piclib) {
675                            libaddr = (unsigned long) status;
676                            flags |= MAP_FIXED;
677                            } */
678                 }
679                 ppnt++;
680         }
681
682         /*
683          * The dynamic_addr must be take into acount lib_loadaddr value, to note
684          * it is zero when the SO has been mapped to the elf's physical addr
685          */
686 #ifdef __LDSO_PRELINK_SUPPORT__
687         if (DL_GET_LIB_OFFSET()) {
688 #else
689         if (piclib) {
690 #endif
691                 dynamic_addr = (unsigned long) DL_RELOC_ADDR(lib_loadaddr, dynamic_addr);
692         }
693
694         /*
695          * OK, the ELF library is now loaded into VM in the correct locations
696          * The next step is to go through and do the dynamic linking (if needed).
697          */
698
699         /* Start by scanning the dynamic section to get all of the pointers */
700
701         if (!dynamic_addr) {
702                 _dl_internal_error_number = LD_ERROR_NODYNAMIC;
703                 _dl_dprintf(2, "%s: '%s' is missing a dynamic section\n",
704                                 _dl_progname, libname);
705                 _dl_munmap(header, _dl_pagesize);
706                 _dl_close(infile);
707                 return NULL;
708         }
709
710         dpnt = (ElfW(Dyn) *) dynamic_addr;
711         _dl_memset(dynamic_info, 0, sizeof(dynamic_info));
712         rtld_flags = _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr);
713         /* If the TEXTREL is set, this means that we need to make the pages
714            writable before we perform relocations.  Do this now. They get set
715            back again later. */
716
717         if (dynamic_info[DT_TEXTREL]) {
718 #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
719                 ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
720                 for (i = 0; i < epnt->e_phnum; i++, ppnt++) {
721                         if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) {
722 #ifdef __ARCH_USE_MMU__
723                                 _dl_mprotect((void *) ((piclib ? libaddr : DL_GET_LIB_OFFSET()) +
724                                                         (ppnt->p_vaddr & PAGE_ALIGN)),
725                                                 (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,
726                                                 PROT_READ | PROT_WRITE | PROT_EXEC);
727 #else
728                                 void *new_addr;
729                                 new_addr = map_writeable (infile, ppnt, piclib, flags, libaddr);
730                                 if (!new_addr) {
731                                         _dl_dprintf(_dl_debug_file, "Can't modify %s's text section.",
732                                                     libname);
733                                         _dl_exit(1);
734                                 }
735                                 DL_UPDATE_LOADADDR_HDR(lib_loadaddr,
736                                                        new_addr + (ppnt->p_vaddr & ADDR_ALIGN),
737                                                        ppnt);
738                                 /* This has invalidated all pointers into the previously readonly segment.
739                                    Update any them to point into the remapped segment.  */
740                                 _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr);
741 #endif
742                         }
743                 }
744 #else
745                 _dl_dprintf(2, "Can't modify %s's text section."
746                         " Use GCC option -fPIC for shared objects, please.\n",
747                         libname);
748                 _dl_exit(1);
749 #endif
750         }
751
752         _dl_close(infile);
753
754         tpnt = _dl_add_elf_hash_table(libname, lib_loadaddr, dynamic_info,
755                         dynamic_addr, 0);
756         tpnt->mapaddr = libaddr;
757         tpnt->relro_addr = relro_addr;
758         tpnt->relro_size = relro_size;
759         tpnt->st_dev = st.st_dev;
760         tpnt->st_ino = st.st_ino;
761         tpnt->ppnt = (ElfW(Phdr) *)
762                 DL_RELOC_ADDR(DL_GET_RUN_ADDR(tpnt->loadaddr, tpnt->mapaddr),
763                 epnt->e_phoff);
764         tpnt->n_phent = epnt->e_phnum;
765         tpnt->rtld_flags |= rtld_flags;
766 #ifdef __LDSO_STANDALONE_SUPPORT__
767         tpnt->l_entry = epnt->e_entry;
768 #endif
769
770 #if defined(USE_TLS) && USE_TLS
771         if (tlsppnt) {
772                 _dl_debug_early("Found TLS header for %s\n", libname);
773 # if NO_TLS_OFFSET != 0
774                 tpnt->l_tls_offset = NO_TLS_OFFSET;
775 # endif
776                 tpnt->l_tls_blocksize = tlsppnt->p_memsz;
777                 tpnt->l_tls_align = tlsppnt->p_align;
778                 if (tlsppnt->p_align == 0)
779                         tpnt->l_tls_firstbyte_offset = 0;
780                 else
781                         tpnt->l_tls_firstbyte_offset = tlsppnt->p_vaddr &
782                                 (tlsppnt->p_align - 1);
783                 tpnt->l_tls_initimage_size = tlsppnt->p_filesz;
784                 tpnt->l_tls_initimage = (void *) tlsppnt->p_vaddr;
785
786                 /* Assign the next available module ID.  */
787                 tpnt->l_tls_modid = _dl_next_tls_modid ();
788
789                 /* We know the load address, so add it to the offset. */
790 #ifdef __LDSO_STANDALONE_SUPPORT__
791                 if ((tpnt->l_tls_initimage != NULL) && piclib)
792 #else
793                 if (tpnt->l_tls_initimage != NULL)
794 #endif
795                 {
796 # ifdef __SUPPORT_LD_DEBUG_EARLY__
797                         char *tmp = (char *) tpnt->l_tls_initimage;
798                         tpnt->l_tls_initimage = (char *) tlsppnt->p_vaddr + tpnt->loadaddr;
799                         _dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n", tmp, tpnt->l_tls_initimage, tpnt->l_tls_initimage_size);
800                         tmp = 0;
801 # else
802                         tpnt->l_tls_initimage = (char *) tlsppnt->p_vaddr + tpnt->loadaddr;
803 # endif
804                 }
805         }
806 #endif
807
808         /*
809          * Add this object into the symbol chain
810          */
811         if (*rpnt
812 #ifdef __LDSO_STANDALONE_SUPPORT__
813                 /* Do not create a new chain entry for the main executable */
814                 && (*rpnt)->dyn
815 #endif
816                 ) {
817                 (*rpnt)->next = _dl_malloc(sizeof(struct dyn_elf));
818                 _dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf));
819                 (*rpnt)->next->prev = (*rpnt);
820                 *rpnt = (*rpnt)->next;
821         }
822 #ifndef SHARED
823         /* When statically linked, the first time we dlopen a DSO
824          * the *rpnt is NULL, so we need to allocate memory for it,
825          * and initialize the _dl_symbol_table.
826          */
827         else {
828                 *rpnt = _dl_symbol_tables = _dl_malloc(sizeof(struct dyn_elf));
829                 _dl_memset(*rpnt, 0, sizeof(struct dyn_elf));
830         }
831 #endif
832         (*rpnt)->dyn = tpnt;
833         tpnt->usage_count++;
834 #ifdef __LDSO_STANDALONE_SUPPORT__
835         tpnt->libtype = (epnt->e_type == ET_DYN) ? elf_lib : elf_executable;
836 #else
837         tpnt->libtype = elf_lib;
838 #endif
839
840         /*
841          * OK, the next thing we need to do is to insert the dynamic linker into
842          * the proper entry in the GOT so that the PLT symbols can be properly
843          * resolved.
844          */
845
846         lpnt = (unsigned long *) dynamic_info[DT_PLTGOT];
847
848         if (lpnt) {
849                 lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT]);
850                 INIT_GOT(lpnt, tpnt);
851         }
852
853 #ifdef __DSBT__
854         /* Handle DSBT initialization */
855         {
856                 struct elf_resolve *t, *ref;
857                 int idx = tpnt->dsbt_index;
858                 void **dsbt = tpnt->dsbt_table;
859
860                 /*
861                  * It is okay (required actually) to have zero idx for an executable.
862                  * This is the case when running ldso standalone and the program
863                  * is being mapped in via _dl_load_shared_library().
864                  */
865                 if (idx == 0 && tpnt->libtype != elf_executable) {
866                         if (!dynamic_info[DT_TEXTREL]) {
867                                 /* This DSO has not been assigned an index. */
868                                 _dl_dprintf(2, "%s: '%s' is missing a dsbt index assignment!\n",
869                                             _dl_progname, libname);
870                                 _dl_exit(1);
871                         }
872                         /* Find a dsbt table from another module. */
873                         ref = NULL;
874                         for (t = _dl_loaded_modules; t; t = t->next) {
875                                 if (ref == NULL && t != tpnt) {
876                                         ref = t;
877                                         break;
878                                 }
879                         }
880                         idx = tpnt->dsbt_size;
881                         while (idx-- > 0)
882                                 if (!ref || ref->dsbt_table[idx] == NULL)
883                                         break;
884                         if (idx <= 0) {
885                                 _dl_dprintf(2, "%s: '%s' caused DSBT table overflow!\n",
886                                             _dl_progname, libname);
887                                 _dl_exit(1);
888                         }
889                         _dl_if_debug_dprint("\n\tfile='%s';  assigned index %d\n",
890                                             libname, idx);
891                         tpnt->dsbt_index = idx;
892                 }
893
894                 /* make sure index is not already used */
895                 if (_dl_ldso_dsbt[idx]) {
896                         struct elf_resolve *dup;
897                         const char *dup_name;
898
899                         for (dup = _dl_loaded_modules; dup; dup = dup->next)
900                                 if (dup != tpnt && dup->dsbt_index == idx)
901                                         break;
902                         if (dup)
903                                 dup_name = dup->libname;
904                         else if (idx == 1)
905                                 dup_name = "runtime linker";
906                         else
907                                 dup_name = "unknown library";
908                         _dl_dprintf(2, "%s: '%s' dsbt index %d already used by %s!\n",
909                                     _dl_progname, libname, idx, dup_name);
910                         _dl_exit(1);
911                 }
912
913                 /*
914                  * Setup dsbt slot for this module in dsbt of all modules.
915                  */
916                 for (t = _dl_loaded_modules; t; t = t->next)
917                         t->dsbt_table[idx] = dsbt;
918                 _dl_ldso_dsbt[idx] = dsbt;
919                 _dl_memcpy(dsbt, _dl_ldso_dsbt,
920                            tpnt->dsbt_size * sizeof(tpnt->dsbt_table[0]));
921         }
922 #endif
923         _dl_if_debug_dprint("\n\tfile='%s';  generating link map\n", libname);
924         _dl_if_debug_dprint("\t\tdynamic: %x  base: %x\n", dynamic_addr, DL_LOADADDR_BASE(lib_loadaddr));
925         _dl_if_debug_dprint("\t\t  entry: %x  phdr: %x  phnum: %x\n\n",
926                         DL_RELOC_ADDR(lib_loadaddr, epnt->e_entry), tpnt->ppnt, tpnt->n_phent);
927
928         _dl_munmap(header, _dl_pagesize);
929
930         return tpnt;
931 }
932
933 /* now_flag must be RTLD_NOW or zero */
934 int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int now_flag)
935 {
936         int goof = 0;
937         struct elf_resolve *tpnt;
938         ElfW(Word) reloc_size, relative_count;
939         ElfW(Addr) reloc_addr;
940
941         if (rpnt->next)
942                 goof = _dl_fixup(rpnt->next, scope, now_flag);
943         if (goof)
944                 return goof;
945         tpnt = rpnt->dyn;
946
947         if (!(tpnt->init_flag & RELOCS_DONE))
948                 _dl_if_debug_dprint("relocation processing: %s\n", tpnt->libname);
949
950         if (unlikely(tpnt->dynamic_info[UNSUPPORTED_RELOC_TYPE])) {
951                 _dl_if_debug_dprint("%s: can't handle %s relocation records\n",
952                                 _dl_progname, UNSUPPORTED_RELOC_STR);
953                 goof++;
954                 return goof;
955         }
956
957         reloc_size = tpnt->dynamic_info[DT_RELOC_TABLE_SIZE];
958 /* On some machines, notably SPARC & PPC, DT_REL* includes DT_JMPREL in its
959    range.  Note that according to the ELF spec, this is completely legal! */
960 #ifdef ELF_MACHINE_PLTREL_OVERLAP
961         reloc_size -= tpnt->dynamic_info [DT_PLTRELSZ];
962 #endif
963         if (tpnt->dynamic_info[DT_RELOC_TABLE_ADDR] &&
964             !(tpnt->init_flag & RELOCS_DONE)) {
965                 reloc_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR];
966                 relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
967                 if (relative_count) { /* Optimize the XX_RELATIVE relocations if possible */
968                         reloc_size -= relative_count * sizeof(ELF_RELOC);
969 #ifdef __LDSO_PRELINK_SUPPORT__
970                         if (tpnt->loadaddr || (!tpnt->dynamic_info[DT_GNU_PRELINKED_IDX]))
971 #endif
972                                 elf_machine_relative(tpnt->loadaddr, reloc_addr, relative_count);
973                         reloc_addr += relative_count * sizeof(ELF_RELOC);
974                 }
975                 goof += _dl_parse_relocation_information(rpnt, scope,
976                                 reloc_addr,
977                                 reloc_size);
978                 tpnt->init_flag |= RELOCS_DONE;
979         }
980         if (tpnt->dynamic_info[DT_BIND_NOW])
981                 now_flag = RTLD_NOW;
982         if (tpnt->dynamic_info[DT_JMPREL] &&
983             (!(tpnt->init_flag & JMP_RELOCS_DONE) ||
984              (now_flag && !(tpnt->rtld_flags & now_flag)))) {
985                 tpnt->rtld_flags |= now_flag;
986                 if (!(tpnt->rtld_flags & RTLD_NOW)) {
987                         _dl_parse_lazy_relocation_information(rpnt,
988                                         tpnt->dynamic_info[DT_JMPREL],
989                                         tpnt->dynamic_info [DT_PLTRELSZ]);
990                 } else {
991                         goof += _dl_parse_relocation_information(rpnt, scope,
992                                         tpnt->dynamic_info[DT_JMPREL],
993                                         tpnt->dynamic_info[DT_PLTRELSZ]);
994                 }
995                 tpnt->init_flag |= JMP_RELOCS_DONE;
996         }
997
998 #if 0
999 /* _dl_add_to_slotinfo is called by init_tls() for initial DSO
1000    or by dlopen() for dynamically loaded DSO. */
1001 #if defined(USE_TLS) && USE_TLS
1002         /* Add object to slot information data if necessasy. */
1003         if (tpnt->l_tls_blocksize != 0 && tls_init_tp_called)
1004                 _dl_add_to_slotinfo ((struct link_map *) tpnt);
1005 #endif
1006 #endif
1007         return goof;
1008 }
1009
1010 #ifdef IS_IN_rtld
1011 /* Minimal printf which handles only %s, %d, and %x */
1012 void _dl_dprintf(int fd, const char *fmt, ...)
1013 {
1014 #if __WORDSIZE > 32
1015         long int num;
1016 #else
1017         int num;
1018 #endif
1019         va_list args;
1020         char *start, *ptr, *string;
1021         char *buf;
1022
1023         if (!fmt)
1024                 return;
1025
1026         buf = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
1027                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1028         if (_dl_mmap_check_error(buf)) {
1029                 _dl_write(fd, "mmap of a spare page failed!\n", 29);
1030                 _dl_exit(20);
1031         }
1032
1033         start = ptr = buf;
1034
1035         if (_dl_strlen(fmt) >= (_dl_pagesize - 1)) {
1036                 _dl_write(fd, "overflow\n", 11);
1037                 _dl_exit(20);
1038         }
1039
1040         _dl_strcpy(buf, fmt);
1041         va_start(args, fmt);
1042
1043         while (start) {
1044                 while (*ptr != '%' && *ptr) {
1045                         ptr++;
1046                 }
1047
1048                 if (*ptr == '%') {
1049                         *ptr++ = '\0';
1050                         _dl_write(fd, start, _dl_strlen(start));
1051
1052                         switch (*ptr++) {
1053                                 case 's':
1054                                         string = va_arg(args, char *);
1055
1056                                         if (!string)
1057                                                 _dl_write(fd, "(null)", 6);
1058                                         else
1059                                                 _dl_write(fd, string, _dl_strlen(string));
1060                                         break;
1061
1062                                 case 'i':
1063                                 case 'd':
1064                                         {
1065                                                 char tmp[22];
1066 #if __WORDSIZE > 32
1067                                                 num = va_arg(args, long int);
1068 #else
1069                                                 num = va_arg(args, int);
1070 #endif
1071                                                 string = _dl_simple_ltoa(tmp, num);
1072                                                 _dl_write(fd, string, _dl_strlen(string));
1073                                                 break;
1074                                         }
1075                                 case 'x':
1076                                 case 'p':
1077                                         {
1078                                                 char tmp[22];
1079 #if __WORDSIZE > 32
1080                                                 num = va_arg(args, long int);
1081 #else
1082                                                 num = va_arg(args, int);
1083 #endif
1084                                                 string = _dl_simple_ltoahex(tmp, num);
1085                                                 _dl_write(fd, string, _dl_strlen(string));
1086                                                 break;
1087                                         }
1088                                 default:
1089                                         _dl_write(fd, "(null)", 6);
1090                                         break;
1091                         }
1092
1093                         start = ptr;
1094                 } else {
1095                         _dl_write(fd, start, _dl_strlen(start));
1096                         start = NULL;
1097                 }
1098         }
1099         _dl_munmap(buf, _dl_pagesize);
1100         return;
1101 }
1102
1103 char *_dl_strdup(const char *string)
1104 {
1105         char *retval;
1106         int len;
1107
1108         len = _dl_strlen(string);
1109         retval = _dl_malloc(len + 1);
1110         _dl_strcpy(retval, string);
1111         return retval;
1112 }
1113 #endif
1114
1115 unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
1116                                     void *debug_addr, DL_LOADADDR_TYPE load_off)
1117 {
1118         return __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off);
1119 }