OSDN Git Service

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