1 /* $NetBSD: headers.c,v 1.59 2014/08/26 21:20:05 joerg Exp $ */
4 * Copyright 1996 John D. Polstra.
5 * Copyright 1996 Matt Thomas <matt@3am-software.com>
6 * Copyright 2002 Charles M. Hannum <root@ihack.net>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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.
36 * Dynamic linker for ELF.
38 * John Polstra <jdp@polstra.com>.
41 #include <sys/cdefs.h>
43 __RCSID("$NetBSD: headers.c,v 1.59 2014/08/26 21:20:05 joerg Exp $");
54 #include <sys/types.h>
56 #include <sys/bitops.h>
63 * Process a shared object's DYNAMIC section, and save the important
64 * information in its Obj_Entry structure.
67 _rtld_digest_dynamic(const char *execname
, Obj_Entry
*obj
)
70 Needed_Entry
**needed_tail
= &obj
->needed
;
71 const Elf_Dyn
*dyn_soname
= NULL
;
72 const Elf_Dyn
*dyn_rpath
= NULL
;
73 bool use_pltrel
= false;
74 bool use_pltrela
= false;
75 Elf_Addr relsz
= 0, relasz
= 0;
76 Elf_Addr pltrel
= 0, pltrelsz
= 0;
78 Elf_Addr init
= 0, fini
= 0;
81 dbg(("headers: digesting PT_DYNAMIC at %p", obj
->dynamic
));
82 for (dynp
= obj
->dynamic
; dynp
->d_tag
!= DT_NULL
; ++dynp
) {
83 dbg((" d_tag %ld at %p", (long)dynp
->d_tag
, dynp
));
84 switch (dynp
->d_tag
) {
87 obj
->rel
= (const Elf_Rel
*)
88 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
92 relsz
= dynp
->d_un
.d_val
;
96 assert(dynp
->d_un
.d_val
== sizeof(Elf_Rel
));
100 pltrel
= dynp
->d_un
.d_ptr
;
104 pltrelsz
= dynp
->d_un
.d_val
;
108 obj
->rela
= (const Elf_Rela
*)
109 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
113 relasz
= dynp
->d_un
.d_val
;
117 assert(dynp
->d_un
.d_val
== sizeof(Elf_Rela
));
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
);
127 obj
->symtab
= (const Elf_Sym
*)
128 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
132 assert(dynp
->d_un
.d_val
== sizeof(Elf_Sym
));
136 obj
->strtab
= (const char *)
137 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
141 obj
->strsize
= dynp
->d_un
.d_val
;
145 obj
->verneed
= (const Elf_Verneed
*)
146 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
150 obj
->verneednum
= dynp
->d_un
.d_val
;
154 obj
->verdef
= (const Elf_Verdef
*)
155 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
159 obj
->verdefnum
= dynp
->d_un
.d_val
;
163 obj
->versyms
= (const Elf_Versym
*)
164 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
169 const Elf_Symindx
*hashtab
= (const Elf_Symindx
*)
170 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
172 if (hashtab
[0] > UINT32_MAX
)
173 obj
->nbuckets
= UINT32_MAX
;
175 obj
->nbuckets
= hashtab
[0];
176 obj
->nchains
= hashtab
[1];
177 obj
->buckets
= hashtab
+ 2;
178 obj
->chains
= obj
->buckets
+ obj
->nbuckets
;
180 * Should really be in _rtld_relocate_objects,
181 * but _rtld_symlook_obj might be used before.
184 fast_divide32_prepare(obj
->nbuckets
,
194 Needed_Entry
*nep
= NEW(Needed_Entry
);
196 nep
->name
= dynp
->d_un
.d_val
;
201 needed_tail
= &nep
->next
;
206 obj
->pltgot
= (Elf_Addr
*)
207 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
215 obj
->symbolic
= true;
220 * We have to wait until later to process this, because
221 * we might not have gotten the address of the string
233 init
= dynp
->d_un
.d_ptr
;
237 #ifdef HAVE_INITFINI_ARRAY
240 (Elf_Addr
*)(obj
->relocbase
+ dynp
->d_un
.d_ptr
);
241 dbg(("headers: DT_INIT_ARRAY at %p",
245 case DT_INIT_ARRAYSZ
:
246 obj
->init_arraysz
= dynp
->d_un
.d_val
/ sizeof(fptr_t
);
247 dbg(("headers: DT_INIT_ARRAYZ %zu",
254 fini
= dynp
->d_un
.d_ptr
;
258 #ifdef HAVE_INITFINI_ARRAY
261 (Elf_Addr
*)(obj
->relocbase
+ dynp
->d_un
.d_ptr
);
262 dbg(("headers: DT_FINI_ARRAY at %p",
266 case DT_FINI_ARRAYSZ
:
267 obj
->fini_arraysz
= dynp
->d_un
.d_val
/ sizeof(fptr_t
);
268 dbg(("headers: DT_FINI_ARRAYZ %zu",
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.
281 dynp
->d_un
.d_ptr
= (Elf_Addr
)&_rtld_debug
;
287 case DT_MIPS_LOCAL_GOTNO
:
288 obj
->local_gotno
= dynp
->d_un
.d_val
;
291 case DT_MIPS_SYMTABNO
:
292 obj
->symtabno
= dynp
->d_un
.d_val
;
296 obj
->gotsym
= dynp
->d_un
.d_val
;
299 case DT_MIPS_RLD_MAP
:
301 *((Elf_Addr
*)(dynp
->d_un
.d_ptr
)) = (Elf_Addr
)
309 obj
->glink
= (Elf_Addr
)(uintptr_t)obj
->relocbase
+ dynp
->d_un
.d_ptr
;
313 obj
->gotptr
= (Elf_Addr
*)(obj
->relocbase
+ dynp
->d_un
.d_ptr
);
319 ((dynp
->d_un
.d_val
& DF_1_BIND_NOW
) != 0);
321 ((dynp
->d_un
.d_val
& DF_1_NODELETE
) != 0);
323 ((dynp
->d_un
.d_val
& DF_1_INITFIRST
) != 0);
325 ((dynp
->d_un
.d_val
& DF_1_NOOPEN
) != 0);
330 obj
->rellim
= (const Elf_Rel
*)((const uint8_t *)obj
->rel
+ relsz
);
331 obj
->relalim
= (const Elf_Rela
*)((const uint8_t *)obj
->rela
+ relasz
);
333 obj
->pltrel
= (const Elf_Rel
*)(obj
->relocbase
+ pltrel
);
334 obj
->pltrellim
= (const Elf_Rel
*)(obj
->relocbase
+ pltrel
+ pltrelsz
);
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
)
341 obj
->rellim
= obj
->pltrel
;
342 } else if (use_pltrela
) {
343 obj
->pltrela
= (const Elf_Rela
*)(obj
->relocbase
+ pltrel
);
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
)
351 obj
->relalim
= obj
->pltrela
;
356 obj
->init
= (Elf_Addr
) obj
->relocbase
+ init
;
358 obj
->fini
= (Elf_Addr
) obj
->relocbase
+ fini
;
361 if (dyn_rpath
!= NULL
) {
362 _rtld_add_paths(execname
, &obj
->rpaths
, obj
->strtab
+
363 dyn_rpath
->d_un
.d_val
);
365 if (dyn_soname
!= NULL
) {
366 _rtld_object_add_name(obj
, obj
->strtab
+
367 dyn_soname
->d_un
.d_val
);
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.
378 _rtld_digest_phdr(const Elf_Phdr
*phdr
, int phnum
, caddr_t entry
)
381 const Elf_Phdr
*phlimit
= phdr
+ phnum
;
386 obj
= _rtld_obj_new();
388 for (ph
= phdr
; ph
< phlimit
; ++ph
) {
389 if (ph
->p_type
!= PT_PHDR
)
392 obj
->phdr
= (void *)(uintptr_t)ph
->p_vaddr
;
393 obj
->phsize
= ph
->p_memsz
;
394 obj
->relocbase
= (caddr_t
)((uintptr_t)phdr
- (uintptr_t)ph
->p_vaddr
);
395 dbg(("headers: phdr %p (%p) phsize %zu relocbase %p",
396 obj
->phdr
, phdr
, obj
->phsize
, obj
->relocbase
));
400 for (ph
= phdr
; ph
< phlimit
; ++ph
) {
401 vaddr
= (Elf_Addr
)(uintptr_t)(obj
->relocbase
+ ph
->p_vaddr
);
402 switch (ph
->p_type
) {
405 obj
->interp
= (const char *)(uintptr_t)vaddr
;
406 dbg(("headers: %s %p phsize %" PRImemsz
,
407 "PT_INTERP", (void *)(uintptr_t)vaddr
,
413 if (nsegs
== 0) { /* First load segment */
414 obj
->vaddrbase
= round_down(vaddr
);
415 obj
->mapbase
= (caddr_t
)(uintptr_t)obj
->vaddrbase
;
416 obj
->textsize
= round_up(vaddr
+ ph
->p_memsz
) -
418 } else { /* Last load segment */
419 obj
->mapsize
= round_up(vaddr
+ ph
->p_memsz
) -
423 dbg(("headers: %s %p phsize %" PRImemsz
,
424 "PT_LOAD", (void *)(uintptr_t)vaddr
,
429 obj
->dynamic
= (Elf_Dyn
*)(uintptr_t)vaddr
;
430 dbg(("headers: %s %p phsize %" PRImemsz
,
431 "PT_DYNAMIC", (void *)(uintptr_t)vaddr
,
435 #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
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
;
442 dbg(("headers: %s %p phsize %" PRImemsz
,
443 "PT_TLS", (void *)(uintptr_t)vaddr
,
449 obj
->exidx_start
= (void *)(uintptr_t)vaddr
;
450 obj
->exidx_sz
= ph
->p_memsz
;
451 dbg(("headers: %s %p phsize %" PRImemsz
,
452 "PT_ARM_EXIDX", (void *)(uintptr_t)vaddr
,