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