diff --git a/include/zephyr/llext/llext.h b/include/zephyr/llext/llext.h index 181df163085..1e026178327 100644 --- a/include/zephyr/llext/llext.h +++ b/include/zephyr/llext/llext.h @@ -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 * diff --git a/include/zephyr/llext/loader.h b/include/zephyr/llext/loader.h index 6684d98a747..3d043806ef7 100644 --- a/include/zephyr/llext/loader.h +++ b/include/zephyr/llext/loader.h @@ -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 */ }; diff --git a/subsys/llext/llext.c b/subsys/llext/llext.c index 4e0ff98c13a..ba1bb0325de 100644 --- a/subsys/llext/llext.c +++ b/subsys/llext/llext.c @@ -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) *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); diff --git a/subsys/llext/llext_link.c b/subsys/llext/llext_link.c index f3eae9f7f76..6d5e2ff23bc 100644 --- a/subsys/llext/llext_link.c +++ b/subsys/llext/llext_link.c @@ -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 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 * 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 /* 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); diff --git a/subsys/llext/llext_load.c b/subsys/llext/llext_load.c index 3e8d7f97677..bd73312c085 100644 --- a/subsys/llext/llext_load.c +++ b/subsys/llext/llext_load.c @@ -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) 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) /* * 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, 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, * 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, 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, #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: 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.