1 /* $NetBSD: headers.c,v 1.39 2011/01/16 01:22:29 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.39 2011/01/16 01:22:29 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
;
141 const Elf_Symindx
*hashtab
= (const Elf_Symindx
*)
142 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
144 if (hashtab
[0] > UINT32_MAX
)
145 obj
->nbuckets
= UINT32_MAX
;
147 obj
->nbuckets
= hashtab
[0];
148 obj
->nchains
= hashtab
[1];
149 obj
->buckets
= hashtab
+ 2;
150 obj
->chains
= obj
->buckets
+ obj
->nbuckets
;
152 * Should really be in _rtld_relocate_objects,
153 * but _rtld_symlook_obj might be used before.
156 fast_divide32_prepare(obj
->nbuckets
,
166 Needed_Entry
*nep
= NEW(Needed_Entry
);
168 nep
->name
= dynp
->d_un
.d_val
;
173 needed_tail
= &nep
->next
;
178 obj
->pltgot
= (Elf_Addr
*)
179 (obj
->relocbase
+ dynp
->d_un
.d_ptr
);
187 obj
->symbolic
= true;
192 * We have to wait until later to process this, because
193 * we might not have gotten the address of the string
200 /* Not used by the dynamic linker. */
204 init
= dynp
->d_un
.d_ptr
;
208 fini
= dynp
->d_un
.d_ptr
;
212 * Don't process DT_DEBUG on MIPS as the dynamic section
213 * is mapped read-only. DT_MIPS_RLD_MAP is used instead.
214 * XXX: n32/n64 may use DT_DEBUG, not sure yet.
219 dynp
->d_un
.d_ptr
= (Elf_Addr
)&_rtld_debug
;
225 case DT_MIPS_LOCAL_GOTNO
:
226 obj
->local_gotno
= dynp
->d_un
.d_val
;
229 case DT_MIPS_SYMTABNO
:
230 obj
->symtabno
= dynp
->d_un
.d_val
;
234 obj
->gotsym
= dynp
->d_un
.d_val
;
237 case DT_MIPS_RLD_MAP
:
239 *((Elf_Addr
*)(dynp
->d_un
.d_ptr
)) = (Elf_Addr
)
246 obj
->gotptr
= (Elf_Addr
*)(obj
->relocbase
+ dynp
->d_un
.d_ptr
);
251 ((dynp
->d_un
.d_val
& DF_1_BIND_NOW
) != 0);
253 ((dynp
->d_un
.d_val
& DF_1_NODELETE
) != 0);
255 ((dynp
->d_un
.d_val
& DF_1_INITFIRST
) != 0);
257 ((dynp
->d_un
.d_val
& DF_1_NOOPEN
) != 0);
262 obj
->rellim
= (const Elf_Rel
*)((const uint8_t *)obj
->rel
+ relsz
);
263 obj
->relalim
= (const Elf_Rela
*)((const uint8_t *)obj
->rela
+ relasz
);
265 obj
->pltrel
= (const Elf_Rel
*)(obj
->relocbase
+ pltrel
);
266 obj
->pltrellim
= (const Elf_Rel
*)(obj
->relocbase
+ pltrel
+ pltrelsz
);
268 /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
269 Trim rel(a)lim to save time later. */
270 if (obj
->rellim
&& obj
->pltrel
&&
271 obj
->rellim
> obj
->pltrel
&&
272 obj
->rellim
<= obj
->pltrellim
)
273 obj
->rellim
= obj
->pltrel
;
274 } else if (use_pltrela
) {
275 obj
->pltrela
= (const Elf_Rela
*)(obj
->relocbase
+ pltrel
);
277 obj
->pltrelalim
= (const Elf_Rela
*)(obj
->relocbase
+ pltrel
+ pltrelsz
);
278 /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
279 Trim rel(a)lim to save time later. */
280 if (obj
->relalim
&& obj
->pltrela
&&
281 obj
->relalim
> obj
->pltrela
&&
282 obj
->relalim
<= obj
->pltrelalim
)
283 obj
->relalim
= obj
->pltrela
;
286 #if defined(RTLD_LOADER) && defined(__HAVE_FUNCTION_DESCRIPTORS)
288 obj
->init
= (void (*)(void))
289 _rtld_function_descriptor_alloc(obj
, NULL
, init
);
291 obj
->fini
= (void (*)(void))
292 _rtld_function_descriptor_alloc(obj
, NULL
, fini
);
295 obj
->init
= (void (*)(void))
296 (obj
->relocbase
+ init
);
298 obj
->fini
= (void (*)(void))
299 (obj
->relocbase
+ fini
);
302 if (dyn_rpath
!= NULL
) {
303 _rtld_add_paths(execname
, &obj
->rpaths
, obj
->strtab
+
304 dyn_rpath
->d_un
.d_val
);
309 * Process a shared object's program header. This is used only for the
310 * main program, when the kernel has already loaded the main program
311 * into memory before calling the dynamic linker. It creates and
312 * returns an Obj_Entry structure.
315 _rtld_digest_phdr(const Elf_Phdr
*phdr
, int phnum
, caddr_t entry
)
318 const Elf_Phdr
*phlimit
= phdr
+ phnum
;
323 obj
= _rtld_obj_new();
325 for (ph
= phdr
; ph
< phlimit
; ++ph
) {
326 if (ph
->p_type
!= PT_PHDR
)
329 obj
->phdr
= (void *)(uintptr_t)phdr
->p_vaddr
;
330 obj
->phsize
= phdr
->p_memsz
;
331 obj
->relocbase
= (caddr_t
)((uintptr_t)phdr
- (uintptr_t)ph
->p_vaddr
);
332 dbg(("headers: phdr %p phsize %zu relocbase %lx", obj
->phdr
,
333 obj
->phsize
, (long)obj
->relocbase
));
336 assert(obj
->phdr
== phdr
);
338 for (ph
= phdr
; ph
< phlimit
; ++ph
) {
339 vaddr
= (Elf_Addr
)(uintptr_t)(obj
->relocbase
+ ph
->p_vaddr
);
340 switch (ph
->p_type
) {
343 obj
->interp
= (const char *)(uintptr_t)vaddr
;
348 if (nsegs
== 0) { /* First load segment */
349 obj
->vaddrbase
= round_down(vaddr
);
350 obj
->mapbase
= (caddr_t
)(uintptr_t)obj
->vaddrbase
;
351 obj
->textsize
= round_up(vaddr
+ ph
->p_memsz
) -
353 } else { /* Last load segment */
354 obj
->mapsize
= round_up(vaddr
+ ph
->p_memsz
) -
361 obj
->dynamic
= (Elf_Dyn
*)(uintptr_t)vaddr
;