From 2f0b772c77c43e19358a97eeb7a97121364828f7 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 19 Sep 2016 11:59:24 +0100 Subject: [PATCH 1/4] Disable destruction of global C++ objects when IAR is used. This behavior is realized by enabling the flag --no_static_destruction when the compilerin the invoked. --- tools/toolchains/iar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/toolchains/iar.py b/tools/toolchains/iar.py index ca41f845b2..e5168194be 100644 --- a/tools/toolchains/iar.py +++ b/tools/toolchains/iar.py @@ -41,7 +41,7 @@ class IAR(mbedToolchain): "--diag_suppress=Pa050,Pa084,Pa093,Pa082"], 'asm': [], 'c': ["--vla"], - 'cxx': ["--guard_calls"], + 'cxx': ["--guard_calls", "--no_static_destruction"], 'ld': ["--skip_dynamic_initialization", "--threaded_lib"], } From b67d863c0a56f3374fb1e5419dae6f9a6d9a5dfa Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 19 Sep 2016 13:29:29 +0100 Subject: [PATCH 2/4] Disable registration of atexit handlers on ARMCC. This prevent destructors for global C++ objects to be invoked at exit. By default atexit handlers registration involved dynamic allocation. --- hal/common/retarget.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/hal/common/retarget.cpp b/hal/common/retarget.cpp index c42190fbc4..298481aa77 100644 --- a/hal/common/retarget.cpp +++ b/hal/common/retarget.cpp @@ -629,6 +629,31 @@ extern "C" void exit(int return_code) { } //namespace std #endif +#if defined(TOOLCHAIN_ARM) + +// This series of function disable the registration of global destructors +// in a dynamic table which will be called when the application exit. +// In mbed, program never exit properly, it dies. +// More informations about this topic for ARMCC here: +// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/6449.html +extern "C" { +int __aeabi_atexit(void *object, void (*dtor)(void* /*this*/), void *handle) { + return 1; +} + +int __cxa_atexit(void (*dtor)(void* /*this*/), void *object, void *handle) { + return 1; +} + +void __cxa_finalize(void *handle) { +} + +} // end of extern "C" + + +#endif + + namespace mbed { From ce23ec312098e974a77f35d3df35bd607d9efde0 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 19 Sep 2016 13:54:50 +0100 Subject: [PATCH 3/4] Disable registration of __libc_fini_array in the init process. With this call, destructors are not registered for execution atexit. --- rtos/rtx/TARGET_CORTEX_M/RTX_CM_lib.h | 1 - 1 file changed, 1 deletion(-) diff --git a/rtos/rtx/TARGET_CORTEX_M/RTX_CM_lib.h b/rtos/rtx/TARGET_CORTEX_M/RTX_CM_lib.h index d7f0117cf0..e1633f74d7 100644 --- a/rtos/rtx/TARGET_CORTEX_M/RTX_CM_lib.h +++ b/rtos/rtx/TARGET_CORTEX_M/RTX_CM_lib.h @@ -798,7 +798,6 @@ void pre_main(void) { singleton_mutex_id = osMutexCreate(osMutex(singleton_mutex)); malloc_mutex_id = osMutexCreate(osMutex(malloc_mutex)); env_mutex_id = osMutexCreate(osMutex(env_mutex)); - atexit(__libc_fini_array); __libc_init_array(); main(0, NULL); } From f4f8b491d1c6c28ddb148f2bcc65f7c550469d1d Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 19 Sep 2016 15:17:39 +0100 Subject: [PATCH 4/4] Override exit and atexit functions from newlib. This change simplify the exit and initialization process. It also reduce the number of hidden memory allocation made by atexit. --- hal/common/retarget.cpp | 35 ++++++++++++++++++++++++++++++++++- tools/toolchains/gcc.py | 3 ++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/hal/common/retarget.cpp b/hal/common/retarget.cpp index 298481aa77..49bea4ee8c 100644 --- a/hal/common/retarget.cpp +++ b/hal/common/retarget.cpp @@ -629,7 +629,7 @@ extern "C" void exit(int return_code) { } //namespace std #endif -#if defined(TOOLCHAIN_ARM) +#if defined(TOOLCHAIN_ARM) || defined(TOOLCHAIN_GCC) // This series of function disable the registration of global destructors // in a dynamic table which will be called when the application exit. @@ -650,6 +650,39 @@ void __cxa_finalize(void *handle) { } // end of extern "C" +#endif + + +#if defined(TOOLCHAIN_GCC) + +/* + * Depending on how newlib is configured, it is often not enough to define + * __aeabi_atexit, __cxa_atexit and __cxa_finalize in order to override the + * behavior regarding the registration of handlers with atexit. + * + * To overcome this limitation, exit and atexit are overriden here. + */ +extern "C"{ + +/** + * @brief Retarget of exit for GCC. + * @details Unlike the standard version, this function doesn't call any function + * registered with atexit before calling _exit. + */ +void __wrap_exit(int return_code) { + _exit(return_code); +} + +/** + * @brief Retarget atexit from GCC. + * @details This function will always fail and never register any handler to be + * called at exit. + */ +int __wrap_atexit(void (*func)()) { + return 1; +} + +} #endif diff --git a/tools/toolchains/gcc.py b/tools/toolchains/gcc.py index 27bc11fede..75f958c592 100644 --- a/tools/toolchains/gcc.py +++ b/tools/toolchains/gcc.py @@ -40,7 +40,8 @@ class GCC(mbedToolchain): 'c': ["-std=gnu99"], 'cxx': ["-std=gnu++98", "-fno-rtti", "-Wvla"], 'ld': ["-Wl,--gc-sections", "-Wl,--wrap,main", - "-Wl,--wrap,_malloc_r", "-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", "-Wl,--wrap,_calloc_r"], + "-Wl,--wrap,_malloc_r", "-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", "-Wl,--wrap,_calloc_r", + "-Wl,--wrap,exit", "-Wl,--wrap,atexit"], } def __init__(self, target, options=None, notify=None, macros=None, silent=False, tool_path="", extra_verbose=False):