diff --git a/include/zephyr/arch/arc/v2/linker.ld b/include/zephyr/arch/arc/v2/linker.ld index 0a4ae19fab81909..cc40784d8b4045b 100644 --- a/include/zephyr/arch/arc/v2/linker.ld +++ b/include/zephyr/arch/arc/v2/linker.ld @@ -142,13 +142,6 @@ SECTIONS { #include #include -#if defined(CONFIG_CPP) && !defined(CONFIG_STATIC_INIT_GNU) && defined(__MWDT_LINKER_CMD__) - . = ALIGN(4); - _fctors = .; - KEEP(*(.ctors*)) - _ectors = .; -#endif /* CONFIG_CPP && !CONFIG_STATIC_INIT_GNU && __MWDT_LINKER_CMD__ */ - /* This extra MPU alignment of RAMABLE_REGION is only required if we put ROMABLE_REGION and * RAMABLE_REGION into the same (continuous) memory - otherwise we can get beginning of the * RAMABLE_REGION in the end of ROMABLE_REGION MPU aperture. @@ -311,11 +304,9 @@ SECTIONS { #endif /DISCARD/ : { -#if defined(CONFIG_CPP) && !defined(CONFIG_STATIC_INIT_GNU) && defined(__MWDT_LINKER_CMD__) + /* Discard all destructors */ *(.dtors*) *(.fini*) - *(.eh_frame*) -#endif /* CONFIG_CPP && !CONFIG_STATIC_INIT_GNU && __MWDT_LINKER_CMD__ */ *(.note.GNU-stack) *(.got.plt) *(.igot.plt) diff --git a/include/zephyr/linker/common-rom/common-rom-init.ld b/include/zephyr/linker/common-rom/common-rom-init.ld index 04c504ce44a0958..5523882a10957da 100644 --- a/include/zephyr/linker/common-rom/common-rom-init.ld +++ b/include/zephyr/linker/common-rom/common-rom-init.ld @@ -1,76 +1,49 @@ /* SPDX-License-Identifier: Apache-2.0 */ -#ifdef CONFIG_STATIC_INIT_GNU - SECTION_PROLOGUE(_CTOR_SECTION_NAME,,) +#ifdef CONFIG_TOOLCHAIN_SUPPORTS_STATIC_INIT_GNU + 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. 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. + * 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 as we run this + * list ourselves, that doesn't matter. + */ + __zephyr_init_array_start = .; + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) + SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array .ctors)) + __zephyr_init_array_end = .; +#ifdef CONFIG_NATIVE_LIBC + /* + * 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). */ -#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) +#endif __CTOR_END__ = .; #endif - } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) - - 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 = .; __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) -#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) +#ifndef CONFIG_STATIC_INIT_GNU + 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 diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 8477508b98af382..17e52682a255c82 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -55,7 +55,6 @@ list(APPEND kernel_files errno.c fatal.c init.c - init_static.c kheap.c mem_slab.c float.c diff --git a/kernel/Kconfig b/kernel/Kconfig index e75944761fd37e6..d862ac0afb6b999 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -970,10 +970,10 @@ config KERNEL_WHOLE_ARCHIVE to be included, rather than searching the archive for required object files. config TOOLCHAIN_SUPPORTS_STATIC_INIT_GNU - # As of today only ARC MWDT toolchain doesn't support GNU-compatible - # initialization of static objects, new toolchains can be added - # here if required. - def_bool "$(ZEPHYR_TOOLCHAIN_VARIANT)" != "arcmwdt" + # As of today, we don't know of any toolchains that don't create + # either .ctors or .init_array sections containing initializer + # addresses in a fashion compatible with how Zephyr uses them. + def_bool y config STATIC_INIT_GNU bool "Support GNU-compatible initializers and constructors" @@ -983,14 +983,11 @@ config STATIC_INIT_GNU help GNU-compatible initialization of static objects. This is required for C++ constructor support as well as for initializer functions as - defined by GNU-compatible toolchains. This increases the size - of Zephyr binaries by around 100 bytes. If you know your - application doesn't need any initializers, you can disable this - option. - The ARC MWDT toolchain, does not support or use this setting, - and has instead separate C++ constructor initialization code. - Note the option CMAKE_LINKER_GENERATOR does not yet support this feature - or CPP. + defined by GNU-compatible toolchains. This increases the size of + Zephyr binaries by around 24 bytes. If you know your application + doesn't need any initializers, you can disable this option. The linker + will emit an error if constructors are needed and this option has been + disabled. endmenu diff --git a/kernel/init.c b/kernel/init.c index 8b7d62b867118ee..02170a09bd7717d 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -403,6 +403,20 @@ static inline int z_vrfy_device_init(const struct device *dev) extern void boot_banner(void); +#ifdef CONFIG_STATIC_INIT_GNU + +extern void (*__zephyr_init_array_start[])(); +extern void (*__zephyr_init_array_end[])(); + +static void z_static_init_gnu(void) +{ + void (**fn)(); + + for (fn = __zephyr_init_array_start; fn != __zephyr_init_array_end; fn++) + (**fn)(); +} + +#endif /** * @brief Mainline for kernel's background thread @@ -433,8 +447,9 @@ static void bg_thread_main(void *unused1, void *unused2, void *unused3) #endif /* CONFIG_STACK_POINTER_RANDOM */ boot_banner(); - void z_init_static(void); - z_init_static(); +#ifdef CONFIG_STATIC_INIT_GNU + z_static_init_gnu(); +#endif /* CONFIG_STATIC_INIT_GNU */ /* Final init level before app starts */ z_sys_init_run_level(INIT_LEVEL_APPLICATION); diff --git a/kernel/init_static.c b/kernel/init_static.c deleted file mode 100644 index 442757a73a63189..000000000000000 --- a/kernel/init_static.c +++ /dev/null @@ -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