Skip to content

Commit

Permalink
llext: Add parameters to arch_elf_relocate
Browse files Browse the repository at this point in the history
The RISC-V port of llext requires additional parameters for
handling non-adjacent HI20/LO12 relocations in arch_elf_relocate():
the current extension (struct llext), the current extension loader
(struct llext_loader), the current section header (elf_shdr_t) and
the current symbol (elf_sym_t).
This changes the signature of arch_elf_relocate accordingly.

Signed-off-by: Eric Ackermann <[email protected]>
  • Loading branch information
WorldofJARcraft committed Feb 18, 2025
1 parent 37f5100 commit 6d9b0c0
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 30 deletions.
11 changes: 9 additions & 2 deletions arch/arc/core/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <zephyr/llext/elf.h>
#include <zephyr/llext/llext.h>
#include <zephyr/llext/llext_internal.h>
#include <zephyr/llext/loader.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/util.h>
Expand All @@ -31,12 +32,18 @@ LOG_MODULE_REGISTER(elf, CONFIG_LLEXT_LOG_LEVEL);
* https://github.com/foss-for-synopsys-dwc-arc-processors/arc-ABI-manual/blob/master/ARCv2_ABI.pdf
* https://github.com/zephyrproject-rtos/binutils-gdb
*/
int arch_elf_relocate(elf_rela_t *rel, uintptr_t loc, uintptr_t sym_base_addr, const char *sym_name,
uintptr_t load_bias)
int arch_elf_relocate(struct llext_loader *ldr, const struct llext *ext, elf_rela_t *rel,
const elf_shdr_t *shdr, const elf_sym_t *sym, uintptr_t loc,
uintptr_t sym_base_addr, const char *sym_name)
{
int ret = 0;
uint32_t insn = UNALIGNED_GET((uint32_t *)loc);
uint32_t value;
const uintptr_t load_bias = llext_text_start(ext);

ARG_UNUSED(ldr);
ARG_UNUSED(shdr);
ARG_UNUSED(sym);

sym_base_addr += rel->r_addend;

Expand Down
11 changes: 9 additions & 2 deletions arch/arm/core/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <zephyr/llext/elf.h>
#include <zephyr/llext/llext.h>
#include <zephyr/llext/llext_internal.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/util.h>

Expand Down Expand Up @@ -316,11 +317,17 @@ static void thm_movs_handler(elf_word reloc_type, uint32_t loc,
* Do NOT mix them with not 'Thumb instructions' in the below switch/case: they are not
* intended to work together.
*/
int arch_elf_relocate(elf_rela_t *rel, uintptr_t loc, uintptr_t sym_base_addr,
const char *sym_name, uintptr_t load_bias)
int arch_elf_relocate(struct llext_loader *ldr, const struct llext *ext, elf_rela_t *rel,
const elf_shdr_t *shdr, const elf_sym_t *sym, uintptr_t loc,
uintptr_t sym_base_addr, const char *sym_name)
{
int ret = 0;
elf_word reloc_type = ELF32_R_TYPE(rel->r_info);
const uintptr_t load_bias = llext_text_start(ext);

ARG_UNUSED(ldr);
ARG_UNUSED(shdr);
ARG_UNUSED(sym);

LOG_DBG("%d %lx %lx %s", reloc_type, loc, sym_base_addr, sym_name);

Expand Down
11 changes: 9 additions & 2 deletions arch/arm64/core/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <zephyr/llext/elf.h>
#include <zephyr/llext/llext.h>
#include <zephyr/llext/llext_internal.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/util.h>
#include <zephyr/sys/byteorder.h>
Expand Down Expand Up @@ -430,13 +431,19 @@ static int imm_reloc_handler(elf_rela_t *rel, elf_word reloc_type, uintptr_t loc
* @retval -ENOTSUP Unsupported relocation
* @retval -ENOEXEC Invalid relocation
*/
int arch_elf_relocate(elf_rela_t *rel, uintptr_t loc, uintptr_t sym_base_addr, const char *sym_name,
uintptr_t load_bias)
int arch_elf_relocate(struct llext_loader *ldr, const struct llext *ext, elf_rela_t *rel,
const elf_shdr_t *shdr, const elf_sym_t *sym, uintptr_t loc,
uintptr_t sym_base_addr, const char *sym_name)
{
int ret = 0;
bool overflow_check = true;
elf_word reloc_type = ELF_R_TYPE(rel->r_info);

ARG_UNUSED(ext);
ARG_UNUSED(ldr);
ARG_UNUSED(shdr);
ARG_UNUSED(sym);

switch (reloc_type) {
case R_ARM_NONE:
case R_AARCH64_NONE:
Expand Down
10 changes: 8 additions & 2 deletions arch/riscv/core/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,13 @@ static long long last_u_type_jump_target;
* https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc
*
*/
int arch_elf_relocate(elf_rela_t *rel, uintptr_t loc_unsigned, uintptr_t sym_base_addr_unsigned,
const char *sym_name, uintptr_t load_bias)
int arch_elf_relocate(struct llext_loader *ldr, const struct llext *ext, elf_rela_t *rel,
const elf_shdr_t *shdr, const elf_sym_t *sym, uintptr_t loc_unsigned,
uintptr_t sym_base_addr_unsigned, const char *sym_name)
{
/* FIXME currently, RISC-V relocations all fit in ELF_32_R_TYPE */
elf_word reloc_type = ELF32_R_TYPE(rel->r_info);
const uintptr_t load_bias = llext_text_start(ext);
/*
* The RISC-V specification uses the following symbolic names for the relocations:
*
Expand Down Expand Up @@ -105,6 +107,10 @@ int arch_elf_relocate(elf_rela_t *rel, uintptr_t loc_unsigned, uintptr_t sym_bas
sym_name, (void *)loc, (void *)sym_base_addr, (void *)load_bias,
(uint64_t)reloc_type);

ARG_UNUSED(ldr);
ARG_UNUSED(shdr);
ARG_UNUSED(sym);

/* FIXME not all types of relocations currently supported, especially TLS */

switch (reloc_type) {
Expand Down
12 changes: 9 additions & 3 deletions include/zephyr/llext/llext.h
Original file line number Diff line number Diff line change
Expand Up @@ -354,18 +354,24 @@ int llext_add_domain(struct llext *ext, struct k_mem_domain *domain);
* symbolic data such as a section, function, or object. These relocations
* are architecture specific and each architecture supporting LLEXT must
* implement this.
* Arguments sym_base_addr, sym_name can be computed from the sym parameter,
* but these parameters are provided redundantly to increase efficiency.
*
* @param[in] ldr Extension loader
* @param[in] ext Extension being relocated refers to
* @param[in] rel Relocation data provided by ELF
* @param[in] shdr Header of the ELF section currently being located
* @param[in] sym ELF symbol to be relocated
* @param[in] loc Address of opcode to rewrite
* @param[in] sym_base_addr Address of symbol referenced by relocation
* @param[in] sym_name Name of symbol referenced by relocation
* @param[in] load_bias `.text` load address
* @retval 0 Success
* @retval -ENOTSUP Unsupported relocation
* @retval -ENOEXEC Invalid relocation
*/
int arch_elf_relocate(elf_rela_t *rel, uintptr_t loc,
uintptr_t sym_base_addr, const char *sym_name, uintptr_t load_bias);
int arch_elf_relocate(struct llext_loader *ldr, const struct llext *ext, elf_rela_t *rel,
const elf_shdr_t *shdr, const elf_sym_t *sym, uintptr_t loc,
uintptr_t sym_base_addr, const char *sym_name);

/**
* @brief Locates an ELF section in the file.
Expand Down
5 changes: 5 additions & 0 deletions include/zephyr/llext/llext_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ struct llext_elf_sect_map {

const void *llext_loaded_sect_ptr(struct llext_loader *ldr, struct llext *ext, unsigned int sh_ndx);

static inline uintptr_t llext_text_start(const struct llext *ext)
{
return (uintptr_t)ext->mem[LLEXT_MEM_TEXT];
}

/** @endcond */

#ifdef __cplusplus
Expand Down
28 changes: 9 additions & 19 deletions subsys/llext/llext_link.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ LOG_MODULE_DECLARE(llext, CONFIG_LLEXT_LOG_LEVEL);
#define SYM_NAME_OR_SLID(name, slid) name
#endif

__weak int arch_elf_relocate(elf_rela_t *rel, uintptr_t loc,
uintptr_t sym_base_addr, const char *sym_name, uintptr_t load_bias)
__weak int arch_elf_relocate(struct llext_loader *ldr, const struct llext *ext, elf_rela_t *rel,
const elf_shdr_t *shdr, const elf_sym_t *sym, uintptr_t loc,
uintptr_t sym_base_addr, const char *sym_name)
{
return -ENOTSUP;
}
Expand Down Expand Up @@ -142,20 +143,10 @@ static const void *llext_find_extension_sym(const char *sym_name, struct llext *
return se.addr;
}

/**
* @brief Determine address of a symbol.
*
* @param ext llext extension
* @param ldr llext loader
* @param link_addr (output) resolved address
* @param rel relocation entry
* @param sym symbol entry
* @param name symbol name
* @param shdr section header
*
* @return 0 for OK, negative for error
/*
* Determine address of a symbol.
*/
static int llext_lookup_symbol(struct llext *ext, struct llext_loader *ldr, uintptr_t *link_addr,
static int llext_lookup_symbol(struct llext_loader *ldr, struct llext *ext, uintptr_t *link_addr,
const elf_rela_t *rel, const elf_sym_t *sym, const char *name,
const elf_shdr_t *shdr)
{
Expand Down Expand Up @@ -219,7 +210,6 @@ static int llext_lookup_symbol(struct llext *ext, struct llext_loader *ldr, uint
return 0;
}


static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, elf_shdr_t *shdr,
const struct llext_load_param *ldr_parm, elf_shdr_t *tgt)
{
Expand Down Expand Up @@ -485,7 +475,7 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l

op_loc = sect_base + rel.r_offset;

ret = llext_lookup_symbol(ext, ldr, &link_addr, &rel, &sym, name, shdr);
ret = llext_lookup_symbol(ldr, ext, &link_addr, &rel, &sym, name, shdr);

if (ret != 0) {
LOG_ERR("Failed to lookup symbol in rela section %d entry %d!", i,
Expand All @@ -499,8 +489,8 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l
op_loc, link_addr);

/* relocation */
ret = arch_elf_relocate(&rel, op_loc, link_addr, name,
(uintptr_t)ext->mem[LLEXT_MEM_TEXT]);
ret = arch_elf_relocate(ldr, ext, &rel, shdr, &sym, op_loc, link_addr,
name);
if (ret != 0) {
return ret;
}
Expand Down

0 comments on commit 6d9b0c0

Please sign in to comment.