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_XTENSA_MMU ptables.c mmu.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.S)
|
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_XTENSA_SYSCALL_USE_HELPER syscall_helper.c)
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_LLEXT elf.c)
|
||||||
|
|
||||||
zephyr_library_sources_ifdef(
|
zephyr_library_sources_ifdef(
|
||||||
CONFIG_KERNEL_VM_USE_CUSTOM_MEM_RANGE_CHECK
|
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);
|
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;
|
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)
|
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;
|
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 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);
|
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
|
* 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) -
|
size_t got_offset = llext_file_offset(ldr, rela.r_offset) -
|
||||||
ldr->sects[LLEXT_SECT_TEXT].sh_offset;
|
ldr->sects[LLEXT_SECT_TEXT].sh_offset;
|
||||||
|
|
||||||
if (stt == STT_NOTYPE && sym_tbl.st_shndx == SHN_UNDEF && name[0] != '\0') {
|
if (stt != STT_NOTYPE || sym_tbl.st_shndx != SHN_UNDEF)
|
||||||
const void *link_addr = llext_find_sym(NULL, name);
|
continue;
|
||||||
|
|
||||||
|
const void *link_addr;
|
||||||
|
|
||||||
|
switch (stb) {
|
||||||
|
case STB_GLOBAL:
|
||||||
|
link_addr = llext_find_sym(NULL, name);
|
||||||
|
|
||||||
if (!link_addr) {
|
if (!link_addr) {
|
||||||
LOG_WRN("PLT: cannot find idx %u name %s", j, name);
|
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 */
|
/* Resolve the symbol */
|
||||||
*(const void **)(text + got_offset) = link_addr;
|
*(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