1 /* $NetBSD: loadfile_elf32.c,v 1.34 2017/01/06 09:14:36 maxv Exp $ */ 2 3 /* 4 * Copyright (c) 1997, 2008 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 and by Christos Zoulas. 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 /* 263 * Load the ELF binary into memory. Layout of the memory: 264 * +-----------------+------------+-----------------+-----------------+ 265 * | KERNEL SEGMENTS | ELF HEADER | SECTION HEADERS | SYMBOL SECTIONS | 266 * +-----------------+------------+-----------------+-----------------+ 267 * The KERNEL SEGMENTS start address is fixed by the segments themselves. We 268 * then map the rest by increasing maxp. 269 * 270 * The offsets of the SYMBOL SECTIONS are relative to the start address of the 271 * ELF HEADER. The shdr offset of ELF HEADER points to SECTION HEADERS. 272 * 273 * We just give the kernel a pointer to the ELF HEADER, which is enough for it 274 * to find the location and number of symbols by itself later. 275 */ 276 277 int 278 ELFNAMEEND(loadfile)(int fd, Elf_Ehdr *elf, u_long *marks, int flags) 279 { 280 Elf_Shdr *shp; 281 Elf_Phdr *phdr; 282 int i, j; 283 ssize_t sz; 284 int first; 285 Elf_Addr shpp; 286 Elf_Addr minp = ~0, maxp = 0, pos = 0, elfp = 0; 287 u_long offset = marks[MARK_START]; 288 ssize_t nr; 289 struct __packed { 290 Elf_Nhdr nh; 291 uint8_t name[ELF_NOTE_NETBSD_NAMESZ + 1]; 292 uint8_t desc[ELF_NOTE_NETBSD_DESCSZ]; 293 } note; 294 char *shstr = NULL; 295 size_t shstrsz = 0; 296 int boot_load_ctf = 1; 297 298 /* some ports dont use the offset */ 299 (void)&offset; 300 301 /* have not seen a data segment so far */ 302 marks[MARK_DATA] = 0; 303 304 internalize_ehdr(elf->e_ident[EI_DATA], elf); 305 306 sz = elf->e_phnum * sizeof(Elf_Phdr); 307 phdr = ALLOC(sz); 308 309 if (lseek(fd, elf->e_phoff, SEEK_SET) == -1) { 310 WARN(("lseek phdr")); 311 goto freephdr; 312 } 313 nr = read(fd, phdr, sz); 314 if (nr == -1) { 315 WARN(("read program headers")); 316 goto freephdr; 317 } 318 if (nr != sz) { 319 errno = EIO; 320 WARN(("read program headers")); 321 goto freephdr; 322 } 323 324 for (first = 1, i = 0; i < elf->e_phnum; i++) { 325 internalize_phdr(elf->e_ident[EI_DATA], &phdr[i]); 326 327 #ifndef MD_LOADSEG /* Allow processor ABI specific segment loads */ 328 #define MD_LOADSEG(a) /*CONSTCOND*/0 329 #endif 330 if (MD_LOADSEG(&phdr[i])) 331 goto loadseg; 332 333 if (phdr[i].p_type != PT_LOAD || 334 (phdr[i].p_flags & (PF_W|PF_X)) == 0) 335 continue; 336 337 if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) || 338 (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) { 339 loadseg: 340 /* XXX: Assume first address is lowest */ 341 if (marks[MARK_DATA] == 0 && IS_DATA(phdr[i])) 342 marks[MARK_DATA] = LOADADDR(phdr[i].p_vaddr); 343 344 /* Read in segment. */ 345 PROGRESS(("%s%lu", first ? "" : "+", 346 (u_long)phdr[i].p_filesz)); 347 348 if (lseek(fd, phdr[i].p_offset, SEEK_SET) == -1) { 349 WARN(("lseek text")); 350 goto freephdr; 351 } 352 nr = READ(fd, phdr[i].p_vaddr, phdr[i].p_filesz); 353 if (nr == -1) { 354 WARN(("read text error")); 355 goto freephdr; 356 } 357 if (nr != (ssize_t)phdr[i].p_filesz) { 358 errno = EIO; 359 WARN(("read text")); 360 goto freephdr; 361 } 362 first = 0; 363 } 364 if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT|COUNT_TEXT))) || 365 (IS_DATA(phdr[i]) && (flags & (LOAD_DATA|COUNT_DATA)))) { 366 pos = phdr[i].p_vaddr; 367 if (minp > pos) 368 minp = pos; 369 pos += phdr[i].p_filesz; 370 if (maxp < pos) 371 maxp = pos; 372 } 373 374 /* Zero out bss. */ 375 if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) { 376 PROGRESS(("+%lu", 377 (u_long)(phdr[i].p_memsz - phdr[i].p_filesz))); 378 BZERO((phdr[i].p_vaddr + phdr[i].p_filesz), 379 phdr[i].p_memsz - phdr[i].p_filesz); 380 } 381 if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) { 382 pos += phdr[i].p_memsz - phdr[i].p_filesz; 383 if (maxp < pos) 384 maxp = pos; 385 } 386 } 387 DEALLOC(phdr, sz); 388 389 /* 390 * Copy the ELF and section headers. 391 */ 392 maxp = roundup(maxp, ELFROUND); 393 if (flags & (LOAD_HDR|COUNT_HDR)) { 394 elfp = maxp; 395 maxp += sizeof(Elf_Ehdr); 396 } 397 398 if (flags & (LOAD_SYM|COUNT_SYM)) { 399 if (lseek(fd, elf->e_shoff, SEEK_SET) == -1) { 400 WARN(("lseek section headers")); 401 return 1; 402 } 403 sz = elf->e_shnum * sizeof(Elf_Shdr); 404 405 shp = ALLOC(sz); 406 407 nr = read(fd, shp, sz); 408 if (nr == -1) { 409 WARN(("read section headers")); 410 goto freeshp; 411 } 412 if (nr != sz) { 413 errno = EIO; 414 WARN(("read section headers")); 415 goto freeshp; 416 } 417 418 shpp = maxp; 419 maxp += roundup(sz, ELFROUND); 420 421 #ifndef _STANDALONE 422 /* Internalize the section headers. */ 423 for (i = 0; i < elf->e_shnum; i++) 424 internalize_shdr(elf->e_ident[EI_DATA], &shp[i]); 425 #endif 426 427 /* 428 * First load the section names section. 429 */ 430 if (boot_load_ctf && (elf->e_shstrndx != 0)) { 431 if (flags & LOAD_SYM) { 432 if (lseek(fd, shp[elf->e_shstrndx].sh_offset, 433 SEEK_SET) == -1) { 434 WARN(("lseek symbols")); 435 goto freeshp; 436 } 437 nr = READ(fd, maxp, 438 shp[elf->e_shstrndx].sh_size); 439 if (nr == -1) { 440 WARN(("read symbols")); 441 goto freeshp; 442 } 443 if (nr != 444 (ssize_t)shp[elf->e_shstrndx].sh_size) { 445 errno = EIO; 446 WARN(("read symbols")); 447 goto freeshp; 448 } 449 450 shstr = ALLOC(shp[elf->e_shstrndx].sh_size); 451 shstrsz = shp[elf->e_shstrndx].sh_size; 452 if (lseek(fd, shp[elf->e_shstrndx].sh_offset, 453 SEEK_SET) == -1) { 454 WARN(("lseek symbols")); 455 goto freeshp; 456 } 457 nr = read(fd, shstr, 458 shp[elf->e_shstrndx].sh_size); 459 if (nr == -1) { 460 WARN(("read symbols")); 461 goto freeshp; 462 } 463 } 464 shp[elf->e_shstrndx].sh_offset = maxp - elfp; 465 maxp += roundup(shp[elf->e_shstrndx].sh_size, ELFROUND); 466 } 467 468 /* 469 * Now load the symbol sections themselves. Make sure 470 * the sections are aligned. Don't bother with any 471 * string table that isn't referenced by a symbol 472 * table. 473 */ 474 for (first = 1, i = 0; i < elf->e_shnum; i++) { 475 if (i == elf->e_shstrndx) { 476 /* already loaded this section */ 477 continue; 478 } 479 switch (shp[i].sh_type) { 480 case SHT_PROGBITS: 481 if (boot_load_ctf && shstr) { 482 /* got a CTF section? */ 483 if (strncmp(".SUNW_ctf", 484 &shstr[shp[i].sh_name], 10) == 0) { 485 goto havesym; 486 } 487 } 488 489 /* Not loading this, so zero out the offset. */ 490 shp[i].sh_offset = 0; 491 break; 492 case SHT_STRTAB: 493 for (j = 0; j < elf->e_shnum; j++) 494 if (shp[j].sh_type == SHT_SYMTAB && 495 shp[j].sh_link == (unsigned int)i) 496 goto havesym; 497 /* FALLTHROUGH */ 498 default: 499 /* Not loading this, so zero out the offset. */ 500 shp[i].sh_offset = 0; 501 break; 502 havesym: 503 case SHT_SYMTAB: 504 if (flags & LOAD_SYM) { 505 PROGRESS(("%s%ld", first ? " [" : "+", 506 (u_long)shp[i].sh_size)); 507 if (lseek(fd, shp[i].sh_offset, 508 SEEK_SET) == -1) { 509 WARN(("lseek symbols")); 510 goto freeshp; 511 } 512 nr = READ(fd, maxp, shp[i].sh_size); 513 if (nr == -1) { 514 WARN(("read symbols")); 515 goto freeshp; 516 } 517 if (nr != (ssize_t)shp[i].sh_size) { 518 errno = EIO; 519 WARN(("read symbols")); 520 goto freeshp; 521 } 522 } 523 shp[i].sh_offset = maxp - elfp; 524 maxp += roundup(shp[i].sh_size, ELFROUND); 525 first = 0; 526 break; 527 case SHT_NOTE: 528 if ((flags & LOAD_NOTE) == 0) 529 break; 530 if (shp[i].sh_size < sizeof(note)) { 531 shp[i].sh_offset = 0; 532 break; 533 } 534 if (lseek(fd, shp[i].sh_offset, SEEK_SET) 535 == -1) { 536 WARN(("lseek note")); 537 goto freeshp; 538 } 539 nr = read(fd, ¬e, sizeof(note)); 540 if (nr == -1) { 541 WARN(("read note")); 542 goto freeshp; 543 } 544 if (note.nh.n_namesz == 545 ELF_NOTE_NETBSD_NAMESZ && 546 note.nh.n_descsz == 547 ELF_NOTE_NETBSD_DESCSZ && 548 note.nh.n_type == 549 ELF_NOTE_TYPE_NETBSD_TAG && 550 memcmp(note.name, ELF_NOTE_NETBSD_NAME, 551 sizeof(note.name)) == 0) { 552 memcpy(&netbsd_version, ¬e.desc, 553 sizeof(netbsd_version)); 554 } 555 shp[i].sh_offset = 0; 556 break; 557 } 558 } 559 if (flags & LOAD_SYM) { 560 #ifndef _STANDALONE 561 /* Externalize the section headers. */ 562 for (i = 0; i < elf->e_shnum; i++) 563 externalize_shdr(elf->e_ident[EI_DATA], 564 &shp[i]); 565 #endif 566 BCOPY(shp, shpp, sz); 567 568 if (first == 0) 569 PROGRESS(("]")); 570 } 571 DEALLOC(shp, sz); 572 } 573 574 if (shstr) { 575 DEALLOC(shstr, shstrsz); 576 } 577 578 /* 579 * Frob the copied ELF header to give information relative 580 * to elfp. 581 */ 582 if (flags & LOAD_HDR) { 583 elf->e_phoff = 0; 584 elf->e_shoff = sizeof(Elf_Ehdr); 585 elf->e_phentsize = 0; 586 elf->e_phnum = 0; 587 externalize_ehdr(elf->e_ident[EI_DATA], elf); 588 BCOPY(elf, elfp, sizeof(*elf)); 589 internalize_ehdr(elf->e_ident[EI_DATA], elf); 590 } 591 592 marks[MARK_START] = LOADADDR(minp); 593 marks[MARK_ENTRY] = LOADADDR(elf->e_entry); 594 /* 595 * Since there can be more than one symbol section in the code 596 * and we need to find strtab too in order to do anything 597 * useful with the symbols, we just pass the whole elf 598 * header back and we let the kernel debugger find the 599 * location and number of symbols by itself. 600 */ 601 marks[MARK_NSYM] = 1; /* XXX: Kernel needs >= 0 */ 602 marks[MARK_SYM] = LOADADDR(elfp); 603 marks[MARK_END] = LOADADDR(maxp); 604 return 0; 605 606 freephdr: 607 DEALLOC(phdr, sz); 608 return 1; 609 610 freeshp: 611 DEALLOC(shp, sz); 612 return 1; 613 } 614 615 #ifdef TEST 616 #include <stdlib.h> 617 #include <fcntl.h> 618 #include <err.h> 619 #include <stdio.h> 620 u_int32_t netbsd_version; 621 int 622 main(int argc, char *argv[]) 623 { 624 int fd; 625 u_long marks[MARK_MAX]; 626 Elf_Ehdr elf; 627 if (argc != 2) { 628 (void)fprintf(stderr, "Usage: %s <file>\n", getprogname()); 629 return 1; 630 } 631 if ((fd = open(argv[1], O_RDONLY)) == -1) 632 err(1, "Can't open `%s'", argv[1]); 633 if (read(fd, &elf, sizeof(elf)) != sizeof(elf)) 634 err(1, "Can't read `%s'", argv[1]); 635 memset(marks, 0, sizeof(marks)); 636 marks[MARK_START] = (u_long)malloc(2LL * 1024 * 2024 * 1024); 637 ELFNAMEEND(loadfile)(fd, &elf, marks, LOAD_ALL); 638 printf("%d\n", netbsd_version); 639 return 0; 640 } 641 #endif 642 643 #endif /* (ELFSIZE == 32 && BOOT_ELF32) || (ELFSIZE == 64 && BOOT_ELF64) */ 644