Browse Source

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>
pull/85575/head
Guennadi Liakhovetski 6 months ago committed by Benjamin Cabé
parent
commit
a2a587ae20
  1. 14
      subsys/llext/llext_link.c
  2. 25
      subsys/llext/llext_load.c
  3. 1
      subsys/llext/llext_priv.h

14
subsys/llext/llext_link.c

@ -48,7 +48,7 @@ __weak void arch_elf_relocate_global(struct llext_loader *ldr, struct llext *ext @@ -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) @@ -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 @@ -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);

25
subsys/llext/llext_load.c

@ -517,7 +517,8 @@ static int llext_allocate_symtab(struct llext_loader *ldr, struct llext *ext) @@ -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) @@ -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, @@ -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;

1
subsys/llext/llext_priv.h

@ -65,6 +65,7 @@ static inline const char *llext_string(struct llext_loader *ldr, struct llext *e @@ -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…
Cancel
Save