Skip to content

Commit

Permalink
llext: add inspection API test suite
Browse files Browse the repository at this point in the history
  • Loading branch information
pillo79 committed Feb 11, 2025
1 parent dc35db9 commit 0f1f3db
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 0 deletions.
1 change: 1 addition & 0 deletions tests/subsys/llext/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ set(ext_names
relative_jump
object
syscalls
inspect
threads_kernel_objects
export_dependent
export_dependency
Expand Down
28 changes: 28 additions & 0 deletions tests/subsys/llext/src/inspect_ext.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2025 Arduino SA
*
* SPDX-License-Identifier: Apache-2.0
*/

/* This extension exports a number of symbols to be used by the LLEXT
* inspection APIs. Each symbol is exported within a different section
* and only the addresses are checked in this test.
*/

#include <zephyr/llext/symbol.h>

int number_in_bss;
int number_in_data = 1;
const int number_in_rodata = 2;
const int number_in_my_rodata Z_GENERIC_SECTION(.my_rodata) = 3;

void function_in_text(void)
{
/* only used for address check */
}

EXPORT_SYMBOL(number_in_bss);
EXPORT_SYMBOL(number_in_data);
EXPORT_SYMBOL(number_in_rodata);
EXPORT_SYMBOL(number_in_my_rodata);
EXPORT_SYMBOL(function_in_text);
59 changes: 59 additions & 0 deletions tests/subsys/llext/src/test_llext.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#endif
#include <zephyr/llext/elf.h>
#include <zephyr/llext/llext.h>
#include <zephyr/llext/inspect.h>
#include <zephyr/llext/symbol.h>
#include <zephyr/llext/buf_loader.h>
#include <zephyr/llext/fs_loader.h>
Expand Down Expand Up @@ -316,6 +317,64 @@ LLEXT_LOAD_UNLOAD(threads_kernel_objects,
.test_setup = threads_objects_test_setup,
)

static LLEXT_CONST uint8_t inspect_ext[] ELF_ALIGN = {
#include "inspect.inc"
};

void do_inspect_checks(struct llext_loader *ldr, struct llext *ext, enum llext_mem reg_idx,
const char *sect_name, const char *sym_name)
{
const elf_shdr_t *sect_hdr = NULL, *reg_hdr = NULL;
enum llext_mem sect_region = LLEXT_MEM_COUNT;
uintptr_t reg_addr = 0, sym_addr = 0;
size_t reg_size = 0, sect_offset = 0;
int sect_shndx, res;

res = llext_get_region_info(ldr, ext, reg_idx, &reg_hdr, (const void **)&reg_addr, &reg_size);

Check warning on line 333 in tests/subsys/llext/src/test_llext.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

tests/subsys/llext/src/test_llext.c:333 line length of 102 exceeds 100 columns

Check warning on line 333 in tests/subsys/llext/src/test_llext.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

tests/subsys/llext/src/test_llext.c:333 line length of 102 exceeds 100 columns
zassert_ok(res, "get_region_info() should succeed");
sect_shndx = llext_section_shndx(ldr, ext, sect_name);
zassert_true(sect_shndx > 0, "section %s should be found", sect_name);
res = llext_get_section_info(ldr, ext, sect_shndx, &sect_hdr, &sect_region, &sect_offset);
zassert_ok(res, "get_section_info() should succeed");
sym_addr = (uintptr_t)llext_find_sym(&ext->exp_tab, sym_name);
zassert_true(sym_addr, "symbol %s must be exported", sym_name);

zassert_equal(reg_idx, sect_region, "region mismatch (expected %d, got %d)",
reg_idx, sect_region);
zassert_true(sect_hdr->sh_offset >= reg_hdr->sh_offset &&
sect_hdr->sh_offset + sect_hdr->sh_size <= reg_hdr->sh_offset + reg_hdr->sh_size,

Check warning on line 345 in tests/subsys/llext/src/test_llext.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

tests/subsys/llext/src/test_llext.c:345 line length of 102 exceeds 100 columns

Check warning on line 345 in tests/subsys/llext/src/test_llext.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

tests/subsys/llext/src/test_llext.c:345 line length of 102 exceeds 100 columns
"section %s overflowing region %d", sect_name, reg_idx);
zassert_true(sect_offset < reg_size, "section offset outside region");
zassert_true(sym_addr >= reg_addr && sym_addr < reg_addr + reg_size,
"symbol %s mapped outside region %d", sym_name, reg_idx);
zassert_true(sym_addr >= reg_addr + sect_offset &&
sym_addr < reg_addr + sect_offset + sect_hdr->sh_size,
"symbol %s mapped outside section %s", sym_name, sect_name);
}

ZTEST(llext, test_inspect)
{
int res;

struct llext_buf_loader buf_loader =
LLEXT_BUF_LOADER(inspect_ext, sizeof(inspect_ext));
struct llext_loader *ldr = &buf_loader.loader;
struct llext_load_param ldr_parm = LLEXT_LOAD_PARAM_DEFAULT;
struct llext *ext = NULL;

ldr_parm.keep_section_info = true;
res = llext_load(ldr, "inspect", &ext, &ldr_parm);
zassert_ok(res, "load should succeed");

do_inspect_checks(ldr, ext, LLEXT_MEM_BSS, ".bss", "number_in_bss");
do_inspect_checks(ldr, ext, LLEXT_MEM_DATA, ".data", "number_in_data");
do_inspect_checks(ldr, ext, LLEXT_MEM_RODATA, ".rodata", "number_in_rodata");
do_inspect_checks(ldr, ext, LLEXT_MEM_RODATA, ".my_rodata", "number_in_my_rodata");
do_inspect_checks(ldr, ext, LLEXT_MEM_TEXT, ".text", "function_in_text");

llext_unload(&ext);
}

#ifndef CONFIG_LLEXT_TYPE_ELF_OBJECT
static LLEXT_CONST uint8_t multi_file_ext[] ELF_ALIGN = {
#include "multi_file.inc"
Expand Down

0 comments on commit 0f1f3db

Please sign in to comment.