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