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