From 8390a5b92a43998a6ef0416c7bf6477c993eb1b0 Mon Sep 17 00:00:00 2001 From: Hesham Almatary Date: Tue, 25 Jul 2023 16:06:50 +0100 Subject: [PATCH] libsel4test: retain _test_type and _test_case unused attribute does not prevent the sections from being garbage-collected during link-time optimisation. This may trigger undefined references errors to [__start|__stop]_test_case symbols that are expected to be emitted by the linker anyway. Adding "retain" attribute makes sure that the section and its associated symbols are kept regardless of linker's garbage collection. Another fix could be adding "nostart-stop-gc" to the linker flags, but since it is only one section (_test_case) where its __start/__stop symbols are references, adding retain to it makes more sense. This additional functionality requires binutils version 2.36 or later. Sponsored by: DARPA. Signed-off-by: Hesham Almatary --- libsel4test/include/sel4test/test.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libsel4test/include/sel4test/test.h b/libsel4test/include/sel4test/test.h index 86522e582..856f4ca14 100644 --- a/libsel4test/include/sel4test/test.h +++ b/libsel4test/include/sel4test/test.h @@ -96,10 +96,17 @@ typedef struct test_type { test_result_t (*run_test)(struct testcase *test, uintptr_t e); } ALIGN(32) test_type_t; +#if defined(__has_attribute) && __has_attribute(retain) +#define ATTR_USED_RETAIN __attribute__((used,retain)) +#else +#define ATTR_USED_RETAIN __attribute__((used)) +#endif + /* Declare a test type. * For now, we put the test types in a separate elf section. */ #define DEFINE_TEST_TYPE(_name, _id, _set_up_test_type, _tear_down_test_type, _set_up, _tear_down, _run_test) \ - __attribute__((used)) __attribute__((section("_test_type"))) struct test_type TEST_TYPE_ ##_name = { \ + ATTR_USED_RETAIN __attribute__((section("_test_type"))) \ + struct test_type TEST_TYPE_ ##_name = { \ .name = #_name, \ .id = _id, \ .set_up_test_type = _set_up_test_type, \ @@ -134,7 +141,8 @@ typedef struct testcase ALIGN(sizeof(struct testcase)) testcase_t; * that it is accepted by C++ compilers. */ #define DEFINE_TEST_WITH_TYPE(_name, _description, _function, _test_type, _enabled) \ - __attribute__((used)) __attribute__((section("_test_case"))) struct testcase TEST_ ## _name = { \ + ATTR_USED_RETAIN __attribute__((section("_test_case"))) \ + struct testcase TEST_ ## _name = { \ #_name, \ _description, \ (test_fn)_function, \