llext: xtensa: add support for local symbol relocations
Add support for relocating local symbols, as specified in the .rela.dyn section. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
This commit is contained in:
parent
d6a5a6e04c
commit
03519afb84
4 changed files with 73 additions and 2 deletions
|
@ -24,6 +24,7 @@ zephyr_library_sources_ifdef(CONFIG_GDBSTUB gdbstub.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_XTENSA_MMU ptables.c mmu.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.S)
|
||||
zephyr_library_sources_ifdef(CONFIG_XTENSA_SYSCALL_USE_HELPER syscall_helper.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_LLEXT elf.c)
|
||||
|
||||
zephyr_library_sources_ifdef(
|
||||
CONFIG_KERNEL_VM_USE_CUSTOM_MEM_RANGE_CHECK
|
||||
|
|
44
arch/xtensa/core/elf.c
Normal file
44
arch/xtensa/core/elf.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/llext/elf.h>
|
||||
#include <zephyr/llext/llext.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
LOG_MODULE_DECLARE(llext);
|
||||
|
||||
#define R_XTENSA_NONE 0
|
||||
#define R_XTENSA_32 1
|
||||
#define R_XTENSA_RTLD 2
|
||||
#define R_XTENSA_GLOB_DAT 3
|
||||
#define R_XTENSA_JMP_SLOT 4
|
||||
#define R_XTENSA_RELATIVE 5
|
||||
#define R_XTENSA_PLT 6
|
||||
|
||||
/**
|
||||
* @brief Architecture specific function for relocating shared elf
|
||||
*
|
||||
* Elf files contain a series of relocations described in multiple sections.
|
||||
* These relocation instructions are architecture specific and each architecture
|
||||
* supporting modules must implement this.
|
||||
*/
|
||||
void arch_elf_relocate_local(struct llext_loader *ldr, struct llext *ext,
|
||||
elf_rela_t *rel, size_t got_offset)
|
||||
{
|
||||
uint8_t *text = ext->mem[LLEXT_MEM_TEXT];
|
||||
int type = ELF32_R_TYPE(rel->r_info);
|
||||
|
||||
if (type == R_XTENSA_RELATIVE) {
|
||||
elf_word ptr_offset = *(elf_word *)(text + got_offset);
|
||||
|
||||
LOG_DBG("relocation type %u offset %#x value %#x",
|
||||
type, got_offset, ptr_offset);
|
||||
|
||||
/* Relocate a local symbol: Xtensa specific */
|
||||
*(elf_word *)(text + got_offset) = (elf_word)(text + ptr_offset -
|
||||
ldr->sects[LLEXT_SECT_TEXT].sh_addr);
|
||||
}
|
||||
}
|
|
@ -142,6 +142,17 @@ int llext_call_fn(struct llext *ext, const char *sym_name);
|
|||
*/
|
||||
void arch_elf_relocate(elf_rela_t *rel, uintptr_t opaddr, uintptr_t opval);
|
||||
|
||||
/**
|
||||
* @brief Architecture specific function for updating addresses via relocation table
|
||||
*
|
||||
* @param[in] loader Extension loader data and context
|
||||
* @param[in] ext Extension to call function in
|
||||
* @param[in] rel Relocation data provided by elf
|
||||
* @param[in] got_offset Offset within a relocation table
|
||||
*/
|
||||
void arch_elf_relocate_local(struct llext_loader *loader, struct llext *ext,
|
||||
elf_rela_t *rel, size_t got_offset);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -462,6 +462,11 @@ static size_t llext_file_offset(struct llext_loader *ldr, size_t offset)
|
|||
return offset;
|
||||
}
|
||||
|
||||
__weak void arch_elf_relocate_local(struct llext_loader *ldr, struct llext *ext,
|
||||
elf_rela_t *rel, size_t got_offset)
|
||||
{
|
||||
}
|
||||
|
||||
static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, elf_shdr_t *shdr)
|
||||
{
|
||||
unsigned int sh_cnt = shdr->sh_size / shdr->sh_entsize;
|
||||
|
@ -514,6 +519,7 @@ static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, elf_shdr
|
|||
}
|
||||
|
||||
uint32_t stt = ELF_ST_TYPE(sym_tbl.st_info);
|
||||
uint32_t stb = ELF_ST_BIND(sym_tbl.st_info);
|
||||
const char *name = llext_string(ldr, ext, LLEXT_MEM_STRTAB, sym_tbl.st_name);
|
||||
/*
|
||||
* Both r_offset and sh_addr are addresses for which the extension
|
||||
|
@ -522,8 +528,14 @@ static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, elf_shdr
|
|||
size_t got_offset = llext_file_offset(ldr, rela.r_offset) -
|
||||
ldr->sects[LLEXT_SECT_TEXT].sh_offset;
|
||||
|
||||
if (stt == STT_NOTYPE && sym_tbl.st_shndx == SHN_UNDEF && name[0] != '\0') {
|
||||
const void *link_addr = llext_find_sym(NULL, name);
|
||||
if (stt != STT_NOTYPE || sym_tbl.st_shndx != SHN_UNDEF)
|
||||
continue;
|
||||
|
||||
const void *link_addr;
|
||||
|
||||
switch (stb) {
|
||||
case STB_GLOBAL:
|
||||
link_addr = llext_find_sym(NULL, name);
|
||||
|
||||
if (!link_addr) {
|
||||
LOG_WRN("PLT: cannot find idx %u name %s", j, name);
|
||||
|
@ -541,6 +553,9 @@ static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, elf_shdr
|
|||
|
||||
/* Resolve the symbol */
|
||||
*(const void **)(text + got_offset) = link_addr;
|
||||
break;
|
||||
case STB_LOCAL:
|
||||
arch_elf_relocate_local(ldr, ext, &rela, got_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue