From b4a7f0f2caab6124fd3f37423c10f6eb88b9338d Mon Sep 17 00:00:00 2001 From: David Palchak Date: Tue, 7 Jun 2022 15:25:37 -0700 Subject: [PATCH] linker: ensure global constructors only run once Rename the symbols used to denote the locations of the global constructor lists and modify the Zephyr start-up code accordingly. On POSIX systems this ensures that the native libc init code won't find any constructors to run before Zephyr loads. Fixes #39347, #36858 Signed-off-by: David Palchak --- .../linker/common-rom/common-rom-cpp.ld | 35 ++++++++++++++++--- kernel/init.c | 2 +- subsys/cpp/cpp_ctors.c | 8 ++--- subsys/cpp/cpp_init_array.c | 8 ++--- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/include/zephyr/linker/common-rom/common-rom-cpp.ld b/include/zephyr/linker/common-rom/common-rom-cpp.ld index 3f302c25468..b5aaa31c79b 100644 --- a/include/zephyr/linker/common-rom/common-rom-cpp.ld +++ b/include/zephyr/linker/common-rom/common-rom-cpp.ld @@ -9,19 +9,33 @@ * boundary. To align with the C++ standard, the first element * of the array contains the number of actual constructors. The * last element is NULL. + * + * The __CTOR_LIST__ and __CTOR_END__ symbols are always defined + * to result in an empty list. This is necessary to fix an issue + * where the glibc process initialization code on native_posix + * platforms calls constructors before Zephyr loads (issue #39347). + * + * Zephyr's start-up code uses the __ZEPHYR_CTOR_LIST__ and + * __ZEHPYR_CTOR_END__ symbols, so these need to be correctly set. */ #ifdef CONFIG_64BIT . = ALIGN(8); - __CTOR_LIST__ = .; - QUAD((__CTOR_END__ - __CTOR_LIST__) / 8 - 2) + __ZEPHYR_CTOR_LIST__ = .; + QUAD((__ZEPHYR_CTOR_END__ - __ZEPHYR_CTOR_LIST__) / 8 - 2) KEEP(*(SORT_BY_NAME(".ctors*"))) + __CTOR_LIST__ = .; + QUAD(0) + __ZEPHYR_CTOR_END__ = .; QUAD(0) __CTOR_END__ = .; #else . = ALIGN(4); - __CTOR_LIST__ = .; - LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) + __ZEPHYR_CTOR_LIST__ = .; + LONG((__ZEPHYR_CTOR_END__ - __ZEPHYR_CTOR_LIST__) / 4 - 2) KEEP(*(SORT_BY_NAME(".ctors*"))) + __CTOR_LIST__ = .; + LONG(0) + __ZEPHYR_CTOR_END__ = .; LONG(0) __CTOR_END__ = .; #endif @@ -29,9 +43,20 @@ SECTION_PROLOGUE(init_array,,) { + /* + * Similar to the schenanigans required for the __CTOR_LIST__ and + * __CTOR_END__ symbols we define __init_array_start and __init_array_end + * to the same address to define an empty list. This prevents the glibc + * startup code from calling any global constructors before Zephyr loads. + * + * Zephyr's start-up code uses the __zephyr_init_array_start and + * __zephyr_init_array_end sybmols, so these need to be set correctly. + */ . = ALIGN(4); __init_array_start = .; - KEEP(*(SORT_BY_NAME(".init_array*"))) __init_array_end = .; + __zephyr_init_array_start = .; + KEEP(*(SORT_BY_NAME(".init_array*"))) + __zephyr_init_array_end = .; } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) #endif diff --git a/kernel/init.c b/kernel/init.c index d4acea3c7a8..f6093ab6d9a 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -216,7 +216,7 @@ static void bg_thread_main(void *unused1, void *unused2, void *unused3) #endif boot_banner(); -#if defined(CONFIG_CPLUSPLUS) && !defined(CONFIG_ARCH_POSIX) +#if defined(CONFIG_CPLUSPLUS) void z_cpp_init_static(void); z_cpp_init_static(); #endif diff --git a/subsys/cpp/cpp_ctors.c b/subsys/cpp/cpp_ctors.c index f91646282ac..5b9fec84ce3 100644 --- a/subsys/cpp/cpp_ctors.c +++ b/subsys/cpp/cpp_ctors.c @@ -21,8 +21,8 @@ typedef void (*CtorFuncPtr)(void); /* Constructor function pointer list is generated by the linker script. */ -extern CtorFuncPtr __CTOR_LIST__[]; -extern CtorFuncPtr __CTOR_END__[]; +extern CtorFuncPtr __ZEPHYR_CTOR_LIST__[]; +extern CtorFuncPtr __ZEPHYR_CTOR_END__[]; /** * @@ -35,9 +35,9 @@ void __do_global_ctors_aux(void) { unsigned int nCtors; - nCtors = (unsigned long)__CTOR_LIST__[0]; + nCtors = (unsigned long)__ZEPHYR_CTOR_LIST__[0]; while (nCtors >= 1U) { - __CTOR_LIST__[nCtors--](); + __ZEPHYR_CTOR_LIST__[nCtors--](); } } diff --git a/subsys/cpp/cpp_init_array.c b/subsys/cpp/cpp_init_array.c index b81ea5c06d7..aca263c46e3 100644 --- a/subsys/cpp/cpp_init_array.c +++ b/subsys/cpp/cpp_init_array.c @@ -11,16 +11,16 @@ typedef void (*func_ptr)(void); -extern func_ptr __init_array_start[]; -extern func_ptr __init_array_end[]; +extern func_ptr __zephyr_init_array_start[]; +extern func_ptr __zephyr_init_array_end[]; /** * @brief Execute initialization routines referenced in .init_array section */ void __do_init_array_aux(void) { - for (func_ptr *func = __init_array_start; - func < __init_array_end; + for (func_ptr *func = __zephyr_init_array_start; + func < __zephyr_init_array_end; func++) { (*func)(); }