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