xref: /netbsd-src/sys/lib/libsa/loadfile_elf32.c (revision 96b5c9e0fe7c4a3d59eb358529a3ec8e001db618)
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
internalize_ehdr(Elf_Byte bo,Elf_Ehdr * ehdr)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
externalize_ehdr(Elf_Byte bo,Elf_Ehdr * ehdr)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
internalize_phdr(Elf_Byte bo,Elf_Phdr * phdr)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
internalize_shdr(Elf_Byte bo,Elf_Shdr * shdr)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
externalize_shdr(Elf_Byte bo,Elf_Shdr * shdr)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
ELFNAMEEND(readfile_local)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
ELFNAMEEND(readfile_global)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
ELFNAMEEND(loadfile_dynamic)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
ELFNAMEEND(loadsym)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
ELFNAMEEND(loadfile_static)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
ELFNAMEEND(loadfile)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