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
|
* boundary. To align with the C++ standard, the first element
|
||||||
* of the array contains the number of actual constructors. The
|
* of the array contains the number of actual constructors. The
|
||||||
* last element is NULL.
|
* 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
|
#ifdef CONFIG_64BIT
|
||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
__CTOR_LIST__ = .;
|
__ZEPHYR_CTOR_LIST__ = .;
|
||||||
QUAD((__CTOR_END__ - __CTOR_LIST__) / 8 - 2)
|
QUAD((__ZEPHYR_CTOR_END__ - __ZEPHYR_CTOR_LIST__) / 8 - 2)
|
||||||
KEEP(*(SORT_BY_NAME(".ctors*")))
|
KEEP(*(SORT_BY_NAME(".ctors*")))
|
||||||
|
__CTOR_LIST__ = .;
|
||||||
|
QUAD(0)
|
||||||
|
__ZEPHYR_CTOR_END__ = .;
|
||||||
QUAD(0)
|
QUAD(0)
|
||||||
__CTOR_END__ = .;
|
__CTOR_END__ = .;
|
||||||
#else
|
#else
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
__CTOR_LIST__ = .;
|
__ZEPHYR_CTOR_LIST__ = .;
|
||||||
LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
|
LONG((__ZEPHYR_CTOR_END__ - __ZEPHYR_CTOR_LIST__) / 4 - 2)
|
||||||
KEEP(*(SORT_BY_NAME(".ctors*")))
|
KEEP(*(SORT_BY_NAME(".ctors*")))
|
||||||
|
__CTOR_LIST__ = .;
|
||||||
|
LONG(0)
|
||||||
|
__ZEPHYR_CTOR_END__ = .;
|
||||||
LONG(0)
|
LONG(0)
|
||||||
__CTOR_END__ = .;
|
__CTOR_END__ = .;
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,9 +43,20 @@
|
||||||
|
|
||||||
SECTION_PROLOGUE(init_array,,)
|
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);
|
. = ALIGN(4);
|
||||||
__init_array_start = .;
|
__init_array_start = .;
|
||||||
KEEP(*(SORT_BY_NAME(".init_array*")))
|
|
||||||
__init_array_end = .;
|
__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)
|
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -216,7 +216,7 @@ static void bg_thread_main(void *unused1, void *unused2, void *unused3)
|
||||||
#endif
|
#endif
|
||||||
boot_banner();
|
boot_banner();
|
||||||
|
|
||||||
#if defined(CONFIG_CPLUSPLUS) && !defined(CONFIG_ARCH_POSIX)
|
#if defined(CONFIG_CPLUSPLUS)
|
||||||
void z_cpp_init_static(void);
|
void z_cpp_init_static(void);
|
||||||
z_cpp_init_static();
|
z_cpp_init_static();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,8 +21,8 @@ typedef void (*CtorFuncPtr)(void);
|
||||||
|
|
||||||
/* Constructor function pointer list is generated by the linker script. */
|
/* Constructor function pointer list is generated by the linker script. */
|
||||||
|
|
||||||
extern CtorFuncPtr __CTOR_LIST__[];
|
extern CtorFuncPtr __ZEPHYR_CTOR_LIST__[];
|
||||||
extern CtorFuncPtr __CTOR_END__[];
|
extern CtorFuncPtr __ZEPHYR_CTOR_END__[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -35,9 +35,9 @@ void __do_global_ctors_aux(void)
|
||||||
{
|
{
|
||||||
unsigned int nCtors;
|
unsigned int nCtors;
|
||||||
|
|
||||||
nCtors = (unsigned long)__CTOR_LIST__[0];
|
nCtors = (unsigned long)__ZEPHYR_CTOR_LIST__[0];
|
||||||
|
|
||||||
while (nCtors >= 1U) {
|
while (nCtors >= 1U) {
|
||||||
__CTOR_LIST__[nCtors--]();
|
__ZEPHYR_CTOR_LIST__[nCtors--]();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,16 +11,16 @@
|
||||||
|
|
||||||
typedef void (*func_ptr)(void);
|
typedef void (*func_ptr)(void);
|
||||||
|
|
||||||
extern func_ptr __init_array_start[];
|
extern func_ptr __zephyr_init_array_start[];
|
||||||
extern func_ptr __init_array_end[];
|
extern func_ptr __zephyr_init_array_end[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Execute initialization routines referenced in .init_array section
|
* @brief Execute initialization routines referenced in .init_array section
|
||||||
*/
|
*/
|
||||||
void __do_init_array_aux(void)
|
void __do_init_array_aux(void)
|
||||||
{
|
{
|
||||||
for (func_ptr *func = __init_array_start;
|
for (func_ptr *func = __zephyr_init_array_start;
|
||||||
func < __init_array_end;
|
func < __zephyr_init_array_end;
|
||||||
func++) {
|
func++) {
|
||||||
(*func)();
|
(*func)();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue