diff --git a/components/esp_system/ld/esp32/memory.ld.in b/components/esp_system/ld/esp32/memory.ld.in index a498654feef..7e79c4ccf88 100644 --- a/components/esp_system/ld/esp32/memory.ld.in +++ b/components/esp_system/ld/esp32/memory.ld.in @@ -195,9 +195,6 @@ _heap_end = ALIGN(0x40000000 - _sram1_iram_len - 3, 4); _heap_end = 0x40000000 - CONFIG_ESP32_TRACEMEM_RESERVE_DRAM; #endif - -_data_seg_org = ORIGIN(rtc_data_seg); - /* The lines below define location alias for .rtc.data section based on Kconfig option. When the option is not defined then use slow memory segment else the data will be placed in fast memory segment */ diff --git a/components/esp_system/ld/esp32/sections.ld.in b/components/esp_system/ld/esp32/sections.ld.in index f8b47ef0807..8e3c76efac8 100644 --- a/components/esp_system/ld/esp32/sections.ld.in +++ b/components/esp_system/ld/esp32/sections.ld.in @@ -19,11 +19,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _rtc_text_start) - mapping[rtc_text] - - /* mutable libs begin */ - mutable[rtc_text] - /* mutable libs end */ + SECTION_MAPPINGS(rtc_text) *rtc_wake_stub*.*(.literal .text .literal.* .text.*) @@ -53,11 +49,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _rtc_force_fast_start) - mapping[rtc_force_fast] - - /* mutable libs begin */ - mutable[rtc_force_fast] - /* mutable libs end */ + SECTION_MAPPINGS(rtc_force_fast) *(.rtc.force_fast .rtc.force_fast.*) @@ -76,11 +68,7 @@ SECTIONS { _rtc_data_start = ABSOLUTE(.); - mapping[rtc_data] - - /* mutable libs begin */ - mutable[rtc_data] - /* mutable libs end */ + SECTION_MAPPINGS(rtc_data) *rtc_wake_stub*.*(.data .rodata .data.* .rodata.*) @@ -95,11 +83,7 @@ SECTIONS *rtc_wake_stub*.*(.bss .bss.*) *rtc_wake_stub*.*(COMMON) - mapping[rtc_bss] - - /* mutable libs begin */ - mutable[rtc_bss] - /* mutable libs end */ + SECTION_MAPPINGS(rtc_bss) _rtc_bss_end = ABSOLUTE(.); } > rtc_data_location @@ -116,7 +100,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _rtc_noinit_start) - mapping[rtc_noinit] + SECTION_MAPPINGS(rtc_noinit) *(.rtc_noinit .rtc_noinit.*) @@ -240,13 +224,7 @@ SECTIONS /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); - mapping[iram0_text] - - /* mutable libs begin */ - mutable[iram0_text] - FAST_REFLASHING_PADDING; - /* mutable libs end */ - + SECTION_MAPPINGS_WITH_PADDING(iram0_text) } > iram0_0_seg .dram0.data : @@ -260,12 +238,7 @@ SECTIONS *(.gnu.linkonce.s2.*) *(.jcr) - mapping[dram0_data] - - /* mutable libs begin */ - mutable[dram0_data] - FAST_REFLASHING_PADDING; - /* mutable libs end */ + SECTION_MAPPINGS_WITH_PADDING(dram0_data) _data_end = ABSOLUTE(.); } > dram0_0_seg @@ -278,6 +251,7 @@ SECTIONS { _ext_ram_noinit_start = ABSOLUTE(.); + SECTION_MAPPINGS(extram_noinit) *(.ext_ram_noinit*) ALIGNED_SYMBOL(4, _ext_ram_noinit_end) @@ -303,11 +277,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _ext_ram_bss_start) - mapping[extern_ram] - - /* mutable libs begin */ - mutable[extern_ram] - /* mutable libs end */ + SECTION_MAPPINGS(extern_ram) ALIGNED_SYMBOL(4, _ext_ram_bss_end) } > extern_ram_seg @@ -317,16 +287,7 @@ SECTIONS { ALIGNED_SYMBOL(8, _bss_start) - /** - * ldgen places all bss-related data to mapping[dram0_bss] - * (See components/esp_system/app.lf). - */ - - mapping[dram0_bss] - - /* mutable libs begin */ - mutable[dram0_bss] - /* mutable libs end */ + SECTION_MAPPINGS(dram0_bss) ALIGNED_SYMBOL(8, _bss_end) } > dram0_0_seg @@ -363,7 +324,7 @@ SECTIONS { _flash_rodata_start = ABSOLUTE(.); - mapping[flash_rodata] + SECTION_MAPPINGS_WITH_PADDING(flash_rodata) *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) @@ -381,16 +342,6 @@ SECTIONS __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); *(.xt_except_desc_end) -#if EH_FRAME_LINKING_ENABLED - ALIGNED_SYMBOL(4, __eh_frame) - KEEP(*(.eh_frame)) - /** - * As we are not linking with crtend.o, which includes the CIE terminator - * (see __FRAME_END__ in libgcc sources), it is manually provided here. - */ - LONG(0); -#endif // EH_FRAME_LINKING_ENABLED - /** * C++ constructor tables. * @@ -416,11 +367,6 @@ SECTIONS KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) _esp_system_init_fn_array_end = ABSOLUTE(.); - /* mutable libs begin */ - mutable[flash_rodata] - FAST_REFLASHING_PADDING; - /* mutable libs end */ - _rodata_end = ABSOLUTE(.); /* Literals are also RO data. */ @@ -429,9 +375,37 @@ SECTIONS *(.lit4.*) *(.gnu.linkonce.lit4.*) _lit4_end = ABSOLUTE(.); + . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.rodata, SECTION_AFTER_FLASH_RODATA) - /* TLS data. */ - ALIGNED_SYMBOL(4, _thread_local_start) +#if EH_FRAME_LINKING_ENABLED + .eh_frame : + { + ALIGNED_SYMBOL(4, __eh_frame) + + KEEP (*(.eh_frame)) + /** + * As we are not linking with crtend.o, which includes the CIE terminator + * (see __FRAME_END__ in libgcc sources), it is manually provided here. + */ + LONG(0); + + __eh_frame_end = ABSOLUTE(.); + + . = ALIGN(ALIGNOF(.flash.tdata)); + } > default_rodata_seg +#endif // EH_FRAME_LINKING_ENABLED + + .flash.tdata : + { + /* Keep tdata and tbss sections contiguous (no gaps between them). + * The TLS runtime code calculates offsets assuming these sections are + * adjacent. Gaps would cause incorrect address calculations, leading + * to accessing wrong memory. + */ + /* tdata sections */ + _thread_local_data_start = ABSOLUTE(.); #if CONFIG_LIBC_PICOLIBC _picolibc_reent_stub_start = ABSOLUTE(.); KEEP(*(.tdata.errno)) @@ -443,15 +417,18 @@ SECTIONS #endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY _picolibc_reent_stub_end = ABSOLUTE(.); #endif // CONFIG_LIBC_PICOLIBC - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) - _thread_local_end = ABSOLUTE(.); + *(.tdata .tdata.* .gnu.linkonce.td.*) + _thread_local_data_end = ABSOLUTE(.); + /* tbss sections */ + _thread_local_bss_start = ABSOLUTE(.); + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg + _tls_section_alignment = ALIGNOF(.flash.tdata); ASSERT_PICOLIBC_REENT_STUB() - - _flash_rodata_align = ALIGNOF(.flash.rodata); + ASSERT(_thread_local_data_end == _thread_local_bss_start, + "tdata and tbss must be contiguous.") /** * This section contains all the rodata that is not used @@ -466,11 +443,7 @@ SECTIONS */ _rodata_reserved_end = ABSOLUTE(.); - mapping[rodata_noload] - - /* mutable libs begin */ - mutable[rodata_noload] - /* mutable libs end */ + SECTION_MAPPINGS(rodata_noload) } > default_rodata_seg .flash.text : @@ -483,12 +456,7 @@ SECTIONS _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); - mapping[flash_text] - - /* mutable libs begin */ - mutable[flash_text] - FAST_REFLASHING_PADDING; - /* mutable libs end */ + SECTION_MAPPINGS_WITH_PADDING(flash_text) *(.stub) *(.gnu.warning) @@ -529,11 +497,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _iram_data_start) - mapping[iram0_data] - - /* mutable libs begin */ - mutable[iram0_data] - /* mutable libs end */ + SECTION_MAPPINGS(iram0_data) _iram_data_end = ABSOLUTE(.); } > iram0_0_seg @@ -542,11 +506,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _iram_bss_start) - mapping[iram0_bss] - - /* mutable libs begin */ - mutable[iram0_bss] - /* mutable libs end */ + SECTION_MAPPINGS(iram0_bss) _iram_bss_end = ABSOLUTE(.); ALIGNED_SYMBOL(4, _iram_end) @@ -559,7 +519,8 @@ SECTIONS ALIGNED_SYMBOL(8, _heap_low_start) } > dram0_0_seg -#include "elf_misc.ld.in" +#include "ld.debug.sections" +#include "ld.discard.sections" } ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), diff --git a/components/esp_system/ld/esp32s2/memory.ld.in b/components/esp_system/ld/esp32s2/memory.ld.in index ca7c4d6d932..94869fa2094 100644 --- a/components/esp_system/ld/esp32s2/memory.ld.in +++ b/components/esp_system/ld/esp32s2/memory.ld.in @@ -165,8 +165,6 @@ _heap_start = _heap_low_start; _heap_end = 0x40000000; -_data_seg_org = ORIGIN(rtc_data_seg); - /* The lines below define location alias for .rtc.data section based on Kconfig option. When the option is not defined then use slow memory segment else the data will be placed in fast memory segment */ diff --git a/components/esp_system/ld/esp32s2/sections.ld.in b/components/esp_system/ld/esp32s2/sections.ld.in index 90b827e82ec..fba99625f0a 100644 --- a/components/esp_system/ld/esp32s2/sections.ld.in +++ b/components/esp_system/ld/esp32s2/sections.ld.in @@ -28,11 +28,7 @@ SECTIONS HIDDEN(_rtc_code_start = .); - mapping[rtc_text] - - /* mutable libs begin */ - mutable[rtc_text] - /* mutable libs end */ + SECTION_MAPPINGS(rtc_text) *rtc_wake_stub*.*(.literal .text .literal.* .text.*) @@ -67,11 +63,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _rtc_force_fast_start) - mapping[rtc_force_fast] - - /* mutable libs begin */ - mutable[rtc_force_fast] - /* mutable libs end */ + SECTION_MAPPINGS(rtc_force_fast) *(.rtc.force_fast .rtc.force_fast.*) @@ -90,11 +82,7 @@ SECTIONS { _rtc_data_start = ABSOLUTE(.); - mapping[rtc_data] - - /* mutable libs begin */ - mutable[rtc_data] - /* mutable libs end */ + SECTION_MAPPINGS(rtc_data) *rtc_wake_stub*.*(.data .rodata .data.* .rodata.*) @@ -109,11 +97,7 @@ SECTIONS *rtc_wake_stub*.*(.bss .bss.*) *rtc_wake_stub*.*(COMMON) - mapping[rtc_bss] - - /* mutable libs begin */ - mutable[rtc_bss] - /* mutable libs end */ + SECTION_MAPPINGS(rtc_bss) _rtc_bss_end = ABSOLUTE(.); } > rtc_data_location @@ -130,7 +114,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _rtc_noinit_start) - mapping[rtc_noinit] + SECTION_MAPPINGS(rtc_noinit) *(.rtc_noinit .rtc_noinit.*) @@ -229,12 +213,7 @@ SECTIONS /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); - mapping[iram0_text] - - /* mutable libs begin */ - mutable[iram0_text] - FAST_REFLASHING_PADDING; - /* mutable libs end */ + SECTION_MAPPINGS_WITH_PADDING(iram0_text) /* Padding for possible CPU prefetch + alignment for PMS split lines */ . += _esp_memprot_prefetch_pad_size; @@ -262,12 +241,7 @@ SECTIONS *(.gnu.linkonce.s2.*) *(.jcr) - mapping[dram0_data] - - /* mutable libs begin */ - mutable[dram0_data] - FAST_REFLASHING_PADDING; - /* mutable libs end */ + SECTION_MAPPINGS_WITH_PADDING(dram0_data) _data_end = ABSOLUTE(.); } > dram0_0_seg @@ -293,11 +267,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _ext_ram_bss_start) - mapping[extern_ram] - - /* mutable libs begin */ - mutable[extern_ram] - /* mutable libs end */ + SECTION_MAPPINGS(extern_ram) ALIGNED_SYMBOL(4, _ext_ram_bss_end) } > extern_ram_seg @@ -312,6 +282,7 @@ SECTIONS { _ext_ram_noinit_start = ABSOLUTE(.); + SECTION_MAPPINGS(extram_noinit) *(.ext_ram_noinit*) ALIGNED_SYMBOL(4, _ext_ram_noinit_end) @@ -323,15 +294,7 @@ SECTIONS { ALIGNED_SYMBOL(8, _bss_start) - /** - * ldgen places all bss-related data to mapping[dram0_bss] - * (See components/esp_system/app.lf). - */ - mapping[dram0_bss] - - /* mutable libs begin */ - mutable[dram0_bss] - /* mutable libs end */ + SECTION_MAPPINGS(dram0_bss) ALIGNED_SYMBOL(8, _bss_end) } > dram0_0_seg @@ -365,7 +328,7 @@ SECTIONS { _flash_rodata_start = ABSOLUTE(.); - mapping[flash_rodata] + SECTION_MAPPINGS_WITH_PADDING(flash_rodata) *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) @@ -383,16 +346,6 @@ SECTIONS __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); *(.xt_except_desc_end) -#if EH_FRAME_LINKING_ENABLED - ALIGNED_SYMBOL(4, __eh_frame) - KEEP(*(.eh_frame)) - /** - * As we are not linking with crtend.o, which includes the CIE terminator - * (see __FRAME_END__ in libgcc sources), it is manually provided here. - */ - LONG(0); -#endif // EH_FRAME_LINKING_ENABLED - /** * C++ constructor tables. * @@ -418,11 +371,6 @@ SECTIONS KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) _esp_system_init_fn_array_end = ABSOLUTE(.); - /* mutable libs begin */ - mutable[flash_rodata] - FAST_REFLASHING_PADDING; - /* mutable libs end */ - _rodata_end = ABSOLUTE(.); /* Literals are also RO data. */ @@ -431,9 +379,37 @@ SECTIONS *(.lit4.*) *(.gnu.linkonce.lit4.*) _lit4_end = ABSOLUTE(.); + . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.rodata, SECTION_AFTER_FLASH_RODATA) - /* TLS data. */ - ALIGNED_SYMBOL(4, _thread_local_start) +#if EH_FRAME_LINKING_ENABLED + .eh_frame : + { + ALIGNED_SYMBOL(4, __eh_frame) + + KEEP (*(.eh_frame)) + /** + * As we are not linking with crtend.o, which includes the CIE terminator + * (see __FRAME_END__ in libgcc sources), it is manually provided here. + */ + LONG(0); + + __eh_frame_end = ABSOLUTE(.); + + . = ALIGN(ALIGNOF(.flash.tdata)); + } > default_rodata_seg +#endif // EH_FRAME_LINKING_ENABLED + + .flash.tdata : + { + /* Keep tdata and tbss sections contiguous (no gaps between them). + * The TLS runtime code calculates offsets assuming these sections are + * adjacent. Gaps would cause incorrect address calculations, leading + * to accessing wrong memory. + */ + /* tdata sections */ + _thread_local_data_start = ABSOLUTE(.); #if CONFIG_LIBC_PICOLIBC _picolibc_reent_stub_start = ABSOLUTE(.); KEEP(*(.tdata.errno)) @@ -445,15 +421,18 @@ SECTIONS #endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY _picolibc_reent_stub_end = ABSOLUTE(.); #endif // CONFIG_LIBC_PICOLIBC - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) - _thread_local_end = ABSOLUTE(.); + *(.tdata .tdata.* .gnu.linkonce.td.*) + _thread_local_data_end = ABSOLUTE(.); + /* tbss sections */ + _thread_local_bss_start = ABSOLUTE(.); + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg + _tls_section_alignment = ALIGNOF(.flash.tdata); ASSERT_PICOLIBC_REENT_STUB() - - _flash_rodata_align = ALIGNOF(.flash.rodata); + ASSERT(_thread_local_data_end == _thread_local_bss_start, + "tdata and tbss must be contiguous.") /** * This section contains all the rodata that is not used @@ -468,11 +447,8 @@ SECTIONS */ _rodata_reserved_end = ABSOLUTE(.); - mapping[rodata_noload] + SECTION_MAPPINGS(rodata_noload) - /* mutable libs begin */ - mutable[rodata_noload] - /* mutable libs end */ } > default_rodata_seg .flash.text : @@ -485,12 +461,7 @@ SECTIONS _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); - mapping[flash_text] - - /* mutable libs begin */ - mutable[flash_text] - FAST_REFLASHING_PADDING; - /* mutable libs end */ + SECTION_MAPPINGS_WITH_PADDING(flash_text) *(.stub) *(.gnu.warning) @@ -534,7 +505,8 @@ SECTIONS ALIGNED_SYMBOL(8, _heap_low_start) } > dram0_0_seg -#include "elf_misc.ld.in" +#include "ld.debug.sections" +#include "ld.discard.sections" } ASSERT(((_iram_text_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), diff --git a/components/esp_system/ld/esp32s3/memory.ld.in b/components/esp_system/ld/esp32s3/memory.ld.in index 87103fff8d9..f847815df55 100644 --- a/components/esp_system/ld/esp32s3/memory.ld.in +++ b/components/esp_system/ld/esp32s3/memory.ld.in @@ -185,9 +185,6 @@ _heap_start = _heap_low_start; /* Heap ends at top of dram0_0_seg */ _heap_end = 0x40000000; -_data_seg_org = ORIGIN(rtc_data_seg); - - /* RTC fast memory shares the same range for both data and instructions */ REGION_ALIAS("rtc_data_seg", rtc_iram_seg ); diff --git a/components/esp_system/ld/esp32s3/sections.ld.in b/components/esp_system/ld/esp32s3/sections.ld.in index 3d4d8257c4a..57da039a2cc 100644 --- a/components/esp_system/ld/esp32s3/sections.ld.in +++ b/components/esp_system/ld/esp32s3/sections.ld.in @@ -24,11 +24,7 @@ SECTIONS *(.rtc.entry.literal .rtc.entry.text) - mapping[rtc_text] - - /* mutable libs begin */ - mutable[rtc_text] - /* mutable libs end */ + SECTION_MAPPINGS(rtc_text) *rtc_wake_stub*.*(.literal .text .literal.* .text.*) *(.rtc_text_end_test) @@ -51,11 +47,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _rtc_force_fast_start) - mapping[rtc_force_fast] - - /* mutable libs begin */ - mutable[rtc_force_fast] - /* mutable libs end */ + SECTION_MAPPINGS(rtc_force_fast) *(.rtc.force_fast .rtc.force_fast.*) @@ -74,11 +66,7 @@ SECTIONS { _rtc_data_start = ABSOLUTE(.); - mapping[rtc_data] - - /* mutable libs begin */ - mutable[rtc_data] - /* mutable libs end */ + SECTION_MAPPINGS(rtc_data) *rtc_wake_stub*.*(.data .rodata .data.* .rodata.*) @@ -93,11 +81,7 @@ SECTIONS *rtc_wake_stub*.*(.bss .bss.*) *rtc_wake_stub*.*(COMMON) - mapping[rtc_bss] - - /* mutable libs begin */ - mutable[rtc_bss] - /* mutable libs end */ + SECTION_MAPPINGS(rtc_bss) _rtc_bss_end = ABSOLUTE(.); } > rtc_data_location @@ -114,7 +98,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _rtc_noinit_start) - mapping[rtc_noinit] + SECTION_MAPPINGS(rtc_noinit) *(.rtc_noinit .rtc_noinit.*) @@ -213,13 +197,7 @@ SECTIONS /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); - mapping[iram0_text] - - /* mutable libs begin */ - mutable[iram0_text] - FAST_REFLASHING_PADDING; - /* mutable libs end */ - + SECTION_MAPPINGS_WITH_PADDING(iram0_text) } > iram0_0_seg /** @@ -228,8 +206,7 @@ SECTIONS */ .dram0.dummy (NOLOAD): { - /* MAX() uses unsigned long arithmetic. Add offset to prevent underflow when _iram_end < _diram_i_start */ - . = ORIGIN(dram0_0_seg) + MAX(_iram_end - _diram_i_start + (_diram_i_start - ORIGIN(iram0_0_seg)), (_diram_i_start - ORIGIN(iram0_0_seg))) - (_diram_i_start - ORIGIN(iram0_0_seg)); + . = ORIGIN(dram0_0_seg) + ((_iram_end > _diram_i_start) ? (_iram_end - _diram_i_start) : 0); } > dram0_0_seg .dram0.data : @@ -243,12 +220,7 @@ SECTIONS *(.gnu.linkonce.s2.*) *(.jcr) - mapping[dram0_data] - - /* mutable libs begin */ - mutable[dram0_data] - FAST_REFLASHING_PADDING; - /* mutable libs end */ + SECTION_MAPPINGS_WITH_PADDING(dram0_data) _data_end = ABSOLUTE(.); } > dram0_0_seg @@ -273,15 +245,7 @@ SECTIONS { ALIGNED_SYMBOL(8, _bss_start) - /** - * ldgen places all bss-related data to mapping[dram0_bss] - * (See components/esp_system/app.lf). - */ - mapping[dram0_bss] - - /* mutable libs begin */ - mutable[dram0_bss] - /* mutable libs end */ + SECTION_MAPPINGS(dram0_bss) ALIGNED_SYMBOL(8, _bss_end) } > dram0_0_seg @@ -299,12 +263,7 @@ SECTIONS _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); - mapping[flash_text] - - /* mutable libs begin */ - mutable[flash_text] - FAST_REFLASHING_PADDING; - /* mutable libs end */ + SECTION_MAPPINGS_WITH_PADDING(flash_text) *(.stub) *(.gnu.warning) @@ -378,7 +337,7 @@ SECTIONS { _flash_rodata_start = ABSOLUTE(.); - mapping[flash_rodata] + SECTION_MAPPINGS_WITH_PADDING(flash_rodata) *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) @@ -396,16 +355,6 @@ SECTIONS __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); *(.xt_except_desc_end) -#if EH_FRAME_LINKING_ENABLED - ALIGNED_SYMBOL(4, __eh_frame) - KEEP(*(.eh_frame)) - /** - * As we are not linking with crtend.o, which includes the CIE terminator - * (see __FRAME_END__ in libgcc sources), it is manually provided here. - */ - LONG(0); -#endif // EH_FRAME_LINKING_ENABLED - /** * C++ constructor tables. * @@ -431,11 +380,6 @@ SECTIONS KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) _esp_system_init_fn_array_end = ABSOLUTE(.); - /* mutable libs begin */ - mutable[flash_rodata] - FAST_REFLASHING_PADDING; - /* mutable libs end */ - _rodata_end = ABSOLUTE(.); /* Literals are also RO data. */ @@ -444,9 +388,37 @@ SECTIONS *(.lit4.*) *(.gnu.linkonce.lit4.*) _lit4_end = ABSOLUTE(.); + . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.rodata, SECTION_AFTER_FLASH_RODATA) - /* TLS data. */ - ALIGNED_SYMBOL(4, _thread_local_start) +#if EH_FRAME_LINKING_ENABLED + .eh_frame : + { + ALIGNED_SYMBOL(4, __eh_frame) + + KEEP (*(.eh_frame)) + /** + * As we are not linking with crtend.o, which includes the CIE terminator + * (see __FRAME_END__ in libgcc sources), it is manually provided here. + */ + LONG(0); + + __eh_frame_end = ABSOLUTE(.); + + . = ALIGN(ALIGNOF(.flash.tdata)); + } > default_rodata_seg +#endif // EH_FRAME_LINKING_ENABLED + + .flash.tdata : + { + /* Keep tdata and tbss sections contiguous (no gaps between them). + * The TLS runtime code calculates offsets assuming these sections are + * adjacent. Gaps would cause incorrect address calculations, leading + * to accessing wrong memory. + */ + /* tdata sections */ + _thread_local_data_start = ABSOLUTE(.); #if CONFIG_LIBC_PICOLIBC _picolibc_reent_stub_start = ABSOLUTE(.); KEEP(*(.tdata.errno)) @@ -458,15 +430,18 @@ SECTIONS #endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY _picolibc_reent_stub_end = ABSOLUTE(.); #endif // CONFIG_LIBC_PICOLIBC - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) - _thread_local_end = ABSOLUTE(.); + *(.tdata .tdata.* .gnu.linkonce.td.*) + _thread_local_data_end = ABSOLUTE(.); + /* tbss sections */ + _thread_local_bss_start = ABSOLUTE(.); + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg + _tls_section_alignment = ALIGNOF(.flash.tdata); ASSERT_PICOLIBC_REENT_STUB() - - _flash_rodata_align = ALIGNOF(.flash.rodata); + ASSERT(_thread_local_data_end == _thread_local_bss_start, + "tdata and tbss must be contiguous.") /** * This section contains all the rodata that is not used @@ -481,11 +456,7 @@ SECTIONS */ _rodata_reserved_end = ABSOLUTE(.); - mapping[rodata_noload] - - /* mutable libs begin */ - mutable[rodata_noload] - /* mutable libs end */ + SECTION_MAPPINGS(rodata_noload) } > default_rodata_seg /** @@ -505,11 +476,7 @@ SECTIONS { _ext_ram_bss_start = ABSOLUTE(.); - mapping[extern_ram] - - /* mutable libs begin */ - mutable[extern_ram] - /* mutable libs end */ + SECTION_MAPPINGS(extern_ram) ALIGNED_SYMBOL(4, _ext_ram_bss_end) } > extern_ram_seg @@ -524,6 +491,7 @@ SECTIONS { _ext_ram_noinit_start = ABSOLUTE(.); + SECTION_MAPPINGS(extram_noinit) *(.ext_ram_noinit*) ALIGNED_SYMBOL(4, _ext_ram_noinit_end) @@ -547,11 +515,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _iram_data_start) - mapping[iram0_data] - - /* mutable libs begin */ - mutable[iram0_data] - /* mutable libs end */ + SECTION_MAPPINGS(iram0_data) ALIGNED_SYMBOL(4, _iram_data_end) } > iram0_0_seg @@ -560,11 +524,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _iram_bss_start) - mapping[iram0_bss] - - /* mutable libs begin */ - mutable[iram0_bss] - /* mutable libs end */ + SECTION_MAPPINGS(iram0_bss) _iram_bss_end = ABSOLUTE(.); ALIGNED_SYMBOL(4, _iram_end) @@ -577,7 +537,8 @@ SECTIONS ALIGNED_SYMBOL(8, _heap_low_start) } > dram0_0_seg -#include "elf_misc.ld.in" +#include "ld.debug.sections" +#include "ld.discard.sections" } ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), diff --git a/components/esp_system/ld/ld.common b/components/esp_system/ld/ld.common index e7ac7f9bc0d..b624c4a365e 100644 --- a/components/esp_system/ld/ld.common +++ b/components/esp_system/ld/ld.common @@ -105,7 +105,12 @@ ASSERT((ADDR(NEXT_SECTION) == ADDR(PREV_SECTION) + SIZEOF(PREV_SECTION)), \ #endif #if EH_FRAME_LINKING_ENABLED +#if CONFIG_IDF_TARGET_ARCH_RISCV #define SECTION_AFTER_FLASH_RODATA .eh_frame_hdr +#endif +#if CONFIG_IDF_TARGET_ARCH_XTENSA +#define SECTION_AFTER_FLASH_RODATA .eh_frame +#endif #else #define SECTION_AFTER_FLASH_RODATA .flash.tdata #endif diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c index 6ccd739fae2..84f751c663c 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -444,30 +444,36 @@ FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, u LOW ADDRESS |---------------------------| Linker Symbols | Section | -------------- - | .flash.rodata | - 0x0|---------------------------| <- _flash_rodata_start - ^ | Other Data | - | |---------------------------| <- _thread_local_start - | | .tbss | ^ - V | | | - 0xNNN | int example; | | tls_area_size - | | | - | .tdata | V - |---------------------------| <- _thread_local_end + | .flash.tdata | + 0x0|---------------------------| <- _thread_local_data_start ^ + | .flash.tdata | | + | int var_1 = 1; | | + | | <- _thread_local_data_end | + | | <- _thread_local_bss_start | tls_area_size + | | | + | .flash.tbss (NOLOAD) | | + | int var_2; | | + |---------------------------| <- _thread_local_bss_end V | Other data | | ... | |---------------------------| HIGH ADDRESS */ // Calculate the TLS area's size (rounded up to multiple of 16 bytes). - extern int _thread_local_start, _thread_local_end, _flash_rodata_start, _flash_rodata_align; - const uint32_t tls_area_size = ALIGNUP(16, (uint32_t)&_thread_local_end - (uint32_t)&_thread_local_start); + extern int _tls_section_alignment; + extern char _thread_local_data_start, _thread_local_data_end; + extern char _thread_local_bss_start, _thread_local_bss_end; + const uint32_t tls_data_size = (uint32_t)&_thread_local_data_end - (uint32_t)&_thread_local_data_start; + const uint32_t tls_bss_size = (uint32_t)&_thread_local_bss_end - (uint32_t)&_thread_local_bss_start; + const uint32_t tls_area_size = ALIGNUP(16, tls_data_size + tls_bss_size); // TODO: check that TLS area fits the stack // Allocate space for the TLS area on the stack. The area must be allocated at a 16-byte aligned address uxStackPointer = STACKPTR_ALIGN_DOWN(16, uxStackPointer - (UBaseType_t)tls_area_size); - // Initialize the TLS area with the initialization values of each TLS variable - memcpy((void *)uxStackPointer, &_thread_local_start, tls_area_size); + // Initialize the TLS data with the initialization values of each TLS variable + memcpy((void *)uxStackPointer, &_thread_local_data_start, tls_data_size); + // Initialize the TLS bss with zeroes + memset((void *)(uxStackPointer + tls_data_size), 0, tls_bss_size); /* Calculate the THREADPTR register's initialization value based on the link-time offset and the TLS area allocated on @@ -494,10 +500,10 @@ FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, u - "offset = address - tls_section_vma + align_up(TCB_SIZE, tls_section_alignment)" - TCB_SIZE is hardcoded to 8 */ - const uint32_t tls_section_align = (uint32_t)&_flash_rodata_align; // ALIGN value of .flash.rodata section + const uint32_t tls_section_align = (uint32_t)&_tls_section_alignment; // ALIGN value of .flash.tdata section #define TCB_SIZE 8 const uint32_t base = ALIGNUP(tls_section_align, TCB_SIZE); - *ret_threadptr_reg_init = (uint32_t)uxStackPointer - ((uint32_t)&_thread_local_start - (uint32_t)&_flash_rodata_start) - base; + *ret_threadptr_reg_init = (uint32_t)uxStackPointer - base; return uxStackPointer; } diff --git a/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c b/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c index 36337aa11a1..655fb4aa35d 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c +++ b/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT * - * SPDX-FileContributor: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2023-2026 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -224,30 +224,36 @@ FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, u LOW ADDRESS |---------------------------| Linker Symbols | Section | -------------- - | .flash.rodata | - 0x0|---------------------------| <- _flash_rodata_start - ^ | Other Data | - | |---------------------------| <- _thread_local_start - | | .tbss | ^ - V | | | - 0xNNN | int example; | | tls_area_size - | | | - | .tdata | V - |---------------------------| <- _thread_local_end + | .flash.tdata | + 0x0|---------------------------| <- _thread_local_data_start ^ + | .flash.tdata | | + | int var_1 = 1; | | + | | <- _thread_local_data_end | + | | <- _thread_local_bss_start | tls_area_size + | | | + | .flash.tbss (NOLOAD) | | + | int var_2; | | + |---------------------------| <- _thread_local_bss_end V | Other data | | ... | |---------------------------| HIGH ADDRESS */ // Calculate the TLS area's size (rounded up to multiple of 16 bytes). - extern int _thread_local_start, _thread_local_end, _flash_rodata_start, _flash_rodata_align; - const uint32_t tls_area_size = ALIGNUP(16, (uint32_t)&_thread_local_end - (uint32_t)&_thread_local_start); + extern int _tls_section_alignment; + extern char _thread_local_data_start, _thread_local_data_end; + extern char _thread_local_bss_start, _thread_local_bss_end; + const uint32_t tls_data_size = (uint32_t)&_thread_local_data_end - (uint32_t)&_thread_local_data_start; + const uint32_t tls_bss_size = (uint32_t)&_thread_local_bss_end - (uint32_t)&_thread_local_bss_start; + const uint32_t tls_area_size = ALIGNUP(16, tls_data_size + tls_bss_size); // TODO: check that TLS area fits the stack // Allocate space for the TLS area on the stack. The area must be allocated at a 16-byte aligned address uxStackPointer = STACKPTR_ALIGN_DOWN(16, uxStackPointer - (UBaseType_t)tls_area_size); - // Initialize the TLS area with the initialization values of each TLS variable - memcpy((void *)uxStackPointer, &_thread_local_start, tls_area_size); + // Initialize the TLS data with the initialization values of each TLS variable + memcpy((void *)uxStackPointer, &_thread_local_data_start, tls_data_size); + // Initialize the TLS bss with zeroes + memset((void *)(uxStackPointer + tls_data_size), 0, tls_bss_size); /* Calculate the THREADPTR register's initialization value based on the link-time offset and the TLS area allocated on @@ -274,10 +280,10 @@ FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, u - "offset = address - tls_section_vma + align_up(TCB_SIZE, tls_section_alignment)" - TCB_SIZE is hardcoded to 8 */ - const uint32_t tls_section_align = (uint32_t)&_flash_rodata_align; // ALIGN value of .flash.rodata section + const uint32_t tls_section_align = (uint32_t)&_tls_section_alignment; // ALIGN value of .flash.tdata section #define TCB_SIZE 8 const uint32_t base = ALIGNUP(tls_section_align, TCB_SIZE); - *ret_threadptr_reg_init = (uint32_t)uxStackPointer - ((uint32_t)&_thread_local_start - (uint32_t)&_flash_rodata_start) - base; + *ret_threadptr_reg_init = (uint32_t)uxStackPointer - base; return uxStackPointer; }