From f6a3444449c452a63e0e0d91e8480f39bca81aed Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 24 Jun 2012 19:22:33 +0100 Subject: [PATCH] Added x86_64 ELF64 relocation functions for the bootloader. All that's left to do now is handle the 64-bit load address properly. --- headers/private/kernel/elf_priv.h | 2 +- .../private/runtime_loader/runtime_loader.h | 2 +- src/system/boot/arch/x86/Jamfile | 1 + src/system/boot/arch/x86/arch_elf64.cpp | 1 + src/system/boot/arch/x86_64/Jamfile | 3 + src/system/boot/loader/Jamfile | 4 +- src/system/kernel/arch/x86/arch_elf.cpp | 1 - src/system/kernel/arch/x86_64/arch_elf.cpp | 86 +++++++++++++++++++ 8 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 src/system/boot/arch/x86/arch_elf64.cpp diff --git a/headers/private/kernel/elf_priv.h b/headers/private/kernel/elf_priv.h index 8169574606..fd386c49d4 100644 --- a/headers/private/kernel/elf_priv.h +++ b/headers/private/kernel/elf_priv.h @@ -69,7 +69,7 @@ struct elf_image_info { #define STRING(image, offset) ((char *)(&(image)->strtab[(offset)])) #define SYMNAME(image, sym) STRING(image, (sym)->st_name) -#define SYMBOL(image, num) ((struct Elf32_Sym *)&(image)->syms[num]) +#define SYMBOL(image, num) (&(image)->syms[num]) #define HASHTABSIZE(image) ((image)->symhash[0]) #define HASHBUCKETS(image) ((unsigned int *)&(image)->symhash[2]) #define HASHCHAINS(image) ((unsigned int *)&(image)->symhash[2+HASHTABSIZE(image)]) diff --git a/headers/private/runtime_loader/runtime_loader.h b/headers/private/runtime_loader/runtime_loader.h index 132a674f5d..ddccda1209 100644 --- a/headers/private/runtime_loader/runtime_loader.h +++ b/headers/private/runtime_loader/runtime_loader.h @@ -154,7 +154,7 @@ typedef struct image_queue_t { #define STRING(image, offset) ((char *)(&(image)->strtab[(offset)])) #define SYMNAME(image, sym) STRING(image, (sym)->st_name) -#define SYMBOL(image, num) ((struct Elf32_Sym *)&(image)->syms[num]) +#define SYMBOL(image, num) (&(image)->syms[num]) #define HASHTABSIZE(image) ((image)->symhash[0]) #define HASHBUCKETS(image) ((unsigned int *)&(image)->symhash[2]) #define HASHCHAINS(image) ((unsigned int *)&(image)->symhash[2+HASHTABSIZE(image)]) diff --git a/src/system/boot/arch/x86/Jamfile b/src/system/boot/arch/x86/Jamfile index 21eb0ac506..e7cff1e494 100644 --- a/src/system/boot/arch/x86/Jamfile +++ b/src/system/boot/arch/x86/Jamfile @@ -19,6 +19,7 @@ local kernelLibArchObjects = ; BootMergeObject boot_arch_$(TARGET_ARCH).o : + arch_elf64.cpp $(kernelArchSources) $(kernelLibArchSources) : # additional flags diff --git a/src/system/boot/arch/x86/arch_elf64.cpp b/src/system/boot/arch/x86/arch_elf64.cpp new file mode 100644 index 0000000000..41e0198ea1 --- /dev/null +++ b/src/system/boot/arch/x86/arch_elf64.cpp @@ -0,0 +1 @@ +#include "../../../kernel/arch/x86_64/arch_elf.cpp" diff --git a/src/system/boot/arch/x86_64/Jamfile b/src/system/boot/arch/x86_64/Jamfile index dae289606e..3dd041891b 100644 --- a/src/system/boot/arch/x86_64/Jamfile +++ b/src/system/boot/arch/x86_64/Jamfile @@ -16,6 +16,7 @@ local librootOsArchSources = ; BootMergeObject boot_arch_$(TARGET_ARCH).o : + arch_elf64.cpp $(kernelArchSources) $(kernelLibArchSources) $(librootOsArchSources) @@ -28,3 +29,5 @@ SEARCH on [ FGristFiles $(kernelLibArchSources) ] = [ FDirName $(HAIKU_TOP) src system kernel lib arch x86 ] ; SEARCH on [ FGristFiles $(librootOsArchSources) ] = [ FDirName $(HAIKU_TOP) src system libroot os arch x86 ] ; +SEARCH on [ FGristFiles $(kernelArchSources) ] + = [ FDirName $(HAIKU_TOP) src system boot arch x86 ] ; diff --git a/src/system/boot/loader/Jamfile b/src/system/boot/loader/Jamfile index c9486992e9..f325c3279f 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/kernel/arch/x86/arch_elf.cpp b/src/system/kernel/arch/x86/arch_elf.cpp index df6cebe250..20570527d0 100644 --- a/src/system/kernel/arch/x86/arch_elf.cpp +++ b/src/system/kernel/arch/x86/arch_elf.cpp @@ -178,4 +178,3 @@ arch_elf_relocate_rela(struct elf_image_info *image, dprintf("arch_elf_relocate_rela: not supported on x86\n"); return B_ERROR; } - diff --git a/src/system/kernel/arch/x86_64/arch_elf.cpp b/src/system/kernel/arch/x86_64/arch_elf.cpp index f8c6ad280e..b0cbe9d04a 100644 --- a/src/system/kernel/arch/x86_64/arch_elf.cpp +++ b/src/system/kernel/arch/x86_64/arch_elf.cpp @@ -3,10 +3,19 @@ * Distributed under the terms of the MIT License. */ +#ifdef _BOOT_MODE +# include +#endif + +#include #include +#include + +#include +#ifndef _BOOT_MODE // Currently got generic elf.cpp #ifdef'd out for x86_64, define stub versions here. status_t @@ -80,3 +89,80 @@ _user_read_kernel_image_symbols(image_id id, struct Elf32_Sym* symbolTable, { return B_ERROR; } +#endif + +#ifdef _BOOT_MODE +status_t +boot_arch_elf_relocate_rel(preloaded_elf64_image* image, Elf64_Rel* rel, + int relLength) +//#else +//int +//arch_elf_relocate_rel(struct elf_image_info *image, +// struct elf_image_info *resolveImage, struct Elf32_Rel *rel, int relLength) +//#endif +{ + dprintf("arch_elf_relocate_rel: not supported on x86_64\n"); + return B_ERROR; +} + + +//#ifdef _BOOT_MODE +status_t +boot_arch_elf_relocate_rela(preloaded_elf64_image* image, Elf64_Rela* rel, + int relLength) +//#else +//int +//arch_elf_relocate_rela(struct elf_image_info *image, +// struct elf_image_info *resolveImage, struct Elf32_Rela *rel, int relLength) +//#endif +{ + for (int i = 0; i < relLength / (int)sizeof(Elf64_Rela); i++) { + int type = ELF64_R_TYPE(rel[i].r_info); + int symIndex = ELF64_R_SYM(rel[i].r_info); + Elf64_Addr symAddr = 0; + + // Resolve the symbol, if any. + if (symIndex != 0) { + Elf64_Sym* symbol = SYMBOL(image, symIndex); + + status_t status; +//#ifdef _BOOT_MODE + status = boot_elf_resolve_symbol(image, symbol, &symAddr); +//#else +// status = elf_resolve_symbol(image, symbol, resolveImage, &S); +//#endif + if (status < B_OK) + return status; + } + + // Address of the relocation. + Elf64_Addr* resolveAddr = (Elf64_Addr *)(image->text_region.delta + + rel[i].r_offset); + + // Perform the relocation. + switch(type) { + case R_X86_64_NONE: + break; + case R_X86_64_64: + *resolveAddr = symAddr + rel[i].r_addend; + break; + case R_X86_64_PC32: + *resolveAddr = symAddr + rel[i].r_addend - rel[i].r_offset; + break; + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: + *resolveAddr = symAddr + rel[i].r_addend; + break; + case R_X86_64_RELATIVE: + *resolveAddr = image->text_region.delta + rel[i].r_addend; + break; + default: + dprintf("arch_elf_relocate_rel: unhandled relocation type %d\n", + type); + return B_BAD_DATA; + } + } + + return B_OK; +} +#endif