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