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
* Find the memory region containing the supplied offset and return the * Find the memory region containing the supplied offset and return the
* corresponding file offset * 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; 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; rel_addr += rela.r_offset + tgt->sh_offset;
} else { } else {
/* Shared / dynamically linked ELF */ /* 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); 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)
return 0; 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_symtable *exp_tab = &ext->exp_tab;
struct llext_symbol *sym; 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++) { 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; exp_tab->syms[i].addr = sym->addr;
LOG_DBG("sym %p name %s", sym->addr, sym->name); 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) { if (ret != 0) {
LOG_ERR("Failed to export, ret %d", ret); LOG_ERR("Failed to export, ret %d", ret);
goto out; 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
int llext_link(struct llext_loader *ldr, struct llext *ext, int llext_link(struct llext_loader *ldr, struct llext *ext,
const struct llext_load_param *ldr_parm); 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); void llext_dependency_remove_all(struct llext *ext);
#endif /* ZEPHYR_SUBSYS_LLEXT_PRIV_H_ */ #endif /* ZEPHYR_SUBSYS_LLEXT_PRIV_H_ */

Loading…
Cancel
Save