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 ¬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 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