diff --git a/subsys/llext/llext_link.c b/subsys/llext/llext_link.c index 61d6859b0b0..a0a4414117f 100644 --- a/subsys/llext/llext_link.c +++ b/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 * 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); diff --git a/subsys/llext/llext_load.c b/subsys/llext/llext_load.c index 1f8d790ad5c..68ce4a3f404 100644 --- a/subsys/llext/llext_load.c +++ b/subsys/llext/llext_load.c @@ -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; diff --git a/subsys/llext/llext_priv.h b/subsys/llext/llext_priv.h index e3b9fd282a6..cf96da165d2 100644 --- a/subsys/llext/llext_priv.h +++ b/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, 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_ */