1 /* 2 * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "elf.h" 9 10 #include <boot/arch.h> 11 #include <boot/platform.h> 12 #include <boot/stage2.h> 13 #include <driver_settings.h> 14 #include <elf_private.h> 15 #include <kernel.h> 16 #include <SupportDefs.h> 17 18 #include <errno.h> 19 #include <unistd.h> 20 #include <string.h> 21 #include <stdlib.h> 22 23 //#define TRACE_ELF 24 #ifdef TRACE_ELF 25 # define TRACE(x) dprintf x 26 #else 27 # define TRACE(x) ; 28 #endif 29 30 31 static bool sLoadElfSymbols = true; 32 33 34 // #pragma mark - Generic ELF loader 35 36 37 template<typename Class> 38 class ELFLoader { 39 private: 40 typedef typename Class::ImageType ImageType; 41 typedef typename Class::RegionType RegionType; 42 typedef typename Class::AddrType AddrType; 43 typedef typename Class::EhdrType EhdrType; 44 typedef typename Class::PhdrType PhdrType; 45 typedef typename Class::ShdrType ShdrType; 46 typedef typename Class::DynType DynType; 47 typedef typename Class::SymType SymType; 48 typedef typename Class::RelType RelType; 49 typedef typename Class::RelaType RelaType; 50 51 public: 52 static status_t Create(int fd, preloaded_image** _image); 53 static status_t Load(int fd, preloaded_image* image); 54 static status_t Relocate(preloaded_image* image); 55 static status_t Resolve(ImageType* image, SymType* symbol, 56 AddrType* symbolAddress); 57 58 private: 59 static status_t _LoadSymbolTable(int fd, ImageType* image); 60 static status_t _ParseDynamicSection(ImageType* image); 61 }; 62 63 64 #ifdef BOOT_SUPPORT_ELF32 65 struct ELF32Class { 66 static const uint8 kIdentClass = ELFCLASS32; 67 68 typedef preloaded_elf32_image ImageType; 69 typedef elf32_region RegionType; 70 typedef Elf32_Addr AddrType; 71 typedef Elf32_Ehdr EhdrType; 72 typedef Elf32_Phdr PhdrType; 73 typedef Elf32_Shdr ShdrType; 74 typedef Elf32_Dyn DynType; 75 typedef Elf32_Sym SymType; 76 typedef Elf32_Rel RelType; 77 typedef Elf32_Rela RelaType; 78 79 static inline status_t 80 AllocateRegion(AddrType* _address, AddrType size, uint8 protection, 81 void** _mappedAddress) 82 { 83 status_t status = platform_allocate_region((void**)_address, size, 84 protection, false); 85 if (status != B_OK) 86 return status; 87 88 *_mappedAddress = (void*)*_address; 89 return B_OK; 90 } 91 92 static inline void* 93 Map(AddrType address) 94 { 95 return (void*)address; 96 } 97 }; 98 99 typedef ELFLoader<ELF32Class> ELF32Loader; 100 #endif 101 102 103 #ifdef BOOT_SUPPORT_ELF64 104 struct ELF64Class { 105 static const uint8 kIdentClass = ELFCLASS64; 106 107 typedef preloaded_elf64_image ImageType; 108 typedef elf64_region RegionType; 109 typedef Elf64_Addr AddrType; 110 typedef Elf64_Ehdr EhdrType; 111 typedef Elf64_Phdr PhdrType; 112 typedef Elf64_Shdr ShdrType; 113 typedef Elf64_Dyn DynType; 114 typedef Elf64_Sym SymType; 115 typedef Elf64_Rel RelType; 116 typedef Elf64_Rela RelaType; 117 118 static inline status_t 119 AllocateRegion(AddrType* _address, AddrType size, uint8 protection, 120 void **_mappedAddress) 121 { 122 #if defined(_BOOT_PLATFORM_BIOS) 123 // Assume the real 64-bit base address is KERNEL_LOAD_BASE_64_BIT and 124 // the mappings in the loader address space are at KERNEL_LOAD_BASE. 125 126 void* address = (void*)(addr_t)(*_address & 0xffffffff); 127 #else 128 void* address = (void*)*_address; 129 #endif 130 131 status_t status = platform_allocate_region(&address, size, protection, 132 false); 133 if (status != B_OK) 134 return status; 135 136 *_mappedAddress = address; 137 #if defined(_BOOT_PLATFORM_BIOS) 138 *_address = (AddrType)(addr_t)address + KERNEL_LOAD_BASE_64_BIT 139 - KERNEL_LOAD_BASE; 140 #else 141 platform_bootloader_address_to_kernel_address(address, _address); 142 #endif 143 return B_OK; 144 } 145 146 static inline void* 147 Map(AddrType address) 148 { 149 #ifdef _BOOT_PLATFORM_BIOS 150 return (void*)(addr_t)(address - KERNEL_LOAD_BASE_64_BIT 151 + KERNEL_LOAD_BASE); 152 #else 153 void *result; 154 if (platform_kernel_address_to_bootloader_address(address, &result) != B_OK) { 155 panic("Couldn't convert address %#" PRIx64, address); 156 } 157 return result; 158 #endif 159 } 160 }; 161 162 typedef ELFLoader<ELF64Class> ELF64Loader; 163 #endif 164 165 166 template<typename Class> 167 /*static*/ status_t 168 ELFLoader<Class>::Create(int fd, preloaded_image** _image) 169 { 170 ImageType* image = (ImageType*)kernel_args_malloc(sizeof(ImageType)); 171 if (image == NULL) 172 return B_NO_MEMORY; 173 174 ssize_t length = read_pos(fd, 0, &image->elf_header, sizeof(EhdrType)); 175 if (length < (ssize_t)sizeof(EhdrType)) { 176 kernel_args_free(image); 177 return B_BAD_TYPE; 178 } 179 180 const EhdrType& elfHeader = image->elf_header; 181 182 if (memcmp(elfHeader.e_ident, ELFMAG, 4) != 0 183 || elfHeader.e_ident[4] != Class::kIdentClass 184 || elfHeader.e_phoff == 0 185 || !elfHeader.IsHostEndian() 186 || elfHeader.e_phentsize != sizeof(PhdrType)) { 187 kernel_args_free(image); 188 return B_BAD_TYPE; 189 } 190 191 image->elf_class = elfHeader.e_ident[EI_CLASS]; 192 193 *_image = image; 194 return B_OK; 195 } 196 197 198 template<typename Class> 199 /*static*/ status_t 200 ELFLoader<Class>::Load(int fd, preloaded_image* _image) 201 { 202 size_t totalSize; 203 ssize_t length; 204 status_t status; 205 void* mappedRegion = NULL; 206 207 ImageType* image = static_cast<ImageType*>(_image); 208 const EhdrType& elfHeader = image->elf_header; 209 210 ssize_t size = elfHeader.e_phnum * elfHeader.e_phentsize; 211 PhdrType* programHeaders = (PhdrType*)malloc(size); 212 if (programHeaders == NULL) { 213 dprintf("error allocating space for program headers\n"); 214 status = B_NO_MEMORY; 215 goto error1; 216 } 217 218 length = read_pos(fd, elfHeader.e_phoff, programHeaders, size); 219 if (length < size) { 220 TRACE(("error reading in program headers\n")); 221 status = B_ERROR; 222 goto error1; 223 } 224 225 // create an area large enough to hold the image 226 227 image->data_region.size = 0; 228 image->text_region.size = 0; 229 230 for (int32 i = 0; i < elfHeader.e_phnum; i++) { 231 PhdrType& header = programHeaders[i]; 232 233 switch (header.p_type) { 234 case PT_LOAD: 235 break; 236 case PT_DYNAMIC: 237 image->dynamic_section.start = header.p_vaddr; 238 image->dynamic_section.size = header.p_memsz; 239 continue; 240 case PT_INTERP: 241 case PT_PHDR: 242 case PT_ARM_UNWIND: 243 // known but unused type 244 continue; 245 default: 246 dprintf("unhandled pheader type 0x%" B_PRIx32 "\n", header.p_type); 247 continue; 248 } 249 250 RegionType* region; 251 if (header.IsReadWrite()) { 252 if (image->data_region.size != 0) { 253 dprintf("elf: rw already handled!\n"); 254 continue; 255 } 256 region = &image->data_region; 257 } else if (header.IsExecutable()) { 258 if (image->text_region.size != 0) { 259 dprintf("elf: ro already handled!\n"); 260 continue; 261 } 262 region = &image->text_region; 263 } else 264 continue; 265 266 region->start = ROUNDDOWN(header.p_vaddr, B_PAGE_SIZE); 267 region->size = ROUNDUP(header.p_memsz + (header.p_vaddr % B_PAGE_SIZE), 268 B_PAGE_SIZE); 269 region->delta = -region->start; 270 271 TRACE(("segment %" B_PRId32 ": start = 0x%" B_PRIx64 ", size = %" 272 B_PRIu64 ", delta = %" B_PRIx64 "\n", i, (uint64)region->start, 273 (uint64)region->size, (int64)(AddrType)region->delta)); 274 } 275 276 277 // found both, text and data? 278 if (image->data_region.size == 0 || image->text_region.size == 0) { 279 dprintf("Couldn't find both text and data segment!\n"); 280 status = B_BAD_DATA; 281 goto error1; 282 } 283 284 // get the segment order 285 RegionType* firstRegion; 286 RegionType* secondRegion; 287 if (image->text_region.start < image->data_region.start) { 288 firstRegion = &image->text_region; 289 secondRegion = &image->data_region; 290 } else { 291 firstRegion = &image->data_region; 292 secondRegion = &image->text_region; 293 } 294 295 // The kernel and the modules are relocatable, thus AllocateRegion() 296 // can automatically allocate an address, but shall prefer the specified 297 // base address. 298 totalSize = secondRegion->start + secondRegion->size - firstRegion->start; 299 { 300 AddrType address = firstRegion->start; 301 if (Class::AllocateRegion(&address, totalSize, 302 B_READ_AREA | B_WRITE_AREA | B_EXECUTE_AREA, &mappedRegion) 303 != B_OK) { 304 status = B_NO_MEMORY; 305 goto error1; 306 } 307 firstRegion->start = address; 308 } 309 310 // initialize the region pointers to the allocated region 311 secondRegion->start += firstRegion->start + firstRegion->delta; 312 313 image->data_region.delta += image->data_region.start; 314 image->text_region.delta += image->text_region.start; 315 316 TRACE(("text: start 0x%" B_PRIx64 ", size 0x%" B_PRIx64 ", delta 0x%" 317 B_PRIx64 "\n", (uint64)image->text_region.start, 318 (uint64)image->text_region.size, 319 (int64)(AddrType)image->text_region.delta)); 320 TRACE(("data: start 0x%" B_PRIx64 ", size 0x%" B_PRIx64 ", delta 0x%" 321 B_PRIx64 "\n", (uint64)image->data_region.start, 322 (uint64)image->data_region.size, 323 (int64)(AddrType)image->data_region.delta)); 324 325 // load program data 326 327 for (int32 i = 0; i < elfHeader.e_phnum; i++) { 328 PhdrType& header = programHeaders[i]; 329 330 if (header.p_type != PT_LOAD) 331 continue; 332 333 RegionType* region; 334 if (header.IsReadWrite()) 335 region = &image->data_region; 336 else if (header.IsExecutable()) 337 region = &image->text_region; 338 else 339 continue; 340 341 TRACE(("load segment %" PRId32 " (%" PRIu64 " bytes) mapped at %p...\n", 342 i, (uint64)header.p_filesz, Class::Map(region->start))); 343 344 length = read_pos(fd, header.p_offset, 345 Class::Map(region->start + (header.p_vaddr % B_PAGE_SIZE)), 346 header.p_filesz); 347 if (length < (ssize_t)header.p_filesz) { 348 status = B_BAD_DATA; 349 dprintf("error reading in seg %" B_PRId32 "\n", i); 350 goto error2; 351 } 352 353 // Clear anything above the file size (that may also contain the BSS 354 // area) 355 356 uint32 offset = (header.p_vaddr % B_PAGE_SIZE) + header.p_filesz; 357 if (offset < region->size) 358 memset(Class::Map(region->start + offset), 0, region->size - offset); 359 } 360 361 // offset dynamic section, and program entry addresses by the delta of the 362 // regions 363 image->dynamic_section.start += image->text_region.delta; 364 image->elf_header.e_entry += image->text_region.delta; 365 366 image->num_debug_symbols = 0; 367 image->debug_symbols = NULL; 368 image->debug_string_table = NULL; 369 370 if (sLoadElfSymbols) 371 _LoadSymbolTable(fd, image); 372 373 free(programHeaders); 374 375 return B_OK; 376 377 error2: 378 if (mappedRegion != NULL) 379 platform_free_region(mappedRegion, totalSize); 380 error1: 381 free(programHeaders); 382 kernel_args_free(image); 383 384 return status; 385 } 386 387 388 template<typename Class> 389 /*static*/ status_t 390 ELFLoader<Class>::Relocate(preloaded_image* _image) 391 { 392 ImageType* image = static_cast<ImageType*>(_image); 393 394 status_t status = _ParseDynamicSection(image); 395 if (status != B_OK) 396 return status; 397 398 // deal with the rels first 399 if (image->rel) { 400 TRACE(("total %i relocs\n", 401 (int)image->rel_len / (int)sizeof(RelType))); 402 403 status = boot_arch_elf_relocate_rel(image, image->rel, image->rel_len); 404 if (status != B_OK) 405 return status; 406 } 407 408 if (image->pltrel) { 409 RelType* pltrel = image->pltrel; 410 if (image->pltrel_type == DT_REL) { 411 TRACE(("total %i plt-relocs\n", 412 (int)image->pltrel_len / (int)sizeof(RelType))); 413 414 status = boot_arch_elf_relocate_rel(image, pltrel, 415 image->pltrel_len); 416 } else { 417 TRACE(("total %i plt-relocs\n", 418 (int)image->pltrel_len / (int)sizeof(RelaType))); 419 420 status = boot_arch_elf_relocate_rela(image, (RelaType*)pltrel, 421 image->pltrel_len); 422 } 423 if (status != B_OK) 424 return status; 425 } 426 427 if (image->rela) { 428 TRACE(("total %i rela relocs\n", 429 (int)image->rela_len / (int)sizeof(RelaType))); 430 status = boot_arch_elf_relocate_rela(image, image->rela, 431 image->rela_len); 432 if (status != B_OK) 433 return status; 434 } 435 436 return B_OK; 437 } 438 439 template<typename Class> 440 /*static*/ status_t 441 ELFLoader<Class>::Resolve(ImageType* image, SymType* symbol, 442 AddrType* symbolAddress) 443 { 444 switch (symbol->st_shndx) { 445 case SHN_UNDEF: 446 // Since we do that only for the kernel, there shouldn't be 447 // undefined symbols. 448 TRACE(("elf_resolve_symbol: undefined symbol\n")); 449 return B_MISSING_SYMBOL; 450 case SHN_ABS: 451 *symbolAddress = symbol->st_value; 452 return B_NO_ERROR; 453 case SHN_COMMON: 454 // ToDo: finish this 455 TRACE(("elf_resolve_symbol: COMMON symbol, finish me!\n")); 456 return B_ERROR; 457 default: 458 // standard symbol 459 *symbolAddress = symbol->st_value + image->text_region.delta; 460 return B_OK; 461 } 462 } 463 464 465 template<typename Class> 466 /*static*/ status_t 467 ELFLoader<Class>::_LoadSymbolTable(int fd, ImageType* image) 468 { 469 const EhdrType& elfHeader = image->elf_header; 470 SymType* symbolTable = NULL; 471 ShdrType* stringHeader = NULL; 472 uint32 numSymbols = 0; 473 char* stringTable; 474 status_t status; 475 476 // get section headers 477 478 ssize_t size = elfHeader.e_shnum * elfHeader.e_shentsize; 479 ShdrType* sectionHeaders = (ShdrType*)malloc(size); 480 if (sectionHeaders == NULL) { 481 dprintf("error allocating space for section headers\n"); 482 return B_NO_MEMORY; 483 } 484 485 ssize_t length = read_pos(fd, elfHeader.e_shoff, sectionHeaders, size); 486 if (length < size) { 487 TRACE(("error reading in program headers\n")); 488 status = B_ERROR; 489 goto error1; 490 } 491 492 // find symbol table in section headers 493 494 for (int32 i = 0; i < elfHeader.e_shnum; i++) { 495 if (sectionHeaders[i].sh_type == SHT_SYMTAB) { 496 stringHeader = §ionHeaders[sectionHeaders[i].sh_link]; 497 498 if (stringHeader->sh_type != SHT_STRTAB) { 499 TRACE(("doesn't link to string table\n")); 500 status = B_BAD_DATA; 501 goto error1; 502 } 503 504 // read in symbol table 505 size = sectionHeaders[i].sh_size; 506 symbolTable = (SymType*)kernel_args_malloc(size); 507 if (symbolTable == NULL) { 508 status = B_NO_MEMORY; 509 goto error1; 510 } 511 512 length = read_pos(fd, sectionHeaders[i].sh_offset, symbolTable, 513 size); 514 if (length < size) { 515 TRACE(("error reading in symbol table\n")); 516 status = B_ERROR; 517 goto error1; 518 } 519 520 numSymbols = size / sizeof(SymType); 521 break; 522 } 523 } 524 525 if (symbolTable == NULL) { 526 TRACE(("no symbol table\n")); 527 status = B_BAD_VALUE; 528 goto error1; 529 } 530 531 // read in string table 532 533 size = stringHeader->sh_size; 534 stringTable = (char*)kernel_args_malloc(size); 535 if (stringTable == NULL) { 536 status = B_NO_MEMORY; 537 goto error2; 538 } 539 540 length = read_pos(fd, stringHeader->sh_offset, stringTable, size); 541 if (length < size) { 542 TRACE(("error reading in string table\n")); 543 status = B_ERROR; 544 goto error3; 545 } 546 547 TRACE(("loaded %" B_PRIu32 " debug symbols\n", numSymbols)); 548 549 // insert tables into image 550 image->debug_symbols = symbolTable; 551 image->num_debug_symbols = numSymbols; 552 image->debug_string_table = stringTable; 553 image->debug_string_table_size = size; 554 555 free(sectionHeaders); 556 return B_OK; 557 558 error3: 559 kernel_args_free(stringTable); 560 error2: 561 kernel_args_free(symbolTable); 562 error1: 563 free(sectionHeaders); 564 565 return status; 566 } 567 568 569 template<typename Class> 570 /*static*/ status_t 571 ELFLoader<Class>::_ParseDynamicSection(ImageType* image) 572 { 573 image->syms = 0; 574 image->rel = 0; 575 image->rel_len = 0; 576 image->rela = 0; 577 image->rela_len = 0; 578 image->pltrel = 0; 579 image->pltrel_len = 0; 580 image->pltrel_type = 0; 581 582 if(image->dynamic_section.start == 0) 583 return B_ERROR; 584 585 DynType* d = (DynType*)Class::Map(image->dynamic_section.start); 586 587 for (int i = 0; d[i].d_tag != DT_NULL; i++) { 588 switch (d[i].d_tag) { 589 case DT_HASH: 590 case DT_STRTAB: 591 break; 592 case DT_SYMTAB: 593 image->syms = (SymType*)Class::Map(d[i].d_un.d_ptr 594 + image->text_region.delta); 595 break; 596 case DT_REL: 597 image->rel = (RelType*)Class::Map(d[i].d_un.d_ptr 598 + image->text_region.delta); 599 break; 600 case DT_RELSZ: 601 image->rel_len = d[i].d_un.d_val; 602 break; 603 case DT_RELA: 604 image->rela = (RelaType*)Class::Map(d[i].d_un.d_ptr 605 + image->text_region.delta); 606 break; 607 case DT_RELASZ: 608 image->rela_len = d[i].d_un.d_val; 609 break; 610 case DT_JMPREL: 611 image->pltrel = (RelType*)Class::Map(d[i].d_un.d_ptr 612 + image->text_region.delta); 613 break; 614 case DT_PLTRELSZ: 615 image->pltrel_len = d[i].d_un.d_val; 616 break; 617 case DT_PLTREL: 618 image->pltrel_type = d[i].d_un.d_val; 619 break; 620 621 default: 622 continue; 623 } 624 } 625 626 // lets make sure we found all the required sections 627 if (image->syms == NULL) 628 return B_ERROR; 629 630 return B_OK; 631 } 632 633 634 // #pragma mark - 635 636 637 void 638 elf_init() 639 { 640 void* settings = load_driver_settings("kernel"); 641 if (settings == NULL) 642 return; 643 644 sLoadElfSymbols = get_driver_boolean_parameter(settings, "load_symbols", 645 false, false); 646 647 unload_driver_settings(settings); 648 } 649 650 651 status_t 652 elf_load_image(int fd, preloaded_image** _image) 653 { 654 status_t status = B_ERROR; 655 656 TRACE(("elf_load_image(fd = %d, _image = %p)\n", fd, _image)); 657 658 #if BOOT_SUPPORT_ELF64 659 if (gKernelArgs.kernel_image == NULL 660 || gKernelArgs.kernel_image->elf_class == ELFCLASS64) { 661 status = ELF64Loader::Create(fd, _image); 662 if (status == B_OK) 663 return ELF64Loader::Load(fd, *_image); 664 else if (status != B_BAD_TYPE) 665 return status; 666 } 667 #endif 668 #if BOOT_SUPPORT_ELF32 669 if (gKernelArgs.kernel_image == NULL 670 || gKernelArgs.kernel_image->elf_class == ELFCLASS32) { 671 status = ELF32Loader::Create(fd, _image); 672 if (status == B_OK) 673 return ELF32Loader::Load(fd, *_image); 674 } 675 #endif 676 677 return status; 678 } 679 680 681 status_t 682 elf_load_image(Directory* directory, const char* path) 683 { 684 preloaded_image* image; 685 686 TRACE(("elf_load_image(directory = %p, \"%s\")\n", directory, path)); 687 688 int fd = open_from(directory, path, O_RDONLY); 689 if (fd < 0) 690 return fd; 691 692 // check if this file has already been loaded 693 694 struct stat stat; 695 if (fstat(fd, &stat) < 0) 696 return errno; 697 698 image = gKernelArgs.preloaded_images; 699 for (; image != NULL; image = image->next) { 700 if (image->inode == stat.st_ino) { 701 // file has already been loaded, no need to load it twice! 702 close(fd); 703 return B_OK; 704 } 705 } 706 707 // we still need to load it, so do it 708 709 status_t status = elf_load_image(fd, &image); 710 if (status == B_OK) { 711 image->name = kernel_args_strdup(path); 712 image->inode = stat.st_ino; 713 714 // insert to kernel args 715 image->next = gKernelArgs.preloaded_images; 716 gKernelArgs.preloaded_images = image; 717 } else 718 kernel_args_free(image); 719 720 close(fd); 721 return status; 722 } 723 724 725 status_t 726 elf_relocate_image(preloaded_image* image) 727 { 728 #ifdef BOOT_SUPPORT_ELF64 729 if (image->elf_class == ELFCLASS64) 730 return ELF64Loader::Relocate(image); 731 #endif 732 #ifdef BOOT_SUPPORT_ELF32 733 if (image->elf_class == ELFCLASS32) 734 return ELF32Loader::Relocate(image); 735 #endif 736 return B_ERROR; 737 } 738 739 740 #ifdef BOOT_SUPPORT_ELF32 741 status_t 742 boot_elf_resolve_symbol(preloaded_elf32_image* image, Elf32_Sym* symbol, 743 Elf32_Addr* symbolAddress) 744 { 745 return ELF32Loader::Resolve(image, symbol, symbolAddress); 746 } 747 #endif 748 749 750 #ifdef BOOT_SUPPORT_ELF64 751 status_t 752 boot_elf_resolve_symbol(preloaded_elf64_image* image, Elf64_Sym* symbol, 753 Elf64_Addr* symbolAddress) 754 { 755 return ELF64Loader::Resolve(image, symbol, symbolAddress); 756 } 757 758 void 759 boot_elf64_set_relocation(Elf64_Addr resolveAddress, Elf64_Addr finalAddress) 760 { 761 Elf64_Addr* dest = (Elf64_Addr*)ELF64Class::Map(resolveAddress); 762 *dest = finalAddress; 763 } 764 #endif 765