xref: /haiku/src/system/boot/loader/elf.cpp (revision 644fa5a93845dc4a1bc155f1fd0f94ebdf0b47bc)
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 = &sectionHeaders[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