Browse Source

LLEXT: preserve section headers

Move cached section headers to struct llext from struct llext_loader
to preserve them after llext_load() returns.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
pull/81485/head
Guennadi Liakhovetski 8 months ago committed by Anas Nashif
parent
commit
c714f0e148
  1. 16
      include/zephyr/llext/llext.h
  2. 3
      include/zephyr/llext/loader.h
  3. 8
      subsys/llext/llext.c
  4. 12
      subsys/llext/llext_link.c
  5. 45
      subsys/llext/llext_load.c

16
include/zephyr/llext/llext.h

@ -120,8 +120,24 @@ struct llext { @@ -120,8 +120,24 @@ struct llext {
/** Array of extensions, whose symbols this extension accesses */
struct llext *dependency[LLEXT_MAX_DEPENDENCIES];
/** @cond ignore */
unsigned int sect_cnt;
elf_shdr_t *sect_hdrs;
bool sect_hdrs_on_heap;
/** @endcond */
};
static inline const elf_shdr_t *llext_section_headers(const struct llext *ext)
{
return ext->sect_hdrs;
}
static inline unsigned int llext_section_count(const struct llext *ext)
{
return ext->sect_cnt;
}
/**
* @brief Advanced llext_load parameters
*

3
include/zephyr/llext/loader.h

@ -98,10 +98,7 @@ struct llext_loader { @@ -98,10 +98,7 @@ struct llext_loader {
/** @cond ignore */
elf_ehdr_t hdr;
elf_shdr_t sects[LLEXT_MEM_COUNT];
elf_shdr_t *sect_hdrs;
bool sect_hdrs_on_heap;
struct llext_elf_sect_map *sect_map;
uint32_t sect_cnt;
/** @endcond */
};

8
subsys/llext/llext.c

@ -25,10 +25,6 @@ static struct k_mutex llext_lock = Z_MUTEX_INITIALIZER(llext_lock); @@ -25,10 +25,6 @@ static struct k_mutex llext_lock = Z_MUTEX_INITIALIZER(llext_lock);
ssize_t llext_find_section(struct llext_loader *ldr, const char *search_name)
{
/* Note that this API is used after llext_load(), so the ldr->sect_hdrs
* cache is already freed. A direct search covers all situations.
*/
elf_shdr_t *shdr;
unsigned int i;
size_t pos;
@ -253,6 +249,10 @@ int llext_unload(struct llext **ext) @@ -253,6 +249,10 @@ int llext_unload(struct llext **ext)
*ext = NULL;
k_mutex_unlock(&llext_lock);
if (tmp->sect_hdrs_on_heap) {
llext_free(tmp->sect_hdrs);
}
llext_free_regions(tmp);
llext_free(tmp->sym_tab.syms);
llext_free(tmp->exp_tab.syms);

12
subsys/llext/llext_link.c

@ -280,8 +280,8 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l @@ -280,8 +280,8 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l
const char *name;
int i, ret;
for (i = 0; i < ldr->sect_cnt; ++i) {
elf_shdr_t *shdr = ldr->sect_hdrs + i;
for (i = 0; i < ext->sect_cnt; ++i) {
elf_shdr_t *shdr = ext->sect_hdrs + i;
/* find proper relocation sections */
switch (shdr->sh_type) {
@ -308,7 +308,7 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l @@ -308,7 +308,7 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l
continue;
}
if (shdr->sh_info >= ldr->sect_cnt ||
if (shdr->sh_info >= ext->sect_cnt ||
shdr->sh_size % shdr->sh_entsize != 0) {
LOG_ERR("Sanity checks failed for section %d "
"(info %zd, size %zd, entsize %zd)", i,
@ -340,7 +340,7 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l @@ -340,7 +340,7 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l
* section .X to local or global symbols. They point to entries
* in the symbol table, describing respective symbols
*/
tgt = ldr->sect_hdrs + shdr->sh_info;
tgt = ext->sect_hdrs + shdr->sh_info;
}
llext_link_plt(ldr, ext, shdr, ldr_parm, tgt);
@ -481,8 +481,8 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l @@ -481,8 +481,8 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l
/* Detached section caches should be synchronized in place */
if (ldr_parm->section_detached) {
for (i = 0; i < ldr->sect_cnt; ++i) {
elf_shdr_t *shdr = ldr->sect_hdrs + i;
for (i = 0; i < ext->sect_cnt; ++i) {
elf_shdr_t *shdr = ext->sect_hdrs + i;
if (ldr_parm->section_detached(shdr)) {
void *base = llext_peek(ldr, shdr->sh_offset);

45
subsys/llext/llext_load.c

@ -103,29 +103,29 @@ static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext) @@ -103,29 +103,29 @@ static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext)
return -ENOEXEC;
}
ldr->sect_cnt = ldr->hdr.e_shnum;
ext->sect_cnt = ldr->hdr.e_shnum;
size_t sect_map_sz = ldr->sect_cnt * sizeof(ldr->sect_map[0]);
size_t sect_map_sz = ext->sect_cnt * sizeof(ldr->sect_map[0]);
ldr->sect_map = llext_alloc(sect_map_sz);
if (!ldr->sect_map) {
LOG_ERR("Failed to allocate section map, size %zu", sect_map_sz);
return -ENOMEM;
}
for (int i = 0; i < ldr->sect_cnt; i++) {
for (int i = 0; i < ext->sect_cnt; i++) {
ldr->sect_map[i].mem_idx = LLEXT_MEM_COUNT;
ldr->sect_map[i].offset = 0;
}
ldr->sect_hdrs = (elf_shdr_t *) llext_peek(ldr, ldr->hdr.e_shoff);
if (ldr->sect_hdrs) {
ldr->sect_hdrs_on_heap = false;
ext->sect_hdrs = (elf_shdr_t *)llext_peek(ldr, ldr->hdr.e_shoff);
if (ext->sect_hdrs) {
ext->sect_hdrs_on_heap = false;
} else {
size_t sect_hdrs_sz = ldr->sect_cnt * sizeof(ldr->sect_hdrs[0]);
size_t sect_hdrs_sz = ext->sect_cnt * sizeof(ext->sect_hdrs[0]);
ldr->sect_hdrs_on_heap = true;
ldr->sect_hdrs = llext_alloc(sect_hdrs_sz);
if (!ldr->sect_hdrs) {
ext->sect_hdrs_on_heap = true;
ext->sect_hdrs = llext_alloc(sect_hdrs_sz);
if (!ext->sect_hdrs) {
LOG_ERR("Failed to allocate section headers, size %zu", sect_hdrs_sz);
return -ENOMEM;
}
@ -136,7 +136,7 @@ static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext) @@ -136,7 +136,7 @@ static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext)
return ret;
}
ret = llext_read(ldr, ldr->sect_hdrs, sect_hdrs_sz);
ret = llext_read(ldr, ext->sect_hdrs, sect_hdrs_sz);
if (ret != 0) {
LOG_ERR("Failed to read section headers");
return ret;
@ -149,15 +149,15 @@ static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext) @@ -149,15 +149,15 @@ static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext)
/*
* Find all relevant string and symbol tables
*/
static int llext_find_tables(struct llext_loader *ldr)
static int llext_find_tables(struct llext_loader *ldr, struct llext *ext)
{
int table_cnt, i;
memset(ldr->sects, 0, sizeof(ldr->sects));
/* Find symbol and string tables */
for (i = 0, table_cnt = 0; i < ldr->sect_cnt && table_cnt < 3; ++i) {
elf_shdr_t *shdr = ldr->sect_hdrs + i;
for (i = 0, table_cnt = 0; i < ext->sect_cnt && table_cnt < 3; ++i) {
elf_shdr_t *shdr = ext->sect_hdrs + i;
LOG_DBG("section %d at 0x%zx: name %d, type %d, flags 0x%zx, "
"addr 0x%zx, size %zd, link %d, info %d",
@ -216,8 +216,8 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext, @@ -216,8 +216,8 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext,
int i, j;
const char *name;
for (i = 0; i < ldr->sect_cnt; ++i) {
elf_shdr_t *shdr = ldr->sect_hdrs + i;
for (i = 0; i < ext->sect_cnt; ++i) {
elf_shdr_t *shdr = ext->sect_hdrs + i;
name = llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr->sh_name);
@ -437,8 +437,8 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext, @@ -437,8 +437,8 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext,
* Calculate each ELF section's offset inside its memory region. This
* is done as a separate pass so the final regions are already defined.
*/
for (i = 0; i < ldr->sect_cnt; ++i) {
elf_shdr_t *shdr = ldr->sect_hdrs + i;
for (i = 0; i < ext->sect_cnt; ++i) {
elf_shdr_t *shdr = ext->sect_hdrs + i;
enum llext_mem mem_idx = ldr->sect_map[i].mem_idx;
if (mem_idx != LLEXT_MEM_COUNT) {
@ -585,7 +585,7 @@ static int llext_copy_symbols(struct llext_loader *ldr, struct llext *ext, @@ -585,7 +585,7 @@ static int llext_copy_symbols(struct llext_loader *ldr, struct llext *ext,
sym_tab->syms[j].name = name;
elf_shdr_t *shdr = ldr->sect_hdrs + shndx;
elf_shdr_t *shdr = ext->sect_hdrs + shndx;
uintptr_t section_addr = shdr->sh_addr;
if (ldr_parm->pre_located &&
@ -664,7 +664,7 @@ int do_llext_load(struct llext_loader *ldr, struct llext *ext, @@ -664,7 +664,7 @@ int do_llext_load(struct llext_loader *ldr, struct llext *ext,
#endif
LOG_DBG("Finding ELF tables...");
ret = llext_find_tables(ldr);
ret = llext_find_tables(ldr, ext);
if (ret != 0) {
LOG_ERR("Failed to find important ELF tables, ret %d", ret);
goto out;
@ -736,11 +736,6 @@ out: @@ -736,11 +736,6 @@ out:
llext_free(ldr->sect_map);
ldr->sect_map = NULL;
if (ldr->sect_hdrs_on_heap) {
llext_free(ldr->sect_hdrs);
}
ldr->sect_hdrs = NULL;
/* Until proper inter-llext linking is implemented, the symbol table is
* not useful outside of the loading process; keep it only if debugging
* is enabled and no error is detected.

Loading…
Cancel
Save