diff --git a/components/esp_system/ld/esp32c2/memory.ld.in b/components/esp_system/ld/esp32c2/memory.ld.in index d13f4acfa3..79ea40cdb3 100644 --- a/components/esp_system/ld/esp32c2/memory.ld.in +++ b/components/esp_system/ld/esp32c2/memory.ld.in @@ -96,3 +96,8 @@ _heap_end = 0x40000000; ASSERT(_flash_rodata_dummy_start == ORIGIN(default_rodata_seg), ".flash_rodata_dummy section must be placed at the beginning of the rodata segment.") #endif + +#if CONFIG_ESP_SYSTEM_USE_EH_FRAME + ASSERT ((__eh_frame_end > __eh_frame), "Error: eh_frame size is null!"); + ASSERT ((__eh_frame_hdr_end > __eh_frame_hdr), "Error: eh_frame_hdr size is null!"); +#endif diff --git a/components/esp_system/ld/esp32c2/sections.ld.in b/components/esp_system/ld/esp32c2/sections.ld.in index b1e1ef0a07..6b7b6a7417 100644 --- a/components/esp_system/ld/esp32c2/sections.ld.in +++ b/components/esp_system/ld/esp32c2/sections.ld.in @@ -175,9 +175,6 @@ SECTIONS *(.gcc_except_table .gcc_except_table.*) *(.gnu.linkonce.e.*) *(.gnu.version_r) - . = (. + 3) & ~ 3; - __eh_frame = ABSOLUTE(.); - KEEP(*(.eh_frame)) . = (. + 7) & ~ 3; /* * C++ constructor and destructor tables @@ -226,7 +223,27 @@ SECTIONS *(.tbss.*) _thread_local_end = ABSOLUTE(.); _rodata_reserved_end = ABSOLUTE(.); - . = ALIGN(4); + . = ALIGN(ALIGNOF(.eh_frame)); + } > default_rodata_seg + + /* Keep this section shall be at least aligned on 4 */ + .eh_frame : ALIGN(8) + { + __eh_frame = ABSOLUTE(.); + KEEP (*(.eh_frame)) + __eh_frame_end = ABSOLUTE(.); + /* Guarantee that this section and the next one will be merged by making + * them adjacent. */ + . = ALIGN(ALIGNOF(.eh_frame_hdr)); + } > default_rodata_seg + + /* To avoid any exception in C++ exception frame unwinding code, this section + * shall be aligned on 8. */ + .eh_frame_hdr : ALIGN(8) + { + __eh_frame_hdr = ABSOLUTE(.); + KEEP (*(.eh_frame_hdr)) + __eh_frame_hdr_end = ABSOLUTE(.); } > default_rodata_seg .flash.rodata_noload (NOLOAD) : diff --git a/tools/test_apps/system/eh_frame/CMakeLists.txt b/tools/test_apps/system/eh_frame/CMakeLists.txt new file mode 100644 index 0000000000..51e1dc8ca5 --- /dev/null +++ b/tools/test_apps/system/eh_frame/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(eh_frame) diff --git a/tools/test_apps/system/eh_frame/README.md b/tools/test_apps/system/eh_frame/README.md new file mode 100644 index 0000000000..c274fdc56a --- /dev/null +++ b/tools/test_apps/system/eh_frame/README.md @@ -0,0 +1,16 @@ +| Supported Targets | ESP32-C3 | ESP32-H2 | ESP32-C2 | +| ----------------- | -------- | -------- | -------- | + +# Building and running + +The main goal of this test is to check whether the compiler/linker generates non-empty sections `.eh_frame` and `.eh_frame_hdr`. + +Thus, as soon as this example compiles we can considered it passed. However, it will also print the addresses of both sections on the UART. + +In order to build and run the example, use the following commands: + +``` +idf.py set-target +idf.py build +idf.py flash monitor +``` diff --git a/tools/test_apps/system/eh_frame/main/CMakeLists.txt b/tools/test_apps/system/eh_frame/main/CMakeLists.txt new file mode 100644 index 0000000000..09f0d02fdf --- /dev/null +++ b/tools/test_apps/system/eh_frame/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "eh_frame_main.c" + INCLUDE_DIRS "." + REQUIRES esp_system) diff --git a/tools/test_apps/system/eh_frame/main/eh_frame_main.c b/tools/test_apps/system/eh_frame/main/eh_frame_main.c new file mode 100644 index 0000000000..8abf55144e --- /dev/null +++ b/tools/test_apps/system/eh_frame/main/eh_frame_main.c @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include +#include + +/** + * @brief Symbols defined by the linker. + * Retrieve the addresses of both .eh_frame_hdr and .eh_frame sections. + */ +extern char __eh_frame_hdr; +extern char __eh_frame_hdr_end; +extern char __eh_frame; +extern char __eh_frame_end; + +/** + * @brief Pointers to both .eh_frame_hdr and .eh_frame sections. + */ +#define EH_FRAME_HDR_ADDR ((void*) (&__eh_frame_hdr)) +#define EH_FRAME_HDR_END_ADDR ((void*) (&__eh_frame_hdr_end)) +#define EH_FRAME_ADDR ((void*) (&__eh_frame)) +#define EH_FRAME_END_ADDR ((void*) (&__eh_frame_end)) + + +void app_main(void) +{ + /* As soon as this test compiles, it can be considered passed. The linker should + * test that the eh_frame and eh_frame_hdr sections are not empty but let's make + * sure again that they are not empty. */ + assert((EH_FRAME_END_ADDR > EH_FRAME_ADDR) && ".eh_frame section must not be empty"); + assert((EH_FRAME_HDR_END_ADDR > EH_FRAME_HDR_ADDR) && ".eh_frame_hdr section must not be empty"); + + /* Use the symbols just to make sure they won't be optimized away */ + printf(".eh_frame start: %p, end: %p\n", EH_FRAME_ADDR, EH_FRAME_END_ADDR); + printf(".eh_frame_hdr start: %p, end: %p\n", EH_FRAME_HDR_ADDR, EH_FRAME_HDR_END_ADDR); +} diff --git a/tools/test_apps/system/eh_frame/sdkconfig.defaults b/tools/test_apps/system/eh_frame/sdkconfig.defaults new file mode 100644 index 0000000000..dae200b3ef --- /dev/null +++ b/tools/test_apps/system/eh_frame/sdkconfig.defaults @@ -0,0 +1,2 @@ +# Enable eh_frame sections generation +CONFIG_ESP_SYSTEM_USE_EH_FRAME=y