Annotation of src/libexec/ld.elf_so/headers.c, Revision 1.60
1.60 ! joerg 1: /* $NetBSD: headers.c,v 1.59 2014/08/26 21:20:05 joerg Exp $ */
1.1 cgd 2:
3: /*
4: * Copyright 1996 John D. Polstra.
5: * Copyright 1996 Matt Thomas <matt@3am-software.com>
1.17 mycroft 6: * Copyright 2002 Charles M. Hannum <root@ihack.net>
1.1 cgd 7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by John Polstra.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33: */
34:
35: /*
36: * Dynamic linker for ELF.
37: *
38: * John Polstra <jdp@polstra.com>.
39: */
40:
1.19 skrll 41: #include <sys/cdefs.h>
42: #ifndef lint
1.60 ! joerg 43: __RCSID("$NetBSD: headers.c,v 1.59 2014/08/26 21:20:05 joerg Exp $");
1.19 skrll 44: #endif /* not lint */
45:
1.1 cgd 46: #include <err.h>
47: #include <errno.h>
48: #include <fcntl.h>
49: #include <stdarg.h>
50: #include <stdio.h>
51: #include <stdlib.h>
52: #include <string.h>
53: #include <unistd.h>
54: #include <sys/types.h>
55: #include <sys/mman.h>
1.29 joerg 56: #include <sys/bitops.h>
1.1 cgd 57: #include <dirent.h>
58:
59: #include "debug.h"
60: #include "rtld.h"
61:
62: /*
63: * Process a shared object's DYNAMIC section, and save the important
64: * information in its Obj_Entry structure.
65: */
66: void
1.22 christos 67: _rtld_digest_dynamic(const char *execname, Obj_Entry *obj)
1.1 cgd 68: {
1.4 christos 69: Elf_Dyn *dynp;
70: Needed_Entry **needed_tail = &obj->needed;
1.51 christos 71: const Elf_Dyn *dyn_soname = NULL;
1.4 christos 72: const Elf_Dyn *dyn_rpath = NULL;
1.30 joerg 73: bool use_pltrel = false;
74: bool use_pltrela = false;
1.8 mycroft 75: Elf_Addr relsz = 0, relasz = 0;
1.13 mycroft 76: Elf_Addr pltrel = 0, pltrelsz = 0;
1.58 christos 77: #ifdef RTLD_LOADER
1.10 fredette 78: Elf_Addr init = 0, fini = 0;
1.58 christos 79: #endif
1.4 christos 80:
1.49 skrll 81: dbg(("headers: digesting PT_DYNAMIC at %p", obj->dynamic));
1.5 kleink 82: for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; ++dynp) {
1.49 skrll 83: dbg((" d_tag %ld at %p", (long)dynp->d_tag, dynp));
1.4 christos 84: switch (dynp->d_tag) {
85:
1.5 kleink 86: case DT_REL:
1.4 christos 87: obj->rel = (const Elf_Rel *)
88: (obj->relocbase + dynp->d_un.d_ptr);
89: break;
90:
1.5 kleink 91: case DT_RELSZ:
1.4 christos 92: relsz = dynp->d_un.d_val;
93: break;
94:
1.5 kleink 95: case DT_RELENT:
1.4 christos 96: assert(dynp->d_un.d_val == sizeof(Elf_Rel));
97: break;
98:
1.5 kleink 99: case DT_JMPREL:
1.13 mycroft 100: pltrel = dynp->d_un.d_ptr;
1.4 christos 101: break;
102:
1.5 kleink 103: case DT_PLTRELSZ:
1.8 mycroft 104: pltrelsz = dynp->d_un.d_val;
1.4 christos 105: break;
106:
1.5 kleink 107: case DT_RELA:
1.9 kleink 108: obj->rela = (const Elf_Rela *)
1.4 christos 109: (obj->relocbase + dynp->d_un.d_ptr);
110: break;
111:
1.5 kleink 112: case DT_RELASZ:
1.4 christos 113: relasz = dynp->d_un.d_val;
114: break;
115:
1.5 kleink 116: case DT_RELAENT:
1.9 kleink 117: assert(dynp->d_un.d_val == sizeof(Elf_Rela));
1.4 christos 118: break;
119:
1.5 kleink 120: case DT_PLTREL:
1.30 joerg 121: use_pltrel = dynp->d_un.d_val == DT_REL;
122: use_pltrela = dynp->d_un.d_val == DT_RELA;
123: assert(use_pltrel || use_pltrela);
1.4 christos 124: break;
125:
1.5 kleink 126: case DT_SYMTAB:
1.4 christos 127: obj->symtab = (const Elf_Sym *)
128: (obj->relocbase + dynp->d_un.d_ptr);
129: break;
130:
1.5 kleink 131: case DT_SYMENT:
1.4 christos 132: assert(dynp->d_un.d_val == sizeof(Elf_Sym));
133: break;
134:
1.5 kleink 135: case DT_STRTAB:
1.4 christos 136: obj->strtab = (const char *)
137: (obj->relocbase + dynp->d_un.d_ptr);
138: break;
139:
1.5 kleink 140: case DT_STRSZ:
1.4 christos 141: obj->strsize = dynp->d_un.d_val;
142: break;
143:
1.41 nonaka 144: case DT_VERNEED:
145: obj->verneed = (const Elf_Verneed *)
146: (obj->relocbase + dynp->d_un.d_ptr);
147: break;
148:
149: case DT_VERNEEDNUM:
150: obj->verneednum = dynp->d_un.d_val;
151: break;
152:
153: case DT_VERDEF:
154: obj->verdef = (const Elf_Verdef *)
155: (obj->relocbase + dynp->d_un.d_ptr);
156: break;
157:
158: case DT_VERDEFNUM:
159: obj->verdefnum = dynp->d_un.d_val;
160: break;
161:
162: case DT_VERSYM:
163: obj->versyms = (const Elf_Versym *)
164: (obj->relocbase + dynp->d_un.d_ptr);
165: break;
166:
1.5 kleink 167: case DT_HASH:
1.4 christos 168: {
1.31 skrll 169: const Elf_Symindx *hashtab = (const Elf_Symindx *)
170: (obj->relocbase + dynp->d_un.d_ptr);
1.4 christos 171:
1.29 joerg 172: if (hashtab[0] > UINT32_MAX)
173: obj->nbuckets = UINT32_MAX;
174: else
175: obj->nbuckets = hashtab[0];
1.4 christos 176: obj->nchains = hashtab[1];
177: obj->buckets = hashtab + 2;
178: obj->chains = obj->buckets + obj->nbuckets;
1.29 joerg 179: /*
180: * Should really be in _rtld_relocate_objects,
181: * but _rtld_symlook_obj might be used before.
182: */
183: if (obj->nbuckets) {
184: fast_divide32_prepare(obj->nbuckets,
185: &obj->nbuckets_m,
186: &obj->nbuckets_s1,
187: &obj->nbuckets_s2);
188: }
1.4 christos 189: }
190: break;
191:
1.5 kleink 192: case DT_NEEDED:
1.4 christos 193: {
194: Needed_Entry *nep = NEW(Needed_Entry);
195:
196: nep->name = dynp->d_un.d_val;
197: nep->obj = NULL;
198: nep->next = NULL;
199:
200: *needed_tail = nep;
201: needed_tail = &nep->next;
202: }
203: break;
204:
1.5 kleink 205: case DT_PLTGOT:
1.4 christos 206: obj->pltgot = (Elf_Addr *)
207: (obj->relocbase + dynp->d_un.d_ptr);
208: break;
209:
1.5 kleink 210: case DT_TEXTREL:
1.4 christos 211: obj->textrel = true;
212: break;
213:
1.5 kleink 214: case DT_SYMBOLIC:
1.4 christos 215: obj->symbolic = true;
216: break;
217:
1.5 kleink 218: case DT_RPATH:
1.4 christos 219: /*
220: * We have to wait until later to process this, because
221: * we might not have gotten the address of the string
222: * table yet.
223: */
224: dyn_rpath = dynp;
225: break;
226:
1.5 kleink 227: case DT_SONAME:
1.51 christos 228: dyn_soname = dynp;
1.4 christos 229: break;
230:
1.5 kleink 231: case DT_INIT:
1.58 christos 232: #ifdef RTLD_LOADER
1.10 fredette 233: init = dynp->d_un.d_ptr;
1.58 christos 234: #endif
1.4 christos 235: break;
236:
1.43 matt 237: #ifdef HAVE_INITFINI_ARRAY
238: case DT_INIT_ARRAY:
1.59 joerg 239: obj->init_array =
240: (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr);
1.49 skrll 241: dbg(("headers: DT_INIT_ARRAY at %p",
242: obj->init_array));
1.43 matt 243: break;
244:
245: case DT_INIT_ARRAYSZ:
246: obj->init_arraysz = dynp->d_un.d_val / sizeof(fptr_t);
1.49 skrll 247: dbg(("headers: DT_INIT_ARRAYZ %zu",
248: obj->init_arraysz));
1.43 matt 249: break;
250: #endif
251:
1.5 kleink 252: case DT_FINI:
1.58 christos 253: #ifdef RTLD_LOADER
1.10 fredette 254: fini = dynp->d_un.d_ptr;
1.58 christos 255: #endif
1.4 christos 256: break;
1.1 cgd 257:
1.43 matt 258: #ifdef HAVE_INITFINI_ARRAY
259: case DT_FINI_ARRAY:
260: obj->fini_array =
1.55 joerg 261: (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr);
1.49 skrll 262: dbg(("headers: DT_FINI_ARRAY at %p",
263: obj->fini_array));
1.43 matt 264: break;
265:
266: case DT_FINI_ARRAYSZ:
1.50 skrll 267: obj->fini_arraysz = dynp->d_un.d_val / sizeof(fptr_t);
1.49 skrll 268: dbg(("headers: DT_FINI_ARRAYZ %zu",
269: obj->fini_arraysz));
1.43 matt 270: break;
271: #endif
272:
1.20 simonb 273: /*
274: * Don't process DT_DEBUG on MIPS as the dynamic section
275: * is mapped read-only. DT_MIPS_RLD_MAP is used instead.
276: * XXX: n32/n64 may use DT_DEBUG, not sure yet.
277: */
278: #ifndef __mips__
1.5 kleink 279: case DT_DEBUG:
1.1 cgd 280: #ifdef RTLD_LOADER
1.4 christos 281: dynp->d_un.d_ptr = (Elf_Addr)&_rtld_debug;
1.1 cgd 282: #endif
1.4 christos 283: break;
1.20 simonb 284: #endif
1.2 mhitch 285:
1.14 mycroft 286: #ifdef __mips__
1.4 christos 287: case DT_MIPS_LOCAL_GOTNO:
288: obj->local_gotno = dynp->d_un.d_val;
289: break;
290:
291: case DT_MIPS_SYMTABNO:
292: obj->symtabno = dynp->d_un.d_val;
293: break;
294:
295: case DT_MIPS_GOTSYM:
296: obj->gotsym = dynp->d_un.d_val;
297: break;
1.2 mhitch 298:
1.4 christos 299: case DT_MIPS_RLD_MAP:
1.2 mhitch 300: #ifdef RTLD_LOADER
1.4 christos 301: *((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr)
302: &_rtld_debug;
1.2 mhitch 303: #endif
1.4 christos 304: break;
1.2 mhitch 305: #endif
1.39 matt 306: #ifdef __powerpc__
1.53 matt 307: #ifdef _LP64
308: case DT_PPC64_GLINK:
1.54 matt 309: obj->glink = (Elf_Addr)(uintptr_t)obj->relocbase + dynp->d_un.d_ptr;
1.53 matt 310: break;
311: #else
1.39 matt 312: case DT_PPC_GOT:
313: obj->gotptr = (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr);
314: break;
315: #endif
1.53 matt 316: #endif
1.23 ad 317: case DT_FLAGS_1:
1.38 skrll 318: obj->z_now =
319: ((dynp->d_un.d_val & DF_1_BIND_NOW) != 0);
320: obj->z_nodelete =
321: ((dynp->d_un.d_val & DF_1_NODELETE) != 0);
322: obj->z_initfirst =
1.23 ad 323: ((dynp->d_un.d_val & DF_1_INITFIRST) != 0);
1.38 skrll 324: obj->z_noopen =
325: ((dynp->d_un.d_val & DF_1_NOOPEN) != 0);
1.23 ad 326: break;
1.4 christos 327: }
1.1 cgd 328: }
329:
1.28 lukem 330: obj->rellim = (const Elf_Rel *)((const uint8_t *)obj->rel + relsz);
331: obj->relalim = (const Elf_Rela *)((const uint8_t *)obj->rela + relasz);
1.30 joerg 332: if (use_pltrel) {
1.13 mycroft 333: obj->pltrel = (const Elf_Rel *)(obj->relocbase + pltrel);
334: obj->pltrellim = (const Elf_Rel *)(obj->relocbase + pltrel + pltrelsz);
335: obj->pltrelalim = 0;
336: /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
337: Trim rel(a)lim to save time later. */
338: if (obj->rellim && obj->pltrel &&
339: obj->rellim > obj->pltrel &&
340: obj->rellim <= obj->pltrellim)
1.11 mycroft 341: obj->rellim = obj->pltrel;
1.30 joerg 342: } else if (use_pltrela) {
1.13 mycroft 343: obj->pltrela = (const Elf_Rela *)(obj->relocbase + pltrel);
344: obj->pltrellim = 0;
345: obj->pltrelalim = (const Elf_Rela *)(obj->relocbase + pltrel + pltrelsz);
346: /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
347: Trim rel(a)lim to save time later. */
348: if (obj->relalim && obj->pltrela &&
349: obj->relalim > obj->pltrela &&
350: obj->relalim <= obj->pltrelalim)
1.11 mycroft 351: obj->relalim = obj->pltrela;
1.8 mycroft 352: }
1.10 fredette 353:
1.57 joerg 354: #ifdef RTLD_LOADER
1.10 fredette 355: if (init != 0)
1.57 joerg 356: obj->init = (Elf_Addr) obj->relocbase + init;
1.10 fredette 357: if (fini != 0)
1.57 joerg 358: obj->fini = (Elf_Addr) obj->relocbase + fini;
359: #endif
1.4 christos 360:
361: if (dyn_rpath != NULL) {
1.22 christos 362: _rtld_add_paths(execname, &obj->rpaths, obj->strtab +
1.12 mycroft 363: dyn_rpath->d_un.d_val);
1.4 christos 364: }
1.51 christos 365: if (dyn_soname != NULL) {
366: _rtld_object_add_name(obj, obj->strtab +
367: dyn_soname->d_un.d_val);
368: }
1.1 cgd 369: }
370:
371: /*
372: * Process a shared object's program header. This is used only for the
373: * main program, when the kernel has already loaded the main program
374: * into memory before calling the dynamic linker. It creates and
375: * returns an Obj_Entry structure.
376: */
377: Obj_Entry *
1.18 skrll 378: _rtld_digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry)
1.1 cgd 379: {
1.6 mycroft 380: Obj_Entry *obj;
1.4 christos 381: const Elf_Phdr *phlimit = phdr + phnum;
382: const Elf_Phdr *ph;
383: int nsegs = 0;
1.24 christos 384: Elf_Addr vaddr;
1.4 christos 385:
1.6 mycroft 386: obj = _rtld_obj_new();
1.36 skrll 387:
388: for (ph = phdr; ph < phlimit; ++ph) {
389: if (ph->p_type != PT_PHDR)
390: continue;
1.50 skrll 391:
1.60 ! joerg 392: obj->relocbase = (caddr_t)((uintptr_t)phdr - (uintptr_t)ph->p_vaddr);
! 393: obj->phdr = phdr; /* Equivalent to relocbase + p_vaddr. */
1.46 matt 394: obj->phsize = ph->p_memsz;
1.49 skrll 395: dbg(("headers: phdr %p (%p) phsize %zu relocbase %p",
396: obj->phdr, phdr, obj->phsize, obj->relocbase));
1.36 skrll 397: break;
398: }
1.50 skrll 399:
1.4 christos 400: for (ph = phdr; ph < phlimit; ++ph) {
1.37 skrll 401: vaddr = (Elf_Addr)(uintptr_t)(obj->relocbase + ph->p_vaddr);
1.4 christos 402: switch (ph->p_type) {
403:
1.6 mycroft 404: case PT_INTERP:
1.27 mrg 405: obj->interp = (const char *)(uintptr_t)vaddr;
1.52 skrll 406: dbg(("headers: %s %p phsize %" PRImemsz,
1.49 skrll 407: "PT_INTERP", (void *)(uintptr_t)vaddr,
408: ph->p_memsz));
1.4 christos 409: break;
410:
1.5 kleink 411: case PT_LOAD:
1.4 christos 412: assert(nsegs < 2);
413: if (nsegs == 0) { /* First load segment */
1.24 christos 414: obj->vaddrbase = round_down(vaddr);
1.27 mrg 415: obj->mapbase = (caddr_t)(uintptr_t)obj->vaddrbase;
1.24 christos 416: obj->textsize = round_up(vaddr + ph->p_memsz) -
417: obj->vaddrbase;
1.4 christos 418: } else { /* Last load segment */
1.24 christos 419: obj->mapsize = round_up(vaddr + ph->p_memsz) -
420: obj->vaddrbase;
1.4 christos 421: }
422: ++nsegs;
1.52 skrll 423: dbg(("headers: %s %p phsize %" PRImemsz,
1.49 skrll 424: "PT_LOAD", (void *)(uintptr_t)vaddr,
425: ph->p_memsz));
1.4 christos 426: break;
427:
1.5 kleink 428: case PT_DYNAMIC:
1.27 mrg 429: obj->dynamic = (Elf_Dyn *)(uintptr_t)vaddr;
1.52 skrll 430: dbg(("headers: %s %p phsize %" PRImemsz,
1.49 skrll 431: "PT_DYNAMIC", (void *)(uintptr_t)vaddr,
432: ph->p_memsz));
1.4 christos 433: break;
1.40 joerg 434:
435: #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
436: case PT_TLS:
437: obj->tlsindex = 1;
438: obj->tlssize = ph->p_memsz;
439: obj->tlsalign = ph->p_align;
440: obj->tlsinitsize = ph->p_filesz;
441: obj->tlsinit = (void *)(uintptr_t)ph->p_vaddr;
1.52 skrll 442: dbg(("headers: %s %p phsize %" PRImemsz,
1.49 skrll 443: "PT_TLS", (void *)(uintptr_t)vaddr,
444: ph->p_memsz));
1.40 joerg 445: break;
446: #endif
1.44 matt 447: #ifdef __ARM_EABI__
448: case PT_ARM_EXIDX:
449: obj->exidx_start = (void *)(uintptr_t)vaddr;
450: obj->exidx_sz = ph->p_memsz;
1.52 skrll 451: dbg(("headers: %s %p phsize %" PRImemsz,
1.49 skrll 452: "PT_ARM_EXIDX", (void *)(uintptr_t)vaddr,
453: ph->p_memsz));
1.44 matt 454: break;
455: #endif
1.4 christos 456: }
1.1 cgd 457: }
1.4 christos 458: assert(nsegs == 2);
1.1 cgd 459:
1.4 christos 460: obj->entry = entry;
461: return obj;
1.1 cgd 462: }
CVSweb <webmaster@jp.NetBSD.org>