From f123afb61faa419a35dacf561040dcd074522531 Mon Sep 17 00:00:00 2001 From: Mikey Sklar Date: Sun, 18 Oct 2026 17:49:07 -0700 Subject: [PATCH] espressif: link the IDF cxx component to keep the unwinder out CircuitPython never enables CONFIG_COMPILER_CXX_EXCEPTIONS (IDF default n). In that case IDF's cxx component wraps libgcc's unwinder and libstdc++'s throw entry points with stubs that abort, so C++ code such as nvs_flash does not pull in libgcc's unwinder. CircuitPython lists IDF components by hand and left cxx out, so the unwinder was linked anyway. The existing -u __cxx_init_dummy and -u __cxa_guard_dummy flags also matched nothing (ld does not error on an unresolved -u). Add cxx to the component list and pass the same --wrap list as esp-idf/components/cxx/CMakeLists.txt. Linking cxx also brings in cxx_init.cpp, which sets the libstdc++ emergency exception pool to 0. Feather ESP32-C6: 15,872 bytes less flash, 160 bytes less static RAM. Metro ESP32-S3: 8,592 bytes less flash, 32 bytes less static RAM. Co-Authored-By: Claude Opus 5.5 (1M context) --- ports/espressif/Makefile | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index 96a71b177b4..55b578c004a 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -985,7 +985,43 @@ ifeq ($(IDF_TARGET),esp32) BINARY_BLOBS += esp-idf/components/esp_phy/lib/$(IDF_TARGET)/librtc.a endif -ESP_IDF_COMPONENTS_LINK = $(IDF_TARGET_ARCH) $(CHIP_COMPONENTS) app_update bootloader_support driver esp_driver_dma esp_driver_gpio esp_driver_gptimer esp_driver_i2c esp_driver_ledc esp_driver_spi esp_driver_uart efuse esp_adc esp_app_format esp_common esp_event esp_gdbstub esp_hal_ana_conv esp_hal_clock esp_hal_gpio esp_hal_gpspi esp_hal_i2c esp_hal_ledc esp_hal_mspi esp_hal_security esp_hal_timg esp_hal_uart esp_hal_wdt esp_hw_support esp_mm esp_partition esp_pm esp_ringbuf esp_rom esp_system esp_timer freertos hal heap log esp_libc nvs_flash nvs_sec_provider pthread soc spi_flash vfs esp_stdio +# CONFIG_COMPILER_CXX_EXCEPTIONS is off, so IDF's cxx component replaces these +# with stubs that abort, and C++ code such as nvs_flash does not link libgcc's +# unwinder. Same list as esp-idf/components/cxx/CMakeLists.txt. +CXX_EXCEPTION_WRAPS = \ + __register_frame_info_bases \ + __register_frame_info \ + __register_frame \ + __register_frame_info_table_bases \ + __register_frame_info_table \ + __register_frame_table \ + __deregister_frame_info_bases \ + __deregister_frame_info \ + _Unwind_Find_FDE \ + _Unwind_GetGR \ + _Unwind_GetCFA \ + _Unwind_GetIP \ + _Unwind_GetIPInfo \ + _Unwind_GetRegionStart \ + _Unwind_GetDataRelBase \ + _Unwind_GetTextRelBase \ + _Unwind_SetIP \ + _Unwind_SetGR \ + _Unwind_GetLanguageSpecificData \ + _Unwind_FindEnclosingFunction \ + _Unwind_Resume \ + _Unwind_RaiseException \ + _Unwind_DeleteException \ + _Unwind_ForcedUnwind \ + _Unwind_Resume_or_Rethrow \ + _Unwind_Backtrace \ + __cxa_call_unexpected \ + __gxx_personality_v0 \ + __cxa_throw \ + __cxa_allocate_exception +LDFLAGS += $(foreach f,$(CXX_EXCEPTION_WRAPS),-Wl,--wrap=$(f)) + +ESP_IDF_COMPONENTS_LINK = $(IDF_TARGET_ARCH) $(CHIP_COMPONENTS) app_update bootloader_support driver esp_driver_dma esp_driver_gpio esp_driver_gptimer esp_driver_i2c esp_driver_ledc esp_driver_spi esp_driver_uart efuse esp_adc esp_app_format esp_common esp_event esp_gdbstub esp_hal_ana_conv esp_hal_clock esp_hal_gpio esp_hal_gpspi esp_hal_i2c esp_hal_ledc esp_hal_mspi esp_hal_security esp_hal_timg esp_hal_uart esp_hal_wdt esp_hw_support esp_mm esp_partition esp_pm esp_ringbuf esp_rom esp_system esp_timer freertos hal heap log esp_libc nvs_flash nvs_sec_provider pthread soc spi_flash vfs esp_stdio cxx ifneq ($(IDF_TARGET),esp32) ESP_IDF_COMPONENTS_LINK += esp_hal_systimer endif