kernel/arch/riscv64: Fix elf image loading / add basic relocations

Change-Id: I0f24ef2585ae9f83a8cff8c145276d54298d1c6b
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3677
Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
This commit is contained in:
Alexander von Gluck IV 2021-01-23 19:50:09 -06:00 committed by Alex von Gluck IV
parent 08e58a41e5
commit 170aff0a14
2 changed files with 86 additions and 60 deletions

View File

@ -70,11 +70,16 @@ for platform in [ MultiBootSubDirSetup ] {
BOOT_SUPPORT_ELF64
;
}
case "risc-v" :
case "riscv64" :
{
DEFINES +=
BOOT_SUPPORT_ELF64
;
if $(TARGET_BOOT_PLATFORM) = efi {
DEFINES +=
_BOOT_PLATFORM_EFI
;
}
}
case "m68k" :
{

View File

@ -1,13 +1,15 @@
/*
* Copyright 2019, Adrien Destugues <pulkomandy@pulkomandy.tk>
* Copyright 2010, Ithamar R. Adema <ithamar.adema@team-embedded.nl>
* Copyright 2009, Johannes Wischert, johanneswi@gmail.com.
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* Copyright 2002, Travis Geiselbrecht. All rights reserved.
* Copyright 2004-2018 Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
* Copyright 2002, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#ifdef _BOOT_MODE
# include <boot/arch.h>
#endif
#include <KernelExport.h>
#include <elf_priv.h>
@ -17,10 +19,8 @@
//#define TRACE_ARCH_ELF
#ifdef TRACE_ARCH_ELF
# define TRACE(x) dprintf x
# define CHATTY 1
#else
# define TRACE(x) ;
# define CHATTY 0
#endif
@ -29,71 +29,92 @@ static bool
is_in_image(struct elf_image_info *image, addr_t address)
{
return (address >= image->text_region.start
&& address < image->text_region.start + image->text_region.size)
&& address < image->text_region.start
+ image->text_region.size)
|| (address >= image->data_region.start
&& address < image->data_region.start + image->data_region.size);
&& address < image->data_region.start
+ image->data_region.size);
}
#endif // !_BOOT_MODE
#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 *resolve_image, Elf64_Rel *rel, int rel_len)
struct elf_image_info *resolveImage, Elf64_Rel *rel, int relLength)
#endif
{
// TODO: rel entries in RISCV64 elf
return B_NO_ERROR;
}
static inline void
write_32(addr_t P, Elf32_Word value)
{
*(Elf32_Word*)P = value;
}
static inline void
write_16(addr_t P, Elf32_Word value)
{
// bits 16:29
*(Elf32_Half*)P = (Elf32_Half)value;
}
static inline bool
write_16_check(addr_t P, Elf32_Word value)
{
// bits 15:0
if ((value & 0xffff0000) && (~value & 0xffff8000))
return false;
*(Elf32_Half*)P = (Elf32_Half)value;
return true;
}
static inline bool
write_8(addr_t P, Elf32_Word value)
{
// bits 7:0
*(uint8 *)P = (uint8)value;
return true;
}
static inline bool
write_8_check(addr_t P, Elf32_Word value)
{
// bits 7:0
if ((value & 0xffffff00) && (~value & 0xffffff80))
return false;
*(uint8 *)P = (uint8)value;
return true;
dprintf("arch_elf_relocate_rel: not supported on riscv64\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 *resolve_image, Elf64_Rela *rel, int rel_len)
struct elf_image_info *resolveImage, Elf64_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,
&symAddr);
#endif
if (status < B_OK)
return status;
}
// Address of the relocation.
Elf64_Addr relocAddr = image->text_region.delta
+ rel[i].r_offset;
// Calculate the relocation value.
Elf64_Addr relocValue;
switch (type) {
case R_RISCV_NONE:
continue;
case R_RISCV_64:
relocValue = symAddr + rel[i].r_addend;
break;
case R_RISCV_RELATIVE:
relocValue = image->text_region.delta
+ rel[i].r_addend;
break;
default:
dprintf("arch_elf_relocate_rela: unhandled"
"relocation type %d\n", type);
return B_BAD_DATA;
}
#ifdef _BOOT_MODE
boot_elf64_set_relocation(relocAddr, relocValue);
#else
if (!is_in_image(image, relocAddr)) {
dprintf("arch_elf_relocate_rela: invalid offset %#lx\n",
rel[i].r_offset);
return B_BAD_ADDRESS;
}
#endif
}
return B_OK;
}