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