1 /* $NetBSD: loadfile_elf32.c,v 1.51 2017/11/15 18:02:37 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 /* Create a local copy of the SECTION HEADERS. */ 356 shdrsz = elf->e_shnum * sizeof(Elf_Shdr); 357 shdr = ALLOC(shdrsz); 358 ret = ELFNAMEEND(readfile_local)(fd, elf->e_shoff, shdr, shdrsz); 359 if (ret == -1) { 360 goto out; 361 } 362 363 /* 364 * Load the ELF HEADER. Update the section offset, to be relative to 365 * elfp. 366 */ 367 elf->e_phoff = 0; 368 elf->e_shoff = sizeof(Elf_Ehdr); 369 elf->e_phentsize = 0; 370 elf->e_phnum = 0; 371 elfp = maxp; 372 externalize_ehdr(elf->e_ident[EI_DATA], elf); 373 BCOPY(elf, elfp, sizeof(*elf)); 374 internalize_ehdr(elf->e_ident[EI_DATA], elf); 375 maxp += sizeof(Elf_Ehdr); 376 377 #ifndef _STANDALONE 378 for (i = 0; i < elf->e_shnum; i++) 379 internalize_shdr(elf->e_ident[EI_DATA], &shdr[i]); 380 #endif 381 382 /* Save location of the SECTION HEADERS. */ 383 shpp = maxp; 384 maxp += roundup(shdrsz, ELFROUND); 385 386 /* 387 * Load the KERNEL SECTIONS. 388 */ 389 maxp = roundup(maxp, KERNALIGN_SMALL); 390 for (i = 0; i < elf->e_shnum; i++) { 391 if (!(shdr[i].sh_flags & SHF_ALLOC)) { 392 continue; 393 } 394 size = (size_t)shdr[i].sh_size; 395 if (size <= KERNALIGN_SMALL) { 396 align = KERNALIGN_SMALL; 397 } else { 398 align = KERNALIGN_LARGE; 399 } 400 addr = roundup(maxp, align); 401 402 loaded = 0; 403 switch (shdr[i].sh_type) { 404 case SHT_NOBITS: 405 /* Zero out bss. */ 406 BZERO(addr, size); 407 loaded = 1; 408 break; 409 case SHT_PROGBITS: 410 ret = ELFNAMEEND(readfile_global)(fd, offset, 411 shdr[i].sh_offset, addr, size); 412 if (ret == -1) { 413 goto out; 414 } 415 loaded = 1; 416 break; 417 default: 418 loaded = 0; 419 break; 420 } 421 422 if (loaded) { 423 shdr[i].sh_offset = addr - elfp; 424 maxp = roundup(addr + size, align); 425 } 426 } 427 maxp = roundup(maxp, KERNALIGN_LARGE); 428 429 /* 430 * Load the SYM+REL SECTIONS. 431 */ 432 maxp = roundup(maxp, ELFROUND); 433 for (i = 0; i < elf->e_shnum; i++) { 434 addr = maxp; 435 size = (size_t)shdr[i].sh_size; 436 437 switch (shdr[i].sh_type) { 438 case SHT_STRTAB: 439 for (j = 0; j < elf->e_shnum; j++) 440 if (shdr[j].sh_type == SHT_SYMTAB && 441 shdr[j].sh_link == (unsigned int)i) 442 goto havesym; 443 if (elf->e_shstrndx == i) 444 goto havesym; 445 /* 446 * Don't bother with any string table that isn't 447 * referenced by a symbol table. 448 */ 449 shdr[i].sh_offset = 0; 450 break; 451 havesym: 452 case SHT_REL: 453 case SHT_RELA: 454 case SHT_SYMTAB: 455 ret = ELFNAMEEND(readfile_global)(fd, offset, 456 shdr[i].sh_offset, addr, size); 457 if (ret == -1) { 458 goto out; 459 } 460 shdr[i].sh_offset = maxp - elfp; 461 maxp += roundup(size, ELFROUND); 462 break; 463 } 464 } 465 maxp = roundup(maxp, KERNALIGN_SMALL); 466 467 /* 468 * Finally, load the SECTION HEADERS. 469 */ 470 #ifndef _STANDALONE 471 for (i = 0; i < elf->e_shnum; i++) 472 externalize_shdr(elf->e_ident[EI_DATA], &shdr[i]); 473 #endif 474 BCOPY(shdr, shpp, shdrsz); 475 476 DEALLOC(shdr, shdrsz); 477 478 /* 479 * Just update MARK_SYM and MARK_END without touching the rest. 480 */ 481 marks[MARK_SYM] = LOADADDR(elfp); 482 marks[MARK_END] = LOADADDR(maxp); 483 return 0; 484 485 out: 486 DEALLOC(shdr, shdrsz); 487 return 1; 488 } 489 490 /* -------------------------------------------------------------------------- */ 491 492 /* 493 * See comment below. This function is in charge of loading the SECTION HEADERS. 494 */ 495 static int 496 ELFNAMEEND(loadsym)(int fd, Elf_Ehdr *elf, Elf_Addr maxp, Elf_Addr elfp, 497 u_long *marks, int flags, Elf_Addr *nmaxp) 498 { 499 const u_long offset = marks[MARK_START]; 500 int boot_load_ctf = 1; 501 Elf_Shdr *shp; 502 Elf_Addr shpp; 503 char *shstr = NULL; 504 size_t sz; 505 size_t i, j, shstrsz = 0; 506 struct __packed { 507 Elf_Nhdr nh; 508 uint8_t name[ELF_NOTE_NETBSD_NAMESZ + 1]; 509 uint8_t desc[ELF_NOTE_NETBSD_DESCSZ]; 510 } note; 511 int first; 512 int ret; 513 514 sz = elf->e_shnum * sizeof(Elf_Shdr); 515 shp = ALLOC(sz); 516 ret = ELFNAMEEND(readfile_local)(fd, elf->e_shoff, shp, sz); 517 if (ret == -1) { 518 goto out; 519 } 520 521 shpp = maxp; 522 maxp += roundup(sz, ELFROUND); 523 524 #ifndef _STANDALONE 525 for (i = 0; i < elf->e_shnum; i++) 526 internalize_shdr(elf->e_ident[EI_DATA], &shp[i]); 527 #endif 528 529 /* 530 * First load the section names section. Only useful for CTF. 531 */ 532 if (boot_load_ctf && (elf->e_shstrndx != SHN_UNDEF)) { 533 Elf_Off shstroff = shp[elf->e_shstrndx].sh_offset; 534 shstrsz = shp[elf->e_shstrndx].sh_size; 535 if (flags & LOAD_SYM) { 536 ret = ELFNAMEEND(readfile_global)(fd, offset, 537 shstroff, maxp, shstrsz); 538 if (ret == -1) { 539 goto out; 540 } 541 } 542 543 /* Create a local copy */ 544 shstr = ALLOC(shstrsz); 545 ret = ELFNAMEEND(readfile_local)(fd, shstroff, shstr, shstrsz); 546 if (ret == -1) { 547 goto out; 548 } 549 shp[elf->e_shstrndx].sh_offset = maxp - elfp; 550 maxp += roundup(shstrsz, ELFROUND); 551 } 552 553 /* 554 * Now load the symbol sections themselves. Make sure the sections are 555 * ELFROUND-aligned. Update sh_offset to be relative to elfp. Set it to 556 * zero when we don't want the sections to be taken care of, the kernel 557 * will properly skip them. 558 */ 559 first = 1; 560 for (i = 1; i < elf->e_shnum; i++) { 561 if (i == elf->e_shstrndx) { 562 /* already loaded this section */ 563 continue; 564 } 565 566 switch (shp[i].sh_type) { 567 case SHT_PROGBITS: 568 if (boot_load_ctf && shstr) { 569 /* got a CTF section? */ 570 if (strncmp(&shstr[shp[i].sh_name], 571 ".SUNW_ctf", 10) == 0) { 572 goto havesym; 573 } 574 } 575 576 shp[i].sh_offset = 0; 577 break; 578 case SHT_STRTAB: 579 for (j = 1; j < elf->e_shnum; j++) 580 if (shp[j].sh_type == SHT_SYMTAB && 581 shp[j].sh_link == (unsigned int)i) 582 goto havesym; 583 /* 584 * Don't bother with any string table that isn't 585 * referenced by a symbol table. 586 */ 587 shp[i].sh_offset = 0; 588 break; 589 havesym: 590 case SHT_SYMTAB: 591 if (flags & LOAD_SYM) { 592 PROGRESS(("%s%ld", first ? " [" : "+", 593 (u_long)shp[i].sh_size)); 594 ret = ELFNAMEEND(readfile_global)(fd, offset, 595 shp[i].sh_offset, maxp, shp[i].sh_size); 596 if (ret == -1) { 597 goto out; 598 } 599 } 600 shp[i].sh_offset = maxp - elfp; 601 maxp += roundup(shp[i].sh_size, ELFROUND); 602 first = 0; 603 break; 604 case SHT_NOTE: 605 if ((flags & LOAD_NOTE) == 0) 606 break; 607 if (shp[i].sh_size < sizeof(note)) { 608 shp[i].sh_offset = 0; 609 break; 610 } 611 612 ret = ELFNAMEEND(readfile_local)(fd, shp[i].sh_offset, 613 ¬e, sizeof(note)); 614 if (ret == -1) { 615 goto out; 616 } 617 618 if (note.nh.n_namesz == ELF_NOTE_NETBSD_NAMESZ && 619 note.nh.n_descsz == ELF_NOTE_NETBSD_DESCSZ && 620 note.nh.n_type == ELF_NOTE_TYPE_NETBSD_TAG && 621 memcmp(note.name, ELF_NOTE_NETBSD_NAME, 622 sizeof(note.name)) == 0) { 623 memcpy(&netbsd_version, ¬e.desc, 624 sizeof(netbsd_version)); 625 } 626 shp[i].sh_offset = 0; 627 break; 628 default: 629 shp[i].sh_offset = 0; 630 break; 631 } 632 } 633 if (flags & LOAD_SYM) { 634 #ifndef _STANDALONE 635 for (i = 0; i < elf->e_shnum; i++) 636 externalize_shdr(elf->e_ident[EI_DATA], &shp[i]); 637 #endif 638 BCOPY(shp, shpp, sz); 639 640 if (first == 0) 641 PROGRESS(("]")); 642 } 643 644 *nmaxp = maxp; 645 DEALLOC(shp, sz); 646 if (shstr != NULL) 647 DEALLOC(shstr, shstrsz); 648 return 0; 649 650 out: 651 DEALLOC(shp, sz); 652 if (shstr != NULL) 653 DEALLOC(shstr, shstrsz); 654 return -1; 655 } 656 657 /* -------------------------------------------------------------------------- */ 658 659 /* 660 * Load a static ELF binary into memory. Layout of the memory: 661 * +-----------------+------------+-----------------+-----------------+ 662 * | KERNEL SEGMENTS | ELF HEADER | SECTION HEADERS | SYMBOL SECTIONS | 663 * +-----------------+------------+-----------------+-----------------+ 664 * The KERNEL SEGMENTS start address is fixed by the segments themselves. We 665 * then map the rest by increasing maxp. 666 * 667 * The offsets of the SYMBOL SECTIONS are relative to the start address of the 668 * ELF HEADER. The shdr offset of ELF HEADER points to SECTION HEADERS. 669 * 670 * We just give the kernel a pointer to the ELF HEADER, which is enough for it 671 * to find the location and number of symbols by itself later. 672 */ 673 static int 674 ELFNAMEEND(loadfile_static)(int fd, Elf_Ehdr *elf, u_long *marks, int flags) 675 { 676 const u_long offset = marks[MARK_START]; 677 Elf_Phdr *phdr; 678 int i, first; 679 size_t sz; 680 Elf_Addr minp = ~0, maxp = 0, pos = 0, elfp = 0; 681 int ret; 682 683 /* for ports that define progress to nothing */ 684 (void)&first; 685 686 /* have not seen a data segment so far */ 687 marks[MARK_DATA] = 0; 688 689 internalize_ehdr(elf->e_ident[EI_DATA], elf); 690 691 sz = elf->e_phnum * sizeof(Elf_Phdr); 692 phdr = ALLOC(sz); 693 ret = ELFNAMEEND(readfile_local)(fd, elf->e_phoff, phdr, sz); 694 if (ret == -1) { 695 goto freephdr; 696 } 697 698 first = 1; 699 for (i = 0; i < elf->e_phnum; i++) { 700 internalize_phdr(elf->e_ident[EI_DATA], &phdr[i]); 701 702 if (MD_LOADSEG(&phdr[i])) 703 goto loadseg; 704 705 if (phdr[i].p_type != PT_LOAD || 706 (phdr[i].p_flags & (PF_W|PF_X)) == 0) 707 continue; 708 709 if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) || 710 (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) { 711 loadseg: 712 /* XXX: Assume first address is lowest */ 713 if (marks[MARK_DATA] == 0 && IS_DATA(phdr[i])) 714 marks[MARK_DATA] = LOADADDR(phdr[i].p_vaddr); 715 716 /* Read in segment. */ 717 PROGRESS(("%s%lu", first ? "" : "+", 718 (u_long)phdr[i].p_filesz)); 719 720 ret = ELFNAMEEND(readfile_global)(fd, offset, 721 phdr[i].p_offset, phdr[i].p_vaddr, 722 phdr[i].p_filesz); 723 if (ret == -1) { 724 goto freephdr; 725 } 726 727 first = 0; 728 } 729 if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT|COUNT_TEXT))) || 730 (IS_DATA(phdr[i]) && (flags & (LOAD_DATA|COUNT_DATA)))) { 731 /* XXX: Assume first address is lowest */ 732 if (marks[MARK_DATA] == 0 && IS_DATA(phdr[i])) 733 marks[MARK_DATA] = LOADADDR(phdr[i].p_vaddr); 734 735 pos = phdr[i].p_vaddr; 736 if (minp > pos) 737 minp = pos; 738 pos += phdr[i].p_filesz; 739 if (maxp < pos) 740 maxp = pos; 741 } 742 743 /* Zero out bss. */ 744 if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) { 745 PROGRESS(("+%lu", 746 (u_long)(phdr[i].p_memsz - phdr[i].p_filesz))); 747 BZERO((phdr[i].p_vaddr + phdr[i].p_filesz), 748 phdr[i].p_memsz - phdr[i].p_filesz); 749 } 750 if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) { 751 pos += phdr[i].p_memsz - phdr[i].p_filesz; 752 if (maxp < pos) 753 maxp = pos; 754 } 755 } 756 DEALLOC(phdr, sz); 757 maxp = roundup(maxp, ELFROUND); 758 759 /* 760 * Load the ELF HEADER, SECTION HEADERS and possibly the SYMBOL 761 * SECTIONS. 762 */ 763 if (flags & (LOAD_HDR|COUNT_HDR)) { 764 elfp = maxp; 765 maxp += sizeof(Elf_Ehdr); 766 } 767 if (flags & (LOAD_SYM|COUNT_SYM)) { 768 if (ELFNAMEEND(loadsym)(fd, elf, maxp, elfp, marks, flags, 769 &maxp) == -1) { 770 return 1; 771 } 772 } 773 774 /* 775 * Update the ELF HEADER to give information relative to elfp. 776 */ 777 if (flags & LOAD_HDR) { 778 elf->e_phoff = 0; 779 elf->e_shoff = sizeof(Elf_Ehdr); 780 elf->e_phentsize = 0; 781 elf->e_phnum = 0; 782 externalize_ehdr(elf->e_ident[EI_DATA], elf); 783 BCOPY(elf, elfp, sizeof(*elf)); 784 internalize_ehdr(elf->e_ident[EI_DATA], elf); 785 } 786 787 marks[MARK_START] = LOADADDR(minp); 788 marks[MARK_ENTRY] = LOADADDR(elf->e_entry); 789 marks[MARK_NSYM] = 1; /* XXX: Kernel needs >= 0 */ 790 marks[MARK_SYM] = LOADADDR(elfp); 791 marks[MARK_END] = LOADADDR(maxp); 792 return 0; 793 794 freephdr: 795 DEALLOC(phdr, sz); 796 return 1; 797 } 798 799 /* -------------------------------------------------------------------------- */ 800 801 int 802 ELFNAMEEND(loadfile)(int fd, Elf_Ehdr *elf, u_long *marks, int flags) 803 { 804 if (flags & LOAD_DYN) { 805 return ELFNAMEEND(loadfile_dynamic)(fd, elf, marks, flags); 806 } else { 807 return ELFNAMEEND(loadfile_static)(fd, elf, marks, flags); 808 } 809 } 810 811 #endif /* (ELFSIZE == 32 && BOOT_ELF32) || (ELFSIZE == 64 && BOOT_ELF64) */ 812