llext: Simple hello world test case

Adds a very simple hello world test case for llext. The loadable
extension is built and then included as a binary array into the test
making it very easy to load, debug, and inspect. The extension is
built using the same toolchain as the base image by default.

Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
This commit is contained in:
Tom Burdick 2023-09-27 08:14:45 -05:00 committed by Anas Nashif
commit b7f3182f79
6 changed files with 138 additions and 0 deletions

View file

@ -0,0 +1,26 @@
# Copyright (c) 2023 Intel Corporation.
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(llext_test)
add_subdirectory(hello_world)
target_sources(app PRIVATE src/test_llext_simple.c)
target_include_directories(app PRIVATE
${ZEPHYR_BASE}/include
${ZEPHYR_BASE}/kernel/include
${ZEPHYR_BASE}/arch/${ARCH}/include
)
set(gen_dir ${ZEPHYR_BINARY_DIR}/include/generated/)
generate_inc_file_for_target(
app
${HELLO_WORLD_LLEXT}
${gen_dir}/hello_world.inc
)
add_dependencies(app hello_world)

View file

@ -0,0 +1,17 @@
# Copyright (c) 2023 Intel Corporation.
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(hello_world)
# TODO check which architecture is being used
set(CMAKE_C_FLAGS "-mlong-calls" "-mthumb")
add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/hello_world.llext
COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS} -c -o ${PROJECT_BINARY_DIR}/hello_world.llext ${PROJECT_SOURCE_DIR}/hello_world.c
)
set(HELLO_WORLD_LLEXT ${PROJECT_BINARY_DIR}/hello_world.llext PARENT_SCOPE)
add_custom_target(hello_world DEPENDS ${PROJECT_BINARY_DIR}/hello_world.llext)

View file

@ -0,0 +1,25 @@
/*
* Copyright (c) 2023 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* This very simple hello world C code can be used as a test case for building
* probably the simplest loadable extension. It requires a single symbol be
* linked, section relocation support, and the ability to export and call out to
* a function.
*/
/* Various build options should be documented here to generate the test elf for
* each architecture.
*
* armv7-thumb: -mlong-call -mthumb -c -o hello_world_armv7_thumb.elf hello_world.c
*/
extern void printk(char *fmt, ...);
extern void hello_world(void)
{
printk("hello world\n");
}

View file

@ -0,0 +1,8 @@
CONFIG_ZTEST=y
CONFIG_ZTEST_NEW_API=y
CONFIG_ZTEST_STACK_SIZE=8192
CONFIG_LOG=y
CONFIG_LOG_MODE_IMMEDIATE=y
CONFIG_LLEXT=y
CONFIG_LLEXT_HEAP_SIZE=32
CONFIG_LLEXT_LOG_LEVEL_DBG=y

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2023 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/ztest.h>
#include <zephyr/kernel.h>
#include <zephyr/llext/llext.h>
#include <zephyr/llext/buf_loader.h>
#ifdef CONFIG_ARM /* ARMV7 */
const static uint8_t hello_world_elf[] __aligned(4) = {
#include "hello_world.inc"
};
#endif
/**
* Attempt to load, list, list symbols, call a fn, and unload a
* hello world extension for each supported architecture
*
* This requires a single linked symbol (printk) and a single
* exported symbol from the extension ( void hello_world(void))
*/
ZTEST(llext, test_llext_simple)
{
const char name[16] = {'h', 'e', 'l', 'l', 'o', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
struct llext_buf_loader buf_loader =
LLEXT_BUF_LOADER(hello_world_elf, ARRAY_SIZE(hello_world_elf));
struct llext_loader *loader = &buf_loader.loader;
struct llext *ext;
const void * const printk_fn = llext_find_sym(NULL, "printk");
zassert_equal(printk_fn, printk, "printk should be an exported symbol");
int res = llext_load(loader, name, &ext);
zassert_ok(res, "load should succeed");
const void * const hello_world_fn = llext_find_sym(&ext->sym_tab, "hello_world");
zassert_not_null(hello_world_fn, "hello_world should be an exported symbol");
res = llext_call_fn(ext, "hello_world");
zassert_ok(res, "calling hello world should succeed");
llext_unload(ext);
}
ZTEST_SUITE(llext, NULL, NULL, NULL, NULL, NULL);

View file

@ -0,0 +1,11 @@
common:
tags: llext
tests:
llext.simple.arm:
filter: not CONFIG_CPU_HAS_MMU
arch_allow: arm
extra_configs:
- CONFIG_ARM_MPU=n
# Broken platforms
platform_exclude:
- nuvoton_pfm_m487 # See #63167