headers.c revision 1.61 1 1.61 christos /* $NetBSD: headers.c,v 1.61 2016/06/14 13:06:41 christos 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.61 christos __RCSID("$NetBSD: headers.c,v 1.61 2016/06/14 13:06:41 christos 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.51 christos const Elf_Dyn *dyn_soname = NULL;
72 1.4 christos const Elf_Dyn *dyn_rpath = NULL;
73 1.30 joerg bool use_pltrel = false;
74 1.30 joerg bool use_pltrela = false;
75 1.8 mycroft Elf_Addr relsz = 0, relasz = 0;
76 1.13 mycroft Elf_Addr pltrel = 0, pltrelsz = 0;
77 1.58 christos #ifdef RTLD_LOADER
78 1.10 fredette Elf_Addr init = 0, fini = 0;
79 1.58 christos #endif
80 1.4 christos
81 1.49 skrll dbg(("headers: digesting PT_DYNAMIC at %p", obj->dynamic));
82 1.5 kleink for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; ++dynp) {
83 1.49 skrll dbg((" d_tag %ld at %p", (long)dynp->d_tag, dynp));
84 1.4 christos switch (dynp->d_tag) {
85 1.4 christos
86 1.5 kleink case DT_REL:
87 1.4 christos obj->rel = (const Elf_Rel *)
88 1.4 christos (obj->relocbase + dynp->d_un.d_ptr);
89 1.4 christos break;
90 1.4 christos
91 1.5 kleink case DT_RELSZ:
92 1.4 christos relsz = dynp->d_un.d_val;
93 1.4 christos break;
94 1.4 christos
95 1.5 kleink case DT_RELENT:
96 1.4 christos assert(dynp->d_un.d_val == sizeof(Elf_Rel));
97 1.4 christos break;
98 1.4 christos
99 1.5 kleink case DT_JMPREL:
100 1.13 mycroft pltrel = dynp->d_un.d_ptr;
101 1.4 christos break;
102 1.4 christos
103 1.5 kleink case DT_PLTRELSZ:
104 1.8 mycroft pltrelsz = dynp->d_un.d_val;
105 1.4 christos break;
106 1.4 christos
107 1.5 kleink case DT_RELA:
108 1.9 kleink obj->rela = (const Elf_Rela *)
109 1.4 christos (obj->relocbase + dynp->d_un.d_ptr);
110 1.4 christos break;
111 1.4 christos
112 1.5 kleink case DT_RELASZ:
113 1.4 christos relasz = dynp->d_un.d_val;
114 1.4 christos break;
115 1.4 christos
116 1.5 kleink case DT_RELAENT:
117 1.9 kleink assert(dynp->d_un.d_val == sizeof(Elf_Rela));
118 1.4 christos break;
119 1.4 christos
120 1.5 kleink case DT_PLTREL:
121 1.30 joerg use_pltrel = dynp->d_un.d_val == DT_REL;
122 1.30 joerg use_pltrela = dynp->d_un.d_val == DT_RELA;
123 1.30 joerg assert(use_pltrel || use_pltrela);
124 1.4 christos break;
125 1.4 christos
126 1.5 kleink case DT_SYMTAB:
127 1.4 christos obj->symtab = (const Elf_Sym *)
128 1.4 christos (obj->relocbase + dynp->d_un.d_ptr);
129 1.4 christos break;
130 1.4 christos
131 1.5 kleink case DT_SYMENT:
132 1.4 christos assert(dynp->d_un.d_val == sizeof(Elf_Sym));
133 1.4 christos break;
134 1.4 christos
135 1.5 kleink case DT_STRTAB:
136 1.4 christos obj->strtab = (const char *)
137 1.4 christos (obj->relocbase + dynp->d_un.d_ptr);
138 1.4 christos break;
139 1.4 christos
140 1.5 kleink case DT_STRSZ:
141 1.4 christos obj->strsize = dynp->d_un.d_val;
142 1.4 christos break;
143 1.4 christos
144 1.41 nonaka case DT_VERNEED:
145 1.41 nonaka obj->verneed = (const Elf_Verneed *)
146 1.41 nonaka (obj->relocbase + dynp->d_un.d_ptr);
147 1.41 nonaka break;
148 1.41 nonaka
149 1.41 nonaka case DT_VERNEEDNUM:
150 1.41 nonaka obj->verneednum = dynp->d_un.d_val;
151 1.41 nonaka break;
152 1.41 nonaka
153 1.41 nonaka case DT_VERDEF:
154 1.41 nonaka obj->verdef = (const Elf_Verdef *)
155 1.41 nonaka (obj->relocbase + dynp->d_un.d_ptr);
156 1.41 nonaka break;
157 1.41 nonaka
158 1.41 nonaka case DT_VERDEFNUM:
159 1.41 nonaka obj->verdefnum = dynp->d_un.d_val;
160 1.41 nonaka break;
161 1.41 nonaka
162 1.41 nonaka case DT_VERSYM:
163 1.41 nonaka obj->versyms = (const Elf_Versym *)
164 1.41 nonaka (obj->relocbase + dynp->d_un.d_ptr);
165 1.41 nonaka break;
166 1.41 nonaka
167 1.5 kleink case DT_HASH:
168 1.4 christos {
169 1.31 skrll const Elf_Symindx *hashtab = (const Elf_Symindx *)
170 1.31 skrll (obj->relocbase + dynp->d_un.d_ptr);
171 1.4 christos
172 1.29 joerg if (hashtab[0] > UINT32_MAX)
173 1.29 joerg obj->nbuckets = UINT32_MAX;
174 1.29 joerg else
175 1.29 joerg obj->nbuckets = hashtab[0];
176 1.4 christos obj->nchains = hashtab[1];
177 1.4 christos obj->buckets = hashtab + 2;
178 1.4 christos obj->chains = obj->buckets + obj->nbuckets;
179 1.29 joerg /*
180 1.29 joerg * Should really be in _rtld_relocate_objects,
181 1.29 joerg * but _rtld_symlook_obj might be used before.
182 1.29 joerg */
183 1.29 joerg if (obj->nbuckets) {
184 1.29 joerg fast_divide32_prepare(obj->nbuckets,
185 1.29 joerg &obj->nbuckets_m,
186 1.29 joerg &obj->nbuckets_s1,
187 1.29 joerg &obj->nbuckets_s2);
188 1.29 joerg }
189 1.4 christos }
190 1.4 christos break;
191 1.4 christos
192 1.5 kleink case DT_NEEDED:
193 1.4 christos {
194 1.4 christos Needed_Entry *nep = NEW(Needed_Entry);
195 1.4 christos
196 1.4 christos nep->name = dynp->d_un.d_val;
197 1.4 christos nep->obj = NULL;
198 1.4 christos nep->next = NULL;
199 1.4 christos
200 1.4 christos *needed_tail = nep;
201 1.4 christos needed_tail = &nep->next;
202 1.4 christos }
203 1.4 christos break;
204 1.4 christos
205 1.5 kleink case DT_PLTGOT:
206 1.4 christos obj->pltgot = (Elf_Addr *)
207 1.4 christos (obj->relocbase + dynp->d_un.d_ptr);
208 1.4 christos break;
209 1.4 christos
210 1.5 kleink case DT_TEXTREL:
211 1.4 christos obj->textrel = true;
212 1.4 christos break;
213 1.4 christos
214 1.5 kleink case DT_SYMBOLIC:
215 1.4 christos obj->symbolic = true;
216 1.4 christos break;
217 1.4 christos
218 1.5 kleink case DT_RPATH:
219 1.4 christos /*
220 1.4 christos * We have to wait until later to process this, because
221 1.4 christos * we might not have gotten the address of the string
222 1.4 christos * table yet.
223 1.4 christos */
224 1.4 christos dyn_rpath = dynp;
225 1.4 christos break;
226 1.4 christos
227 1.5 kleink case DT_SONAME:
228 1.51 christos dyn_soname = dynp;
229 1.4 christos break;
230 1.4 christos
231 1.5 kleink case DT_INIT:
232 1.58 christos #ifdef RTLD_LOADER
233 1.10 fredette init = dynp->d_un.d_ptr;
234 1.58 christos #endif
235 1.4 christos break;
236 1.4 christos
237 1.43 matt #ifdef HAVE_INITFINI_ARRAY
238 1.43 matt case DT_INIT_ARRAY:
239 1.59 joerg obj->init_array =
240 1.59 joerg (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr);
241 1.49 skrll dbg(("headers: DT_INIT_ARRAY at %p",
242 1.49 skrll obj->init_array));
243 1.43 matt break;
244 1.43 matt
245 1.43 matt case DT_INIT_ARRAYSZ:
246 1.43 matt obj->init_arraysz = dynp->d_un.d_val / sizeof(fptr_t);
247 1.49 skrll dbg(("headers: DT_INIT_ARRAYZ %zu",
248 1.49 skrll obj->init_arraysz));
249 1.43 matt break;
250 1.43 matt #endif
251 1.43 matt
252 1.5 kleink case DT_FINI:
253 1.58 christos #ifdef RTLD_LOADER
254 1.10 fredette fini = dynp->d_un.d_ptr;
255 1.58 christos #endif
256 1.4 christos break;
257 1.1 cgd
258 1.43 matt #ifdef HAVE_INITFINI_ARRAY
259 1.43 matt case DT_FINI_ARRAY:
260 1.43 matt obj->fini_array =
261 1.55 joerg (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr);
262 1.49 skrll dbg(("headers: DT_FINI_ARRAY at %p",
263 1.49 skrll obj->fini_array));
264 1.43 matt break;
265 1.43 matt
266 1.43 matt case DT_FINI_ARRAYSZ:
267 1.50 skrll obj->fini_arraysz = dynp->d_un.d_val / sizeof(fptr_t);
268 1.49 skrll dbg(("headers: DT_FINI_ARRAYZ %zu",
269 1.49 skrll obj->fini_arraysz));
270 1.43 matt break;
271 1.43 matt #endif
272 1.43 matt
273 1.20 simonb /*
274 1.20 simonb * Don't process DT_DEBUG on MIPS as the dynamic section
275 1.20 simonb * is mapped read-only. DT_MIPS_RLD_MAP is used instead.
276 1.20 simonb * XXX: n32/n64 may use DT_DEBUG, not sure yet.
277 1.20 simonb */
278 1.20 simonb #ifndef __mips__
279 1.5 kleink case DT_DEBUG:
280 1.1 cgd #ifdef RTLD_LOADER
281 1.4 christos dynp->d_un.d_ptr = (Elf_Addr)&_rtld_debug;
282 1.1 cgd #endif
283 1.4 christos break;
284 1.20 simonb #endif
285 1.2 mhitch
286 1.14 mycroft #ifdef __mips__
287 1.4 christos case DT_MIPS_LOCAL_GOTNO:
288 1.4 christos obj->local_gotno = dynp->d_un.d_val;
289 1.4 christos break;
290 1.4 christos
291 1.4 christos case DT_MIPS_SYMTABNO:
292 1.4 christos obj->symtabno = dynp->d_un.d_val;
293 1.4 christos break;
294 1.4 christos
295 1.4 christos case DT_MIPS_GOTSYM:
296 1.4 christos obj->gotsym = dynp->d_un.d_val;
297 1.4 christos break;
298 1.2 mhitch
299 1.4 christos case DT_MIPS_RLD_MAP:
300 1.2 mhitch #ifdef RTLD_LOADER
301 1.4 christos *((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr)
302 1.4 christos &_rtld_debug;
303 1.2 mhitch #endif
304 1.4 christos break;
305 1.2 mhitch #endif
306 1.39 matt #ifdef __powerpc__
307 1.53 matt #ifdef _LP64
308 1.53 matt case DT_PPC64_GLINK:
309 1.54 matt obj->glink = (Elf_Addr)(uintptr_t)obj->relocbase + dynp->d_un.d_ptr;
310 1.53 matt break;
311 1.53 matt #else
312 1.39 matt case DT_PPC_GOT:
313 1.39 matt obj->gotptr = (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr);
314 1.39 matt break;
315 1.39 matt #endif
316 1.53 matt #endif
317 1.23 ad case DT_FLAGS_1:
318 1.38 skrll obj->z_now =
319 1.38 skrll ((dynp->d_un.d_val & DF_1_BIND_NOW) != 0);
320 1.38 skrll obj->z_nodelete =
321 1.38 skrll ((dynp->d_un.d_val & DF_1_NODELETE) != 0);
322 1.38 skrll obj->z_initfirst =
323 1.23 ad ((dynp->d_un.d_val & DF_1_INITFIRST) != 0);
324 1.38 skrll obj->z_noopen =
325 1.38 skrll ((dynp->d_un.d_val & DF_1_NOOPEN) != 0);
326 1.23 ad break;
327 1.4 christos }
328 1.1 cgd }
329 1.1 cgd
330 1.28 lukem obj->rellim = (const Elf_Rel *)((const uint8_t *)obj->rel + relsz);
331 1.28 lukem obj->relalim = (const Elf_Rela *)((const uint8_t *)obj->rela + relasz);
332 1.30 joerg if (use_pltrel) {
333 1.13 mycroft obj->pltrel = (const Elf_Rel *)(obj->relocbase + pltrel);
334 1.13 mycroft obj->pltrellim = (const Elf_Rel *)(obj->relocbase + pltrel + pltrelsz);
335 1.13 mycroft obj->pltrelalim = 0;
336 1.13 mycroft /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
337 1.13 mycroft Trim rel(a)lim to save time later. */
338 1.13 mycroft if (obj->rellim && obj->pltrel &&
339 1.13 mycroft obj->rellim > obj->pltrel &&
340 1.13 mycroft obj->rellim <= obj->pltrellim)
341 1.11 mycroft obj->rellim = obj->pltrel;
342 1.30 joerg } else if (use_pltrela) {
343 1.13 mycroft obj->pltrela = (const Elf_Rela *)(obj->relocbase + pltrel);
344 1.13 mycroft obj->pltrellim = 0;
345 1.13 mycroft obj->pltrelalim = (const Elf_Rela *)(obj->relocbase + pltrel + pltrelsz);
346 1.13 mycroft /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
347 1.13 mycroft Trim rel(a)lim to save time later. */
348 1.13 mycroft if (obj->relalim && obj->pltrela &&
349 1.13 mycroft obj->relalim > obj->pltrela &&
350 1.13 mycroft obj->relalim <= obj->pltrelalim)
351 1.11 mycroft obj->relalim = obj->pltrela;
352 1.8 mycroft }
353 1.10 fredette
354 1.57 joerg #ifdef RTLD_LOADER
355 1.10 fredette if (init != 0)
356 1.57 joerg obj->init = (Elf_Addr) obj->relocbase + init;
357 1.10 fredette if (fini != 0)
358 1.57 joerg obj->fini = (Elf_Addr) obj->relocbase + fini;
359 1.57 joerg #endif
360 1.4 christos
361 1.4 christos if (dyn_rpath != NULL) {
362 1.22 christos _rtld_add_paths(execname, &obj->rpaths, obj->strtab +
363 1.12 mycroft dyn_rpath->d_un.d_val);
364 1.4 christos }
365 1.51 christos if (dyn_soname != NULL) {
366 1.51 christos _rtld_object_add_name(obj, obj->strtab +
367 1.51 christos dyn_soname->d_un.d_val);
368 1.51 christos }
369 1.1 cgd }
370 1.1 cgd
371 1.1 cgd /*
372 1.1 cgd * Process a shared object's program header. This is used only for the
373 1.1 cgd * main program, when the kernel has already loaded the main program
374 1.1 cgd * into memory before calling the dynamic linker. It creates and
375 1.1 cgd * returns an Obj_Entry structure.
376 1.1 cgd */
377 1.1 cgd Obj_Entry *
378 1.18 skrll _rtld_digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry)
379 1.1 cgd {
380 1.6 mycroft Obj_Entry *obj;
381 1.4 christos const Elf_Phdr *phlimit = phdr + phnum;
382 1.4 christos const Elf_Phdr *ph;
383 1.4 christos int nsegs = 0;
384 1.24 christos Elf_Addr vaddr;
385 1.4 christos
386 1.6 mycroft obj = _rtld_obj_new();
387 1.36 skrll
388 1.36 skrll for (ph = phdr; ph < phlimit; ++ph) {
389 1.36 skrll if (ph->p_type != PT_PHDR)
390 1.36 skrll continue;
391 1.50 skrll
392 1.60 joerg obj->relocbase = (caddr_t)((uintptr_t)phdr - (uintptr_t)ph->p_vaddr);
393 1.60 joerg obj->phdr = phdr; /* Equivalent to relocbase + p_vaddr. */
394 1.46 matt obj->phsize = ph->p_memsz;
395 1.49 skrll dbg(("headers: phdr %p (%p) phsize %zu relocbase %p",
396 1.49 skrll obj->phdr, phdr, obj->phsize, obj->relocbase));
397 1.36 skrll break;
398 1.36 skrll }
399 1.50 skrll
400 1.4 christos for (ph = phdr; ph < phlimit; ++ph) {
401 1.37 skrll vaddr = (Elf_Addr)(uintptr_t)(obj->relocbase + ph->p_vaddr);
402 1.4 christos switch (ph->p_type) {
403 1.4 christos
404 1.6 mycroft case PT_INTERP:
405 1.27 mrg obj->interp = (const char *)(uintptr_t)vaddr;
406 1.52 skrll dbg(("headers: %s %p phsize %" PRImemsz,
407 1.49 skrll "PT_INTERP", (void *)(uintptr_t)vaddr,
408 1.49 skrll ph->p_memsz));
409 1.4 christos break;
410 1.4 christos
411 1.5 kleink case PT_LOAD:
412 1.4 christos assert(nsegs < 2);
413 1.4 christos if (nsegs == 0) { /* First load segment */
414 1.24 christos obj->vaddrbase = round_down(vaddr);
415 1.27 mrg obj->mapbase = (caddr_t)(uintptr_t)obj->vaddrbase;
416 1.24 christos obj->textsize = round_up(vaddr + ph->p_memsz) -
417 1.24 christos obj->vaddrbase;
418 1.4 christos } else { /* Last load segment */
419 1.24 christos obj->mapsize = round_up(vaddr + ph->p_memsz) -
420 1.24 christos obj->vaddrbase;
421 1.4 christos }
422 1.4 christos ++nsegs;
423 1.52 skrll dbg(("headers: %s %p phsize %" PRImemsz,
424 1.49 skrll "PT_LOAD", (void *)(uintptr_t)vaddr,
425 1.49 skrll ph->p_memsz));
426 1.4 christos break;
427 1.4 christos
428 1.5 kleink case PT_DYNAMIC:
429 1.27 mrg obj->dynamic = (Elf_Dyn *)(uintptr_t)vaddr;
430 1.52 skrll dbg(("headers: %s %p phsize %" PRImemsz,
431 1.49 skrll "PT_DYNAMIC", (void *)(uintptr_t)vaddr,
432 1.49 skrll ph->p_memsz));
433 1.4 christos break;
434 1.40 joerg
435 1.61 christos #ifdef GNU_RELRO
436 1.61 christos case PT_GNU_RELRO:
437 1.61 christos obj->relro_page = obj->relocbase
438 1.61 christos + round_down(ph->p_vaddr);
439 1.61 christos obj->relro_size = round_up(ph->p_memsz);
440 1.61 christos dbg(("headers: %s %p phsize %" PRImemsz,
441 1.61 christos "PT_GNU_RELRO", (void *)(uintptr_t)vaddr,
442 1.61 christos ph->p_memsz));
443 1.61 christos break;
444 1.61 christos #endif
445 1.61 christos
446 1.40 joerg #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
447 1.40 joerg case PT_TLS:
448 1.40 joerg obj->tlsindex = 1;
449 1.40 joerg obj->tlssize = ph->p_memsz;
450 1.40 joerg obj->tlsalign = ph->p_align;
451 1.40 joerg obj->tlsinitsize = ph->p_filesz;
452 1.40 joerg obj->tlsinit = (void *)(uintptr_t)ph->p_vaddr;
453 1.52 skrll dbg(("headers: %s %p phsize %" PRImemsz,
454 1.49 skrll "PT_TLS", (void *)(uintptr_t)vaddr,
455 1.49 skrll ph->p_memsz));
456 1.40 joerg break;
457 1.40 joerg #endif
458 1.44 matt #ifdef __ARM_EABI__
459 1.44 matt case PT_ARM_EXIDX:
460 1.44 matt obj->exidx_start = (void *)(uintptr_t)vaddr;
461 1.44 matt obj->exidx_sz = ph->p_memsz;
462 1.52 skrll dbg(("headers: %s %p phsize %" PRImemsz,
463 1.49 skrll "PT_ARM_EXIDX", (void *)(uintptr_t)vaddr,
464 1.49 skrll ph->p_memsz));
465 1.44 matt break;
466 1.44 matt #endif
467 1.4 christos }
468 1.1 cgd }
469 1.4 christos assert(nsegs == 2);
470 1.1 cgd
471 1.4 christos obj->entry = entry;
472 1.4 christos return obj;
473 1.1 cgd }
474