Annotation of src/libexec/ld.elf_so/headers.c, Revision 1.24
1.24 ! christos 1: /* $NetBSD: headers.c,v 1.23 2007/12/07 20:34:04 ad 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.24 ! christos 43: __RCSID("$NetBSD: headers.c,v 1.23 2007/12/07 20:34:04 ad 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>
56: #include <dirent.h>
57:
58: #include "debug.h"
59: #include "rtld.h"
60:
61: /*
62: * Process a shared object's DYNAMIC section, and save the important
63: * information in its Obj_Entry structure.
64: */
65: void
1.22 christos 66: _rtld_digest_dynamic(const char *execname, Obj_Entry *obj)
1.1 cgd 67: {
1.4 christos 68: Elf_Dyn *dynp;
69: Needed_Entry **needed_tail = &obj->needed;
70: const Elf_Dyn *dyn_rpath = NULL;
1.15 mycroft 71: Elf_Sword plttype = DT_NULL;
1.8 mycroft 72: Elf_Addr relsz = 0, relasz = 0;
1.13 mycroft 73: Elf_Addr pltrel = 0, pltrelsz = 0;
1.10 fredette 74: Elf_Addr init = 0, fini = 0;
1.4 christos 75:
1.5 kleink 76: for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; ++dynp) {
1.4 christos 77: switch (dynp->d_tag) {
78:
1.5 kleink 79: case DT_REL:
1.4 christos 80: obj->rel = (const Elf_Rel *)
81: (obj->relocbase + dynp->d_un.d_ptr);
82: break;
83:
1.5 kleink 84: case DT_RELSZ:
1.4 christos 85: relsz = dynp->d_un.d_val;
86: break;
87:
1.5 kleink 88: case DT_RELENT:
1.4 christos 89: assert(dynp->d_un.d_val == sizeof(Elf_Rel));
90: break;
91:
1.5 kleink 92: case DT_JMPREL:
1.13 mycroft 93: pltrel = dynp->d_un.d_ptr;
1.4 christos 94: break;
95:
1.5 kleink 96: case DT_PLTRELSZ:
1.8 mycroft 97: pltrelsz = dynp->d_un.d_val;
1.4 christos 98: break;
99:
1.5 kleink 100: case DT_RELA:
1.9 kleink 101: obj->rela = (const Elf_Rela *)
1.4 christos 102: (obj->relocbase + dynp->d_un.d_ptr);
103: break;
104:
1.5 kleink 105: case DT_RELASZ:
1.4 christos 106: relasz = dynp->d_un.d_val;
107: break;
108:
1.5 kleink 109: case DT_RELAENT:
1.9 kleink 110: assert(dynp->d_un.d_val == sizeof(Elf_Rela));
1.4 christos 111: break;
112:
1.5 kleink 113: case DT_PLTREL:
1.4 christos 114: plttype = dynp->d_un.d_val;
1.13 mycroft 115: assert(plttype == DT_REL || plttype == DT_RELA);
1.4 christos 116: break;
117:
1.5 kleink 118: case DT_SYMTAB:
1.4 christos 119: obj->symtab = (const Elf_Sym *)
120: (obj->relocbase + dynp->d_un.d_ptr);
121: break;
122:
1.5 kleink 123: case DT_SYMENT:
1.4 christos 124: assert(dynp->d_un.d_val == sizeof(Elf_Sym));
125: break;
126:
1.5 kleink 127: case DT_STRTAB:
1.4 christos 128: obj->strtab = (const char *)
129: (obj->relocbase + dynp->d_un.d_ptr);
130: break;
131:
1.5 kleink 132: case DT_STRSZ:
1.4 christos 133: obj->strsize = dynp->d_un.d_val;
134: break;
135:
1.5 kleink 136: case DT_HASH:
1.4 christos 137: {
138: const Elf_Word *hashtab = (const Elf_Word *)
139: (obj->relocbase + dynp->d_un.d_ptr);
140:
141: obj->nbuckets = hashtab[0];
142: obj->nchains = hashtab[1];
143: obj->buckets = hashtab + 2;
144: obj->chains = obj->buckets + obj->nbuckets;
145: }
146: break;
147:
1.5 kleink 148: case DT_NEEDED:
1.4 christos 149: {
150: Needed_Entry *nep = NEW(Needed_Entry);
151:
152: nep->name = dynp->d_un.d_val;
153: nep->obj = NULL;
154: nep->next = NULL;
155:
156: *needed_tail = nep;
157: needed_tail = &nep->next;
158: }
159: break;
160:
1.5 kleink 161: case DT_PLTGOT:
1.4 christos 162: obj->pltgot = (Elf_Addr *)
163: (obj->relocbase + dynp->d_un.d_ptr);
164: break;
165:
1.5 kleink 166: case DT_TEXTREL:
1.4 christos 167: obj->textrel = true;
168: break;
169:
1.5 kleink 170: case DT_SYMBOLIC:
1.4 christos 171: obj->symbolic = true;
172: break;
173:
1.5 kleink 174: case DT_RPATH:
1.4 christos 175: /*
176: * We have to wait until later to process this, because
177: * we might not have gotten the address of the string
178: * table yet.
179: */
180: dyn_rpath = dynp;
181: break;
182:
1.5 kleink 183: case DT_SONAME:
1.4 christos 184: /* Not used by the dynamic linker. */
185: break;
186:
1.5 kleink 187: case DT_INIT:
1.10 fredette 188: init = dynp->d_un.d_ptr;
1.4 christos 189: break;
190:
1.5 kleink 191: case DT_FINI:
1.10 fredette 192: fini = dynp->d_un.d_ptr;
1.4 christos 193: break;
1.1 cgd 194:
1.20 simonb 195: /*
196: * Don't process DT_DEBUG on MIPS as the dynamic section
197: * is mapped read-only. DT_MIPS_RLD_MAP is used instead.
198: * XXX: n32/n64 may use DT_DEBUG, not sure yet.
199: */
200: #ifndef __mips__
1.5 kleink 201: case DT_DEBUG:
1.1 cgd 202: #ifdef RTLD_LOADER
1.4 christos 203: dynp->d_un.d_ptr = (Elf_Addr)&_rtld_debug;
1.1 cgd 204: #endif
1.4 christos 205: break;
1.20 simonb 206: #endif
1.2 mhitch 207:
1.14 mycroft 208: #ifdef __mips__
1.4 christos 209: case DT_MIPS_LOCAL_GOTNO:
210: obj->local_gotno = dynp->d_un.d_val;
211: break;
212:
213: case DT_MIPS_SYMTABNO:
214: obj->symtabno = dynp->d_un.d_val;
215: break;
216:
217: case DT_MIPS_GOTSYM:
218: obj->gotsym = dynp->d_un.d_val;
219: break;
1.2 mhitch 220:
1.4 christos 221: case DT_MIPS_RLD_MAP:
1.2 mhitch 222: #ifdef RTLD_LOADER
1.4 christos 223: *((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr)
224: &_rtld_debug;
1.2 mhitch 225: #endif
1.4 christos 226: break;
1.2 mhitch 227: #endif
1.23 ad 228: case DT_FLAGS_1:
229: obj->initfirst =
230: ((dynp->d_un.d_val & DF_1_INITFIRST) != 0);
231: break;
1.4 christos 232: }
1.1 cgd 233: }
234:
1.4 christos 235: obj->rellim = (const Elf_Rel *)((caddr_t)obj->rel + relsz);
1.9 kleink 236: obj->relalim = (const Elf_Rela *)((caddr_t)obj->rela + relasz);
1.8 mycroft 237: if (plttype == DT_REL) {
1.13 mycroft 238: obj->pltrel = (const Elf_Rel *)(obj->relocbase + pltrel);
239: obj->pltrellim = (const Elf_Rel *)(obj->relocbase + pltrel + pltrelsz);
240: obj->pltrelalim = 0;
241: /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
242: Trim rel(a)lim to save time later. */
243: if (obj->rellim && obj->pltrel &&
244: obj->rellim > obj->pltrel &&
245: obj->rellim <= obj->pltrellim)
1.11 mycroft 246: obj->rellim = obj->pltrel;
1.15 mycroft 247: } else if (plttype == DT_RELA) {
1.13 mycroft 248: obj->pltrela = (const Elf_Rela *)(obj->relocbase + pltrel);
249: obj->pltrellim = 0;
250: obj->pltrelalim = (const Elf_Rela *)(obj->relocbase + pltrel + pltrelsz);
251: /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
252: Trim rel(a)lim to save time later. */
253: if (obj->relalim && obj->pltrela &&
254: obj->relalim > obj->pltrela &&
255: obj->relalim <= obj->pltrelalim)
1.11 mycroft 256: obj->relalim = obj->pltrela;
1.8 mycroft 257: }
1.10 fredette 258:
259: #if defined(RTLD_LOADER) && defined(__HAVE_FUNCTION_DESCRIPTORS)
260: if (init != 0)
1.18 skrll 261: obj->init = (void (*)(void))
1.10 fredette 262: _rtld_function_descriptor_alloc(obj, NULL, init);
263: if (fini != 0)
1.18 skrll 264: obj->fini = (void (*)(void))
1.10 fredette 265: _rtld_function_descriptor_alloc(obj, NULL, fini);
266: #else
267: if (init != 0)
1.18 skrll 268: obj->init = (void (*)(void))
1.10 fredette 269: (obj->relocbase + init);
270: if (fini != 0)
1.18 skrll 271: obj->fini = (void (*)(void))
1.10 fredette 272: (obj->relocbase + fini);
273: #endif
1.4 christos 274:
275: if (dyn_rpath != NULL) {
1.22 christos 276: _rtld_add_paths(execname, &obj->rpaths, obj->strtab +
1.12 mycroft 277: dyn_rpath->d_un.d_val);
1.4 christos 278: }
1.1 cgd 279: }
280:
281: /*
282: * Process a shared object's program header. This is used only for the
283: * main program, when the kernel has already loaded the main program
284: * into memory before calling the dynamic linker. It creates and
285: * returns an Obj_Entry structure.
286: */
287: Obj_Entry *
1.18 skrll 288: _rtld_digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry)
1.1 cgd 289: {
1.6 mycroft 290: Obj_Entry *obj;
1.4 christos 291: const Elf_Phdr *phlimit = phdr + phnum;
292: const Elf_Phdr *ph;
293: int nsegs = 0;
1.24 ! christos 294: ptrdiff_t relocoffs = 0;
! 295: Elf_Addr vaddr;
1.4 christos 296:
1.6 mycroft 297: obj = _rtld_obj_new();
1.4 christos 298: for (ph = phdr; ph < phlimit; ++ph) {
1.24 ! christos 299: vaddr = ph->p_vaddr + relocoffs;
! 300: dbg(("headers: relocoffs = %lx\n", (long)relocoffs));
1.4 christos 301: switch (ph->p_type) {
302:
1.5 kleink 303: case PT_PHDR:
1.24 ! christos 304: relocoffs = (char *)phdr - (char *)ph->p_vaddr;
1.6 mycroft 305: break;
306:
307: case PT_INTERP:
1.24 ! christos 308: obj->interp = (const char *)vaddr;
1.4 christos 309: break;
310:
1.5 kleink 311: case PT_LOAD:
1.4 christos 312: assert(nsegs < 2);
313: if (nsegs == 0) { /* First load segment */
1.24 ! christos 314: obj->vaddrbase = round_down(vaddr);
! 315: obj->mapbase = (caddr_t)obj->vaddrbase;
! 316: obj->relocbase = relocoffs ? (void *)relocoffs :
! 317: (obj->mapbase - obj->vaddrbase);
! 318: obj->textsize = round_up(vaddr + ph->p_memsz) -
! 319: obj->vaddrbase;
1.4 christos 320: } else { /* Last load segment */
1.24 ! christos 321: obj->mapsize = round_up(vaddr + ph->p_memsz) -
! 322: obj->vaddrbase;
1.4 christos 323: }
324: ++nsegs;
325: break;
326:
1.5 kleink 327: case PT_DYNAMIC:
1.24 ! christos 328: obj->dynamic = (Elf_Dyn *)vaddr;
1.4 christos 329: break;
330: }
1.1 cgd 331: }
1.4 christos 332: assert(nsegs == 2);
1.1 cgd 333:
1.4 christos 334: obj->entry = entry;
335: return obj;
1.1 cgd 336: }
CVSweb <webmaster@jp.NetBSD.org>