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