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 <[email protected]>
This commit is contained in:
committed by
Alex von Gluck IV
parent
08e58a41e5
commit
170aff0a14
@@ -70,11 +70,16 @@ for platform in [ MultiBootSubDirSetup ] {
|
|||||||
BOOT_SUPPORT_ELF64
|
BOOT_SUPPORT_ELF64
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
case "risc-v" :
|
case "riscv64" :
|
||||||
{
|
{
|
||||||
DEFINES +=
|
DEFINES +=
|
||||||
BOOT_SUPPORT_ELF64
|
BOOT_SUPPORT_ELF64
|
||||||
;
|
;
|
||||||
|
if $(TARGET_BOOT_PLATFORM) = efi {
|
||||||
|
DEFINES +=
|
||||||
|
_BOOT_PLATFORM_EFI
|
||||||
|
;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case "m68k" :
|
case "m68k" :
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019, Adrien Destugues <[email protected]>
|
* Copyright 2004-2018 Haiku, Inc. All Rights Reserved.
|
||||||
* Copyright 2010, Ithamar R. Adema <[email protected]>
|
|
||||||
* Copyright 2009, Johannes Wischert, [email protected].
|
|
||||||
* Copyright 2005, Ingo Weinhold <[email protected]>.
|
|
||||||
* Copyright 2002, Travis Geiselbrecht. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
* 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 <KernelExport.h>
|
||||||
|
|
||||||
#include <elf_priv.h>
|
#include <elf_priv.h>
|
||||||
@@ -17,10 +19,8 @@
|
|||||||
//#define TRACE_ARCH_ELF
|
//#define TRACE_ARCH_ELF
|
||||||
#ifdef TRACE_ARCH_ELF
|
#ifdef TRACE_ARCH_ELF
|
||||||
# define TRACE(x) dprintf x
|
# define TRACE(x) dprintf x
|
||||||
# define CHATTY 1
|
|
||||||
#else
|
#else
|
||||||
# define TRACE(x) ;
|
# define TRACE(x) ;
|
||||||
# define CHATTY 0
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -29,71 +29,92 @@ static bool
|
|||||||
is_in_image(struct elf_image_info *image, addr_t address)
|
is_in_image(struct elf_image_info *image, addr_t address)
|
||||||
{
|
{
|
||||||
return (address >= image->text_region.start
|
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
|
||||||
&& address < image->data_region.start + image->data_region.size);
|
&& address < image->data_region.start
|
||||||
|
+ image->data_region.size);
|
||||||
}
|
}
|
||||||
#endif // !_BOOT_MODE
|
#endif // !_BOOT_MODE
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _BOOT_MODE
|
||||||
|
status_t
|
||||||
|
boot_arch_elf_relocate_rel(preloaded_elf64_image* image, Elf64_Rel* rel,
|
||||||
|
int relLength)
|
||||||
|
#else
|
||||||
int
|
int
|
||||||
arch_elf_relocate_rel(struct elf_image_info *image,
|
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
|
dprintf("arch_elf_relocate_rel: not supported on riscv64\n");
|
||||||
return B_NO_ERROR;
|
return B_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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _BOOT_MODE
|
||||||
|
status_t
|
||||||
|
boot_arch_elf_relocate_rela(preloaded_elf64_image* image, Elf64_Rela* rel,
|
||||||
|
int relLength)
|
||||||
|
#else
|
||||||
int
|
int
|
||||||
arch_elf_relocate_rela(struct elf_image_info *image,
|
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;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user