llext: add a test for the pre_located feature
This test checks that the pre_located feature works as expected. It creates a new extension that is manually relocated to a specific address via the add_llext_command() CMake function invoking a custom linker command. The test then loads the extension setting the pre_located option and checks that the symbol is resolved properly. Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
This commit is contained in:
parent
92002b2dff
commit
435b72dc18
3 changed files with 62 additions and 9 deletions
|
@ -23,6 +23,10 @@ if(CONFIG_ARM)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (CONFIG_LLEXT_TYPE_ELF_RELOCATABLE AND CONFIG_XTENSA)
|
||||||
|
list(APPEND ext_names pre_located)
|
||||||
|
endif()
|
||||||
|
|
||||||
# generate extension targets foreach extension given by 'ext_names'
|
# generate extension targets foreach extension given by 'ext_names'
|
||||||
foreach(ext_name ${ext_names})
|
foreach(ext_name ${ext_names})
|
||||||
set(ext_src ${PROJECT_SOURCE_DIR}/src/${ext_name}_ext.c)
|
set(ext_src ${PROJECT_SOURCE_DIR}/src/${ext_name}_ext.c)
|
||||||
|
@ -45,12 +49,15 @@ if(NOT CONFIG_LLEXT_TYPE_ELF_OBJECT)
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Add a dummy custom processing command to test add_llext_command
|
if (CONFIG_LLEXT_TYPE_ELF_RELOCATABLE AND CONFIG_XTENSA)
|
||||||
get_target_property(proc_in_file hello_world_ext lib_output)
|
# Manually fix the pre_located extension's text address at a multiple of 4
|
||||||
get_target_property(proc_out_file hello_world_ext pkg_input)
|
get_target_property(pre_located_target pre_located_ext lib_target)
|
||||||
add_llext_command(
|
get_target_property(pre_located_file pre_located_ext pkg_input)
|
||||||
TARGET hello_world_ext
|
add_llext_command(
|
||||||
POST_BUILD
|
TARGET pre_located_ext
|
||||||
COMMAND echo "dummy patching ${proc_in_file} to create ${proc_out_file}"
|
POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${proc_in_file} ${proc_out_file}
|
COMMAND ${CMAKE_C_COMPILER}
|
||||||
)
|
-Wl,-r -Wl,-Ttext=0xbada110c -nostdlib -nodefaultlibs -nostartfiles
|
||||||
|
$<TARGET_OBJECTS:${pre_located_target}> -o ${pre_located_file}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
19
tests/subsys/llext/simple/src/pre_located_ext.c
Normal file
19
tests/subsys/llext/simple/src/pre_located_ext.c
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Arduino SA.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file contains a simple test extension that defines an entry point
|
||||||
|
* in the .text section. The entry point is never called, but the symbol
|
||||||
|
* address is fixed via a linker call and then checked by the test.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/llext/symbol.h>
|
||||||
|
|
||||||
|
void test_entry(void)
|
||||||
|
{
|
||||||
|
/* This function is never called */
|
||||||
|
}
|
||||||
|
LL_EXTENSION_SYMBOL(test_entry);
|
|
@ -237,6 +237,33 @@ static LLEXT_CONST uint8_t multi_file_ext[] __aligned(4) = {
|
||||||
LLEXT_LOAD_UNLOAD(multi_file, true, NULL)
|
LLEXT_LOAD_UNLOAD(multi_file, true, NULL)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_LLEXT_TYPE_ELF_RELOCATABLE) && defined(CONFIG_XTENSA)
|
||||||
|
static LLEXT_CONST uint8_t pre_located_ext[] __aligned(4) = {
|
||||||
|
#include "pre_located.inc"
|
||||||
|
};
|
||||||
|
|
||||||
|
ZTEST(llext, test_pre_located)
|
||||||
|
{
|
||||||
|
struct llext_buf_loader buf_loader =
|
||||||
|
LLEXT_BUF_LOADER(pre_located_ext, ARRAY_SIZE(pre_located_ext));
|
||||||
|
struct llext_loader *loader = &buf_loader.loader;
|
||||||
|
struct llext_load_param ldr_parm = LLEXT_LOAD_PARAM_DEFAULT;
|
||||||
|
struct llext *ext = NULL;
|
||||||
|
const void *test_entry_fn;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
/* load the extension trying to respect the addresses in the ELF */
|
||||||
|
ldr_parm.pre_located = true;
|
||||||
|
res = llext_load(loader, "pre_located", &ext, &ldr_parm);
|
||||||
|
zassert_ok(res, "load should succeed");
|
||||||
|
|
||||||
|
/* check the function address is the expected one */
|
||||||
|
test_entry_fn = llext_find_sym(&ext->exp_tab, "test_entry");
|
||||||
|
zassert_equal(test_entry_fn, (void *)0xbada110c, "test_entry should be at 0xbada110c");
|
||||||
|
|
||||||
|
llext_unload(&ext);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure that EXPORT_SYMBOL does indeed provide a symbol and a valid address
|
* Ensure that EXPORT_SYMBOL does indeed provide a symbol and a valid address
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue