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 <palchak@google.com>
This commit is contained in:
parent
be606f0932
commit
b4a7f0f2ca
4 changed files with 39 additions and 14 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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--]();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue