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 ¬e, 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, ¬e.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