diff --git a/include/zephyr/llext/llext.h b/include/zephyr/llext/llext.h index 1e026178327..5bd16ea3356 100644 --- a/include/zephyr/llext/llext.h +++ b/include/zephyr/llext/llext.h @@ -354,6 +354,22 @@ int arch_elf_relocate(elf_rela_t *rel, uintptr_t loc, */ ssize_t llext_find_section(struct llext_loader *loader, const char *search_name); +/** + * @brief Extract ELF section header by name. + * + * Searches for a section by name in the ELF file and retrieves its full header. + * + * @param[in] loader Extension loader data and context + * @param[in] ext Extension to be searched + * @param[in] search_name Section name to search for + * @param[out] shdr Buffer for the section header + * @retval 0 Success + * @retval -ENOTSUP "peek" method not supported + * @retval -ENOENT section not found + */ +int llext_get_section_header(struct llext_loader *loader, struct llext *ext, + const char *search_name, elf_shdr_t *shdr); + /** * @brief Architecture specific function for local binding relocations * diff --git a/subsys/llext/llext.c b/subsys/llext/llext.c index ba1bb0325de..c1871a0c6f0 100644 --- a/subsys/llext/llext.c +++ b/subsys/llext/llext.c @@ -23,6 +23,32 @@ static sys_slist_t _llext_list = SYS_SLIST_STATIC_INIT(&_llext_list); static struct k_mutex llext_lock = Z_MUTEX_INITIALIZER(llext_lock); +int llext_get_section_header(struct llext_loader *ldr, struct llext *ext, const char *search_name, + elf_shdr_t *shdr) +{ + const elf_shdr_t *tmp; + unsigned int i; + + for (i = 0, tmp = ext->sect_hdrs; + i < ext->sect_cnt; + i++, tmp++) { + const char *name = llext_peek(ldr, + ldr->sects[LLEXT_MEM_SHSTRTAB].sh_offset + + tmp->sh_name); + + if (!name) { + return -ENOTSUP; + } + + if (!strcmp(name, search_name)) { + *shdr = *tmp; + return 0; + } + } + + return -ENOENT; +} + ssize_t llext_find_section(struct llext_loader *ldr, const char *search_name) { elf_shdr_t *shdr; diff --git a/tests/subsys/llext/simple/src/test_llext_simple.c b/tests/subsys/llext/simple/src/test_llext_simple.c index 6368a1b60ad..025a715ddbf 100644 --- a/tests/subsys/llext/simple/src/test_llext_simple.c +++ b/tests/subsys/llext/simple/src/test_llext_simple.c @@ -11,6 +11,7 @@ #if defined(CONFIG_FILE_SYSTEM_LITTLEFS) #include #endif +#include #include #include #include @@ -411,6 +412,7 @@ ZTEST(llext, test_find_section) struct llext_loader *loader = &buf_loader.loader; struct llext_load_param ldr_parm = LLEXT_LOAD_PARAM_DEFAULT; struct llext *ext = NULL; + elf_shdr_t shdr; res = llext_load(loader, "find_section", &ext, &ldr_parm); zassert_ok(res, "load should succeed"); @@ -418,6 +420,11 @@ ZTEST(llext, test_find_section) section_ofs = llext_find_section(loader, ".data"); zassert_true(section_ofs > 0, "find_section returned %zd", section_ofs); + res = llext_get_section_header(loader, ext, ".data", &shdr); + zassert_ok(res, "get_section_header() should succeed"); + zassert_equal(shdr.sh_offset, section_ofs, + "different section offset %zd from get_section_header", shdr.sh_offset); + uintptr_t symbol_ptr = (uintptr_t)llext_find_sym(&ext->exp_tab, "number"); uintptr_t section_ptr = (uintptr_t)find_section_ext + section_ofs;