llext: fix symbol exporting for ET_REL
When building relocatable extensions, exported symbol names might end up in a separate section (in my case ".rodata.str1.1") for which storage address don't match section address. To access those names addresses have to be relalculated. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
This commit is contained in:
parent
acf6aff7ee
commit
a2a587ae20
3 changed files with 34 additions and 6 deletions
|
@ -48,7 +48,7 @@ __weak void arch_elf_relocate_global(struct llext_loader *ldr, struct llext *ext
|
|||
* Find the memory region containing the supplied offset and return the
|
||||
* corresponding file offset
|
||||
*/
|
||||
static size_t llext_file_offset(struct llext_loader *ldr, size_t offset)
|
||||
ssize_t llext_file_offset(struct llext_loader *ldr, uintptr_t offset)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
|
@ -59,7 +59,7 @@ static size_t llext_file_offset(struct llext_loader *ldr, size_t offset)
|
|||
}
|
||||
}
|
||||
|
||||
return offset;
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -224,7 +224,15 @@ static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, elf_shdr
|
|||
rel_addr += rela.r_offset + tgt->sh_offset;
|
||||
} else {
|
||||
/* Shared / dynamically linked ELF */
|
||||
rel_addr += llext_file_offset(ldr, rela.r_offset);
|
||||
ssize_t offset = llext_file_offset(ldr, rela.r_offset);
|
||||
|
||||
if (offset < 0) {
|
||||
LOG_ERR("Offset %#zx not found in ELF, trying to continue",
|
||||
(size_t)rela.r_offset);
|
||||
continue;
|
||||
}
|
||||
|
||||
rel_addr += offset;
|
||||
}
|
||||
|
||||
uint32_t stb = ELF_ST_BIND(sym.st_info);
|
||||
|
|
|
@ -517,7 +517,8 @@ static int llext_allocate_symtab(struct llext_loader *ldr, struct llext *ext)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int llext_export_symbols(struct llext_loader *ldr, struct llext *ext)
|
||||
static int llext_export_symbols(struct llext_loader *ldr, struct llext *ext,
|
||||
const struct llext_load_param *ldr_parm)
|
||||
{
|
||||
struct llext_symtable *exp_tab = &ext->exp_tab;
|
||||
struct llext_symbol *sym;
|
||||
|
@ -545,7 +546,25 @@ static int llext_export_symbols(struct llext_loader *ldr, struct llext *ext)
|
|||
}
|
||||
|
||||
for (i = 0; i < exp_tab->sym_cnt; i++, sym++) {
|
||||
exp_tab->syms[i].name = sym->name;
|
||||
/*
|
||||
* Offsets in objects, built for pre-defined addresses have to
|
||||
* be translated to memory locations for symbol name access
|
||||
* during dependency resolution.
|
||||
*/
|
||||
const char *name = NULL;
|
||||
|
||||
if (ldr_parm && ldr_parm->pre_located) {
|
||||
ssize_t name_offset = llext_file_offset(ldr, (uintptr_t)sym->name);
|
||||
|
||||
if (name_offset > 0) {
|
||||
name = llext_peek(ldr, name_offset);
|
||||
}
|
||||
}
|
||||
if (!name) {
|
||||
name = sym->name;
|
||||
}
|
||||
|
||||
exp_tab->syms[i].name = name;
|
||||
exp_tab->syms[i].addr = sym->addr;
|
||||
LOG_DBG("sym %p name %s", sym->addr, sym->name);
|
||||
}
|
||||
|
@ -730,7 +749,7 @@ int do_llext_load(struct llext_loader *ldr, struct llext *ext,
|
|||
}
|
||||
}
|
||||
|
||||
ret = llext_export_symbols(ldr, ext);
|
||||
ret = llext_export_symbols(ldr, ext, ldr_parm);
|
||||
if (ret != 0) {
|
||||
LOG_ERR("Failed to export, ret %d", ret);
|
||||
goto out;
|
||||
|
|
|
@ -65,6 +65,7 @@ static inline const char *llext_string(struct llext_loader *ldr, struct llext *e
|
|||
|
||||
int llext_link(struct llext_loader *ldr, struct llext *ext,
|
||||
const struct llext_load_param *ldr_parm);
|
||||
ssize_t llext_file_offset(struct llext_loader *ldr, uintptr_t offset);
|
||||
void llext_dependency_remove_all(struct llext *ext);
|
||||
|
||||
#endif /* ZEPHYR_SUBSYS_LLEXT_PRIV_H_ */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue