xref: /netbsd-src/sys/lib/libsa/loadfile_elf32.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /* $NetBSD: loadfile_elf32.c,v 1.52 2017/12/21 14:28:39 maxv Exp $ */
2 
3 /*
4  * Copyright (c) 1997, 2008, 2017 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, by Christos Zoulas, and by Maxime Villard.
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  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /* If not included by exec_elf64.c, ELFSIZE won't be defined. */
34 #ifndef ELFSIZE
35 #define	ELFSIZE	32
36 #endif
37 
38 #ifdef _STANDALONE
39 #include <lib/libsa/stand.h>
40 #include <lib/libkern/libkern.h>
41 #else
42 #include <stdio.h>
43 #include <string.h>
44 #include <errno.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <fcntl.h>
48 #include <err.h>
49 #endif
50 
51 #include <sys/param.h>
52 #include <sys/exec.h>
53 
54 #include "loadfile.h"
55 
56 #if ((ELFSIZE == 32) && defined(BOOT_ELF32)) || \
57     ((ELFSIZE == 64) && defined(BOOT_ELF64))
58 
59 #define	ELFROUND	(ELFSIZE / 8)
60 
61 #ifndef _STANDALONE
62 #include "byteorder.h"
63 
64 /*
65  * Byte swapping may be necessary in the non-_STANDLONE case because
66  * we may be built with a host compiler.
67  */
68 #define	E16(f)								\
69 	f = (bo == ELFDATA2LSB) ? sa_htole16(f) : sa_htobe16(f)
70 #define	E32(f)								\
71 	f = (bo == ELFDATA2LSB) ? sa_htole32(f) : sa_htobe32(f)
72 #define	E64(f)								\
73 	f = (bo == ELFDATA2LSB) ? sa_htole64(f) : sa_htobe64(f)
74 
75 #define	I16(f)								\
76 	f = (bo == ELFDATA2LSB) ? sa_le16toh(f) : sa_be16toh(f)
77 #define	I32(f)								\
78 	f = (bo == ELFDATA2LSB) ? sa_le32toh(f) : sa_be32toh(f)
79 #define	I64(f)								\
80 	f = (bo == ELFDATA2LSB) ? sa_le64toh(f) : sa_be64toh(f)
81 
82 static void
83 internalize_ehdr(Elf_Byte bo, Elf_Ehdr *ehdr)
84 {
85 
86 #if ELFSIZE == 32
87 	I16(ehdr->e_type);
88 	I16(ehdr->e_machine);
89 	I32(ehdr->e_version);
90 	I32(ehdr->e_entry);
91 	I32(ehdr->e_phoff);
92 	I32(ehdr->e_shoff);
93 	I32(ehdr->e_flags);
94 	I16(ehdr->e_ehsize);
95 	I16(ehdr->e_phentsize);
96 	I16(ehdr->e_phnum);
97 	I16(ehdr->e_shentsize);
98 	I16(ehdr->e_shnum);
99 	I16(ehdr->e_shstrndx);
100 #elif ELFSIZE == 64
101 	I16(ehdr->e_type);
102 	I16(ehdr->e_machine);
103 	I32(ehdr->e_version);
104 	I64(ehdr->e_entry);
105 	I64(ehdr->e_phoff);
106 	I64(ehdr->e_shoff);
107 	I32(ehdr->e_flags);
108 	I16(ehdr->e_ehsize);
109 	I16(ehdr->e_phentsize);
110 	I16(ehdr->e_phnum);
111 	I16(ehdr->e_shentsize);
112 	I16(ehdr->e_shnum);
113 	I16(ehdr->e_shstrndx);
114 #else
115 #error ELFSIZE is not 32 or 64
116 #endif
117 }
118 
119 static void
120 externalize_ehdr(Elf_Byte bo, Elf_Ehdr *ehdr)
121 {
122 
123 #if ELFSIZE == 32
124 	E16(ehdr->e_type);
125 	E16(ehdr->e_machine);
126 	E32(ehdr->e_version);
127 	E32(ehdr->e_entry);
128 	E32(ehdr->e_phoff);
129 	E32(ehdr->e_shoff);
130 	E32(ehdr->e_flags);
131 	E16(ehdr->e_ehsize);
132 	E16(ehdr->e_phentsize);
133 	E16(ehdr->e_phnum);
134 	E16(ehdr->e_shentsize);
135 	E16(ehdr->e_shnum);
136 	E16(ehdr->e_shstrndx);
137 #elif ELFSIZE == 64
138 	E16(ehdr->e_type);
139 	E16(ehdr->e_machine);
140 	E32(ehdr->e_version);
141 	E64(ehdr->e_entry);
142 	E64(ehdr->e_phoff);
143 	E64(ehdr->e_shoff);
144 	E32(ehdr->e_flags);
145 	E16(ehdr->e_ehsize);
146 	E16(ehdr->e_phentsize);
147 	E16(ehdr->e_phnum);
148 	E16(ehdr->e_shentsize);
149 	E16(ehdr->e_shnum);
150 	E16(ehdr->e_shstrndx);
151 #else
152 #error ELFSIZE is not 32 or 64
153 #endif
154 }
155 
156 static void
157 internalize_phdr(Elf_Byte bo, Elf_Phdr *phdr)
158 {
159 
160 #if ELFSIZE == 32
161 	I32(phdr->p_type);
162 	I32(phdr->p_offset);
163 	I32(phdr->p_vaddr);
164 	I32(phdr->p_paddr);
165 	I32(phdr->p_filesz);
166 	I32(phdr->p_memsz);
167 	I32(phdr->p_flags);
168 	I32(phdr->p_align);
169 #elif ELFSIZE == 64
170 	I32(phdr->p_type);
171 	I32(phdr->p_offset);
172 	I64(phdr->p_vaddr);
173 	I64(phdr->p_paddr);
174 	I64(phdr->p_filesz);
175 	I64(phdr->p_memsz);
176 	I64(phdr->p_flags);
177 	I64(phdr->p_align);
178 #else
179 #error ELFSIZE is not 32 or 64
180 #endif
181 }
182 
183 static void
184 internalize_shdr(Elf_Byte bo, Elf_Shdr *shdr)
185 {
186 
187 #if ELFSIZE == 32
188 	I32(shdr->sh_name);
189 	I32(shdr->sh_type);
190 	I32(shdr->sh_flags);
191 	I32(shdr->sh_addr);
192 	I32(shdr->sh_offset);
193 	I32(shdr->sh_size);
194 	I32(shdr->sh_link);
195 	I32(shdr->sh_info);
196 	I32(shdr->sh_addralign);
197 	I32(shdr->sh_entsize);
198 #elif ELFSIZE == 64
199 	I32(shdr->sh_name);
200 	I32(shdr->sh_type);
201 	I64(shdr->sh_flags);
202 	I64(shdr->sh_addr);
203 	I64(shdr->sh_offset);
204 	I64(shdr->sh_size);
205 	I32(shdr->sh_link);
206 	I32(shdr->sh_info);
207 	I64(shdr->sh_addralign);
208 	I64(shdr->sh_entsize);
209 #else
210 #error ELFSIZE is not 32 or 64
211 #endif
212 }
213 
214 static void
215 externalize_shdr(Elf_Byte bo, Elf_Shdr *shdr)
216 {
217 
218 #if ELFSIZE == 32
219 	E32(shdr->sh_name);
220 	E32(shdr->sh_type);
221 	E32(shdr->sh_flags);
222 	E32(shdr->sh_addr);
223 	E32(shdr->sh_offset);
224 	E32(shdr->sh_size);
225 	E32(shdr->sh_link);
226 	E32(shdr->sh_info);
227 	E32(shdr->sh_addralign);
228 	E32(shdr->sh_entsize);
229 #elif ELFSIZE == 64
230 	E32(shdr->sh_name);
231 	E32(shdr->sh_type);
232 	E64(shdr->sh_flags);
233 	E64(shdr->sh_addr);
234 	E64(shdr->sh_offset);
235 	E64(shdr->sh_size);
236 	E32(shdr->sh_link);
237 	E32(shdr->sh_info);
238 	E64(shdr->sh_addralign);
239 	E64(shdr->sh_entsize);
240 #else
241 #error ELFSIZE is not 32 or 64
242 #endif
243 }
244 #else /* _STANDALONE */
245 /*
246  * Byte swapping is never necessary in the _STANDALONE case because
247  * we are being built with the target compiler.
248  */
249 #define	internalize_ehdr(bo, ehdr)	/* nothing */
250 #define	externalize_ehdr(bo, ehdr)	/* nothing */
251 
252 #define	internalize_phdr(bo, phdr)	/* nothing */
253 
254 #define	internalize_shdr(bo, shdr)	/* nothing */
255 #define	externalize_shdr(bo, shdr)	/* nothing */
256 #endif /* _STANDALONE */
257 
258 #define IS_TEXT(p)	(p.p_flags & PF_X)
259 #define IS_DATA(p)	(p.p_flags & PF_W)
260 #define IS_BSS(p)	(p.p_filesz < p.p_memsz)
261 
262 #ifndef MD_LOADSEG /* Allow processor ABI specific segment loads */
263 #define MD_LOADSEG(a) /*CONSTCOND*/0
264 #endif
265 
266 /* -------------------------------------------------------------------------- */
267 
268 #define KERNALIGN_SMALL (1 << 12)	/* XXX should depend on marks[] */
269 #define KERNALIGN_LARGE (1 << 21)	/* XXX should depend on marks[] */
270 
271 /*
272  * Read some data from a file, and put it in the bootloader memory (local).
273  */
274 static int
275 ELFNAMEEND(readfile_local)(int fd, Elf_Off elfoff, void *addr, size_t size)
276 {
277 	ssize_t nr;
278 
279 	if (lseek(fd, elfoff, SEEK_SET) == -1)  {
280 		WARN(("lseek section headers"));
281 		return -1;
282 	}
283 	nr = read(fd, addr, size);
284 	if (nr == -1) {
285 		WARN(("read section headers"));
286 		return -1;
287 	}
288 	if (nr != (ssize_t)size) {
289 		errno = EIO;
290 		WARN(("read section headers"));
291 		return -1;
292 	}
293 
294 	return 0;
295 }
296 
297 /*
298  * Read some data from a file, and put it in wherever in memory (global).
299  */
300 static int
301 ELFNAMEEND(readfile_global)(int fd, u_long offset, Elf_Off elfoff,
302     Elf_Addr addr, size_t size)
303 {
304 	ssize_t nr;
305 
306 	/* some ports dont use the offset */
307 	(void)&offset;
308 
309 	if (lseek(fd, elfoff, SEEK_SET) == -1) {
310 		WARN(("lseek section"));
311 		return -1;
312 	}
313 	nr = READ(fd, addr, size);
314 	if (nr == -1) {
315 		WARN(("read section"));
316 		return -1;
317 	}
318 	if (nr != (ssize_t)size) {
319 		errno = EIO;
320 		WARN(("read section"));
321 		return -1;
322 	}
323 
324 	return 0;
325 }
326 
327 /*
328  * Load a dynamic ELF binary into memory. Layout of the memory:
329  * +------------+-----------------+-----------------+------------------+
330  * | ELF HEADER | SECTION HEADERS | KERNEL SECTIONS | SYM+REL SECTIONS |
331  * +------------+-----------------+-----------------+------------------+
332  * The ELF HEADER start address is marks[MARK_END]. We then map the rest
333  * by increasing maxp. An alignment is enforced between the code sections.
334  *
335  * The offsets of the KERNEL and SYM+REL sections are relative to the start
336  * address of the ELF HEADER. We just give the kernel a pointer to the ELF
337  * HEADER, and we let the kernel find the location and number of symbols by
338  * itself.
339  */
340 static int
341 ELFNAMEEND(loadfile_dynamic)(int fd, Elf_Ehdr *elf, u_long *marks, int flags)
342 {
343 	const u_long offset = 0;
344 	Elf_Shdr *shdr;
345 	Elf_Addr shpp, addr;
346 	int i, j, loaded;
347 	size_t size, shdrsz, align;
348 	Elf_Addr maxp, elfp = 0;
349 	int ret;
350 
351 	maxp = marks[MARK_END];
352 
353 	internalize_ehdr(elf->e_ident[EI_DATA], elf);
354 
355 	if (elf->e_type != ET_REL) {
356 		errno = EINVAL;
357 		return 1;
358 	}
359 
360 	/* Create a local copy of the SECTION HEADERS. */
361 	shdrsz = elf->e_shnum * sizeof(Elf_Shdr);
362 	shdr = ALLOC(shdrsz);
363 	ret = ELFNAMEEND(readfile_local)(fd, elf->e_shoff, shdr, shdrsz);
364 	if (ret == -1) {
365 		goto out;
366 	}
367 
368 	/*
369 	 * Load the ELF HEADER. Update the section offset, to be relative to
370 	 * elfp.
371 	 */
372 	elf->e_phoff = 0;
373 	elf->e_shoff = sizeof(Elf_Ehdr);
374 	elf->e_phentsize = 0;
375 	elf->e_phnum = 0;
376 	elfp = maxp;
377 	externalize_ehdr(elf->e_ident[EI_DATA], elf);
378 	BCOPY(elf, elfp, sizeof(*elf));
379 	internalize_ehdr(elf->e_ident[EI_DATA], elf);
380 	maxp += sizeof(Elf_Ehdr);
381 
382 #ifndef _STANDALONE
383 	for (i = 0; i < elf->e_shnum; i++)
384 		internalize_shdr(elf->e_ident[EI_DATA], &shdr[i]);
385 #endif
386 
387 	/* Save location of the SECTION HEADERS. */
388 	shpp = maxp;
389 	maxp += roundup(shdrsz, ELFROUND);
390 
391 	/*
392 	 * Load the KERNEL SECTIONS.
393 	 */
394 	maxp = roundup(maxp, KERNALIGN_SMALL);
395 	for (i = 0; i < elf->e_shnum; i++) {
396 		if (!(shdr[i].sh_flags & SHF_ALLOC)) {
397 			continue;
398 		}
399 		size = (size_t)shdr[i].sh_size;
400 		if (size <= KERNALIGN_SMALL) {
401 			align = KERNALIGN_SMALL;
402 		} else {
403 			align = KERNALIGN_LARGE;
404 		}
405 		addr = roundup(maxp, align);
406 
407 		loaded = 0;
408 		switch (shdr[i].sh_type) {
409 		case SHT_NOBITS:
410 			/* Zero out bss. */
411 			BZERO(addr, size);
412 			loaded = 1;
413 			break;
414 		case SHT_PROGBITS:
415 			ret = ELFNAMEEND(readfile_global)(fd, offset,
416 			    shdr[i].sh_offset, addr, size);
417 			if (ret == -1) {
418 				goto out;
419 			}
420 			loaded = 1;
421 			break;
422 		default:
423 			loaded = 0;
424 			break;
425 		}
426 
427 		if (loaded) {
428 			shdr[i].sh_offset = addr - elfp;
429 			maxp = roundup(addr + size, align);
430 		}
431 	}
432 	maxp = roundup(maxp, KERNALIGN_LARGE);
433 
434 	/*
435 	 * Load the SYM+REL SECTIONS.
436 	 */
437 	maxp = roundup(maxp, ELFROUND);
438 	for (i = 0; i < elf->e_shnum; i++) {
439 		addr = maxp;
440 		size = (size_t)shdr[i].sh_size;
441 
442 		switch (shdr[i].sh_type) {
443 		case SHT_STRTAB:
444 			for (j = 0; j < elf->e_shnum; j++)
445 				if (shdr[j].sh_type == SHT_SYMTAB &&
446 				    shdr[j].sh_link == (unsigned int)i)
447 					goto havesym;
448 			if (elf->e_shstrndx == i)
449 				goto havesym;
450 			/*
451 			 * Don't bother with any string table that isn't
452 			 * referenced by a symbol table.
453 			 */
454 			shdr[i].sh_offset = 0;
455 			break;
456 	havesym:
457 		case SHT_REL:
458 		case SHT_RELA:
459 		case SHT_SYMTAB:
460 			ret = ELFNAMEEND(readfile_global)(fd, offset,
461 			    shdr[i].sh_offset, addr, size);
462 			if (ret == -1) {
463 				goto out;
464 			}
465 			shdr[i].sh_offset = maxp - elfp;
466 			maxp += roundup(size, ELFROUND);
467 			break;
468 		}
469 	}
470 	maxp = roundup(maxp, KERNALIGN_SMALL);
471 
472 	/*
473 	 * Finally, load the SECTION HEADERS.
474 	 */
475 #ifndef _STANDALONE
476 	for (i = 0; i < elf->e_shnum; i++)
477 		externalize_shdr(elf->e_ident[EI_DATA], &shdr[i]);
478 #endif
479 	BCOPY(shdr, shpp, shdrsz);
480 
481 	DEALLOC(shdr, shdrsz);
482 
483 	/*
484 	 * Just update MARK_SYM and MARK_END without touching the rest.
485 	 */
486 	marks[MARK_SYM] = LOADADDR(elfp);
487 	marks[MARK_END] = LOADADDR(maxp);
488 	return 0;
489 
490 out:
491 	DEALLOC(shdr, shdrsz);
492 	return 1;
493 }
494 
495 /* -------------------------------------------------------------------------- */
496 
497 /*
498  * See comment below. This function is in charge of loading the SECTION HEADERS.
499  */
500 static int
501 ELFNAMEEND(loadsym)(int fd, Elf_Ehdr *elf, Elf_Addr maxp, Elf_Addr elfp,
502     u_long *marks, int flags, Elf_Addr *nmaxp)
503 {
504 	const u_long offset = marks[MARK_START];
505 	int boot_load_ctf = 1;
506 	Elf_Shdr *shp;
507 	Elf_Addr shpp;
508 	char *shstr = NULL;
509 	size_t sz;
510 	size_t i, j, shstrsz = 0;
511 	struct __packed {
512 		Elf_Nhdr nh;
513 		uint8_t name[ELF_NOTE_NETBSD_NAMESZ + 1];
514 		uint8_t desc[ELF_NOTE_NETBSD_DESCSZ];
515 	} note;
516 	int first;
517 	int ret;
518 
519 	sz = elf->e_shnum * sizeof(Elf_Shdr);
520 	shp = ALLOC(sz);
521 	ret = ELFNAMEEND(readfile_local)(fd, elf->e_shoff, shp, sz);
522 	if (ret == -1) {
523 		goto out;
524 	}
525 
526 	shpp = maxp;
527 	maxp += roundup(sz, ELFROUND);
528 
529 #ifndef _STANDALONE
530 	for (i = 0; i < elf->e_shnum; i++)
531 		internalize_shdr(elf->e_ident[EI_DATA], &shp[i]);
532 #endif
533 
534 	/*
535 	 * First load the section names section. Only useful for CTF.
536 	 */
537 	if (boot_load_ctf && (elf->e_shstrndx != SHN_UNDEF)) {
538 		Elf_Off shstroff = shp[elf->e_shstrndx].sh_offset;
539 		shstrsz = shp[elf->e_shstrndx].sh_size;
540 		if (flags & LOAD_SYM) {
541 			ret = ELFNAMEEND(readfile_global)(fd, offset,
542 			    shstroff, maxp, shstrsz);
543 			if (ret == -1) {
544 				goto out;
545 			}
546 		}
547 
548 		/* Create a local copy */
549 		shstr = ALLOC(shstrsz);
550 		ret = ELFNAMEEND(readfile_local)(fd, shstroff, shstr, shstrsz);
551 		if (ret == -1) {
552 			goto out;
553 		}
554 		shp[elf->e_shstrndx].sh_offset = maxp - elfp;
555 		maxp += roundup(shstrsz, ELFROUND);
556 	}
557 
558 	/*
559 	 * Now load the symbol sections themselves. Make sure the sections are
560 	 * ELFROUND-aligned. Update sh_offset to be relative to elfp. Set it to
561 	 * zero when we don't want the sections to be taken care of, the kernel
562 	 * will properly skip them.
563 	 */
564 	first = 1;
565 	for (i = 1; i < elf->e_shnum; i++) {
566 		if (i == elf->e_shstrndx) {
567 			/* already loaded this section */
568 			continue;
569 		}
570 
571 		switch (shp[i].sh_type) {
572 		case SHT_PROGBITS:
573 			if (boot_load_ctf && shstr) {
574 				/* got a CTF section? */
575 				if (strncmp(&shstr[shp[i].sh_name],
576 					    ".SUNW_ctf", 10) == 0) {
577 					goto havesym;
578 				}
579 			}
580 
581 			shp[i].sh_offset = 0;
582 			break;
583 		case SHT_STRTAB:
584 			for (j = 1; j < elf->e_shnum; j++)
585 				if (shp[j].sh_type == SHT_SYMTAB &&
586 				    shp[j].sh_link == (unsigned int)i)
587 					goto havesym;
588 			/*
589 			 * Don't bother with any string table that isn't
590 			 * referenced by a symbol table.
591 			 */
592 			shp[i].sh_offset = 0;
593 			break;
594 havesym:
595 		case SHT_SYMTAB:
596 			if (flags & LOAD_SYM) {
597 				PROGRESS(("%s%ld", first ? " [" : "+",
598 				    (u_long)shp[i].sh_size));
599 				ret = ELFNAMEEND(readfile_global)(fd, offset,
600 				    shp[i].sh_offset, maxp, shp[i].sh_size);
601 				if (ret == -1) {
602 					goto out;
603 				}
604 			}
605 			shp[i].sh_offset = maxp - elfp;
606 			maxp += roundup(shp[i].sh_size, ELFROUND);
607 			first = 0;
608 			break;
609 		case SHT_NOTE:
610 			if ((flags & LOAD_NOTE) == 0)
611 				break;
612 			if (shp[i].sh_size < sizeof(note)) {
613 				shp[i].sh_offset = 0;
614 				break;
615 			}
616 
617 			ret = ELFNAMEEND(readfile_local)(fd, shp[i].sh_offset,
618 			    &note, sizeof(note));
619 			if (ret == -1) {
620 				goto out;
621 			}
622 
623 			if (note.nh.n_namesz == ELF_NOTE_NETBSD_NAMESZ &&
624 			    note.nh.n_descsz == ELF_NOTE_NETBSD_DESCSZ &&
625 			    note.nh.n_type == ELF_NOTE_TYPE_NETBSD_TAG &&
626 			    memcmp(note.name, ELF_NOTE_NETBSD_NAME,
627 			    sizeof(note.name)) == 0) {
628 				memcpy(&netbsd_version, &note.desc,
629 				    sizeof(netbsd_version));
630 			}
631 			shp[i].sh_offset = 0;
632 			break;
633 		default:
634 			shp[i].sh_offset = 0;
635 			break;
636 		}
637 	}
638 	if (flags & LOAD_SYM) {
639 #ifndef _STANDALONE
640 		for (i = 0; i < elf->e_shnum; i++)
641 			externalize_shdr(elf->e_ident[EI_DATA], &shp[i]);
642 #endif
643 		BCOPY(shp, shpp, sz);
644 
645 		if (first == 0)
646 			PROGRESS(("]"));
647 	}
648 
649 	*nmaxp = maxp;
650 	DEALLOC(shp, sz);
651 	if (shstr != NULL)
652 		DEALLOC(shstr, shstrsz);
653 	return 0;
654 
655 out:
656 	DEALLOC(shp, sz);
657 	if (shstr != NULL)
658 		DEALLOC(shstr, shstrsz);
659 	return -1;
660 }
661 
662 /* -------------------------------------------------------------------------- */
663 
664 /*
665  * Load a static ELF binary into memory. Layout of the memory:
666  * +-----------------+------------+-----------------+-----------------+
667  * | KERNEL SEGMENTS | ELF HEADER | SECTION HEADERS | SYMBOL SECTIONS |
668  * +-----------------+------------+-----------------+-----------------+
669  * The KERNEL SEGMENTS start address is fixed by the segments themselves. We
670  * then map the rest by increasing maxp.
671  *
672  * The offsets of the SYMBOL SECTIONS are relative to the start address of the
673  * ELF HEADER. The shdr offset of ELF HEADER points to SECTION HEADERS.
674  *
675  * We just give the kernel a pointer to the ELF HEADER, which is enough for it
676  * to find the location and number of symbols by itself later.
677  */
678 static int
679 ELFNAMEEND(loadfile_static)(int fd, Elf_Ehdr *elf, u_long *marks, int flags)
680 {
681 	const u_long offset = marks[MARK_START];
682 	Elf_Phdr *phdr;
683 	int i, first;
684 	size_t sz;
685 	Elf_Addr minp = ~0, maxp = 0, pos = 0, elfp = 0;
686 	int ret;
687 
688 	/* for ports that define progress to nothing */
689 	(void)&first;
690 
691 	/* have not seen a data segment so far */
692 	marks[MARK_DATA] = 0;
693 
694 	internalize_ehdr(elf->e_ident[EI_DATA], elf);
695 
696 	sz = elf->e_phnum * sizeof(Elf_Phdr);
697 	phdr = ALLOC(sz);
698 	ret = ELFNAMEEND(readfile_local)(fd, elf->e_phoff, phdr, sz);
699 	if (ret == -1) {
700 		goto freephdr;
701 	}
702 
703 	first = 1;
704 	for (i = 0; i < elf->e_phnum; i++) {
705 		internalize_phdr(elf->e_ident[EI_DATA], &phdr[i]);
706 
707 		if (MD_LOADSEG(&phdr[i]))
708 			goto loadseg;
709 
710 		if (phdr[i].p_type != PT_LOAD ||
711 		    (phdr[i].p_flags & (PF_W|PF_X)) == 0)
712 			continue;
713 
714 		if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) ||
715 		    (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) {
716 		loadseg:
717 			/* XXX: Assume first address is lowest */
718 			if (marks[MARK_DATA] == 0 && IS_DATA(phdr[i]))
719 				marks[MARK_DATA] = LOADADDR(phdr[i].p_vaddr);
720 
721 			/* Read in segment. */
722 			PROGRESS(("%s%lu", first ? "" : "+",
723 			    (u_long)phdr[i].p_filesz));
724 
725 			ret = ELFNAMEEND(readfile_global)(fd, offset,
726 			    phdr[i].p_offset, phdr[i].p_vaddr,
727 			    phdr[i].p_filesz);
728 			if (ret == -1) {
729 				goto freephdr;
730 			}
731 
732 			first = 0;
733 		}
734 		if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT|COUNT_TEXT))) ||
735 		    (IS_DATA(phdr[i]) && (flags & (LOAD_DATA|COUNT_DATA)))) {
736 			/* XXX: Assume first address is lowest */
737 			if (marks[MARK_DATA] == 0 && IS_DATA(phdr[i]))
738 				marks[MARK_DATA] = LOADADDR(phdr[i].p_vaddr);
739 
740 			pos = phdr[i].p_vaddr;
741 			if (minp > pos)
742 				minp = pos;
743 			pos += phdr[i].p_filesz;
744 			if (maxp < pos)
745 				maxp = pos;
746 		}
747 
748 		/* Zero out bss. */
749 		if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) {
750 			PROGRESS(("+%lu",
751 			    (u_long)(phdr[i].p_memsz - phdr[i].p_filesz)));
752 			BZERO((phdr[i].p_vaddr + phdr[i].p_filesz),
753 			    phdr[i].p_memsz - phdr[i].p_filesz);
754 		}
755 		if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) {
756 			pos += phdr[i].p_memsz - phdr[i].p_filesz;
757 			if (maxp < pos)
758 				maxp = pos;
759 		}
760 	}
761 	DEALLOC(phdr, sz);
762 	maxp = roundup(maxp, ELFROUND);
763 
764 	/*
765 	 * Load the ELF HEADER, SECTION HEADERS and possibly the SYMBOL
766 	 * SECTIONS.
767 	 */
768 	if (flags & (LOAD_HDR|COUNT_HDR)) {
769 		elfp = maxp;
770 		maxp += sizeof(Elf_Ehdr);
771 	}
772 	if (flags & (LOAD_SYM|COUNT_SYM)) {
773 		if (ELFNAMEEND(loadsym)(fd, elf, maxp, elfp, marks, flags,
774 		    &maxp) == -1) {
775  			return 1;
776 		}
777 	}
778 
779 	/*
780 	 * Update the ELF HEADER to give information relative to elfp.
781 	 */
782 	if (flags & LOAD_HDR) {
783 		elf->e_phoff = 0;
784 		elf->e_shoff = sizeof(Elf_Ehdr);
785 		elf->e_phentsize = 0;
786 		elf->e_phnum = 0;
787 		externalize_ehdr(elf->e_ident[EI_DATA], elf);
788 		BCOPY(elf, elfp, sizeof(*elf));
789 		internalize_ehdr(elf->e_ident[EI_DATA], elf);
790 	}
791 
792 	marks[MARK_START] = LOADADDR(minp);
793 	marks[MARK_ENTRY] = LOADADDR(elf->e_entry);
794 	marks[MARK_NSYM] = 1;	/* XXX: Kernel needs >= 0 */
795 	marks[MARK_SYM] = LOADADDR(elfp);
796 	marks[MARK_END] = LOADADDR(maxp);
797 	return 0;
798 
799 freephdr:
800 	DEALLOC(phdr, sz);
801 	return 1;
802 }
803 
804 /* -------------------------------------------------------------------------- */
805 
806 int
807 ELFNAMEEND(loadfile)(int fd, Elf_Ehdr *elf, u_long *marks, int flags)
808 {
809 	if (flags & LOAD_DYN) {
810 		return ELFNAMEEND(loadfile_dynamic)(fd, elf, marks, flags);
811 	} else {
812 		return ELFNAMEEND(loadfile_static)(fd, elf, marks, flags);
813 	}
814 }
815 
816 #endif /* (ELFSIZE == 32 && BOOT_ELF32) || (ELFSIZE == 64 && BOOT_ELF64) */
817