1 /*
2  * Copyright (c) 2024 Arduino SA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /*
8  * This test checks for proper support of ELF init arrays. This processing is
9  * performed by llext_bootstrap(), which gets the array of function pointers
10  * from LLEXT via the llext_get_fn_table() syscall.
11  *
12  * Each function in this test shifts the number left by 4 bits and sets the
13  * lower 4 bits to a specific value. The proper init sequence (preinit_fn_1,
14  * preinit_fn_2, init_fn) would leave number set to 0x123; the termination
15  * function will further shift the number to 0x1234. If a different result is
16  * detected, then either not all routines were executed, or their order was not
17  * correct.
18  */
19 
20 #include <stdint.h>
21 #include <zephyr/llext/symbol.h>
22 #include <zephyr/toolchain.h>
23 #include <zephyr/sys/printk.h>
24 #include <zephyr/ztest_assert.h>
25 
26 static int number;
27 EXPORT_SYMBOL(number);
28 
preinit_fn_1(void)29 static void preinit_fn_1(void)
30 {
31 	number = 1;
32 }
33 
preinit_fn_2(void)34 static void preinit_fn_2(void)
35 {
36 	number <<= 4;
37 	number |= 2;
38 }
39 
init_fn(void)40 static void init_fn(void)
41 {
42 	number <<= 4;
43 	number |= 3;
44 }
45 
fini_fn(void)46 static void fini_fn(void)
47 {
48 	number <<= 4;
49 	number |= 4;
50 }
51 
52 static const void *const preinit_fn_ptrs[] __used Z_GENERIC_SECTION(".preinit_array") = {
53 	preinit_fn_1,
54 	preinit_fn_2
55 };
56 static const void *const init_fn_ptrs[] __used Z_GENERIC_SECTION(".init_array") = {
57 	init_fn
58 };
59 static const void *const fini_fn_ptrs[] __used Z_GENERIC_SECTION(".fini_array") = {
60 	fini_fn
61 };
62 
test_entry(void)63 void test_entry(void)
64 {
65 	/* fini_fn() is not called yet, so we expect 0x123 here */
66 	const int expected = (((1 << 4) | 2) << 4) | 3;
67 
68 	zassert_equal(number, expected, "got 0x%x instead of 0x%x during test",
69 		      number, expected);
70 }
71 EXPORT_SYMBOL(test_entry);
72