Skip to content

Commit a2a587a

Browse files
lyakhkartben
authored andcommitted
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>
1 parent acf6aff commit a2a587a

File tree

3 files changed

+34
-6
lines changed

3 files changed

+34
-6
lines changed

subsys/llext/llext_link.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ __weak void arch_elf_relocate_global(struct llext_loader *ldr, struct llext *ext
4848
* Find the memory region containing the supplied offset and return the
4949
* corresponding file offset
5050
*/
51-
static size_t llext_file_offset(struct llext_loader *ldr, size_t offset)
51+
ssize_t llext_file_offset(struct llext_loader *ldr, uintptr_t offset)
5252
{
5353
unsigned int i;
5454

@@ -59,7 +59,7 @@ static size_t llext_file_offset(struct llext_loader *ldr, size_t offset)
5959
}
6060
}
6161

62-
return offset;
62+
return -ENOEXEC;
6363
}
6464

6565
/*
@@ -224,7 +224,15 @@ static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, elf_shdr
224224
rel_addr += rela.r_offset + tgt->sh_offset;
225225
} else {
226226
/* Shared / dynamically linked ELF */
227-
rel_addr += llext_file_offset(ldr, rela.r_offset);
227+
ssize_t offset = llext_file_offset(ldr, rela.r_offset);
228+
229+
if (offset < 0) {
230+
LOG_ERR("Offset %#zx not found in ELF, trying to continue",
231+
(size_t)rela.r_offset);
232+
continue;
233+
}
234+
235+
rel_addr += offset;
228236
}
229237

230238
uint32_t stb = ELF_ST_BIND(sym.st_info);

subsys/llext/llext_load.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,8 @@ static int llext_allocate_symtab(struct llext_loader *ldr, struct llext *ext)
517517
return 0;
518518
}
519519

520-
static int llext_export_symbols(struct llext_loader *ldr, struct llext *ext)
520+
static int llext_export_symbols(struct llext_loader *ldr, struct llext *ext,
521+
const struct llext_load_param *ldr_parm)
521522
{
522523
struct llext_symtable *exp_tab = &ext->exp_tab;
523524
struct llext_symbol *sym;
@@ -545,7 +546,25 @@ static int llext_export_symbols(struct llext_loader *ldr, struct llext *ext)
545546
}
546547

547548
for (i = 0; i < exp_tab->sym_cnt; i++, sym++) {
548-
exp_tab->syms[i].name = sym->name;
549+
/*
550+
* Offsets in objects, built for pre-defined addresses have to
551+
* be translated to memory locations for symbol name access
552+
* during dependency resolution.
553+
*/
554+
const char *name = NULL;
555+
556+
if (ldr_parm && ldr_parm->pre_located) {
557+
ssize_t name_offset = llext_file_offset(ldr, (uintptr_t)sym->name);
558+
559+
if (name_offset > 0) {
560+
name = llext_peek(ldr, name_offset);
561+
}
562+
}
563+
if (!name) {
564+
name = sym->name;
565+
}
566+
567+
exp_tab->syms[i].name = name;
549568
exp_tab->syms[i].addr = sym->addr;
550569
LOG_DBG("sym %p name %s", sym->addr, sym->name);
551570
}
@@ -730,7 +749,7 @@ int do_llext_load(struct llext_loader *ldr, struct llext *ext,
730749
}
731750
}
732751

733-
ret = llext_export_symbols(ldr, ext);
752+
ret = llext_export_symbols(ldr, ext, ldr_parm);
734753
if (ret != 0) {
735754
LOG_ERR("Failed to export, ret %d", ret);
736755
goto out;

subsys/llext/llext_priv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ static inline const char *llext_string(struct llext_loader *ldr, struct llext *e
6565

6666
int llext_link(struct llext_loader *ldr, struct llext *ext,
6767
const struct llext_load_param *ldr_parm);
68+
ssize_t llext_file_offset(struct llext_loader *ldr, uintptr_t offset);
6869
void llext_dependency_remove_all(struct llext *ext);
6970

7071
#endif /* ZEPHYR_SUBSYS_LLEXT_PRIV_H_ */

0 commit comments

Comments
 (0)