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:
parent
08e58a41e5
commit
170aff0a14
@ -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" :
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user