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