diff --git a/include/zephyr/llext/llext.h b/include/zephyr/llext/llext.h index 2aa588f8243c6..476da676619f6 100644 --- a/include/zephyr/llext/llext.h +++ b/include/zephyr/llext/llext.h @@ -177,7 +177,7 @@ int llext_iterate(int (*fn)(struct llext *ext, void *arg), void *arg); * @retval -ENOTSUP Unsupported ELF features */ int llext_load(struct llext_loader *loader, const char *name, struct llext **ext, - struct llext_load_param *ldr_parm); + const struct llext_load_param *ldr_parm); /** * @brief Unload an extension diff --git a/subsys/llext/llext.c b/subsys/llext/llext.c index 8d25198726ae4..fed381cbb4450 100644 --- a/subsys/llext/llext.c +++ b/subsys/llext/llext.c @@ -139,7 +139,7 @@ const void *llext_find_sym(const struct llext_symtable *sym_table, const char *s } int llext_load(struct llext_loader *ldr, const char *name, struct llext **ext, - struct llext_load_param *ldr_parm) + const struct llext_load_param *ldr_parm) { int ret; diff --git a/subsys/llext/llext_load.c b/subsys/llext/llext_load.c index ef9c33b026dd0..ede4e59fe757a 100644 --- a/subsys/llext/llext_load.c +++ b/subsys/llext/llext_load.c @@ -585,7 +585,7 @@ static int llext_copy_symbols(struct llext_loader *ldr, struct llext *ext, * Load a valid ELF as an extension */ int do_llext_load(struct llext_loader *ldr, struct llext *ext, - struct llext_load_param *ldr_parm) + const struct llext_load_param *ldr_parm) { int ret; diff --git a/subsys/llext/llext_priv.h b/subsys/llext/llext_priv.h index b502f683e96df..5e39c8557abd3 100644 --- a/subsys/llext/llext_priv.h +++ b/subsys/llext/llext_priv.h @@ -50,7 +50,7 @@ static inline void llext_free(void *ptr) */ int do_llext_load(struct llext_loader *ldr, struct llext *ext, - struct llext_load_param *ldr_parm); + const struct llext_load_param *ldr_parm); static inline const char *llext_string(struct llext_loader *ldr, struct llext *ext, enum llext_mem mem_idx, unsigned int idx) diff --git a/tests/subsys/llext/simple/CMakeLists.txt b/tests/subsys/llext/simple/CMakeLists.txt index b38f66c9a3a33..a36a70ab7cf44 100644 --- a/tests/subsys/llext/simple/CMakeLists.txt +++ b/tests/subsys/llext/simple/CMakeLists.txt @@ -15,7 +15,16 @@ target_include_directories(app PRIVATE ${ZEPHYR_BASE}/arch/${ARCH}/include ) -set(ext_names hello_world logging relative_jump object syscalls threads_kernel_objects) +set(ext_names + hello_world + logging + relative_jump + object + syscalls + threads_kernel_objects + export_dependent + export_dependency +) if(CONFIG_ARM) if(NOT CONFIG_CPU_CORTEX_M0 AND NOT CONFIG_CPU_CORTEX_M0PLUS AND NOT CONFIG_CPU_CORTEX_M1) diff --git a/tests/subsys/llext/simple/src/export_dependency_ext.c b/tests/subsys/llext/simple/src/export_dependency_ext.c new file mode 100644 index 0000000000000..ed71d984e2ddc --- /dev/null +++ b/tests/subsys/llext/simple/src/export_dependency_ext.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Test exporting symbols, imported by other LLEXTs */ + +#include + +long test_dependency(int a, int b) +{ + return (long)a * b; +} +EXPORT_SYMBOL(test_dependency); diff --git a/tests/subsys/llext/simple/src/export_dependent_ext.c b/tests/subsys/llext/simple/src/export_dependent_ext.c new file mode 100644 index 0000000000000..ee2fc66096a2a --- /dev/null +++ b/tests/subsys/llext/simple/src/export_dependent_ext.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Test importing symbols, exported by other LLEXTs */ + +#include +#include +#include + +extern long test_dependency(int a, int b); + +void test_entry(void) +{ + unsigned long half_ptr_bits = sizeof(uintptr_t) * 8 / 2; + unsigned long mask = BIT(half_ptr_bits) - 1; + int a = mask & (uintptr_t)test_entry; + int b = mask & ((uintptr_t)test_entry >> half_ptr_bits); + + zassert_equal(test_dependency(a, b), (long)a * b); +} +EXPORT_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/test_llext_simple.c b/tests/subsys/llext/simple/src/test_llext_simple.c index 3455806bed074..2a33d92be4e72 100644 --- a/tests/subsys/llext/simple/src/test_llext_simple.c +++ b/tests/subsys/llext/simple/src/test_llext_simple.c @@ -241,7 +241,7 @@ void load_call_unload(const struct llext_test *test_case) const struct llext_test test_case = { \ .name = STRINGIFY(_name), \ .buf = _name ## _ext, \ - .buf_len = ARRAY_SIZE(_name ## _ext), \ + .buf_len = sizeof(_name ## _ext), \ extra_args \ }; \ load_call_unload(&test_case); \ @@ -320,6 +320,45 @@ static LLEXT_CONST uint8_t multi_file_ext[] ELF_ALIGN = { LLEXT_LOAD_UNLOAD(multi_file) #endif +#ifndef CONFIG_USERSPACE +static LLEXT_CONST uint8_t export_dependent_ext[] ELF_ALIGN = { + #include "export_dependent.inc" +}; + +static LLEXT_CONST uint8_t export_dependency_ext[] ELF_ALIGN = { + #include "export_dependency.inc" +}; + +ZTEST(llext, test_inter_ext) +{ + const void *dependency_buf = export_dependency_ext; + const void *dependent_buf = export_dependent_ext; + struct llext_buf_loader buf_loader_dependency = + LLEXT_BUF_LOADER(dependency_buf, sizeof(hello_world_ext)); + struct llext_buf_loader buf_loader_dependent = + LLEXT_BUF_LOADER(dependent_buf, sizeof(export_dependent_ext)); + struct llext_loader *loader_dependency = &buf_loader_dependency.loader; + struct llext_loader *loader_dependent = &buf_loader_dependent.loader; + const struct llext_load_param ldr_parm = LLEXT_LOAD_PARAM_DEFAULT; + struct llext *ext_dependency = NULL, *ext_dependent = NULL; + int ret = llext_load(loader_dependency, "inter_ext_dependency", &ext_dependency, &ldr_parm); + + zassert_ok(ret, "dependency load should succeed"); + + ret = llext_load(loader_dependent, "export_dependent", &ext_dependent, &ldr_parm); + + zassert_ok(ret, "dependent load should succeed"); + + int (*test_entry_fn)() = llext_find_sym(&ext_dependent->exp_tab, "test_entry"); + + zassert_not_null(test_entry_fn, "test_dependent should be an exported symbol"); + test_entry_fn(); + + llext_unload(&ext_dependent); + llext_unload(&ext_dependency); +} +#endif + #if defined(CONFIG_LLEXT_TYPE_ELF_RELOCATABLE) && defined(CONFIG_XTENSA) static LLEXT_CONST uint8_t pre_located_ext[] ELF_ALIGN = { #include "pre_located.inc" @@ -328,7 +367,7 @@ static LLEXT_CONST uint8_t pre_located_ext[] ELF_ALIGN = { ZTEST(llext, test_pre_located) { struct llext_buf_loader buf_loader = - LLEXT_BUF_LOADER(pre_located_ext, ARRAY_SIZE(pre_located_ext)); + LLEXT_BUF_LOADER(pre_located_ext, sizeof(pre_located_ext)); struct llext_loader *loader = &buf_loader.loader; struct llext_load_param ldr_parm = LLEXT_LOAD_PARAM_DEFAULT; struct llext *ext = NULL; @@ -364,7 +403,7 @@ ZTEST(llext, test_find_section) ssize_t section_ofs; struct llext_buf_loader buf_loader = - LLEXT_BUF_LOADER(find_section_ext, ARRAY_SIZE(find_section_ext)); + LLEXT_BUF_LOADER(find_section_ext, sizeof(find_section_ext)); struct llext_loader *loader = &buf_loader.loader; struct llext_load_param ldr_parm = LLEXT_LOAD_PARAM_DEFAULT; struct llext *ext = NULL;