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
AllocateRegionELF32Class80 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*
MapELF32Class99 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
AllocateRegionELF64Class130 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*
MapELF64Class157 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
Create(int fd,preloaded_image ** _image)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
Load(int fd,preloaded_image * _image)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
Relocate(preloaded_image * _image)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
Resolve(ImageType * image,SymType * symbol,AddrType * symbolAddress)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
_LoadSymbolTable(int fd,ImageType * image)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
_ParseDynamicSection(ImageType * image)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
elf_init()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
elf_load_image(int fd,preloaded_image ** _image)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
elf_load_image(Directory * directory,const char * path)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
elf_relocate_image(preloaded_image * image)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
boot_elf_resolve_symbol(preloaded_elf32_image * image,Elf32_Sym * symbol,Elf32_Addr * symbolAddress)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
boot_elf32_get_relocation(Elf32_Addr resolveAddress)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
boot_elf32_set_relocation(Elf32_Addr resolveAddress,Elf32_Addr finalAddress)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
boot_elf_resolve_symbol(preloaded_elf64_image * image,Elf64_Sym * symbol,Elf64_Addr * symbolAddress)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
boot_elf64_set_relocation(Elf64_Addr resolveAddress,Elf64_Addr finalAddress)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