headers.c revision 1.30 1 1.30 joerg /* $NetBSD: headers.c,v 1.30 2010/09/23 13:03:35 joerg 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.30 joerg __RCSID("$NetBSD: headers.c,v 1.30 2010/09/23 13:03:35 joerg 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.5 kleink case DT_HASH:
140 1.4 christos {
141 1.4 christos const Elf_Word *hashtab = (const Elf_Word *)
142 1.4 christos (obj->relocbase + dynp->d_un.d_ptr);
143 1.4 christos
144 1.29 joerg if (hashtab[0] > UINT32_MAX)
145 1.29 joerg obj->nbuckets = UINT32_MAX;
146 1.29 joerg else
147 1.29 joerg obj->nbuckets = hashtab[0];
148 1.4 christos obj->nchains = hashtab[1];
149 1.4 christos obj->buckets = hashtab + 2;
150 1.4 christos obj->chains = obj->buckets + obj->nbuckets;
151 1.29 joerg /*
152 1.29 joerg * Should really be in _rtld_relocate_objects,
153 1.29 joerg * but _rtld_symlook_obj might be used before.
154 1.29 joerg */
155 1.29 joerg if (obj->nbuckets) {
156 1.29 joerg fast_divide32_prepare(obj->nbuckets,
157 1.29 joerg &obj->nbuckets_m,
158 1.29 joerg &obj->nbuckets_s1,
159 1.29 joerg &obj->nbuckets_s2);
160 1.29 joerg }
161 1.4 christos }
162 1.4 christos break;
163 1.4 christos
164 1.5 kleink case DT_NEEDED:
165 1.4 christos {
166 1.4 christos Needed_Entry *nep = NEW(Needed_Entry);
167 1.4 christos
168 1.4 christos nep->name = dynp->d_un.d_val;
169 1.4 christos nep->obj = NULL;
170 1.4 christos nep->next = NULL;
171 1.4 christos
172 1.4 christos *needed_tail = nep;
173 1.4 christos needed_tail = &nep->next;
174 1.4 christos }
175 1.4 christos break;
176 1.4 christos
177 1.5 kleink case DT_PLTGOT:
178 1.4 christos obj->pltgot = (Elf_Addr *)
179 1.4 christos (obj->relocbase + dynp->d_un.d_ptr);
180 1.4 christos break;
181 1.4 christos
182 1.5 kleink case DT_TEXTREL:
183 1.4 christos obj->textrel = true;
184 1.4 christos break;
185 1.4 christos
186 1.5 kleink case DT_SYMBOLIC:
187 1.4 christos obj->symbolic = true;
188 1.4 christos break;
189 1.4 christos
190 1.5 kleink case DT_RPATH:
191 1.4 christos /*
192 1.4 christos * We have to wait until later to process this, because
193 1.4 christos * we might not have gotten the address of the string
194 1.4 christos * table yet.
195 1.4 christos */
196 1.4 christos dyn_rpath = dynp;
197 1.4 christos break;
198 1.4 christos
199 1.5 kleink case DT_SONAME:
200 1.4 christos /* Not used by the dynamic linker. */
201 1.4 christos break;
202 1.4 christos
203 1.5 kleink case DT_INIT:
204 1.10 fredette init = dynp->d_un.d_ptr;
205 1.4 christos break;
206 1.4 christos
207 1.5 kleink case DT_FINI:
208 1.10 fredette fini = dynp->d_un.d_ptr;
209 1.4 christos break;
210 1.1 cgd
211 1.20 simonb /*
212 1.20 simonb * Don't process DT_DEBUG on MIPS as the dynamic section
213 1.20 simonb * is mapped read-only. DT_MIPS_RLD_MAP is used instead.
214 1.20 simonb * XXX: n32/n64 may use DT_DEBUG, not sure yet.
215 1.20 simonb */
216 1.20 simonb #ifndef __mips__
217 1.5 kleink case DT_DEBUG:
218 1.1 cgd #ifdef RTLD_LOADER
219 1.4 christos dynp->d_un.d_ptr = (Elf_Addr)&_rtld_debug;
220 1.1 cgd #endif
221 1.4 christos break;
222 1.20 simonb #endif
223 1.2 mhitch
224 1.14 mycroft #ifdef __mips__
225 1.4 christos case DT_MIPS_LOCAL_GOTNO:
226 1.4 christos obj->local_gotno = dynp->d_un.d_val;
227 1.4 christos break;
228 1.4 christos
229 1.4 christos case DT_MIPS_SYMTABNO:
230 1.4 christos obj->symtabno = dynp->d_un.d_val;
231 1.4 christos break;
232 1.4 christos
233 1.4 christos case DT_MIPS_GOTSYM:
234 1.4 christos obj->gotsym = dynp->d_un.d_val;
235 1.4 christos break;
236 1.2 mhitch
237 1.4 christos case DT_MIPS_RLD_MAP:
238 1.2 mhitch #ifdef RTLD_LOADER
239 1.4 christos *((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr)
240 1.4 christos &_rtld_debug;
241 1.2 mhitch #endif
242 1.4 christos break;
243 1.2 mhitch #endif
244 1.23 ad case DT_FLAGS_1:
245 1.23 ad obj->initfirst =
246 1.23 ad ((dynp->d_un.d_val & DF_1_INITFIRST) != 0);
247 1.23 ad break;
248 1.4 christos }
249 1.1 cgd }
250 1.1 cgd
251 1.28 lukem obj->rellim = (const Elf_Rel *)((const uint8_t *)obj->rel + relsz);
252 1.28 lukem obj->relalim = (const Elf_Rela *)((const uint8_t *)obj->rela + relasz);
253 1.30 joerg if (use_pltrel) {
254 1.13 mycroft obj->pltrel = (const Elf_Rel *)(obj->relocbase + pltrel);
255 1.13 mycroft obj->pltrellim = (const Elf_Rel *)(obj->relocbase + pltrel + pltrelsz);
256 1.13 mycroft obj->pltrelalim = 0;
257 1.13 mycroft /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
258 1.13 mycroft Trim rel(a)lim to save time later. */
259 1.13 mycroft if (obj->rellim && obj->pltrel &&
260 1.13 mycroft obj->rellim > obj->pltrel &&
261 1.13 mycroft obj->rellim <= obj->pltrellim)
262 1.11 mycroft obj->rellim = obj->pltrel;
263 1.30 joerg } else if (use_pltrela) {
264 1.13 mycroft obj->pltrela = (const Elf_Rela *)(obj->relocbase + pltrel);
265 1.13 mycroft obj->pltrellim = 0;
266 1.13 mycroft obj->pltrelalim = (const Elf_Rela *)(obj->relocbase + pltrel + pltrelsz);
267 1.13 mycroft /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
268 1.13 mycroft Trim rel(a)lim to save time later. */
269 1.13 mycroft if (obj->relalim && obj->pltrela &&
270 1.13 mycroft obj->relalim > obj->pltrela &&
271 1.13 mycroft obj->relalim <= obj->pltrelalim)
272 1.11 mycroft obj->relalim = obj->pltrela;
273 1.8 mycroft }
274 1.10 fredette
275 1.10 fredette #if defined(RTLD_LOADER) && defined(__HAVE_FUNCTION_DESCRIPTORS)
276 1.10 fredette if (init != 0)
277 1.18 skrll obj->init = (void (*)(void))
278 1.10 fredette _rtld_function_descriptor_alloc(obj, NULL, init);
279 1.10 fredette if (fini != 0)
280 1.18 skrll obj->fini = (void (*)(void))
281 1.10 fredette _rtld_function_descriptor_alloc(obj, NULL, fini);
282 1.10 fredette #else
283 1.10 fredette if (init != 0)
284 1.18 skrll obj->init = (void (*)(void))
285 1.10 fredette (obj->relocbase + init);
286 1.10 fredette if (fini != 0)
287 1.18 skrll obj->fini = (void (*)(void))
288 1.10 fredette (obj->relocbase + fini);
289 1.10 fredette #endif
290 1.4 christos
291 1.4 christos if (dyn_rpath != NULL) {
292 1.22 christos _rtld_add_paths(execname, &obj->rpaths, obj->strtab +
293 1.12 mycroft dyn_rpath->d_un.d_val);
294 1.4 christos }
295 1.1 cgd }
296 1.1 cgd
297 1.1 cgd /*
298 1.1 cgd * Process a shared object's program header. This is used only for the
299 1.1 cgd * main program, when the kernel has already loaded the main program
300 1.1 cgd * into memory before calling the dynamic linker. It creates and
301 1.1 cgd * returns an Obj_Entry structure.
302 1.1 cgd */
303 1.1 cgd Obj_Entry *
304 1.18 skrll _rtld_digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry)
305 1.1 cgd {
306 1.6 mycroft Obj_Entry *obj;
307 1.4 christos const Elf_Phdr *phlimit = phdr + phnum;
308 1.4 christos const Elf_Phdr *ph;
309 1.4 christos int nsegs = 0;
310 1.24 christos ptrdiff_t relocoffs = 0;
311 1.24 christos Elf_Addr vaddr;
312 1.4 christos
313 1.6 mycroft obj = _rtld_obj_new();
314 1.4 christos for (ph = phdr; ph < phlimit; ++ph) {
315 1.24 christos vaddr = ph->p_vaddr + relocoffs;
316 1.24 christos dbg(("headers: relocoffs = %lx\n", (long)relocoffs));
317 1.4 christos switch (ph->p_type) {
318 1.4 christos
319 1.5 kleink case PT_PHDR:
320 1.27 mrg relocoffs = (uintptr_t)phdr - (uintptr_t)ph->p_vaddr;
321 1.6 mycroft break;
322 1.6 mycroft
323 1.6 mycroft case PT_INTERP:
324 1.27 mrg obj->interp = (const char *)(uintptr_t)vaddr;
325 1.4 christos break;
326 1.4 christos
327 1.5 kleink case PT_LOAD:
328 1.4 christos assert(nsegs < 2);
329 1.4 christos if (nsegs == 0) { /* First load segment */
330 1.24 christos obj->vaddrbase = round_down(vaddr);
331 1.27 mrg obj->mapbase = (caddr_t)(uintptr_t)obj->vaddrbase;
332 1.26 christos obj->relocbase = (void *)relocoffs;
333 1.24 christos obj->textsize = round_up(vaddr + ph->p_memsz) -
334 1.24 christos obj->vaddrbase;
335 1.4 christos } else { /* Last load segment */
336 1.24 christos obj->mapsize = round_up(vaddr + ph->p_memsz) -
337 1.24 christos obj->vaddrbase;
338 1.4 christos }
339 1.4 christos ++nsegs;
340 1.4 christos break;
341 1.4 christos
342 1.5 kleink case PT_DYNAMIC:
343 1.27 mrg obj->dynamic = (Elf_Dyn *)(uintptr_t)vaddr;
344 1.4 christos break;
345 1.4 christos }
346 1.1 cgd }
347 1.4 christos assert(nsegs == 2);
348 1.1 cgd
349 1.4 christos obj->entry = entry;
350 1.4 christos return obj;
351 1.1 cgd }
352