From bafaf07c189669f7776d2a4d2251ba3b77fe4c80 Mon Sep 17 00:00:00 2001 From: Jakob Hasse Date: Sun, 18 Feb 2024 16:07:41 +0800 Subject: [PATCH] refactor(cxx): moved C++ init functions to cxx component * Also fixed setting the C++ exception emergency pool size correctly when C++ exceptions are disabled: __cxx_eh_arena_size_get() is now called again even if CONFIG_COMPILER_CXX_EXCEPTIONS=n --- components/cxx/CMakeLists.txt | 4 +- components/cxx/cxx_init.cpp | 50 ++++++++++++++++++++++++ components/esp_system/startup_funcs.c | 35 ----------------- components/esp_system/system_init_fn.txt | 2 +- 4 files changed, 54 insertions(+), 37 deletions(-) create mode 100644 components/cxx/cxx_init.cpp diff --git a/components/cxx/CMakeLists.txt b/components/cxx/CMakeLists.txt index a4075b34b5..a6e61100fc 100644 --- a/components/cxx/CMakeLists.txt +++ b/components/cxx/CMakeLists.txt @@ -6,8 +6,9 @@ endif() idf_component_register(SRCS "cxx_exception_stubs.cpp" "cxx_guards.cpp" + "cxx_init.cpp" # Make sure that pthread is in component list - PRIV_REQUIRES pthread) + PRIV_REQUIRES pthread esp_system) if(NOT CONFIG_CXX_EXCEPTIONS) set(WRAP_FUNCTIONS @@ -54,6 +55,7 @@ else() target_link_libraries(${COMPONENT_LIB} PUBLIC stdc++ gcc) endif() target_link_libraries(${COMPONENT_LIB} INTERFACE "-u __cxa_guard_dummy") +target_link_libraries(${COMPONENT_LIB} INTERFACE "-u __cxx_init_dummy") # Force libpthread to appear later than libstdc++ in link line since libstdc++ depends on libpthread. # Furthermore, force libcxx to appear later than libgcc because some libgcc unwind code is wrapped, if C++ diff --git a/components/cxx/cxx_init.cpp b/components/cxx/cxx_init.cpp new file mode 100644 index 0000000000..7ade550d76 --- /dev/null +++ b/components/cxx/cxx_init.cpp @@ -0,0 +1,50 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include "esp_log.h" +#include "esp_private/startup_internal.h" + +namespace { + const char *TAG = "C++ init"; +} + +#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS +// workaround for C++ exception large memory allocation +extern "C" void _Unwind_SetEnableExceptionFdeSorting(unsigned char enable); + +ESP_SYSTEM_INIT_FN(init_cxx_exceptions, SECONDARY, BIT(0), 205) +{ + ESP_EARLY_LOGD(TAG, "Setting C++ exception workarounds."); + _Unwind_SetEnableExceptionFdeSorting(0); + return ESP_OK; +} +#endif // CONFIG_COMPILER_CXX_EXCEPTIONS + +/** + * This function overwrites the same function of libsupc++ (part of libstdc++). + * Consequently, libsupc++ will then follow our configured exception emergency pool size. + * + * It will be called even with -fno-exception for user code since the stdlib still uses exceptions. + */ +extern "C" size_t __cxx_eh_arena_size_get(void) +{ +#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS + ESP_EARLY_LOGD(TAG, "Setting C++ exception emergency pool to %u.", CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE); + return CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE; +#else + ESP_EARLY_LOGD(TAG, "Setting C++ exception emergency pool to 0."); + return 0; +#endif +} + +/** + * Dummy function used to force linking this file. + * This works via -u __cxx_init_dummy flag in CMakeLists.txt + */ +extern "C" void __cxx_init_dummy(void) +{ +} diff --git a/components/esp_system/startup_funcs.c b/components/esp_system/startup_funcs.c index dc188f33f0..216c2a883a 100644 --- a/components/esp_system/startup_funcs.c +++ b/components/esp_system/startup_funcs.c @@ -259,41 +259,6 @@ ESP_SYSTEM_INIT_FN(init_coexist, SECONDARY, BIT(0), 204) } #endif // CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE -#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS -/** - * This function overwrites a the same function of libsupc++ (part of libstdc++). - * Consequently, libsupc++ will then follow our configured exception emergency pool size. - * - * It will be called even with -fno-exception for user code since the stdlib still uses exceptions. - */ -size_t __cxx_eh_arena_size_get(void) -{ -#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS - return CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE; -#else - return 0; -#endif -} - -// workaround for C++ exception crashes -void _Unwind_SetNoFunctionContextInstall(unsigned char enable) __attribute__((weak, alias("_Unwind_SetNoFunctionContextInstall_Default"))); -// workaround for C++ exception large memory allocation -void _Unwind_SetEnableExceptionFdeSorting(unsigned char enable); - -static IRAM_ATTR void _Unwind_SetNoFunctionContextInstall_Default(unsigned char enable __attribute__((unused))) -{ - (void)0; -} - -ESP_SYSTEM_INIT_FN(init_cxx_exceptions, SECONDARY, BIT(0), 205) -{ - ESP_EARLY_LOGD(TAG, "Setting C++ exception workarounds."); - _Unwind_SetNoFunctionContextInstall(1); - _Unwind_SetEnableExceptionFdeSorting(0); - return ESP_OK; -} -#endif // CONFIG_COMPILER_CXX_EXCEPTIONS - #ifndef CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE ESP_SYSTEM_INIT_FN(init_disable_rtc_wdt, SECONDARY, BIT(0), 999) { diff --git a/components/esp_system/system_init_fn.txt b/components/esp_system/system_init_fn.txt index 51db470feb..75c02856c8 100644 --- a/components/esp_system/system_init_fn.txt +++ b/components/esp_system/system_init_fn.txt @@ -86,7 +86,7 @@ SECONDARY: 140: init_dbg_stubs in components/app_trace/debug_stubs.c on BIT(0) SECONDARY: 201: init_pm in components/esp_system/startup_funcs.c on BIT(0) SECONDARY: 203: init_apb_dma in components/esp_system/startup_funcs.c on BIT(0) SECONDARY: 204: init_coexist in components/esp_system/startup_funcs.c on BIT(0) -SECONDARY: 205: init_cxx_exceptions in components/esp_system/startup_funcs.c on BIT(0) +SECONDARY: 205: init_cxx_exceptions in components/cxx/cxx_init.cpp on BIT(0) # usb_console needs to create an esp_timer at startup. # This can be done only after esp_timer initialization (esp_timer_init_os).