Commit 3466dab8 authored by Eric Ackermann's avatar Eric Ackermann Committed by Carles Cufi
Browse files

llext: Add parameters to arch_elf_relocate



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: default avatarEric Ackermann <eric.ackermann@cispa.de>
parent 7293f59a
Loading
Loading
Loading
Loading
+24 −3
Original line number Diff line number Diff line
@@ -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>
@@ -31,12 +32,32 @@ 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, struct llext *ext, elf_rela_t *rel,
		      const elf_shdr_t *shdr)
{
	int ret = 0;
	uint32_t insn = UNALIGNED_GET((uint32_t *)loc);
	uint32_t value;
	const uintptr_t loc = llext_get_reloc_instruction_location(ldr, ext, shdr->sh_info, rel);
	uint32_t insn = UNALIGNED_GET((uint32_t *)loc);
	elf_sym_t sym;
	uintptr_t sym_base_addr;
	const char *sym_name;

	ret = llext_read_symbol(ldr, ext, rel, &sym);

	if (ret != 0) {
		LOG_ERR("Could not read symbol from binary!");
		return ret;
	}

	sym_name = llext_symbol_name(ldr, ext, &sym);

	ret = llext_lookup_symbol(ldr, ext, &sym_base_addr, rel, &sym, sym_name, shdr);

	if (ret != 0) {
		LOG_ERR("Could not find symbol %s!", sym_name);
		return ret;
	}

	sym_base_addr += rel->r_addend;

+24 −2
Original line number Diff line number Diff line
@@ -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>

@@ -316,11 +317,32 @@ 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, struct llext *ext, elf_rela_t *rel,
		      const elf_shdr_t *shdr)
{
	int ret = 0;
	elf_word reloc_type = ELF32_R_TYPE(rel->r_info);
	const uintptr_t load_bias = (uintptr_t)ext->mem[LLEXT_MEM_TEXT];
	const uintptr_t loc = llext_get_reloc_instruction_location(ldr, ext, shdr->sh_info, rel);
	elf_sym_t sym;
	uintptr_t sym_base_addr;
	const char *sym_name;

	ret = llext_read_symbol(ldr, ext, rel, &sym);

	if (ret != 0) {
		LOG_ERR("Could not read symbol from binary!");
		return ret;
	}

	sym_name = llext_symbol_name(ldr, ext, &sym);

	ret = llext_lookup_symbol(ldr, ext, &sym_base_addr, rel, &sym, sym_name, shdr);

	if (ret != 0) {
		LOG_ERR("Could not find symbol %s!", sym_name);
		return ret;
	}

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

+23 −2
Original line number Diff line number Diff line
@@ -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>
@@ -430,12 +431,32 @@ 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, struct llext *ext, elf_rela_t *rel,
		      const elf_shdr_t *shdr)
{
	int ret = 0;
	bool overflow_check = true;
	elf_word reloc_type = ELF_R_TYPE(rel->r_info);
	const uintptr_t loc = llext_get_reloc_instruction_location(ldr, ext, shdr->sh_info, rel);
	elf_sym_t sym;
	uintptr_t sym_base_addr;
	const char *sym_name;

	ret = llext_read_symbol(ldr, ext, rel, &sym);

	if (ret != 0) {
		LOG_ERR("Could not read symbol from binary!");
		return ret;
	}

	sym_name = llext_symbol_name(ldr, ext, &sym);

	ret = llext_lookup_symbol(ldr, ext, &sym_base_addr, rel, &sym, sym_name, shdr);

	if (ret != 0) {
		LOG_ERR("Could not find symbol %s!", sym_name);
		return ret;
	}

	switch (reloc_type) {
	case R_ARM_NONE:
+27 −3
Original line number Diff line number Diff line
@@ -8,6 +8,9 @@
 */
#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>

@@ -68,11 +71,32 @@ 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, struct llext *ext, elf_rela_t *rel,
		      const elf_shdr_t *shdr)
{
	/* 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 = (uintptr_t)ext->mem[LLEXT_MEM_TEXT];
	const uintptr_t loc_unsigned = llext_get_reloc_instruction_location(ldr, ext,
									    shdr->sh_info, rel);
	elf_sym_t sym;
	uintptr_t sym_base_addr_unsigned;
	const char *sym_name;
	int ret;

	ret = llext_read_symbol(ldr, ext, rel, &sym);
	if (ret != 0) {
		LOG_ERR("Could not read symbol from binary!");
		return ret;
	}

	sym_name = llext_symbol_name(ldr, ext, &sym);
	ret = llext_lookup_symbol(ldr, ext, &sym_base_addr_unsigned, rel, &sym, sym_name, shdr);

	if (ret != 0) {
		LOG_ERR("Could not find symbol %s!", sym_name);
		return ret;
	}
	/*
	 * The RISC-V specification uses the following symbolic names for the relocations:
	 *
@@ -99,7 +123,7 @@ int arch_elf_relocate(elf_rela_t *rel, uintptr_t loc_unsigned, uintptr_t sym_bas
	long long original_imm8, jump_target;
	int16_t compressed_imm8;
	__typeof__(rel->r_addend) target_alignment = 1;
	const intptr_t sym_base_addr = (intptr_t)sym_base_addr_unsigned;
	intptr_t sym_base_addr = (intptr_t)sym_base_addr_unsigned;

	LOG_DBG("Relocating symbol %s at %p with base address %p load address %p type %" PRIu64,
		sym_name, (void *)loc, (void *)sym_base_addr, (void *)load_bias,
+7 −6
Original line number Diff line number Diff line
@@ -354,18 +354,19 @@ 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] 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
 * @param[in] shdr Header of the ELF section currently being located
 * @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, struct llext *ext, elf_rela_t *rel,
		      const elf_shdr_t *shdr);

/**
 * @brief Locates an ELF section in the file.
Loading