added 1 changeset to branch 'refs/remotes/xyzzy-github/x86_64' old head: 3a2a3367dc9bec2a5fbcd4ac849da6ac65e74e79 new head: ccadfaeeb577eb5f129adcc1441b92aaf9f5e443 ---------------------------------------------------------------------------- ccadfae: Changed the boot ELF code to use templates and added ELF64 support. The actual implementation of the ELF loading methods have been put into an ELFLoader template class that takes a single template parameter, which is a structure containing all the necessary ELF typedefs. It's a bit verbose, but I thought it was a neater solution than using a bunch of standalone functions with a huge number of template parameters. There is no change to code outside of elf.cpp, the ELF32/ELF64 differences are handled internally. [ Alex Smith <alex@xxxxxxxxxxxxxxxx> ] ---------------------------------------------------------------------------- Commit: ccadfaeeb577eb5f129adcc1441b92aaf9f5e443 Author: Alex Smith <alex@xxxxxxxxxxxxxxxx> Date: Sat Jun 23 11:05:16 2012 UTC ---------------------------------------------------------------------------- 6 files changed, 411 insertions(+), 302 deletions(-) headers/private/kernel/boot/arch.h | 21 +- headers/private/kernel/boot/elf.h | 19 +- headers/private/system/elf_common.h | 8 - src/system/boot/loader/Jamfile | 4 +- src/system/boot/loader/elf.cpp | 654 ++++++++++++++++++------------- src/system/boot/loader/elf.h | 7 +- ---------------------------------------------------------------------------- diff --git a/headers/private/kernel/boot/arch.h b/headers/private/kernel/boot/arch.h index 8642efe..2f4be42 100644 --- a/headers/private/kernel/boot/arch.h +++ b/headers/private/kernel/boot/arch.h @@ -5,24 +5,21 @@ #ifndef KERNEL_BOOT_ARCH_H #define KERNEL_BOOT_ARCH_H + #include <SupportDefs.h> #include <boot/elf.h> -#ifdef __cplusplus -extern "C" { -#endif - /* ELF support */ -extern status_t boot_arch_elf_relocate_rel(preloaded_elf32_image *image, - struct Elf32_Rel *rel, int rel_len); -extern status_t boot_arch_elf_relocate_rela(preloaded_elf32_image *image, - struct Elf32_Rela *rel, int rel_len); - +extern status_t boot_arch_elf_relocate_rel(preloaded_elf32_image* image, + struct Elf32_Rel* rel, int rel_len); +extern status_t boot_arch_elf_relocate_rel(preloaded_elf64_image* image, + struct Elf64_Rel* rel, int rel_len); +extern status_t boot_arch_elf_relocate_rela(preloaded_elf32_image* image, + struct Elf32_Rela* rel, int rel_len); +extern status_t boot_arch_elf_relocate_rela(preloaded_elf64_image* image, + struct Elf64_Rela* rel, int rel_len); -#ifdef __cplusplus -} -#endif #endif /* KERNEL_BOOT_ARCH_H */ diff --git a/headers/private/kernel/boot/elf.h b/headers/private/kernel/boot/elf.h index 1ef93c2..6c07ebc 100644 --- a/headers/private/kernel/boot/elf.h +++ b/headers/private/kernel/boot/elf.h @@ -1,7 +1,8 @@ /* -** Copyright 2003-2004, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights reserved. -** Distributed under the terms of the OpenBeOS License. -*/ + * Copyright 2003-2004, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx All rights reserved. + * Copyright 2012, Alex Smith, alex@xxxxxxxxxxxxxxxxx + * Distributed under the terms of the OpenBeOS License. + */ #ifndef KERNEL_BOOT_ELF_H #define KERNEL_BOOT_ELF_H @@ -76,15 +77,11 @@ struct preloaded_elf64_image : public preloaded_image { FixedWidthPointer<Elf64_Sym> debug_symbols; } _PACKED; -#ifdef __cplusplus -extern "C" { -#endif -extern status_t boot_elf_resolve_symbol(struct preloaded_elf32_image *image, - struct Elf32_Sym *symbol, addr_t *symbolAddress); +extern status_t boot_elf_resolve_symbol(preloaded_elf32_image* image, + struct Elf32_Sym* symbol, Elf32_Addr* symbolAddress); +extern status_t boot_elf_resolve_symbol(preloaded_elf64_image* image, + struct Elf64_Sym* symbol, Elf64_Addr* symbolAddress); -#ifdef __cplusplus -} -#endif #endif /* KERNEL_BOOT_ELF_H */ diff --git a/headers/private/system/elf_common.h b/headers/private/system/elf_common.h index 6a85bf2..61eb43f 100644 --- a/headers/private/system/elf_common.h +++ b/headers/private/system/elf_common.h @@ -15,14 +15,6 @@ #include <arch_elf.h> -typedef uint32 Elf32_Addr; -typedef uint16 Elf32_Half; -typedef uint32 Elf32_Off; -typedef int32 Elf32_Sword; -typedef uint32 Elf32_Word; - -typedef Elf32_Half Elf32_Versym; - /*** ELF header ***/ #define EI_NIDENT 16 diff --git a/src/system/boot/loader/Jamfile b/src/system/boot/loader/Jamfile index f325c32..c948699 100644 --- a/src/system/boot/loader/Jamfile +++ b/src/system/boot/loader/Jamfile @@ -39,7 +39,7 @@ UsePrivateHeaders shared storage ; { defines += ALTERNATE_BOOT_ARCH=\\\"x86_64\\\" - BOOT_SUPPORT_ELF64 + #BOOT_SUPPORT_ELF64 BOOT_SUPPORT_PARTITION_EFI @@ -50,7 +50,7 @@ UsePrivateHeaders shared storage ; { defines += ALTERNATE_BOOT_ARCH=\\\"x86\\\" - BOOT_SUPPORT_ELF64 + #BOOT_SUPPORT_ELF64 BOOT_SUPPORT_PARTITION_EFI diff --git a/src/system/boot/loader/elf.cpp b/src/system/boot/loader/elf.cpp index 841966b..f54e96b 100644 --- a/src/system/boot/loader/elf.cpp +++ b/src/system/boot/loader/elf.cpp @@ -30,233 +30,114 @@ static bool sLoadElfSymbols = true; -void -elf_init() -{ -// TODO: This cannot work, since the driver settings are loaded *after* the -// kernel has been loaded successfully. -#if 0 - void *settings = load_driver_settings("kernel"); - if (settings == NULL) - return; - - sLoadElfSymbols = !get_driver_boolean_parameter(settings, "load_symbols", - false, false); - unload_driver_settings(settings); +// #pragma mark - Generic ELF loader + + +template<typename Class> +class ELFLoader { +private: + typedef typename Class::ImageType ImageType; + typedef typename Class::RegionType RegionType; + typedef typename Class::EhdrType EhdrType; + typedef typename Class::PhdrType PhdrType; + typedef typename Class::ShdrType ShdrType; + typedef typename Class::DynType DynType; + typedef typename Class::SymType SymType; + typedef typename Class::RelType RelType; + typedef typename Class::RelaType RelaType; + +public: + static status_t Create(int fd, preloaded_image** _image); + static status_t Load(int fd, preloaded_image* image); + static status_t Relocate(preloaded_image* image); + +private: + static status_t _LoadSymbolTable(int fd, ImageType* image); + static status_t _ParseDynamicSection(ImageType* image); +}; + + +struct ELF32Class { + static const uint8 kIdentClass = ELFCLASS32; + + typedef preloaded_elf32_image ImageType; + typedef elf32_region RegionType; + typedef Elf32_Ehdr EhdrType; + typedef Elf32_Phdr PhdrType; + typedef Elf32_Shdr ShdrType; + typedef Elf32_Dyn DynType; + typedef Elf32_Sym SymType; + typedef Elf32_Rel RelType; + typedef Elf32_Rela RelaType; +}; + +typedef ELFLoader<ELF32Class> ELF32Loader; + + +#ifdef BOOT_SUPPORT_ELF64 +struct ELF64Class { + static const uint8 kIdentClass = ELFCLASS64; + + typedef preloaded_elf64_image ImageType; + typedef elf64_region RegionType; + typedef Elf64_Ehdr EhdrType; + typedef Elf64_Phdr PhdrType; + typedef Elf64_Shdr ShdrType; + typedef Elf64_Dyn DynType; + typedef Elf64_Sym SymType; + typedef Elf64_Rel RelType; + typedef Elf64_Rela RelaType; +}; + +typedef ELFLoader<ELF64Class> ELF64Loader; #endif -} - - -static status_t -verify_elf_header(struct Elf32_Ehdr &header) -{ - if (memcmp(header.e_ident, ELF_MAGIC, 4) != 0 - || header.e_ident[4] != ELFCLASS32 - || header.e_phoff == 0 - || !header.IsHostEndian() - || header.e_phentsize != sizeof(struct Elf32_Phdr)) - return B_BAD_TYPE; - - return B_OK; -} - - -static status_t -elf_parse_dynamic_section(preloaded_elf32_image *image) -{ - image->syms = 0; - image->rel = 0; - image->rel_len = 0; - image->rela = 0; - image->rela_len = 0; - image->pltrel = 0; - image->pltrel_len = 0; - image->pltrel_type = 0; - - struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_section.start; - if (!d) - return B_ERROR; - - for (int i = 0; d[i].d_tag != DT_NULL; i++) { - switch (d[i].d_tag) { - case DT_HASH: - case DT_STRTAB: - break; - case DT_SYMTAB: - image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr - + image->text_region.delta); - break; - case DT_REL: - image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr - + image->text_region.delta); - break; - case DT_RELSZ: - image->rel_len = d[i].d_un.d_val; - break; - case DT_RELA: - image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr - + image->text_region.delta); - break; - case DT_RELASZ: - image->rela_len = d[i].d_un.d_val; - break; - case DT_JMPREL: - image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr - + image->text_region.delta); - break; - case DT_PLTRELSZ: - image->pltrel_len = d[i].d_un.d_val; - break; - case DT_PLTREL: - image->pltrel_type = d[i].d_un.d_val; - break; - - default: - continue; - } - } - - // lets make sure we found all the required sections - if (image->syms == NULL) - return B_ERROR; - - return B_OK; -} -static status_t -load_elf_symbol_table(int fd, preloaded_elf32_image *image) +template<typename Class> +/*static*/ status_t +ELFLoader<Class>::Create(int fd, preloaded_image** _image) { - struct Elf32_Ehdr &elfHeader = image->elf_header; - Elf32_Sym *symbolTable = NULL; - Elf32_Shdr *stringHeader = NULL; - uint32 numSymbols = 0; - char *stringTable; - status_t status; - - // get section headers - - ssize_t size = elfHeader.e_shnum * elfHeader.e_shentsize; - Elf32_Shdr *sectionHeaders = (struct Elf32_Shdr *)malloc(size); - if (sectionHeaders == NULL) { - dprintf("error allocating space for section headers\n"); + ImageType* image = (ImageType*)kernel_args_malloc(sizeof(ImageType)); + if (image == NULL) return B_NO_MEMORY; - } - - ssize_t length = read_pos(fd, elfHeader.e_shoff, sectionHeaders, size); - if (length < size) { - TRACE(("error reading in program headers\n")); - status = B_ERROR; - goto error1; - } - - // find symbol table in section headers - - for (int32 i = 0; i < elfHeader.e_shnum; i++) { - if (sectionHeaders[i].sh_type == SHT_SYMTAB) { - stringHeader = §ionHeaders[sectionHeaders[i].sh_link]; - - if (stringHeader->sh_type != SHT_STRTAB) { - TRACE(("doesn't link to string table\n")); - status = B_BAD_DATA; - goto error1; - } - // read in symbol table - symbolTable = (Elf32_Sym *)kernel_args_malloc( - size = sectionHeaders[i].sh_size); - if (symbolTable == NULL) { - status = B_NO_MEMORY; - goto error1; - } + EhdrType& elfHeader = image->elf_header; - length = read_pos(fd, sectionHeaders[i].sh_offset, symbolTable, - size); - if (length < size) { - TRACE(("error reading in symbol table\n")); - status = B_ERROR; - goto error1; - } - - numSymbols = size / sizeof(Elf32_Sym); - break; - } - } - - if (symbolTable == NULL) { - TRACE(("no symbol table\n")); - status = B_BAD_VALUE; - goto error1; - } - - // read in string table - - stringTable = (char *)kernel_args_malloc(size = stringHeader->sh_size); - if (stringTable == NULL) { - status = B_NO_MEMORY; - goto error2; + ssize_t length = read_pos(fd, 0, &elfHeader, sizeof(EhdrType)); + if (length < (ssize_t)sizeof(EhdrType)) { + kernel_args_free(image); + return B_BAD_TYPE; } - length = read_pos(fd, stringHeader->sh_offset, stringTable, size); - if (length < size) { - TRACE(("error reading in string table\n")); - status = B_ERROR; - goto error3; + if (memcmp(elfHeader.e_ident, ELF_MAGIC, 4) != 0 + || elfHeader.e_ident[4] != Class::kIdentClass + || elfHeader.e_phoff == 0 + || !elfHeader.IsHostEndian() + || elfHeader.e_phentsize != sizeof(PhdrType)) { + kernel_args_free(image); + return B_BAD_TYPE; } - TRACE(("loaded %ld debug symbols\n", numSymbols)); - - // insert tables into image - image->debug_symbols = symbolTable; - image->num_debug_symbols = numSymbols; - image->debug_string_table = stringTable; - image->debug_string_table_size = size; + image->elf_class = elfHeader.e_ident[EI_CLASS]; - free(sectionHeaders); + *_image = image; return B_OK; - -error3: - kernel_args_free(stringTable); -error2: - kernel_args_free(symbolTable); -error1: - free(sectionHeaders); - - return status; } -status_t -elf_load_image(int fd, preloaded_image **_image) +template<typename Class> +/*static*/ status_t +ELFLoader<Class>::Load(int fd, preloaded_image* _image) { size_t totalSize; + ssize_t length; status_t status; - TRACE(("elf_load_image(fd = %d, _image = %p)\n", fd, _image)); - - preloaded_elf32_image *image = (preloaded_elf32_image *)kernel_args_malloc( - sizeof(preloaded_elf32_image)); - if (image == NULL) - return B_NO_MEMORY; - - struct Elf32_Ehdr &elfHeader = image->elf_header; - - ssize_t length = read_pos(fd, 0, &elfHeader, sizeof(Elf32_Ehdr)); - if (length < (ssize_t)sizeof(Elf32_Ehdr)) { - kernel_args_free(image); - return B_BAD_TYPE; - } - - status = verify_elf_header(elfHeader); - if (status < B_OK) { - kernel_args_free(image); - return status; - } - - image->elf_class = elfHeader.e_ident[EI_CLASS]; + ImageType* image = static_cast<ImageType*>(_image); + EhdrType& elfHeader = image->elf_header; ssize_t size = elfHeader.e_phnum * elfHeader.e_phentsize; - Elf32_Phdr *programHeaders = (struct Elf32_Phdr *)malloc(size); + PhdrType* programHeaders = (PhdrType*)malloc(size); if (programHeaders == NULL) { dprintf("error allocating space for program headers\n"); status = B_NO_MEMORY; @@ -276,7 +157,7 @@ elf_load_image(int fd, preloaded_image **_image) image->text_region.size = 0; for (int32 i = 0; i < elfHeader.e_phnum; i++) { - Elf32_Phdr &header = programHeaders[i]; + PhdrType& header = programHeaders[i]; switch (header.p_type) { case PT_LOAD: @@ -294,7 +175,7 @@ elf_load_image(int fd, preloaded_image **_image) continue; } - elf32_region *region; + RegionType* region; if (header.IsReadWrite()) { if (image->data_region.size != 0) { dprintf("elf: rw already handled!\n"); @@ -327,8 +208,8 @@ elf_load_image(int fd, preloaded_image **_image) } // get the segment order - elf32_region *firstRegion; - elf32_region *secondRegion; + RegionType* firstRegion; + RegionType* secondRegion; if (image->text_region.start < image->data_region.start) { firstRegion = &image->text_region; secondRegion = &image->data_region; @@ -363,13 +244,13 @@ elf_load_image(int fd, preloaded_image **_image) // load program data - for (int i = 0; i < elfHeader.e_phnum; i++) { - Elf32_Phdr &header = programHeaders[i]; + for (int32 i = 0; i < elfHeader.e_phnum; i++) { + PhdrType& header = programHeaders[i]; if (header.p_type != PT_LOAD) continue; - elf32_region *region; + RegionType* region; if (header.IsReadWrite()) region = &image->data_region; else if (header.IsExecutable()) @@ -380,11 +261,11 @@ elf_load_image(int fd, preloaded_image **_image) TRACE(("load segment %d (%ld bytes)...\n", i, header.p_filesz)); length = read_pos(fd, header.p_offset, - (void *)(region->start + (header.p_vaddr % B_PAGE_SIZE)), + (void*)(region->start + (header.p_vaddr % B_PAGE_SIZE)), header.p_filesz); if (length < (ssize_t)header.p_filesz) { status = B_BAD_DATA; - dprintf("error reading in seg %d\n", i); + dprintf("error reading in seg %ld\n", i); goto error2; } @@ -393,7 +274,7 @@ elf_load_image(int fd, preloaded_image **_image) uint32 offset = (header.p_vaddr % B_PAGE_SIZE) + header.p_filesz; if (offset < region->size) - memset((void *)(region->start + offset), 0, region->size - offset); + memset((void*)(region->start + offset), 0, region->size - offset); } // offset dynamic section, and program entry addresses by the delta of the @@ -406,16 +287,15 @@ elf_load_image(int fd, preloaded_image **_image) image->debug_string_table = NULL; if (sLoadElfSymbols) - load_elf_symbol_table(fd, image); + _LoadSymbolTable(fd, image); free(programHeaders); - *_image = image; return B_OK; error2: if (image->text_region.start != 0) - platform_free_region((void *)image->text_region.start, totalSize); + platform_free_region((void*)image->text_region.start, totalSize); error1: free(programHeaders); kernel_args_free(image); @@ -424,10 +304,270 @@ error1: } +template<typename Class> +/*static*/ status_t +ELFLoader<Class>::Relocate(preloaded_image* _image) +{ + ImageType* image = static_cast<ImageType*>(_image); + + status_t status = _ParseDynamicSection(image); + if (status != B_OK) + return status; + + // deal with the rels first + if (image->rel) { + TRACE(("total %i relocs\n", image->rel_len / (int)sizeof(RelType))); + + status = boot_arch_elf_relocate_rel(image, image->rel, image->rel_len); + if (status < B_OK) + return status; + } + + if (image->pltrel) { + TRACE(("total %i plt-relocs\n", + image->pltrel_len / (int)sizeof(RelType))); + + RelType* pltrel = image->pltrel; + if (image->pltrel_type == DT_REL) { + status = boot_arch_elf_relocate_rel(image, pltrel, + image->pltrel_len); + } else { + status = boot_arch_elf_relocate_rela(image, (RelaType *)pltrel, + image->pltrel_len); + } + if (status < B_OK) + return status; + } + + if (image->rela) { + TRACE(("total %i rela relocs\n", + image->rela_len / (int)sizeof(RelaType))); + status = boot_arch_elf_relocate_rela(image, image->rela, + image->rela_len); + if (status < B_OK) + return status; + } + + return B_OK; +} + + +template<typename Class> +/*static*/ status_t +ELFLoader<Class>::_LoadSymbolTable(int fd, ImageType* image) +{ + EhdrType& elfHeader = image->elf_header; + SymType* symbolTable = NULL; + ShdrType* stringHeader = NULL; + uint32 numSymbols = 0; + char* stringTable; + status_t status; + + // get section headers + + ssize_t size = elfHeader.e_shnum * elfHeader.e_shentsize; + ShdrType* sectionHeaders = (ShdrType*)malloc(size); + if (sectionHeaders == NULL) { + dprintf("error allocating space for section headers\n"); + return B_NO_MEMORY; + } + + ssize_t length = read_pos(fd, elfHeader.e_shoff, sectionHeaders, size); + if (length < size) { + TRACE(("error reading in program headers\n")); + status = B_ERROR; + goto error1; + } + + // find symbol table in section headers + + for (int32 i = 0; i < elfHeader.e_shnum; i++) { + if (sectionHeaders[i].sh_type == SHT_SYMTAB) { + stringHeader = §ionHeaders[sectionHeaders[i].sh_link]; + + if (stringHeader->sh_type != SHT_STRTAB) { + TRACE(("doesn't link to string table\n")); + status = B_BAD_DATA; + goto error1; + } + + // read in symbol table + size = sectionHeaders[i].sh_size; + symbolTable = (SymType*)kernel_args_malloc(size); + if (symbolTable == NULL) { + status = B_NO_MEMORY; + goto error1; + } + + length = read_pos(fd, sectionHeaders[i].sh_offset, symbolTable, + size); + if (length < size) { + TRACE(("error reading in symbol table\n")); + status = B_ERROR; + goto error1; + } + + numSymbols = size / sizeof(SymType); + break; + } + } + + if (symbolTable == NULL) { + TRACE(("no symbol table\n")); + status = B_BAD_VALUE; + goto error1; + } + + // read in string table + + size = stringHeader->sh_size; + stringTable = (char*)kernel_args_malloc(size); + if (stringTable == NULL) { + status = B_NO_MEMORY; + goto error2; + } + + length = read_pos(fd, stringHeader->sh_offset, stringTable, size); + if (length < size) { + TRACE(("error reading in string table\n")); + status = B_ERROR; + goto error3; + } + + TRACE(("loaded %ld debug symbols\n", numSymbols)); + + // insert tables into image + image->debug_symbols = symbolTable; + image->num_debug_symbols = numSymbols; + image->debug_string_table = stringTable; + image->debug_string_table_size = size; + + free(sectionHeaders); + return B_OK; + +error3: + kernel_args_free(stringTable); +error2: + kernel_args_free(symbolTable); +error1: + free(sectionHeaders); + + return status; +} + + +template<typename Class> +/*static*/ status_t +ELFLoader<Class>::_ParseDynamicSection(ImageType* image) +{ + image->syms = 0; + image->rel = 0; + image->rel_len = 0; + image->rela = 0; + image->rela_len = 0; + image->pltrel = 0; + image->pltrel_len = 0; + image->pltrel_type = 0; + + DynType* d = (DynType*)image->dynamic_section.start; + if (!d) + return B_ERROR; + + for (int i = 0; d[i].d_tag != DT_NULL; i++) { + switch (d[i].d_tag) { + case DT_HASH: + case DT_STRTAB: + break; + case DT_SYMTAB: + image->syms = (SymType*)(d[i].d_un.d_ptr + + image->text_region.delta); + break; + case DT_REL: + image->rel = (RelType*)(d[i].d_un.d_ptr + + image->text_region.delta); + break; + case DT_RELSZ: + image->rel_len = d[i].d_un.d_val; + break; + case DT_RELA: + image->rela = (RelaType*)(d[i].d_un.d_ptr + + image->text_region.delta); + break; + case DT_RELASZ: + image->rela_len = d[i].d_un.d_val; + break; + case DT_JMPREL: + image->pltrel = (RelType*)(d[i].d_un.d_ptr + + image->text_region.delta); + break; + case DT_PLTRELSZ: + image->pltrel_len = d[i].d_un.d_val; + break; + case DT_PLTREL: + image->pltrel_type = d[i].d_un.d_val; + break; + + default: + continue; + } + } + + // lets make sure we found all the required sections + if (image->syms == NULL) + return B_ERROR; + + return B_OK; +} + + +// #pragma mark - + + +void +elf_init() +{ +// TODO: This cannot work, since the driver settings are loaded *after* the +// kernel has been loaded successfully. +#if 0 + void *settings = load_driver_settings("kernel"); + if (settings == NULL) + return; + + sLoadElfSymbols = !get_driver_boolean_parameter(settings, "load_symbols", + false, false); + unload_driver_settings(settings); +#endif +} + + status_t -elf_load_image(Directory *directory, const char *path) +elf_load_image(int fd, preloaded_image** _image) { - preloaded_image *image; + status_t status; + + TRACE(("elf_load_image(fd = %d, _image = %p)\n", fd, _image)); + +#if BOOT_SUPPORT_ELF64 + status = ELF64Loader::Create(fd, _image); + if (status == B_OK) { + return ELF64Loader::Load(fd, *_image); + } else if (status == B_BAD_TYPE) { +#endif + status = ELF32Loader::Create(fd, _image); + if (status == B_OK) + return ELF32Loader::Load(fd, *_image); +#if BOOT_SUPPORT_ELF64 + } +#endif + + return status; +} + + +status_t +elf_load_image(Directory* directory, const char* path) +{ + preloaded_image* image; TRACE(("elf_load_image(directory = %p, \"%s\")\n", directory, path)); @@ -469,56 +609,20 @@ elf_load_image(Directory *directory, const char *path) status_t -elf_relocate_image(preloaded_image *_image) +elf_relocate_image(preloaded_image* image) { - preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(_image); - - status_t status = elf_parse_dynamic_section(image); - if (status != B_OK) - return status; - - // deal with the rels first - if (image->rel) { - TRACE(("total %i relocs\n", - image->rel_len / (int)sizeof(struct Elf32_Rel))); - - status = boot_arch_elf_relocate_rel(image, image->rel, image->rel_len); - if (status < B_OK) - return status; - } - - if (image->pltrel) { - TRACE(("total %i plt-relocs\n", - image->pltrel_len / (int)sizeof(struct Elf32_Rel))); - - struct Elf32_Rel *pltrel = image->pltrel; - if (image->pltrel_type == DT_REL) { - status = boot_arch_elf_relocate_rel(image, pltrel, - image->pltrel_len); - } else { - status = boot_arch_elf_relocate_rela(image, - (struct Elf32_Rela *)pltrel, image->pltrel_len); - } - if (status < B_OK) - return status; - } - - if (image->rela) { - TRACE(("total %i rela relocs\n", - image->rela_len / (int)sizeof(struct Elf32_Rela))); - status = boot_arch_elf_relocate_rela(image, image->rela, - image->rela_len); - if (status < B_OK) - return status; - } - - return B_OK; +#ifdef BOOT_SUPPORT_ELF64 + if (image->elf_class == ELFCLASS64) + return ELF64Loader::Relocate(image); + else +#endif + return ELF32Loader::Relocate(image); } -status_t -boot_elf_resolve_symbol(struct preloaded_elf32_image *image, - struct Elf32_Sym *symbol, addr_t *symbolAddress) +template<typename ImageType, typename SymType, typename AddrType> +inline status_t +resolve_symbol(ImageType* image, SymType* symbol, AddrType* symbolAddress) { switch (symbol->st_shndx) { case SHN_UNDEF: @@ -538,3 +642,21 @@ boot_elf_resolve_symbol(struct preloaded_elf32_image *image, return B_NO_ERROR; } } + + +status_t +boot_elf_resolve_symbol(preloaded_elf32_image* image, struct Elf32_Sym* symbol, + Elf32_Addr* symbolAddress) +{ + return resolve_symbol(image, symbol, symbolAddress); +} + + +#ifdef BOOT_SUPPORT_ELF64 +status_t +boot_elf_resolve_symbol(preloaded_elf64_image* image, struct Elf64_Sym* symbol, + Elf64_Addr* symbolAddress) +{ + return resolve_symbol(image, symbol, symbolAddress); +} +#endif diff --git a/src/system/boot/loader/elf.h b/src/system/boot/loader/elf.h index 9f5358a..9a0e610 100644 --- a/src/system/boot/loader/elf.h +++ b/src/system/boot/loader/elf.h @@ -11,9 +11,10 @@ extern void elf_init(); -extern status_t elf_load_image(Directory *directory, const char *path); -extern status_t elf_load_image(int fd, preloaded_image **_image); +extern status_t elf_load_image(Directory* directory, const char* path); +extern status_t elf_load_image(int fd, preloaded_image** _image); + +extern status_t elf_relocate_image(preloaded_image* image); -extern status_t elf_relocate_image(preloaded_image *image); #endif /* LOADER_ELF_H */