llext: make unresolved symbol errors fatal
With experience it becomes clear, that failing to resolve symbols during the linking process is likely fatal for the module loading and a simple warning isn't enough. Fail loading instead. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
This commit is contained in:
parent
64bb8b6796
commit
53a179ac4e
3 changed files with 58 additions and 34 deletions
|
@ -32,10 +32,10 @@ LOG_MODULE_DECLARE(llext, CONFIG_LLEXT_LOG_LEVEL);
|
||||||
#define R_XTENSA_ASM_EXPAND 11
|
#define R_XTENSA_ASM_EXPAND 11
|
||||||
#define R_XTENSA_SLOT0_OP 20
|
#define R_XTENSA_SLOT0_OP 20
|
||||||
|
|
||||||
static void xtensa_elf_relocate(struct llext_loader *ldr, struct llext *ext,
|
static int xtensa_elf_relocate(struct llext_loader *ldr, struct llext *ext,
|
||||||
const elf_rela_t *rel, uintptr_t addr,
|
const elf_rela_t *rel, uintptr_t addr,
|
||||||
uint8_t *loc, int type, uint32_t stb,
|
uint8_t *loc, int type, uint32_t stb,
|
||||||
const struct llext_load_param *ldr_parm)
|
const struct llext_load_param *ldr_parm)
|
||||||
{
|
{
|
||||||
elf_word *got_entry = (elf_word *)loc;
|
elf_word *got_entry = (elf_word *)loc;
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ static void xtensa_elf_relocate(struct llext_loader *ldr, struct llext *ext,
|
||||||
|
|
||||||
if (sh_ndx == ext->sect_cnt) {
|
if (sh_ndx == ext->sect_cnt) {
|
||||||
LOG_ERR("%#x not found in any of the sections", *got_entry);
|
LOG_ERR("%#x not found in any of the sections", *got_entry);
|
||||||
return;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
*got_entry += (uintptr_t)llext_loaded_sect_ptr(ldr, ext, sh_ndx) -
|
*got_entry += (uintptr_t)llext_loaded_sect_ptr(ldr, ext, sh_ndx) -
|
||||||
|
@ -87,7 +87,7 @@ static void xtensa_elf_relocate(struct llext_loader *ldr, struct llext *ext,
|
||||||
}
|
}
|
||||||
if (ret) {
|
if (ret) {
|
||||||
LOG_ERR("Failed to read a symbol table entry, LLEXT linking might fail.");
|
LOG_ERR("Failed to read a symbol table entry, LLEXT linking might fail.");
|
||||||
return;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -124,19 +124,21 @@ static void xtensa_elf_relocate(struct llext_loader *ldr, struct llext *ext,
|
||||||
default:
|
default:
|
||||||
LOG_DBG("Unsupported relocation type %u", type);
|
LOG_DBG("Unsupported relocation type %u", type);
|
||||||
|
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DBG("Applied relocation to %#x type %u at %p",
|
LOG_DBG("Applied relocation to %#x type %u at %p",
|
||||||
*(uint32_t *)((uintptr_t)got_entry & ~3), type, (void *)got_entry);
|
*(uint32_t *)((uintptr_t)got_entry & ~3), type, (void *)got_entry);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Architecture specific function for STB_LOCAL ELF relocations
|
* @brief Architecture specific function for STB_LOCAL ELF relocations
|
||||||
*/
|
*/
|
||||||
void arch_elf_relocate_local(struct llext_loader *ldr, struct llext *ext, const elf_rela_t *rel,
|
int arch_elf_relocate_local(struct llext_loader *ldr, struct llext *ext, const elf_rela_t *rel,
|
||||||
const elf_sym_t *sym, uint8_t *rel_addr,
|
const elf_sym_t *sym, uint8_t *rel_addr,
|
||||||
const struct llext_load_param *ldr_parm)
|
const struct llext_load_param *ldr_parm)
|
||||||
{
|
{
|
||||||
int type = ELF32_R_TYPE(rel->r_info);
|
int type = ELF32_R_TYPE(rel->r_info);
|
||||||
uintptr_t sh_addr;
|
uintptr_t sh_addr;
|
||||||
|
@ -152,15 +154,15 @@ void arch_elf_relocate_local(struct llext_loader *ldr, struct llext *ext, const
|
||||||
sh_addr = ldr->sects[LLEXT_MEM_TEXT].sh_addr;
|
sh_addr = ldr->sects[LLEXT_MEM_TEXT].sh_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
xtensa_elf_relocate(ldr, ext, rel, sh_addr, rel_addr, type, ELF_ST_BIND(sym->st_info),
|
return xtensa_elf_relocate(ldr, ext, rel, sh_addr, rel_addr, type,
|
||||||
ldr_parm);
|
ELF_ST_BIND(sym->st_info), ldr_parm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Architecture specific function for STB_GLOBAL ELF relocations
|
* @brief Architecture specific function for STB_GLOBAL ELF relocations
|
||||||
*/
|
*/
|
||||||
void arch_elf_relocate_global(struct llext_loader *ldr, struct llext *ext, const elf_rela_t *rel,
|
int arch_elf_relocate_global(struct llext_loader *ldr, struct llext *ext, const elf_rela_t *rel,
|
||||||
const elf_sym_t *sym, uint8_t *rel_addr, const void *link_addr)
|
const elf_sym_t *sym, uint8_t *rel_addr, const void *link_addr)
|
||||||
{
|
{
|
||||||
int type = ELF32_R_TYPE(rel->r_info);
|
int type = ELF32_R_TYPE(rel->r_info);
|
||||||
|
|
||||||
|
@ -169,6 +171,6 @@ void arch_elf_relocate_global(struct llext_loader *ldr, struct llext *ext, const
|
||||||
LOG_WRN("global: non-zero relative value %#x", *(elf_word *)rel_addr);
|
LOG_WRN("global: non-zero relative value %#x", *(elf_word *)rel_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
xtensa_elf_relocate(ldr, ext, rel, (uintptr_t)link_addr, rel_addr, type,
|
return xtensa_elf_relocate(ldr, ext, rel, (uintptr_t)link_addr, rel_addr, type,
|
||||||
ELF_ST_BIND(sym->st_info), NULL);
|
ELF_ST_BIND(sym->st_info), NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -409,10 +409,11 @@ int llext_get_section_header(struct llext_loader *loader, struct llext *ext,
|
||||||
* @param[in] sym Corresponding symbol table entry
|
* @param[in] sym Corresponding symbol table entry
|
||||||
* @param[in] rel_addr Address where relocation should be performed
|
* @param[in] rel_addr Address where relocation should be performed
|
||||||
* @param[in] ldr_parm Loader parameters
|
* @param[in] ldr_parm Loader parameters
|
||||||
|
* @returns 0 on success or a negative error code
|
||||||
*/
|
*/
|
||||||
void arch_elf_relocate_local(struct llext_loader *loader, struct llext *ext, const elf_rela_t *rel,
|
int arch_elf_relocate_local(struct llext_loader *loader, struct llext *ext, const elf_rela_t *rel,
|
||||||
const elf_sym_t *sym, uint8_t *rel_addr,
|
const elf_sym_t *sym, uint8_t *rel_addr,
|
||||||
const struct llext_load_param *ldr_parm);
|
const struct llext_load_param *ldr_parm);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Architecture specific function for global binding relocations
|
* @brief Architecture specific function for global binding relocations
|
||||||
|
@ -423,9 +424,10 @@ void arch_elf_relocate_local(struct llext_loader *loader, struct llext *ext, con
|
||||||
* @param[in] sym Corresponding symbol table entry
|
* @param[in] sym Corresponding symbol table entry
|
||||||
* @param[in] rel_addr Address where relocation should be performed
|
* @param[in] rel_addr Address where relocation should be performed
|
||||||
* @param[in] link_addr target address for table-based relocations
|
* @param[in] link_addr target address for table-based relocations
|
||||||
|
* @returns 0 on success or a negative error code
|
||||||
*/
|
*/
|
||||||
void arch_elf_relocate_global(struct llext_loader *loader, struct llext *ext, const elf_rela_t *rel,
|
int arch_elf_relocate_global(struct llext_loader *loader, struct llext *ext, const elf_rela_t *rel,
|
||||||
const elf_sym_t *sym, uint8_t *rel_addr, const void *link_addr);
|
const elf_sym_t *sym, uint8_t *rel_addr, const void *link_addr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize LLEXT heap dynamically
|
* @brief Initialize LLEXT heap dynamically
|
||||||
|
|
|
@ -32,16 +32,18 @@ __weak int arch_elf_relocate(struct llext_loader *ldr, struct llext *ext, elf_re
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
__weak void arch_elf_relocate_local(struct llext_loader *ldr, struct llext *ext,
|
__weak int arch_elf_relocate_local(struct llext_loader *ldr, struct llext *ext,
|
||||||
const elf_rela_t *rel, const elf_sym_t *sym, uint8_t *rel_addr,
|
const elf_rela_t *rel, const elf_sym_t *sym, uint8_t *rel_addr,
|
||||||
const struct llext_load_param *ldr_parm)
|
const struct llext_load_param *ldr_parm)
|
||||||
{
|
{
|
||||||
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
__weak void arch_elf_relocate_global(struct llext_loader *ldr, struct llext *ext,
|
__weak int arch_elf_relocate_global(struct llext_loader *ldr, struct llext *ext,
|
||||||
const elf_rela_t *rel, const elf_sym_t *sym, uint8_t *rel_addr,
|
const elf_rela_t *rel, const elf_sym_t *sym, uint8_t *rel_addr,
|
||||||
const void *link_addr)
|
const void *link_addr)
|
||||||
{
|
{
|
||||||
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -246,8 +248,8 @@ int llext_lookup_symbol(struct llext_loader *ldr, struct llext *ext, uintptr_t *
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, elf_shdr_t *shdr,
|
static int 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)
|
const struct llext_load_param *ldr_parm, elf_shdr_t *tgt)
|
||||||
{
|
{
|
||||||
unsigned int sh_cnt = shdr->sh_size / shdr->sh_entsize;
|
unsigned int sh_cnt = shdr->sh_size / shdr->sh_entsize;
|
||||||
/*
|
/*
|
||||||
|
@ -255,6 +257,7 @@ static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, elf_shdr
|
||||||
* reference point
|
* reference point
|
||||||
*/
|
*/
|
||||||
uint8_t *text = ext->mem[LLEXT_MEM_TEXT];
|
uint8_t *text = ext->mem[LLEXT_MEM_TEXT];
|
||||||
|
int link_err = 0;
|
||||||
|
|
||||||
LOG_DBG("Found %p in PLT %u size %zu cnt %u text %p",
|
LOG_DBG("Found %p in PLT %u size %zu cnt %u text %p",
|
||||||
(void *)llext_section_name(ldr, ext, shdr),
|
(void *)llext_section_name(ldr, ext, shdr),
|
||||||
|
@ -370,20 +373,34 @@ static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, elf_shdr
|
||||||
|
|
||||||
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);
|
||||||
continue;
|
/* Will fail after reporting all missing symbols */
|
||||||
|
if (!link_err) {
|
||||||
|
link_err = -ENOENT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resolve the symbol */
|
/* Resolve the symbol */
|
||||||
arch_elf_relocate_global(ldr, ext, &rela, &sym, rel_addr, link_addr);
|
ret = arch_elf_relocate_global(ldr, ext, &rela, &sym, rel_addr, link_addr);
|
||||||
|
if (!link_err) {
|
||||||
|
link_err = ret;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case STB_LOCAL:
|
case STB_LOCAL:
|
||||||
arch_elf_relocate_local(ldr, ext, &rela, &sym, rel_addr, ldr_parm);
|
ret = arch_elf_relocate_local(ldr, ext, &rela, &sym, rel_addr, ldr_parm);
|
||||||
|
if (!link_err) {
|
||||||
|
link_err = ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DBG("symbol %s relocation @%p r-offset %#zx .text offset %#zx stb %u",
|
if (!link_err) {
|
||||||
name, (void *)rel_addr,
|
LOG_DBG("symbol %s relocation @%p r-offset %#zx .text offset %#zx stb %u",
|
||||||
(size_t)rela.r_offset, (size_t)ldr->sects[LLEXT_MEM_TEXT].sh_offset, stb);
|
name, (void *)rel_addr, (size_t)rela.r_offset,
|
||||||
|
(size_t)ldr->sects[LLEXT_MEM_TEXT].sh_offset, stb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return link_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_load_param *ldr_parm)
|
int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_load_param *ldr_parm)
|
||||||
|
@ -457,7 +474,10 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l
|
||||||
tgt = ext->sect_hdrs + shdr->sh_info;
|
tgt = ext->sect_hdrs + shdr->sh_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
llext_link_plt(ldr, ext, shdr, ldr_parm, tgt);
|
ret = llext_link_plt(ldr, ext, shdr, ldr_parm, tgt);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue