1 /* $NetBSD: headers.c,v 1.43 2012/08/15 03:46:06 matt 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.43 2012/08/15 03:46:06 matt 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_rpath
= NULL
;
72 bool use_pltrel
= false;
73 bool use_pltrela
= false;
74 Elf_Addr relsz
= 0, relasz
= 0;
75 Elf_Addr pltrel
= 0, pltrelsz
= 0;
76 Elf_Addr init
= 0, fini
= 0;
78 for (dynp
= obj
->dynamic
; dynp
->d_tag
!= DT_NULL
; ++dynp
) {
79 switch (dynp
->d_tag
) {
82 obj
->rel
= (const Elf_Rel
*)
83 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
87 relsz
= dynp
->d_un
.d_val
;
91 assert(dynp
->d_un
.d_val
== sizeof(Elf_Rel
));
95 pltrel
= dynp
->d_un
.d_ptr
;
99 pltrelsz
= dynp
->d_un
.d_val
;
103 obj
->rela
= (const Elf_Rela
*)
104 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
108 relasz
= dynp
->d_un
.d_val
;
112 assert(dynp
->d_un
.d_val
== sizeof(Elf_Rela
));
116 use_pltrel
= dynp
->d_un
.d_val
== DT_REL
;
117 use_pltrela
= dynp
->d_un
.d_val
== DT_RELA
;
118 assert(use_pltrel
|| use_pltrela
);
122 obj
->symtab
= (const Elf_Sym
*)
123 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
127 assert(dynp
->d_un
.d_val
== sizeof(Elf_Sym
));
131 obj
->strtab
= (const char *)
132 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
136 obj
->strsize
= dynp
->d_un
.d_val
;
140 obj
->verneed
= (const Elf_Verneed
*)
141 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
145 obj
->verneednum
= dynp
->d_un
.d_val
;
149 obj
->verdef
= (const Elf_Verdef
*)
150 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
154 obj
->verdefnum
= dynp
->d_un
.d_val
;
158 obj
->versyms
= (const Elf_Versym
*)
159 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
164 const Elf_Symindx
*hashtab
= (const Elf_Symindx
*)
165 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
167 if (hashtab
[0] > UINT32_MAX
)
168 obj
->nbuckets
= UINT32_MAX
;
170 obj
->nbuckets
= hashtab
[0];
171 obj
->nchains
= hashtab
[1];
172 obj
->buckets
= hashtab
+ 2;
173 obj
->chains
= obj
->buckets
+ obj
->nbuckets
;
175 * Should really be in _rtld_relocate_objects,
176 * but _rtld_symlook_obj might be used before.
179 fast_divide32_prepare(obj
->nbuckets
,
189 Needed_Entry
*nep
= NEW(Needed_Entry
);
191 nep
->name
= dynp
->d_un
.d_val
;
196 needed_tail
= &nep
->next
;
201 obj
->pltgot
= (Elf_Addr
*)
202 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
210 obj
->symbolic
= true;
215 * We have to wait until later to process this, because
216 * we might not have gotten the address of the string
223 /* Not used by the dynamic linker. */
227 init
= dynp
->d_un
.d_ptr
;
230 #ifdef HAVE_INITFINI_ARRAY
233 (fptr_t
*)(obj
->relocbase
+ dynp
->d_un
.d_ptr
);
236 case DT_INIT_ARRAYSZ
:
237 obj
->init_arraysz
= dynp
->d_un
.d_val
/ sizeof(fptr_t
);
242 fini
= dynp
->d_un
.d_ptr
;
245 #ifdef HAVE_INITFINI_ARRAY
248 (fptr_t
*)(obj
->relocbase
+ dynp
->d_un
.d_ptr
);
251 case DT_FINI_ARRAYSZ
:
252 obj
->fini_arraysz
= dynp
->d_un
.d_val
/ sizeof(fptr_t
);
257 * Don't process DT_DEBUG on MIPS as the dynamic section
258 * is mapped read-only. DT_MIPS_RLD_MAP is used instead.
259 * XXX: n32/n64 may use DT_DEBUG, not sure yet.
264 dynp
->d_un
.d_ptr
= (Elf_Addr
)&_rtld_debug
;
270 case DT_MIPS_LOCAL_GOTNO
:
271 obj
->local_gotno
= dynp
->d_un
.d_val
;
274 case DT_MIPS_SYMTABNO
:
275 obj
->symtabno
= dynp
->d_un
.d_val
;
279 obj
->gotsym
= dynp
->d_un
.d_val
;
282 case DT_MIPS_RLD_MAP
:
284 *((Elf_Addr
*)(dynp
->d_un
.d_ptr
)) = (Elf_Addr
)
291 obj
->gotptr
= (Elf_Addr
*)(obj
->relocbase
+ dynp
->d_un
.d_ptr
);
296 ((dynp
->d_un
.d_val
& DF_1_BIND_NOW
) != 0);
298 ((dynp
->d_un
.d_val
& DF_1_NODELETE
) != 0);
300 ((dynp
->d_un
.d_val
& DF_1_INITFIRST
) != 0);
302 ((dynp
->d_un
.d_val
& DF_1_NOOPEN
) != 0);
307 obj
->rellim
= (const Elf_Rel
*)((const uint8_t *)obj
->rel
+ relsz
);
308 obj
->relalim
= (const Elf_Rela
*)((const uint8_t *)obj
->rela
+ relasz
);
310 obj
->pltrel
= (const Elf_Rel
*)(obj
->relocbase
+ pltrel
);
311 obj
->pltrellim
= (const Elf_Rel
*)(obj
->relocbase
+ pltrel
+ pltrelsz
);
313 /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
314 Trim rel(a)lim to save time later. */
315 if (obj
->rellim
&& obj
->pltrel
&&
316 obj
->rellim
> obj
->pltrel
&&
317 obj
->rellim
<= obj
->pltrellim
)
318 obj
->rellim
= obj
->pltrel
;
319 } else if (use_pltrela
) {
320 obj
->pltrela
= (const Elf_Rela
*)(obj
->relocbase
+ pltrel
);
322 obj
->pltrelalim
= (const Elf_Rela
*)(obj
->relocbase
+ pltrel
+ pltrelsz
);
323 /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
324 Trim rel(a)lim to save time later. */
325 if (obj
->relalim
&& obj
->pltrela
&&
326 obj
->relalim
> obj
->pltrela
&&
327 obj
->relalim
<= obj
->pltrelalim
)
328 obj
->relalim
= obj
->pltrela
;
331 #if defined(RTLD_LOADER) && defined(__HAVE_FUNCTION_DESCRIPTORS)
333 obj
->init
= (void (*)(void))
334 _rtld_function_descriptor_alloc(obj
, NULL
, init
);
336 obj
->fini
= (void (*)(void))
337 _rtld_function_descriptor_alloc(obj
, NULL
, fini
);
340 obj
->init
= (void (*)(void))
341 (obj
->relocbase
+ init
);
343 obj
->fini
= (void (*)(void))
344 (obj
->relocbase
+ fini
);
347 if (dyn_rpath
!= NULL
) {
348 _rtld_add_paths(execname
, &obj
->rpaths
, obj
->strtab
+
349 dyn_rpath
->d_un
.d_val
);
354 * Process a shared object's program header. This is used only for the
355 * main program, when the kernel has already loaded the main program
356 * into memory before calling the dynamic linker. It creates and
357 * returns an Obj_Entry structure.
360 _rtld_digest_phdr(const Elf_Phdr
*phdr
, int phnum
, caddr_t entry
)
363 const Elf_Phdr
*phlimit
= phdr
+ phnum
;
368 obj
= _rtld_obj_new();
370 for (ph
= phdr
; ph
< phlimit
; ++ph
) {
371 if (ph
->p_type
!= PT_PHDR
)
374 obj
->phdr
= (void *)(uintptr_t)phdr
->p_vaddr
;
375 obj
->phsize
= phdr
->p_memsz
;
376 obj
->relocbase
= (caddr_t
)((uintptr_t)phdr
- (uintptr_t)ph
->p_vaddr
);
377 dbg(("headers: phdr %p phsize %zu relocbase %lx", obj
->phdr
,
378 obj
->phsize
, (long)obj
->relocbase
));
382 for (ph
= phdr
; ph
< phlimit
; ++ph
) {
383 vaddr
= (Elf_Addr
)(uintptr_t)(obj
->relocbase
+ ph
->p_vaddr
);
384 switch (ph
->p_type
) {
387 obj
->interp
= (const char *)(uintptr_t)vaddr
;
392 if (nsegs
== 0) { /* First load segment */
393 obj
->vaddrbase
= round_down(vaddr
);
394 obj
->mapbase
= (caddr_t
)(uintptr_t)obj
->vaddrbase
;
395 obj
->textsize
= round_up(vaddr
+ ph
->p_memsz
) -
397 } else { /* Last load segment */
398 obj
->mapsize
= round_up(vaddr
+ ph
->p_memsz
) -
405 obj
->dynamic
= (Elf_Dyn
*)(uintptr_t)vaddr
;
408 #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
411 obj
->tlssize
= ph
->p_memsz
;
412 obj
->tlsalign
= ph
->p_align
;
413 obj
->tlsinitsize
= ph
->p_filesz
;
414 obj
->tlsinit
= (void *)(uintptr_t)ph
->p_vaddr
;