Skip to content

Commit ebde539

Browse files
lyakhMaureenHelm
authored andcommitted
llext: fix handling of non-standard sections in relocatable case
When building partially linked / relocatable objects no ELF segments are created and it becomes more difficult to predict which sections the compiler will build and use. In this case a .data.rel.local section is created by the compiler and it is needed to link .rodata strings in a twister test. We can handle arbitrary sections at run- time if .peek() is supported. If it isn't we need to allocate and copy the section. For now we simply error out in such cases. Fixing that would represent a larger change and can be done incrementally. This also fixes the relocation calculation to point to the correct symbol address instead of the memory location, where it's currently residing, because that can be a temporary buffer as is the case with SOF. Signed-off-by: Guennadi Liakhovetski <[email protected]>
1 parent 29026e8 commit ebde539

File tree

2 files changed

+55
-7
lines changed

2 files changed

+55
-7
lines changed

include/zephyr/llext/llext.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ int llext_iterate(int (*fn)(struct llext *ext, void *arg), void *arg);
124124
struct llext_load_param {
125125
/** Should local relocation be performed */
126126
bool relocate_local;
127+
/**
128+
* Use the virtual symbol addresses from the ELF, not addresses within
129+
* the memory buffer, where the object is loaded
130+
*/
131+
bool pre_located;
127132
};
128133

129134
#define LLEXT_LOAD_PARAM_DEFAULT {.relocate_local = true,}

subsys/llext/llext.c

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,8 @@ static int llext_export_symbols(struct llext_loader *ldr, struct llext *ext)
530530
return 0;
531531
}
532532

533-
static int llext_copy_symbols(struct llext_loader *ldr, struct llext *ext)
533+
static int llext_copy_symbols(struct llext_loader *ldr, struct llext *ext,
534+
bool pre_located)
534535
{
535536
size_t ent_size = ldr->sects[LLEXT_MEM_SYMTAB].sh_entsize;
536537
size_t syms_size = ldr->sects[LLEXT_MEM_SYMTAB].sh_size;
@@ -564,16 +565,58 @@ static int llext_copy_symbols(struct llext_loader *ldr, struct llext *ext)
564565

565566
if ((stt == STT_FUNC || stt == STT_OBJECT) &&
566567
stb == STB_GLOBAL && sect != SHN_UNDEF) {
567-
enum llext_mem mem_idx = ldr->sect_map[sect];
568568
const char *name = llext_string(ldr, ext, LLEXT_MEM_STRTAB, sym.st_name);
569569

570570
__ASSERT(j <= sym_tab->sym_cnt, "Miscalculated symbol number %u\n", j);
571571

572572
sym_tab->syms[j].name = name;
573-
sym_tab->syms[j].addr = (void *)((uintptr_t)ext->mem[mem_idx] +
574-
sym.st_value -
575-
(ldr->hdr.e_type == ET_REL ? 0 :
576-
ldr->sects[mem_idx].sh_addr));
573+
574+
uintptr_t section_addr;
575+
void *base;
576+
577+
if (sect < LLEXT_MEM_BSS) {
578+
/*
579+
* This is just a slight optimisation for cached
580+
* sections, we could use the generic path below
581+
* for all of them
582+
*/
583+
base = ext->mem[ldr->sect_map[sect]];
584+
section_addr = ldr->sects[ldr->sect_map[sect]].sh_addr;
585+
} else {
586+
/* Section header isn't stored, have to read it */
587+
size_t shdr_pos = ldr->hdr.e_shoff + sect * ldr->hdr.e_shentsize;
588+
elf_shdr_t shdr;
589+
590+
ret = llext_seek(ldr, shdr_pos);
591+
if (ret != 0) {
592+
LOG_ERR("failed seeking to position %zu\n", shdr_pos);
593+
return ret;
594+
}
595+
596+
ret = llext_read(ldr, &shdr, sizeof(elf_shdr_t));
597+
if (ret != 0) {
598+
LOG_ERR("failed reading section header at position %zu\n",
599+
shdr_pos);
600+
return ret;
601+
}
602+
603+
base = llext_peek(ldr, shdr.sh_offset);
604+
if (!base) {
605+
LOG_ERR("cannot handle arbitrary sections without .peek\n");
606+
return -EOPNOTSUPP;
607+
}
608+
609+
section_addr = shdr.sh_addr;
610+
}
611+
612+
if (pre_located) {
613+
sym_tab->syms[j].addr = (uint8_t *)sym.st_value +
614+
(ldr->hdr.e_type == ET_REL ? section_addr : 0);
615+
} else {
616+
sym_tab->syms[j].addr = (uint8_t *)base + sym.st_value -
617+
(ldr->hdr.e_type == ET_REL ? 0 : section_addr);
618+
}
619+
577620
LOG_DBG("function symbol %d name %s addr %p",
578621
j, name, sym_tab->syms[j].addr);
579622
j++;
@@ -954,7 +997,7 @@ static int do_llext_load(struct llext_loader *ldr, struct llext *ext,
954997
}
955998

956999
LOG_DBG("Copying symbols...");
957-
ret = llext_copy_symbols(ldr, ext);
1000+
ret = llext_copy_symbols(ldr, ext, ldr_parm ? ldr_parm->pre_located : false);
9581001
if (ret != 0) {
9591002
LOG_ERR("Failed to copy symbols, ret %d", ret);
9601003
goto out;

0 commit comments

Comments
 (0)