1 /* $NetBSD: loadfile_elf32.c,v 1.9 2003/10/23 15:06:26 he Exp $ */
2
3 /*-
4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center and by Christos Zoulas.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 /* If not included by exec_elf64.c, ELFSIZE won't be defined. */
41 #ifndef ELFSIZE
42 #define ELFSIZE 32
43 #endif
44
45 #ifdef _STANDALONE
46 #include <lib/libsa/stand.h>
47 #include <lib/libkern/libkern.h>
48 #else
49 #include <stdio.h>
50 #include <string.h>
51 #include <errno.h>
52 #include <stdlib.h>
53 #include <unistd.h>
54 #include <fcntl.h>
55 #include <err.h>
56 #endif
57
58 #include <sys/param.h>
59 #include <sys/exec.h>
60
61 #include "loadfile.h"
62
63 #if ((ELFSIZE == 32) && defined(BOOT_ELF32)) || \
64 ((ELFSIZE == 64) && defined(BOOT_ELF64))
65
66 #define ELFROUND (ELFSIZE / 8)
67
68 #ifndef _STANDALONE
69 #include "byteorder.h"
70
71 /*
72 * Byte swapping may be necessary in the non-_STANDLONE case because
73 * we may be built with a host compiler.
74 */
75 #define E16(f) \
76 f = (bo == ELFDATA2LSB) ? sa_htole16(f) : sa_htobe16(f)
77 #define E32(f) \
78 f = (bo == ELFDATA2LSB) ? sa_htole32(f) : sa_htobe32(f)
79 #define E64(f) \
80 f = (bo == ELFDATA2LSB) ? sa_htole64(f) : sa_htobe64(f)
81
82 #define I16(f) \
83 f = (bo == ELFDATA2LSB) ? sa_le16toh(f) : sa_be16toh(f)
84 #define I32(f) \
85 f = (bo == ELFDATA2LSB) ? sa_le32toh(f) : sa_be32toh(f)
86 #define I64(f) \
87 f = (bo == ELFDATA2LSB) ? sa_le64toh(f) : sa_be64toh(f)
88
89 static void
90 internalize_ehdr(Elf_Byte bo, Elf_Ehdr *ehdr)
91 {
92
93 #if ELFSIZE == 32
94 I16(ehdr->e_type);
95 I16(ehdr->e_machine);
96 I32(ehdr->e_version);
97 I32(ehdr->e_entry);
98 I32(ehdr->e_phoff);
99 I32(ehdr->e_shoff);
100 I32(ehdr->e_flags);
101 I16(ehdr->e_ehsize);
102 I16(ehdr->e_phentsize);
103 I16(ehdr->e_phnum);
104 I16(ehdr->e_shentsize);
105 I16(ehdr->e_shnum);
106 I16(ehdr->e_shstrndx);
107 #elif ELFSIZE == 64
108 I16(ehdr->e_type);
109 I16(ehdr->e_machine);
110 I32(ehdr->e_version);
111 I64(ehdr->e_entry);
112 I64(ehdr->e_phoff);
113 I64(ehdr->e_shoff);
114 I32(ehdr->e_flags);
115 I16(ehdr->e_ehsize);
116 I16(ehdr->e_phentsize);
117 I16(ehdr->e_phnum);
118 I16(ehdr->e_shentsize);
119 I16(ehdr->e_shnum);
120 I16(ehdr->e_shstrndx);
121 #else
122 #error ELFSIZE is not 32 or 64
123 #endif
124 }
125
126 static void
127 externalize_ehdr(Elf_Byte bo, Elf_Ehdr *ehdr)
128 {
129
130 #if ELFSIZE == 32
131 E16(ehdr->e_type);
132 E16(ehdr->e_machine);
133 E32(ehdr->e_version);
134 E32(ehdr->e_entry);
135 E32(ehdr->e_phoff);
136 E32(ehdr->e_shoff);
137 E32(ehdr->e_flags);
138 E16(ehdr->e_ehsize);
139 E16(ehdr->e_phentsize);
140 E16(ehdr->e_phnum);
141 E16(ehdr->e_shentsize);
142 E16(ehdr->e_shnum);
143 E16(ehdr->e_shstrndx);
144 #elif ELFSIZE == 64
145 E16(ehdr->e_type);
146 E16(ehdr->e_machine);
147 E32(ehdr->e_version);
148 E64(ehdr->e_entry);
149 E64(ehdr->e_phoff);
150 E64(ehdr->e_shoff);
151 E32(ehdr->e_flags);
152 E16(ehdr->e_ehsize);
153 E16(ehdr->e_phentsize);
154 E16(ehdr->e_phnum);
155 E16(ehdr->e_shentsize);
156 E16(ehdr->e_shnum);
157 E16(ehdr->e_shstrndx);
158 #else
159 #error ELFSIZE is not 32 or 64
160 #endif
161 }
162
163 static void
164 internalize_phdr(Elf_Byte bo, Elf_Phdr *phdr)
165 {
166
167 #if ELFSIZE == 32
168 I32(phdr->p_type);
169 I32(phdr->p_offset);
170 I32(phdr->p_vaddr);
171 I32(phdr->p_paddr);
172 I32(phdr->p_filesz);
173 I32(phdr->p_memsz);
174 I32(phdr->p_flags);
175 I32(phdr->p_align);
176 #elif ELFSIZE == 64
177 I32(phdr->p_type);
178 I32(phdr->p_offset);
179 I64(phdr->p_vaddr);
180 I64(phdr->p_paddr);
181 I64(phdr->p_filesz);
182 I64(phdr->p_memsz);
183 I64(phdr->p_flags);
184 I64(phdr->p_align);
185 #else
186 #error ELFSIZE is not 32 or 64
187 #endif
188 }
189
190 static void
191 internalize_shdr(Elf_Byte bo, Elf_Shdr *shdr)
192 {
193
194 #if ELFSIZE == 32
195 I32(shdr->sh_name);
196 I32(shdr->sh_type);
197 I32(shdr->sh_flags);
198 I32(shdr->sh_addr);
199 I32(shdr->sh_offset);
200 I32(shdr->sh_size);
201 I32(shdr->sh_link);
202 I32(shdr->sh_info);
203 I32(shdr->sh_addralign);
204 I32(shdr->sh_entsize);
205 #elif ELFSIZE == 64
206 I32(shdr->sh_name);
207 I32(shdr->sh_type);
208 I64(shdr->sh_flags);
209 I64(shdr->sh_addr);
210 I64(shdr->sh_offset);
211 I64(shdr->sh_size);
212 I32(shdr->sh_link);
213 I32(shdr->sh_info);
214 I64(shdr->sh_addralign);
215 I64(shdr->sh_entsize);
216 #else
217 #error ELFSIZE is not 32 or 64
218 #endif
219 }
220
221 static void
222 externalize_shdr(Elf_Byte bo, Elf_Shdr *shdr)
223 {
224
225 #if ELFSIZE == 32
226 E32(shdr->sh_name);
227 E32(shdr->sh_type);
228 E32(shdr->sh_flags);
229 E32(shdr->sh_addr);
230 E32(shdr->sh_offset);
231 E32(shdr->sh_size);
232 E32(shdr->sh_link);
233 E32(shdr->sh_info);
234 E32(shdr->sh_addralign);
235 E32(shdr->sh_entsize);
236 #elif ELFSIZE == 64
237 E32(shdr->sh_name);
238 E32(shdr->sh_type);
239 E64(shdr->sh_flags);
240 E64(shdr->sh_addr);
241 E64(shdr->sh_offset);
242 E64(shdr->sh_size);
243 E32(shdr->sh_link);
244 E32(shdr->sh_info);
245 E64(shdr->sh_addralign);
246 E64(shdr->sh_entsize);
247 #else
248 #error ELFSIZE is not 32 or 64
249 #endif
250 }
251 #else /* _STANDALONE */
252 /*
253 * Byte swapping is never necessary in the _STANDALONE case because
254 * we are being built with the target compiler.
255 */
256 #define internalize_ehdr(bo, ehdr) /* nothing */
257 #define externalize_ehdr(bo, ehdr) /* nothing */
258
259 #define internalize_phdr(bo, phdr) /* nothing */
260
261 #define internalize_shdr(bo, shdr) /* nothing */
262 #define externalize_shdr(bo, shdr) /* nothing */
263 #endif /* _STANDALONE */
264
265 int
266 ELFNAMEEND(loadfile)(fd, elf, marks, flags)
267 int fd;
268 Elf_Ehdr *elf;
269 u_long *marks;
270 int flags;
271 {
272 Elf_Shdr *shp;
273 Elf_Phdr *phdr;
274 int i, j;
275 ssize_t sz;
276 int first;
277 paddr_t minp = ~0, maxp = 0, pos = 0;
278 paddr_t offset = marks[MARK_START], shpp, elfp = 0;
279
280 /* some ports dont use the offset */
281 offset = offset;
282
283 internalize_ehdr(elf->e_ident[EI_DATA], elf);
284
285 sz = elf->e_phnum * sizeof(Elf_Phdr);
286 phdr = ALLOC(sz);
287
288 if (lseek(fd, elf->e_phoff, SEEK_SET) == -1) {
289 WARN(("lseek phdr"));
290 FREE(phdr, sz);
291 return 1;
292 }
293 if (read(fd, phdr, sz) != sz) {
294 WARN(("read program headers"));
295 FREE(phdr, sz);
296 return 1;
297 }
298
299 for (first = 1, i = 0; i < elf->e_phnum; i++) {
300 internalize_phdr(elf->e_ident[EI_DATA], &phdr[i]);
301 if (phdr[i].p_type != PT_LOAD ||
302 (phdr[i].p_flags & (PF_W|PF_X)) == 0)
303 continue;
304
305 #define IS_TEXT(p) (p.p_flags & PF_X)
306 #define IS_DATA(p) (p.p_flags & PF_W)
307 #define IS_BSS(p) (p.p_filesz < p.p_memsz)
308 /*
309 * XXX: Assume first address is lowest
310 */
311 if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) ||
312 (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) {
313
314 /* Read in segment. */
315 PROGRESS(("%s%lu", first ? "" : "+",
316 (u_long)phdr[i].p_filesz));
317
318 if (lseek(fd, phdr[i].p_offset, SEEK_SET) == -1) {
319 WARN(("lseek text"));
320 FREE(phdr, sz);
321 return 1;
322 }
323 if (READ(fd, phdr[i].p_vaddr, phdr[i].p_filesz) !=
324 (ssize_t)phdr[i].p_filesz) {
325 WARN(("read text"));
326 FREE(phdr, sz);
327 return 1;
328 }
329 first = 0;
330
331 }
332 if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT|COUNT_TEXT))) ||
333 (IS_DATA(phdr[i]) && (flags & (LOAD_DATA|COUNT_TEXT)))) {
334 pos = phdr[i].p_vaddr;
335 if (minp > pos)
336 minp = pos;
337 pos += phdr[i].p_filesz;
338 if (maxp < pos)
339 maxp = pos;
340 }
341
342 /* Zero out bss. */
343 if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) {
344 PROGRESS(("+%lu",
345 (u_long)(phdr[i].p_memsz - phdr[i].p_filesz)));
346 BZERO((phdr[i].p_vaddr + phdr[i].p_filesz),
347 phdr[i].p_memsz - phdr[i].p_filesz);
348 }
349 if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) {
350 pos += phdr[i].p_memsz - phdr[i].p_filesz;
351 if (maxp < pos)
352 maxp = pos;
353 }
354 }
355 FREE(phdr, sz);
356
357 /*
358 * Copy the ELF and section headers.
359 */
360 maxp = roundup(maxp, ELFROUND);
361 if (flags & (LOAD_HDR|COUNT_HDR)) {
362 elfp = maxp;
363 maxp += sizeof(Elf_Ehdr);
364 }
365
366 if (flags & (LOAD_SYM|COUNT_SYM)) {
367 if (lseek(fd, elf->e_shoff, SEEK_SET) == -1) {
368 WARN(("lseek section headers"));
369 return 1;
370 }
371 sz = elf->e_shnum * sizeof(Elf_Shdr);
372
373 shp = ALLOC(sz);
374
375 if (read(fd, shp, sz) != sz) {
376 WARN(("read section headers"));
377 return 1;
378 }
379
380 shpp = maxp;
381 maxp += roundup(sz, ELFROUND);
382
383 #ifndef _STANDALONE
384 /* Internalize the section headers. */
385 for (i = 0; i < elf->e_shnum; i++)
386 internalize_shdr(elf->e_ident[EI_DATA], &shp[i]);
387 #endif /* ! _STANDALONE */
388
389 /*
390 * Now load the symbol sections themselves. Make sure
391 * the sections are aligned. Don't bother with any
392 * string table that isn't referenced by a symbol
393 * table.
394 */
395 for (first = 1, i = 0; i < elf->e_shnum; i++) {
396 switch (shp[i].sh_type) {
397 case SHT_STRTAB:
398 for (j = 0; j < elf->e_shnum; j++)
399 if (shp[j].sh_type == SHT_SYMTAB &&
400 shp[j].sh_link == (unsigned)i)
401 goto havesym;
402 /* FALLTHROUGH */
403 default:
404 /* Not loading this, so zero out the offset. */
405 shp[i].sh_offset = 0;
406 break;
407 havesym:
408 case SHT_SYMTAB:
409 if (flags & LOAD_SYM) {
410 PROGRESS(("%s%ld", first ? " [" : "+",
411 (u_long)shp[i].sh_size));
412 if (lseek(fd, shp[i].sh_offset,
413 SEEK_SET) == -1) {
414 WARN(("lseek symbols"));
415 FREE(shp, sz);
416 return 1;
417 }
418 if (READ(fd, maxp, shp[i].sh_size) !=
419 (ssize_t)shp[i].sh_size) {
420 WARN(("read symbols"));
421 FREE(shp, sz);
422 return 1;
423 }
424 }
425 shp[i].sh_offset = maxp - elfp;
426 maxp += roundup(shp[i].sh_size, ELFROUND);
427 first = 0;
428 }
429 /* Since we don't load .shstrtab, zero the name. */
430 shp[i].sh_name = 0;
431 }
432 if (flags & LOAD_SYM) {
433 #ifndef _STANDALONE
434 /* Externalize the section headers. */
435 for (i = 0; i < elf->e_shnum; i++)
436 externalize_shdr(elf->e_ident[EI_DATA],
437 &shp[i]);
438 #endif /* ! _STANDALONE */
439 BCOPY(shp, shpp, sz);
440
441 if (first == 0)
442 PROGRESS(("]"));
443 }
444 FREE(shp, sz);
445 }
446
447 /*
448 * Frob the copied ELF header to give information relative
449 * to elfp.
450 */
451 if (flags & LOAD_HDR) {
452 elf->e_phoff = 0;
453 elf->e_shoff = sizeof(Elf_Ehdr);
454 elf->e_phentsize = 0;
455 elf->e_phnum = 0;
456 elf->e_shstrndx = SHN_UNDEF;
457 externalize_ehdr(elf->e_ident[EI_DATA], elf);
458 BCOPY(elf, elfp, sizeof(*elf));
459 internalize_ehdr(elf->e_ident[EI_DATA], elf);
460 }
461
462 marks[MARK_START] = LOADADDR(minp);
463 marks[MARK_ENTRY] = LOADADDR(elf->e_entry);
464 /*
465 * Since there can be more than one symbol section in the code
466 * and we need to find strtab too in order to do anything
467 * useful with the symbols, we just pass the whole elf
468 * header back and we let the kernel debugger find the
469 * location and number of symbols by itself.
470 */
471 marks[MARK_NSYM] = 1; /* XXX: Kernel needs >= 0 */
472 marks[MARK_SYM] = LOADADDR(elfp);
473 marks[MARK_END] = LOADADDR(maxp);
474 return 0;
475 }
476
477 #endif /* (ELFSIZE == 32 && BOOT_ELF32) || (ELFSIZE == 64 && BOOT_ELF64) */
Cache object: b523e52491cee76d7b81e53aacebeca4
|