From 96852bc45e002642b369ef6f105a79553ec5186a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 29 Aug 2024 12:50:41 +0200 Subject: [PATCH] llext: add a test for inter-extension linking This test uses two LLEXT objects: one of them exports a symbol and the other one calls the exported function. Signed-off-by: Guennadi Liakhovetski --- tests/subsys/llext/simple/CMakeLists.txt | 11 +++++- .../llext/simple/src/export_dependency_ext.c | 15 +++++++ .../llext/simple/src/export_dependent_ext.c | 24 ++++++++++++ .../llext/simple/src/test_llext_simple.c | 39 +++++++++++++++++++ 4 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 tests/subsys/llext/simple/src/export_dependency_ext.c create mode 100644 tests/subsys/llext/simple/src/export_dependent_ext.c diff --git a/tests/subsys/llext/simple/CMakeLists.txt b/tests/subsys/llext/simple/CMakeLists.txt index 43d7c79bd2ab6c..c8899aa32d2d4a 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 00000000000000..ed71d984e2ddca --- /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 00000000000000..ee2fc66096a2a6 --- /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 b4cc6170a476cd..2a33d92be4e72e 100644 --- a/tests/subsys/llext/simple/src/test_llext_simple.c +++ b/tests/subsys/llext/simple/src/test_llext_simple.c @@ -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"