Browse Source
Handle both of these sections in a single chunk of code instead of separately. We don't need to use the legacy .ctors ABI as both the constructors array and startup logic are managed within a single link result. This can now also be used with ARC MWDT which had been using the .ctors sections but with .init_array semantics. For ARC MWDT, we now always discard .dtors and .fini sections as Zephyr will never cause global destructors to execute. Stop discarding .eh_frame sections so that exception handling works as expected. When building a NATIVE_APPLICATION, we ask the native C library to run all of the constructors to ensure any non-Zephyr constructors are run before main is invoked. It might be "nice" to split the constructors so that the Zephyr constructors were executed by the Zephyr code while the non-Zephyr ones were executed by the native C library. I think that could be done if we knew the pathnames of either the Zephyr or non-Zephyr files. That might make a good future enhancement. Signed-off-by: Keith Packard <keithp@keithp.com>pull/88729/head
6 changed files with 78 additions and 166 deletions
@ -1,75 +1,65 @@
@@ -1,75 +1,65 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0 */ |
||||
|
||||
#ifdef CONFIG_STATIC_INIT_GNU |
||||
SECTION_PROLOGUE(_CTOR_SECTION_NAME,,) |
||||
#if defined(CONFIG_TOOLCHAIN_SUPPORTS_STATIC_INIT_GNU) || defined(CONFIG_NATIVE_APPLICATION) |
||||
SECTION_PROLOGUE(init_array,,) |
||||
{ |
||||
/* |
||||
* The compiler fills the constructor pointers table below, |
||||
* hence symbol __CTOR_LIST__ must be aligned on word |
||||
* 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. |
||||
* Instead, Zephyr's start-up code uses the __ZEPHYR_CTOR_LIST__ and |
||||
* __ZEHPYR_CTOR_END__ symbols. |
||||
* Add all of the GNU-style constructors in priority order. Note |
||||
* that this doesn't build the ctors in the "usual" fashion with |
||||
* a length value first and NULL terminator, but we're creating |
||||
* an init_array style list and leaving the ctors list empty |
||||
*/ |
||||
#ifdef CONFIG_NATIVE_APPLICATION |
||||
/* Use the native LIBC constructor code so that any native |
||||
* constructors get run before main is invoked |
||||
*/ |
||||
__init_array_start = .; |
||||
#else |
||||
__zephyr_init_array_start = .; |
||||
#endif |
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) |
||||
SORT_BY_INIT_PRIORITY(.ctors.*))) |
||||
KEEP (*(.init_array .ctors)) |
||||
#ifdef CONFIG_NATIVE_APPLICATION |
||||
__init_array_end = .; |
||||
#else |
||||
__zephyr_init_array_end = .; |
||||
#endif |
||||
|
||||
#ifdef CONFIG_NATIVE_LIBC |
||||
/* |
||||
* The __CTOR_LIST__ and __CTOR_END__ symbols are always defined |
||||
* to result in an empty list. |
||||
* Instead, Zephyr's start-up code uses the __zephyr_init_array_start__ and |
||||
* __zephyr_init_array_end__ symbols. |
||||
* In this way, in native_simulator based targets, the host glibc process |
||||
* initialization code will not call the constructors before Zephyr loads. |
||||
*/ |
||||
#ifdef CONFIG_64BIT |
||||
. = ALIGN(8); |
||||
__ZEPHYR_CTOR_LIST__ = .; |
||||
QUAD((__ZEPHYR_CTOR_END__ - __ZEPHYR_CTOR_LIST__) / 8 - 2) |
||||
KEEP(*(SORT_BY_NAME(".ctors*"))) |
||||
__CTOR_LIST__ = .; |
||||
#ifdef CONFIG_64BIT |
||||
QUAD(0) |
||||
__ZEPHYR_CTOR_END__ = .; |
||||
QUAD(0) |
||||
__CTOR_END__ = .; |
||||
#else |
||||
. = ALIGN(4); |
||||
__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 |
||||
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) |
||||
|
||||
SECTION_PROLOGUE(init_array,,) |
||||
{ |
||||
__CTOR_END__ = .; |
||||
#ifndef CONFIG_NATIVE_APPLICATION |
||||
/* |
||||
* 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 symbols, so these need to be set correctly. |
||||
*/ |
||||
. = ALIGN(4); |
||||
* 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. |
||||
*/ |
||||
__init_array_start = .; |
||||
__init_array_end = .; |
||||
__zephyr_init_array_start = .; |
||||
KEEP(*(SORT_BY_NAME(".init_array*"))) |
||||
__zephyr_init_array_end = .; |
||||
#endif |
||||
#endif |
||||
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) |
||||
|
||||
#elif defined(CONFIG_TOOLCHAIN_SUPPORTS_STATIC_INIT_GNU) && !defined(CONFIG_NATIVE_APPLICATION) |
||||
/* |
||||
* If the code to invoke constructors is not enabled, |
||||
* make sure there aren't any in the application |
||||
*/ |
||||
SECTION_PROLOGUE(init_array,,) |
||||
{ |
||||
KEEP(*(SORT_BY_NAME(".ctors*"))) |
||||
KEEP(*(SORT_BY_NAME(".init_array*"))) |
||||
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) |
||||
#if !defined(CONFIG_STATIC_INIT_GNU) && !defined(CONFIG_NATIVE_APPLICATION) |
||||
ASSERT(__zephyr_init_array_start == __zephyr_init_array_end, |
||||
"GNU-style constructors required but STATIC_INIT_GNU not enabled") |
||||
#endif |
||||
|
||||
ASSERT (SIZEOF(init_array) == 0, |
||||
"GNU-style constructors required but STATIC_INIT_GNU not enabled") |
||||
#endif |
||||
|
@ -1,87 +0,0 @@
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2015 Wind River Systems, Inc. |
||||
* Copyright (c) 2021 Synopsys, Inc. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
void __do_global_ctors_aux(void); |
||||
void __do_init_array_aux(void); |
||||
|
||||
void z_init_static(void) |
||||
{ |
||||
#if defined(CONFIG_STATIC_INIT_GNU) |
||||
__do_global_ctors_aux(); |
||||
__do_init_array_aux(); |
||||
#elif defined(__CCAC__) /* ARC MWDT */ |
||||
__do_global_ctors_aux(); |
||||
#endif |
||||
} |
||||
|
||||
/**
|
||||
* @section - Constructor module |
||||
* @brief |
||||
* The ctors section contains a list of function pointers that execute both the C++ constructors of |
||||
* static global objects, as well as either C or C++ initializer functions (declared with the |
||||
* attribute constructor). These must be executed before the application's main() routine. |
||||
* |
||||
* NOTE: Not all compilers put those function pointers into the ctors section; |
||||
* some put them into the init_array section instead. |
||||
*/ |
||||
|
||||
#ifdef CONFIG_STATIC_INIT_GNU |
||||
|
||||
/* What a constructor function pointer looks like */ |
||||
|
||||
typedef void (*CtorFuncPtr)(void); |
||||
|
||||
/* Constructor function pointer list is generated by the linker script. */ |
||||
|
||||
extern CtorFuncPtr __ZEPHYR_CTOR_LIST__[]; |
||||
extern CtorFuncPtr __ZEPHYR_CTOR_END__[]; |
||||
|
||||
/**
|
||||
* |
||||
* @brief Invoke all C++ style global object constructors |
||||
* |
||||
* This routine is invoked by the kernel prior to the execution of the |
||||
* application's main(). |
||||
*/ |
||||
void __do_global_ctors_aux(void) |
||||
{ |
||||
unsigned int nCtors; |
||||
|
||||
nCtors = (unsigned long)__ZEPHYR_CTOR_LIST__[0]; |
||||
|
||||
while (nCtors >= 1U) { |
||||
__ZEPHYR_CTOR_LIST__[nCtors--](); |
||||
} |
||||
} |
||||
|
||||
#endif |
||||
|
||||
/*
|
||||
* @section |
||||
* @brief Execute initialization routines referenced in .init_array section |
||||
*/ |
||||
|
||||
#ifdef CONFIG_STATIC_INIT_GNU |
||||
|
||||
typedef void (*func_ptr)(void); |
||||
|
||||
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 = __zephyr_init_array_start; |
||||
func < __zephyr_init_array_end; |
||||
func++) { |
||||
(*func)(); |
||||
} |
||||
} |
||||
|
||||
#endif |
Loading…
Reference in new issue