From 7deb037497c00d151b887887cd04edbf7ce0d400 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 5 Jul 2024 09:06:10 +0200 Subject: [PATCH 1/7] llext: remove an unused variable Remove a loop counter, that isn't actually used for anything. Signed-off-by: Guennadi Liakhovetski --- subsys/llext/llext.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/subsys/llext/llext.c b/subsys/llext/llext.c index 831667f7c96c7..c61b5006947ba 100644 --- a/subsys/llext/llext.c +++ b/subsys/llext/llext.c @@ -82,14 +82,13 @@ struct llext *llext_by_name(const char *name) int llext_iterate(int (*fn)(struct llext *ext, void *arg), void *arg) { sys_snode_t *node; - unsigned int i; int ret = 0; k_mutex_lock(&llext_lock, K_FOREVER); - for (node = sys_slist_peek_head(&_llext_list), i = 0; + for (node = sys_slist_peek_head(&_llext_list); node; - node = sys_slist_peek_next(node), i++) { + node = sys_slist_peek_next(node)) { struct llext *ext = CONTAINER_OF(node, struct llext, _llext_list); ret = fn(ext, arg); From d1d3c67305185d52f5cf5e93a61d615b8280935c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 28 Aug 2024 15:13:48 +0200 Subject: [PATCH 2/7] llext: make EXPORT_SYMBOL() universal Currently LLEXT has two ways to export symbols: EXPORT_SYMBOL() to exort symbols from the main firmware to extensions LL_EXTENSION_SYMBOL() to export symbols from extensions but it is possible to write code, that needs to export symbols regardless of whether it is built into the main image or an extension. And in fact there's no real need in two distinct macros - we can use one for both cases and recognise at build time which direction exporting is happening. This patch extends EXPORT_SYMBOL() to also work from extensions. Signed-off-by: Guennadi Liakhovetski --- include/zephyr/llext/symbol.h | 44 ++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/include/zephyr/llext/symbol.h b/include/zephyr/llext/symbol.h index 412924ddd4607..330bb19d9de48 100644 --- a/include/zephyr/llext/symbol.h +++ b/include/zephyr/llext/symbol.h @@ -87,6 +87,26 @@ struct llext_symtable { }; +/** + * @brief Exports a symbol from an extension to the base image + * + * This macro can be used in extensions to add a symbol (function or object) + * to the extension's exported symbol table, so that it may be referenced by + * the base image. + * + * @param x Extension symbol to export to the base image + */ +#if defined(CONFIG_LLEXT) && defined(LL_EXTENSION_BUILD) +#define LL_EXTENSION_SYMBOL(x) \ + static const struct llext_const_symbol \ + Z_GENERIC_SECTION(".exported_sym") __used \ + x ## _sym = { \ + .name = STRINGIFY(x), .addr = (const void *)&x, \ + } +#else +#define LL_EXTENSION_SYMBOL(x) +#endif + /** * @brief Export a constant symbol to extensions * @@ -96,7 +116,9 @@ struct llext_symtable { * * @param x Symbol to export to extensions */ -#if defined(CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID) +#if defined(LL_EXTENSION_BUILD) +#define EXPORT_SYMBOL(x) LL_EXTENSION_SYMBOL(x) +#elif defined(CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID) #define EXPORT_SYMBOL(x) \ static const char Z_GENERIC_SECTION("llext_exports_strtab") __used \ x ## _sym_name[] = STRINGIFY(x); \ @@ -112,26 +134,6 @@ struct llext_symtable { #define EXPORT_SYMBOL(x) #endif -/** - * @brief Exports a symbol from an extension to the base image - * - * This macro can be used in extensions to add a symbol (function or object) - * to the extension's exported symbol table, so that it may be referenced by - * the base image. - * - * @param x Extension symbol to export to the base image - */ -#if defined(CONFIG_LLEXT) && defined(LL_EXTENSION_BUILD) -#define LL_EXTENSION_SYMBOL(x) \ - static const struct llext_const_symbol \ - Z_GENERIC_SECTION(".exported_sym") __used \ - x ## _sym = { \ - .name = STRINGIFY(x), .addr = (const void *)&x, \ - } -#else -#define LL_EXTENSION_SYMBOL(x) -#endif - /** * @} */ From d59650906e98031a4e38d5a72fac82a671122eeb Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 28 Aug 2024 15:23:50 +0200 Subject: [PATCH 3/7] llext: use EXPORT_SYMBOL() universally Replace LL_EXTENSION_SYMBOL() with EXPORT_SYMBOL() in all tests and samples. Signed-off-by: Guennadi Liakhovetski --- samples/subsys/llext/edk/ext1/src/main.c | 2 +- samples/subsys/llext/edk/ext2/src/main.c | 2 +- samples/subsys/llext/edk/ext3/src/main.c | 2 +- samples/subsys/llext/edk/k-ext1/src/main.c | 2 +- samples/subsys/llext/modules/src/hello_world_ext.c | 2 +- tests/misc/llext-edk/extension/src/main.c | 2 +- tests/subsys/llext/simple/src/find_section_ext.c | 2 +- tests/subsys/llext/simple/src/hello_world_ext.c | 2 +- tests/subsys/llext/simple/src/logging_ext.c | 2 +- tests/subsys/llext/simple/src/movwmovt_ext.c | 2 +- tests/subsys/llext/simple/src/multi_file_ext1.c | 2 +- tests/subsys/llext/simple/src/object_ext.c | 2 +- tests/subsys/llext/simple/src/pre_located_ext.c | 2 +- tests/subsys/llext/simple/src/relative_jump_ext.c | 2 +- tests/subsys/llext/simple/src/syscalls_ext.c | 2 +- tests/subsys/llext/simple/src/threads_kernel_objects_ext.c | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/samples/subsys/llext/edk/ext1/src/main.c b/samples/subsys/llext/edk/ext1/src/main.c index d7f9c6aa71b3f..a2d98a937845f 100644 --- a/samples/subsys/llext/edk/ext1/src/main.c +++ b/samples/subsys/llext/edk/ext1/src/main.c @@ -31,4 +31,4 @@ int start(void) return 0; } -LL_EXTENSION_SYMBOL(start); +EXPORT_SYMBOL(start); diff --git a/samples/subsys/llext/edk/ext2/src/main.c b/samples/subsys/llext/edk/ext2/src/main.c index 38a054a5ccb19..f6fd7822f4de1 100644 --- a/samples/subsys/llext/edk/ext2/src/main.c +++ b/samples/subsys/llext/edk/ext2/src/main.c @@ -23,4 +23,4 @@ int start(void) return 0; } -LL_EXTENSION_SYMBOL(start); +EXPORT_SYMBOL(start); diff --git a/samples/subsys/llext/edk/ext3/src/main.c b/samples/subsys/llext/edk/ext3/src/main.c index 19aff8352d967..fcaf40186c4a5 100644 --- a/samples/subsys/llext/edk/ext3/src/main.c +++ b/samples/subsys/llext/edk/ext3/src/main.c @@ -62,4 +62,4 @@ int start(void) return 0; } -LL_EXTENSION_SYMBOL(start); +EXPORT_SYMBOL(start); diff --git a/samples/subsys/llext/edk/k-ext1/src/main.c b/samples/subsys/llext/edk/k-ext1/src/main.c index 34dedc6372820..121cc2568a88f 100644 --- a/samples/subsys/llext/edk/k-ext1/src/main.c +++ b/samples/subsys/llext/edk/k-ext1/src/main.c @@ -61,4 +61,4 @@ int start(void) return 0; } -LL_EXTENSION_SYMBOL(start); +EXPORT_SYMBOL(start); diff --git a/samples/subsys/llext/modules/src/hello_world_ext.c b/samples/subsys/llext/modules/src/hello_world_ext.c index 41220b027255e..b7251d6917d04 100644 --- a/samples/subsys/llext/modules/src/hello_world_ext.c +++ b/samples/subsys/llext/modules/src/hello_world_ext.c @@ -24,4 +24,4 @@ void hello_world(void) printk("Hello, world, from an llext!\n"); #endif } -LL_EXTENSION_SYMBOL(hello_world); +EXPORT_SYMBOL(hello_world); diff --git a/tests/misc/llext-edk/extension/src/main.c b/tests/misc/llext-edk/extension/src/main.c index 59038de2cdf05..235504f5f8c37 100644 --- a/tests/misc/llext-edk/extension/src/main.c +++ b/tests/misc/llext-edk/extension/src/main.c @@ -14,4 +14,4 @@ int start(int bar) printk("foo(%d) is %d\n", bar, foo(bar)); return 0; } -LL_EXTENSION_SYMBOL(start); +EXPORT_SYMBOL(start); diff --git a/tests/subsys/llext/simple/src/find_section_ext.c b/tests/subsys/llext/simple/src/find_section_ext.c index fcbe5c92a4d8b..5d947914ef402 100644 --- a/tests/subsys/llext/simple/src/find_section_ext.c +++ b/tests/subsys/llext/simple/src/find_section_ext.c @@ -22,4 +22,4 @@ void test_entry(void) /* unused */ } -LL_EXTENSION_SYMBOL(number); +EXPORT_SYMBOL(number); diff --git a/tests/subsys/llext/simple/src/hello_world_ext.c b/tests/subsys/llext/simple/src/hello_world_ext.c index 2a8bdf56c95eb..4cd2713cd9306 100644 --- a/tests/subsys/llext/simple/src/hello_world_ext.c +++ b/tests/subsys/llext/simple/src/hello_world_ext.c @@ -24,4 +24,4 @@ void test_entry(void) printk("A number is %u\n", number); zassert_equal(number, 42); } -LL_EXTENSION_SYMBOL(test_entry); +EXPORT_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/logging_ext.c b/tests/subsys/llext/simple/src/logging_ext.c index 94298ce2f150d..75a6428ebcf81 100644 --- a/tests/subsys/llext/simple/src/logging_ext.c +++ b/tests/subsys/llext/simple/src/logging_ext.c @@ -23,4 +23,4 @@ void test_entry(void) LOG_INF("hello world"); LOG_INF("A number is %" PRIu32, number); } -LL_EXTENSION_SYMBOL(test_entry); +EXPORT_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/movwmovt_ext.c b/tests/subsys/llext/simple/src/movwmovt_ext.c index 21633228778b1..aecaf029ddc97 100644 --- a/tests/subsys/llext/simple/src/movwmovt_ext.c +++ b/tests/subsys/llext/simple/src/movwmovt_ext.c @@ -32,4 +32,4 @@ void test_entry(void) __asm volatile ("blx r0"); zassert_equal(test_var, 1, "mov.w and mov.t test failed"); } -LL_EXTENSION_SYMBOL(test_entry); +EXPORT_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/multi_file_ext1.c b/tests/subsys/llext/simple/src/multi_file_ext1.c index bdc8bccaaa128..8aa9092ee2801 100644 --- a/tests/subsys/llext/simple/src/multi_file_ext1.c +++ b/tests/subsys/llext/simple/src/multi_file_ext1.c @@ -50,4 +50,4 @@ void test_entry(void) run_id += 1; } -LL_EXTENSION_SYMBOL(test_entry); +EXPORT_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/object_ext.c b/tests/subsys/llext/simple/src/object_ext.c index 7efe1a916d64e..1a4ea53158efd 100644 --- a/tests/subsys/llext/simple/src/object_ext.c +++ b/tests/subsys/llext/simple/src/object_ext.c @@ -45,4 +45,4 @@ void test_entry(void) run_id += 1; } -LL_EXTENSION_SYMBOL(test_entry); +EXPORT_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/pre_located_ext.c b/tests/subsys/llext/simple/src/pre_located_ext.c index 1308c8d662fc6..99d4b77ca5772 100644 --- a/tests/subsys/llext/simple/src/pre_located_ext.c +++ b/tests/subsys/llext/simple/src/pre_located_ext.c @@ -16,4 +16,4 @@ void test_entry(void) { /* This function is never called */ } -LL_EXTENSION_SYMBOL(test_entry); +EXPORT_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/relative_jump_ext.c b/tests/subsys/llext/simple/src/relative_jump_ext.c index e7f67469b834e..8153d84903ca8 100644 --- a/tests/subsys/llext/simple/src/relative_jump_ext.c +++ b/tests/subsys/llext/simple/src/relative_jump_ext.c @@ -62,4 +62,4 @@ void test_entry(void) printk("exit\n"); zassert_equal(test_var, 1, "relative jump test failed"); } -LL_EXTENSION_SYMBOL(test_entry); +EXPORT_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/syscalls_ext.c b/tests/subsys/llext/simple/src/syscalls_ext.c index f8f073fb6f99f..d8e6449ee2ff3 100644 --- a/tests/subsys/llext/simple/src/syscalls_ext.c +++ b/tests/subsys/llext/simple/src/syscalls_ext.c @@ -23,4 +23,4 @@ void test_entry(void) input, input + 1, output); zassert_equal(output, input + 1); } -LL_EXTENSION_SYMBOL(test_entry); +EXPORT_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/threads_kernel_objects_ext.c b/tests/subsys/llext/simple/src/threads_kernel_objects_ext.c index fd6b9673c9578..ab9763b912151 100644 --- a/tests/subsys/llext/simple/src/threads_kernel_objects_ext.c +++ b/tests/subsys/llext/simple/src/threads_kernel_objects_ext.c @@ -42,4 +42,4 @@ void test_entry(void) k_thread_join(&my_thread, K_FOREVER); printk("Test thread joined\n"); } -LL_EXTENSION_SYMBOL(test_entry); +EXPORT_SYMBOL(test_entry); From b8ec7e368c38d1b22f73b3e1fbda0fa1e89400d2 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 5 Jul 2024 09:20:08 +0200 Subject: [PATCH 4/7] llext: look for symbols in other LLEXT objects too LLEXT objects can also export symbols for use by other such objects. That means, that when linking an LLEXT object we have to look for unresolved symbols in previously loaded objects too. Signed-off-by: Guennadi Liakhovetski --- subsys/llext/llext_link.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/subsys/llext/llext_link.c b/subsys/llext/llext_link.c index 4ee19f57583bd..6c5373d491675 100644 --- a/subsys/llext/llext_link.c +++ b/subsys/llext/llext_link.c @@ -52,6 +52,33 @@ static size_t llext_file_offset(struct llext_loader *ldr, size_t offset) return offset; } +struct llext_extension_sym { + const char *sym; + const void *addr; +}; + +static int llext_find_extension_sym_iterate(struct llext *ext, void *arg) +{ + struct llext_extension_sym *se = arg; + const void *addr = llext_find_sym(&ext->exp_tab, se->sym); + + if (addr) { + se->addr = addr; + return 1; + } + + return 0; +} + +static const void *llext_find_extension_sym(const char *sym_name) +{ + struct llext_extension_sym se = {.sym = sym_name}; + + llext_iterate(llext_find_extension_sym_iterate, &se); + + return se.addr; +} + static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, elf_shdr_t *shdr, bool do_local, elf_shdr_t *tgt) { @@ -148,6 +175,10 @@ static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, link_addr = llext_find_sym(&ext->sym_tab, name); } + if (!link_addr) { + link_addr = llext_find_extension_sym(name); + } + if (!link_addr) { LOG_WRN("PLT: cannot find idx %u name %s", j, name); continue; From 9a1f217cab2acee8bdd9b612a8ad231f8c4e0c19 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 19 Jul 2024 11:16:11 +0300 Subject: [PATCH 5/7] llext: export a symbol needed for immediate logging Using the immediate logging option from LLEXT modules requires one more symbol export. Signed-off-by: Guennadi Liakhovetski --- subsys/logging/log_msg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/logging/log_msg.c b/subsys/logging/log_msg.c index c45eb2201daf1..e6534998c5071 100644 --- a/subsys/logging/log_msg.c +++ b/subsys/logging/log_msg.c @@ -397,6 +397,7 @@ void z_log_msg_runtime_vcreate(uint8_t domain_id, const void *source, z_log_msg_finalize(msg, source, desc, data); } } +EXPORT_SYMBOL(z_log_msg_runtime_vcreate); int16_t log_msg_get_source_id(struct log_msg *msg) { From b2114eaf761e950fd18c95851f7d9c312fb2c448 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 23 Aug 2024 10:20:22 +0200 Subject: [PATCH 6/7] llext: fix flag evaluation for section grouping When deciding which sections to group together, only the low 3 section attribute bits are relevant, ignore the rest. Signed-off-by: Guennadi Liakhovetski --- include/zephyr/llext/elf.h | 2 ++ subsys/llext/llext_load.c | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/zephyr/llext/elf.h b/include/zephyr/llext/elf.h index b0477416a4338..ca9f498a49ac0 100644 --- a/include/zephyr/llext/elf.h +++ b/include/zephyr/llext/elf.h @@ -212,6 +212,8 @@ struct elf64_shdr { #define SHF_ALLOC 0x2 /**< Section is present in memory */ #define SHF_EXECINSTR 0x4 /**< Section contains executable instructions */ +#define SHF_BASIC_TYPE_MASK (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR) + /** * @brief Symbol table entry(32-bit) */ diff --git a/subsys/llext/llext_load.c b/subsys/llext/llext_load.c index de3cdd6402b96..fcc26210ebcfc 100644 --- a/subsys/llext/llext_load.c +++ b/subsys/llext/llext_load.c @@ -253,8 +253,10 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext) memcpy(region, shdr, sizeof(*region)); } else { /* Make sure this section is compatible with the region */ - if (shdr->sh_flags != region->sh_flags) { - LOG_ERR("Unsupported section flags for %s (region %d)", + if ((shdr->sh_flags & SHF_BASIC_TYPE_MASK) != + (region->sh_flags & SHF_BASIC_TYPE_MASK)) { + LOG_ERR("Unsupported section flags %#x / %#x for %s (region %d)", + (uint32_t)shdr->sh_flags, (uint32_t)region->sh_flags, name, mem_idx); return -ENOEXEC; } From c110441d9be138005a882b628e02735d8eac9d89 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 23 Aug 2024 10:45:17 +0200 Subject: [PATCH 7/7] llext: add dependencies When an LLEXT object uses symbols of another such object, it depends on it. Such dependencies have to be tracked to prevent their accidental unloading. Ideally we should be able to track arbitrary numbers of such dependencies, but this is a bit difficult. In this first implementation we use a fixed-size array, currently consisting of 8 entries. Signed-off-by: Guennadi Liakhovetski --- include/zephyr/llext/llext.h | 6 +++ subsys/llext/llext.c | 2 + subsys/llext/llext_link.c | 75 +++++++++++++++++++++++++++++++++++- subsys/llext/llext_priv.h | 1 + 4 files changed, 82 insertions(+), 2 deletions(-) diff --git a/include/zephyr/llext/llext.h b/include/zephyr/llext/llext.h index 19fbe7a0b55da..9256f1db8a65d 100644 --- a/include/zephyr/llext/llext.h +++ b/include/zephyr/llext/llext.h @@ -62,6 +62,9 @@ enum llext_mem { struct llext_loader; /** @endcond */ +/* Maximim number of dependency LLEXTs */ +#define LLEXT_MAX_DEPENDENCIES 8 + /** * @brief Structure describing a linkable loadable extension * @@ -111,6 +114,9 @@ struct llext { /** Extension use counter, prevents unloading while in use */ unsigned int use_count; + + /** Array of extensions, whose symbols this extension accesses */ + struct llext *dependency[LLEXT_MAX_DEPENDENCIES]; }; /** diff --git a/subsys/llext/llext.c b/subsys/llext/llext.c index c61b5006947ba..8469e316b5c34 100644 --- a/subsys/llext/llext.c +++ b/subsys/llext/llext.c @@ -197,6 +197,8 @@ int llext_unload(struct llext **ext) /* FIXME: protect the global list */ sys_slist_find_and_remove(&_llext_list, &tmp->_llext_list); + llext_dependency_remove_all(tmp); + *ext = NULL; k_mutex_unlock(&llext_lock); diff --git a/subsys/llext/llext_link.c b/subsys/llext/llext_link.c index 6c5373d491675..959db4db28a03 100644 --- a/subsys/llext/llext_link.c +++ b/subsys/llext/llext_link.c @@ -52,7 +52,56 @@ static size_t llext_file_offset(struct llext_loader *ldr, size_t offset) return offset; } +/* + * We increment use-count every time a new dependent is added, and have to + * decrement it again, when one is removed. Ideally we should be able to add + * arbitrary numbers of dependencies, but using lists for this doesn't work, + * because multiple extensions can have common dependencies. Dynamically + * allocating dependency entries would be too wasteful. In this initial + * implementation we use an array of dependencies, if at some point we run out + * of array entries, we'll implement re-allocation. + * We add dependencies incrementally as we discover them, but we only ever + * expect them to be removed all at once, when their user is removed. So the + * dependency array is always "dense" - it cannot have NULL entries between + * valid ones. + */ +static int llext_dependency_add(struct llext *ext, struct llext *dependency) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(ext->dependency); i++) { + if (ext->dependency[i] == dependency) { + return 0; + } + + if (!ext->dependency[i]) { + ext->dependency[i] = dependency; + dependency->use_count++; + + return 0; + } + } + + return -ENOENT; +} + +void llext_dependency_remove_all(struct llext *ext) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(ext->dependency) && ext->dependency[i]; i++) { + /* + * The use-count of dependencies is tightly bound to dependent's + * life cycle, so it shouldn't underrun. + */ + ext->dependency[i]->use_count--; + __ASSERT(ext->dependency[i]->use_count, "LLEXT dependency use-count underrun!"); + /* No need to NULL-ify the pointer - ext is freed after this */ + } +} + struct llext_extension_sym { + struct llext *ext; const char *sym; const void *addr; }; @@ -64,17 +113,21 @@ static int llext_find_extension_sym_iterate(struct llext *ext, void *arg) if (addr) { se->addr = addr; + se->ext = ext; return 1; } return 0; } -static const void *llext_find_extension_sym(const char *sym_name) +static const void *llext_find_extension_sym(const char *sym_name, struct llext **ext) { struct llext_extension_sym se = {.sym = sym_name}; llext_iterate(llext_find_extension_sym_iterate, &se); + if (ext) { + *ext = se.ext; + } return se.addr; } @@ -168,15 +221,23 @@ static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, switch (stb) { case STB_GLOBAL: + /* First try the global symbol table */ link_addr = llext_find_sym(NULL, SYM_NAME_OR_SLID(name, sym_tbl.st_value)); if (!link_addr) { + /* Next try internal tables */ link_addr = llext_find_sym(&ext->sym_tab, name); } if (!link_addr) { - link_addr = llext_find_extension_sym(name); + /* Finally try any loaded tables */ + struct llext *dep; + + link_addr = llext_find_extension_sym(name, &dep); + if (link_addr) { + llext_dependency_add(ext, dep); + } } if (!link_addr) { @@ -328,6 +389,16 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, bool do_local) link_addr = (uintptr_t)llext_find_sym(NULL, SYM_NAME_OR_SLID(name, sym.st_value)); + if (link_addr == 0) { + /* Try loaded tables */ + struct llext *dep; + + link_addr = (uintptr_t)llext_find_extension_sym(name, &dep); + if (link_addr) { + llext_dependency_add(ext, dep); + } + } + if (link_addr == 0) { LOG_ERR("Undefined symbol with no entry in " "symbol table %s, offset %zd, link section %d", diff --git a/subsys/llext/llext_priv.h b/subsys/llext/llext_priv.h index be11877395709..da2484dc3fe21 100644 --- a/subsys/llext/llext_priv.h +++ b/subsys/llext/llext_priv.h @@ -74,5 +74,6 @@ static inline const void *llext_loaded_sect_ptr(struct llext_loader *ldr, struct */ int llext_link(struct llext_loader *ldr, struct llext *ext, bool do_local); +void llext_dependency_remove_all(struct llext *ext); #endif /* ZEPHYR_SUBSYS_LLEXT_PRIV_H_ */