diff --git a/components/esp_system/ld/esp32/sections.ld.in b/components/esp_system/ld/esp32/sections.ld.in index b4fc9ea0e2..19c395cbe5 100644 --- a/components/esp_system/ld/esp32/sections.ld.in +++ b/components/esp_system/ld/esp32/sections.ld.in @@ -6,60 +6,64 @@ #include "ld.common" -/* Default entry point: */ +/* Default entry point */ ENTRY(call_start_cpu0); SECTIONS { - /* RTC fast memory holds RTC wake stub code, - including from any source file named rtc_wake_stub*.c - */ + /** + * RTC fast memory holds RTC wake stub code, + * including from any source file named rtc_wake_stub*.c + */ .rtc.text : { - . = ALIGN(4); + ALIGNED_SYMBOL(4, _rtc_text_start) mapping[rtc_text] *rtc_wake_stub*.*(.literal .text .literal.* .text.*) + _rtc_text_end = ABSOLUTE(.); } > rtc_iram_seg - /* - This section is required to skip rtc.text area because rtc_iram_seg and - rtc_data_seg are reflect the same address space on different buses. - */ + /** + * This section is required to skip rtc.text area because rtc_iram_seg and + * rtc_data_seg are reflect the same address space on different buses. + */ .rtc.dummy : { _rtc_dummy_start = ABSOLUTE(.); _rtc_fast_start = ABSOLUTE(.); + . = SIZEOF(.rtc.text); + _rtc_dummy_end = ABSOLUTE(.); } > rtc_data_seg - /* This section located in RTC FAST Memory area. - It holds data marked with RTC_FAST_ATTR attribute. - See the file "esp_attr.h" for more information. - */ + /** + * This section located in RTC FAST Memory area. + * It holds data marked with RTC_FAST_ATTR attribute. + * See the file "esp_attr.h" for more information. + */ .rtc.force_fast : { - . = ALIGN(4); - _rtc_force_fast_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_fast_start) mapping[rtc_force_fast] *(.rtc.force_fast .rtc.force_fast.*) - . = ALIGN(4) ; - _rtc_force_fast_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_fast_end) } > rtc_data_seg - /* RTC data section holds RTC wake stub - data/rodata, including from any source file - named rtc_wake_stub*.c and the data marked with - RTC_DATA_ATTR, RTC_RODATA_ATTR attributes. - The memory location of the data is dependent on - CONFIG_ESP32_RTCDATA_IN_FAST_MEM option. - */ + /** + * RTC data section holds RTC wake stub + * data/rodata, including from any source file + * named rtc_wake_stub*.c and the data marked with + * RTC_DATA_ATTR, RTC_RODATA_ATTR attributes. + * The memory location of the data is dependent on + * CONFIG_ESP32_RTCDATA_IN_FAST_MEM option. + */ .rtc.data : { _rtc_data_start = ABSOLUTE(.); @@ -67,14 +71,15 @@ SECTIONS mapping[rtc_data] *rtc_wake_stub*.*(.data .rodata .data.* .rodata.*) - _rtc_data_end = ABSOLUTE(.); + _rtc_data_end = ABSOLUTE(.); } > rtc_data_location /* RTC bss, from any source file named rtc_wake_stub*.c */ .rtc.bss (NOLOAD) : { _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.*(.bss .bss.*) *rtc_wake_stub*.*(COMMON) @@ -83,47 +88,55 @@ SECTIONS _rtc_bss_end = ABSOLUTE(.); } > rtc_data_location - /* This section holds data that should not be initialized at power up - and will be retained during deep sleep. - User data marked with RTC_NOINIT_ATTR will be placed - into this section. See the file "esp_attr.h" for more information. - The memory location of the data is dependent on - CONFIG_ESP32_RTCDATA_IN_FAST_MEM option. - */ + /** + * This section holds data that should not be initialized at power up + * and will be retained during deep sleep. + * User data marked with RTC_NOINIT_ATTR will be placed + * into this section. See the file "esp_attr.h" for more information. + * The memory location of the data is dependent on + * CONFIG_ESP32_RTCDATA_IN_FAST_MEM option. + */ .rtc_noinit (NOLOAD): { - . = ALIGN(4); - _rtc_noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_noinit_start) + *(.rtc_noinit .rtc_noinit.*) - . = ALIGN(4) ; - _rtc_noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_noinit_end) } > rtc_data_location - /* This section located in RTC SLOW Memory area. - It holds data marked with RTC_SLOW_ATTR attribute. - See the file "esp_attr.h" for more information. - */ + /** + * This section located in RTC SLOW Memory area. + * It holds data marked with RTC_SLOW_ATTR attribute. + * See the file "esp_attr.h" for more information. + */ .rtc.force_slow : { - . = ALIGN(4); - _rtc_force_slow_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_slow_start) + *(.rtc.force_slow .rtc.force_slow.*) - . = ALIGN(4) ; - _rtc_force_slow_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_force_slow_end) } > rtc_slow_seg /** * This section holds RTC FAST data that should have fixed addresses. - * The data are not initialized at power-up and are retained during deep sleep. + * The data are not initialized at power-up and are retained during deep + * sleep. */ .rtc_fast_reserved (NOLOAD): { - . = ALIGN(4); - _rtc_fast_reserved_start = ABSOLUTE(.); - /* New data can only be added here to ensure existing data are not moved. - Because data have adhered to the end of the segment and code is relied on it. - >> put new data here << */ + ALIGNED_SYMBOL(4, _rtc_fast_reserved_start) + + /** + * New data can only be added here to ensure existing data are not moved. + * Because data have adhered to the end of the segment and code is relied + * on it. + * >> put new data here << + */ + KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) + _rtc_fast_reserved_end = ABSOLUTE(.); } > rtc_fast_reserved_seg @@ -133,17 +146,22 @@ SECTIONS /** * This section holds RTC SLOW data that should have fixed addresses. - * The data are not initialized at power-up and are retained during deep sleep. + * The data are not initialized at power-up and are retained during deep + * sleep. */ .rtc_slow_reserved (NOLOAD): { - . = ALIGN(4); - _rtc_slow_reserved_start = ABSOLUTE(.); - /* New data can only be added here to ensure existing data are not moved. - Because data have adhered to the end of the segment and code is relied on it. - >> put new data here << */ + ALIGNED_SYMBOL(4, _rtc_slow_reserved_start) + + /** + * New data can only be added here to ensure existing data are not moved. + * Because data have adhered to the end of the segment and code is relied + * on it. + * >> put new data here << + */ *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) + _rtc_slow_reserved_end = ABSOLUTE(.); } > rtc_slow_reserved_seg @@ -173,7 +191,6 @@ SECTIONS _iram_start = ABSOLUTE(.); /* Vectors go to IRAM */ _vector_table = ABSOLUTE(.); - /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */ . = 0x0; KEEP(*(.WindowVectors.text)); . = 0x180; @@ -210,7 +227,7 @@ SECTIONS .iram0.text : { - /* Code marked as runnning out of IRAM */ + /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); mapping[iram0_text] @@ -231,7 +248,6 @@ SECTIONS mapping[dram0_data] _data_end = ABSOLUTE(.); - . = ALIGN(4); } > dram0_0_seg /** @@ -241,46 +257,49 @@ SECTIONS .ext_ram_noinit (NOLOAD) : { _ext_ram_noinit_start = ABSOLUTE(.); + *(.ext_ram_noinit*) - . = ALIGN(4); - _ext_ram_noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _ext_ram_noinit_end) } > extern_ram_seg - /*This section holds data that should not be initialized at power up. - The section located in Internal SRAM memory region. The macro _NOINIT - can be used as attribute to place data into this section. - See the esp_attr.h file for more information. - */ + /** + * This section holds data that should not be initialized at power up. + * The section located in Internal SRAM memory region. The macro _NOINIT + * can be used as attribute to place data into this section. + * See the "esp_attr.h" file for more information. + */ .noinit (NOLOAD): { - . = ALIGN(4); - _noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _noinit_start) + *(.noinit .noinit.*) - . = ALIGN(4) ; - _noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _noinit_end) } > dram0_0_seg - /* external memory bss, from any global variable with EXT_RAM_BSS_ATTR attribute*/ + /* External Memory BSS. (Variables with EXT_RAM_BSS_ATTR attribute). */ .ext_ram.bss (NOLOAD) : { - _ext_ram_bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _ext_ram_bss_start) mapping[extern_ram] - . = ALIGN(4); - _ext_ram_bss_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _ext_ram_bss_end) } > extern_ram_seg /* Shared RAM */ .dram0.bss (NOLOAD) : { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_start) + /** + * ldgen places all bss-related data to mapping[dram0_bss] + * (See components/esp_system/app.lf). + */ mapping[dram0_bss] - . = ALIGN (8); - _bss_end = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_end) } > dram0_0_seg ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), @@ -288,17 +307,27 @@ SECTIONS .flash.appdesc : ALIGN(0x10) { - _rodata_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.rodata start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark flash.rodata start. + * This can be used for mmu driver to maintain virtual address + */ + _rodata_reserved_start = ABSOLUTE(.); _rodata_start = ABSOLUTE(.); - *(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */ - *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */ + /* !DO NOT PUT ANYTHING BEFORE THIS! */ - /* Create an empty gap within this section. Thanks to this, the end of this + /* Should be the first. App version info. */ + *(.rodata_desc .rodata_desc.*) + /* Should be the second. Custom app version info. */ + *(.rodata_custom_desc .rodata_custom_desc.*) + + /** + * Create an empty gap within this section. Thanks to this, the end of this * section will match .flah.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. */ + * will be merged when creating the final bin image. + */ . = ALIGN(ALIGNOF(.flash.rodata)); - } >default_rodata_seg + } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) .flash.rodata : ALIGN(0x10) @@ -307,125 +336,135 @@ SECTIONS mapping[flash_rodata] - *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) - __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + + /* C++ exception handlers table. */ + ALIGNED_SYMBOL(4, __XT_EXCEPTION_TABLE_) *(.xt_except_table) *(.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 - Make a point of not including anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt - */ - __init_array_start = ABSOLUTE(.); - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .ctors SORT(.ctors.*))) - __init_array_end = ABSOLUTE(.); - - KEEP (*crtbegin.*(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - /* C++ exception handlers table: */ - __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __XT_EXCEPTION_DESCS_) *(.xt_except_desc) *(.gnu.linkonce.h.*) __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); *(.xt_except_desc_end) - *(.dynamic) - *(.gnu.version_d) - /* Addresses of memory regions reserved via - SOC_RESERVE_MEMORY_REGION() */ - soc_reserved_memory_region_start = ABSOLUTE(.); + + 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); + + /** + * C++ constructor tables. + * + * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. + */ + ALIGNED_SYMBOL(4, __init_array_start) + KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .ctors SORT(.ctors.*))) + __init_array_end = ABSOLUTE(.); + + /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ + ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) KEEP (*(.reserved_memory_address)) soc_reserved_memory_region_end = ABSOLUTE(.); + /* System init functions registered via ESP_SYSTEM_INIT_FN */ - _esp_system_init_fn_array_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) _esp_system_init_fn_array_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + /* Literals are also RO data. */ _lit4_start = ABSOLUTE(.); *(*.lit4) *(.lit4.*) *(.gnu.linkonce.lit4.*) _lit4_end = ABSOLUTE(.); - . = ALIGN(4); - _thread_local_start = ABSOLUTE(.); + + /* TLS data. */ + ALIGNED_SYMBOL(4, _thread_local_start) *(.tdata) *(.tdata.*) *(.tbss) *(.tbss.*) _thread_local_end = ABSOLUTE(.); - . = ALIGN(4); - } >default_rodata_seg + } > default_rodata_seg _flash_rodata_align = ALIGNOF(.flash.rodata); - /* - This section is a place where we dump all the rodata which aren't used at runtime, - so as to avoid binary size increase - */ + /** + * This section contains all the rodata that is not used + * at runtime, helping to avoid an increase in binary size. + */ .flash.rodata_noload (NOLOAD) : { - /* - This is a symbol marking the flash.rodata end, this can be used for mmu driver to maintain virtual address - We don't need to include the noload rodata in this section - */ + /** + * This symbol marks the end of flash.rodata. It can be utilized by the MMU + * driver to maintain the virtual address. + * NOLOAD rodata may not be included in this section. + */ _rodata_reserved_end = ABSOLUTE(.); - . = ALIGN (4); + mapping[rodata_noload] } > default_rodata_seg .flash.text : { _stext = .; - _instruction_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.text start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the start of flash.text. + * This can be used by the MMU driver to maintain the virtual address. + */ + _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); mapping[flash_text] - *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.stub) + *(.gnu.warning) + *(.gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.fini.literal) - *(.fini) - *(.gnu.version) - /** CPU will try to prefetch up to 16 bytes of - * of instructions. This means that any configuration (e.g. MMU, PMS) must allow - * safe access to up to 16 bytes after the last real instruction, add - * dummy bytes to ensure this - */ + /** + * CPU will try to prefetch up to 16 bytes of of instructions. + * This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, + * add dummy bytes to ensure this. + */ . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); - _instruction_reserved_end = ABSOLUTE(.); /* This is a symbol marking the flash.text end, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the flash.text end. + * This can be used for MMU driver to maintain virtual address. + */ + _instruction_reserved_end = ABSOLUTE(.); _etext = .; - /* Similar to _iram_start, this symbol goes here so it is - resolved by addr2line in preference to the first symbol in - the flash.text segment. - */ + /** + * Similar to _iram_start, this symbol goes here so it is + * resolved by addr2line in preference to the first symbol in + * the flash.text segment. + */ _flash_cache_start = ABSOLUTE(0); - } >default_code_seg + } > default_code_seg /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : { - . = ALIGN (4); - _iram_text_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _iram_text_end) } > iram0_0_seg .iram0.data : { - . = ALIGN(4); - _iram_data_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _iram_data_start) mapping[iram0_data] @@ -434,33 +473,31 @@ SECTIONS .iram0.bss (NOLOAD) : { - . = ALIGN(4); - _iram_bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _iram_bss_start) mapping[iram0_bss] _iram_bss_end = ABSOLUTE(.); - . = ALIGN(4); - _iram_end = ABSOLUTE(.); - } > iram0_0_seg + ALIGNED_SYMBOL(4, _iram_end) + } > iram0_0_seg /* Marks the end of data, bss and possibly rodata */ .dram0.heap_start (NOLOAD) : { - . = ALIGN (8); /* Lowest possible start address for the heap */ - _heap_low_start = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _heap_low_start) } > dram0_0_seg - /** This section will be used by the debugger and disassembler to get more information - * about raw data present in the code. - * Indeed, it may be required to add some padding at some points in the code - * in order to align a branch/jump destination on a particular bound. - * Padding these instructions will generate null bytes that shall be - * interpreted as data, and not code by the debugger or disassembler. - * This section will only be present in the ELF file, not in the final binary - * For more details, check GCC-212 - */ + /** + * This section will be used by the debugger and disassembler to get more + * information about raw data present in the code. + * Indeed, it may be required to add some padding at some points in the code + * in order to align a branch/jump destination on a particular bound. + * Padding these instructions will generate null bytes that shall be + * interpreted as data, and not code by the debugger or disassembler. + * This section will only be present in the ELF file, not in the final binary + * For more details, check GCC-212 + */ .xt.prop 0 : { KEEP (*(.xt.prop .gnu.linkonce.prop.*)) diff --git a/components/esp_system/ld/esp32c2/sections.ld.in b/components/esp_system/ld/esp32c2/sections.ld.in index dc42e6c2d6..42c906acad 100644 --- a/components/esp_system/ld/esp32c2/sections.ld.in +++ b/components/esp_system/ld/esp32c2/sections.ld.in @@ -18,9 +18,8 @@ SECTIONS ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); KEEP(*(.exception_vectors_table.text)); KEEP(*(.exception_vectors.text)); - . = ALIGN(4); - _invalid_pc_placeholder = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _invalid_pc_placeholder) /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); @@ -39,21 +38,21 @@ SECTIONS } > dram0_0_seg /** - * This section MUST be placed at the beginning of the DRAM0, - * which will be released along with iram0_bt.text when Bluetooth is no longer in use + * This section MUST be placed at the beginning of the DRAM0, which will be + * released along with iram0_bt.text when Bluetooth is no longer in use. */ .dram0.bt.data : { _data_start = ABSOLUTE(.); mapping[dram0_bt_data] - . = ALIGN(8); } > dram0_0_seg .dram0.bt.bss (NOLOAD) : { - . = ALIGN (8); - _bss_bt_start = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_bt_start) + mapping[dram0_bt_bss] + _bss_bt_end = ABSOLUTE(.); } > dram0_0_seg @@ -71,7 +70,6 @@ SECTIONS mapping[dram0_data] _data_end = ABSOLUTE(.); - . = ALIGN(4); } > dram0_0_seg /** @@ -82,51 +80,61 @@ SECTIONS */ .noinit (NOLOAD): { - . = ALIGN(4); - _noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _noinit_start) + *(.noinit .noinit.*) - . = ALIGN(4) ; - _noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _noinit_end) } > dram0_0_seg /* Shared RAM */ .dram0.bss (NOLOAD) : { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_start) - /* ldgen places all bss-related data to mapping[dram0_bss] (See esp_system/app.lf). */ + /** + * ldgen places all bss-related data to mapping[dram0_bss] + * (See components/esp_system/app.lf). + */ mapping[dram0_bss] - . = ALIGN (8); - _bss_end = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_end) } > dram0_0_seg - ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.") + ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), + "DRAM segment data does not fit.") .flash.text : { _stext = .; - _instruction_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.text start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the start of flash.text. + * This can be used by the MMU driver to maintain the virtual address. + */ + _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); mapping[flash_text] - *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.stub) + *(.gnu.linkonce.t.*) + *(.gnu.warning) *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.fini.literal) - *(.fini) - *(.gnu.version) - /** CPU will try to prefetch up to 16 bytes of - * of instructions. This means that any configuration (e.g. MMU, PMS) must allow - * safe access to up to 16 bytes after the last real instruction, add - * dummy bytes to ensure this - */ + /** + * CPU will try to prefetch up to 16 bytes of of instructions. + * This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add + * dummy bytes to ensure this + */ . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); - _instruction_reserved_end = ABSOLUTE(.); /* This is a symbol marking the flash.text end, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the flash.text end. + * This can be used for MMU driver to maintain virtual address. + */ + _instruction_reserved_end = ABSOLUTE(.); _etext = .; /** @@ -138,32 +146,40 @@ SECTIONS } > default_code_seg /** - * This dummy section represents the .flash.text section but in default_rodata_seg. + * Dummy section represents the .flash.text section but in default_rodata_seg. * Thus, it must have its alignment and (at least) its size. */ .flash_rodata_dummy (NOLOAD): { _flash_rodata_dummy_start = .; - /* Start at the same alignment constraint than .flash.text */ - . = ALIGN(ALIGNOF(.flash.text)); - /* Create an empty gap as big as .flash.text section */ - . = . + SIZEOF(.flash.text); - /* Prepare the alignment of the section above. Few bytes (0x20) must be - * added for the mapping header. */ - . = ALIGN(_esp_mmu_block_size) + 0x20; + + . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); + + /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ + . = ALIGN(_esp_mmu_page_size) + 0x20; } > default_rodata_seg .flash.appdesc : ALIGN(0x10) { - _rodata_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.rodata start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark flash.rodata start. + * This can be used for mmu driver to maintain virtual address + */ + _rodata_reserved_start = ABSOLUTE(.); _rodata_start = ABSOLUTE(.); - *(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */ - *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */ + /* !DO NOT PUT ANYTHING BEFORE THIS! */ - /* Create an empty gap within this section. Thanks to this, the end of this + /* Should be the first. App version info. */ + *(.rodata_desc .rodata_desc.*) + /* Should be the second. Custom app version info. */ + *(.rodata_custom_desc .rodata_custom_desc.*) + + /** + * Create an empty gap within this section. Thanks to this, the end of this * section will match .flash.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. */ + * will be merged when creating the final bin image. + */ . = ALIGN(ALIGNOF(.flash.rodata)); } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) @@ -177,119 +193,117 @@ SECTIONS *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) - __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); - *(.xt_except_table) *(.gcc_except_table .gcc_except_table.*) *(.gnu.linkonce.e.*) - *(.gnu.version_r) - . = (. + 7) & ~ 3; - /* - * C++ constructor and destructor tables - * Don't include anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt. + /** + * C++ constructor tables. * - * RISC-V gcc is configured with --enable-initfini-array so it emits an .init_array section instead. - * But the init_priority sections will be sorted for iteration in ascending order during startup. - * The rest of the init_array sections is sorted for iteration in descending order during startup, however. - * Hence a different section is generated for the init_priority functions which is iterated in - * ascending order during startup. The corresponding code can be found in startup.c. + * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. + * + * RISC-V gcc is configured with --enable-initfini-array so it emits + * .init_array section instead. But the init_priority sections will be + * sorted for iteration in ascending order during startup. + * The rest of the init_array sections is sorted for iteration in descending + * order during startup, however. Hence a different section is generated for + * the init_priority functions which is iterated in ascending order during + * startup. The corresponding code can be found in startup.c. */ - __init_priority_array_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __init_priority_array_start) KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) __init_priority_array_end = ABSOLUTE(.); - __init_array_start = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, __init_array_start) KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) __init_array_end = ABSOLUTE(.); - KEEP (*crtbegin.*(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - /* C++ exception handlers table: */ - __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); - *(.xt_except_desc) - *(.gnu.linkonce.h.*) - __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); - *(.xt_except_desc_end) - *(.dynamic) - *(.gnu.version_d) + /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - soc_reserved_memory_region_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) KEEP (*(.reserved_memory_address)) soc_reserved_memory_region_end = ABSOLUTE(.); + /* System init functions registered via ESP_SYSTEM_INIT_FN */ - _esp_system_init_fn_array_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) _esp_system_init_fn_array_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); - /* Literals are also RO data. */ - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(.flash.tls)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.rodata, .flash.tls) - - .flash.tls : ALIGN(8) - { - _thread_local_start = ABSOLUTE(.); - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) - _thread_local_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(.eh_frame)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.tls, .eh_frame) - - /* 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 - ASSERT_SECTIONS_GAP(.eh_frame, .eh_frame_hdr) + ASSERT_SECTIONS_GAP(.flash.rodata, .eh_frame_hdr) - /* 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 : { - __eh_frame_hdr = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __eh_frame_hdr) + KEEP (*(.eh_frame_hdr)) + __eh_frame_hdr_end = ABSOLUTE(.); + . = ALIGN(ALIGNOF(.eh_frame)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) + + .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 + ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) + + .flash.tdata : + { + _thread_local_data_start = ABSOLUTE(.); + + *(.tdata .tdata.* .gnu.linkonce.td.*) + + . = ALIGN(ALIGNOF(.flash.tbss)); + _thread_local_data_end = ABSOLUTE(.); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + + .flash.tbss (NOLOAD) : + { + _thread_local_bss_start = ABSOLUTE(.); + + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + + _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg - /* - This section is a place where we dump all the rodata which aren't used at runtime, - so as to avoid binary size increase - */ + /** + * This section contains all the rodata that is not used + * at runtime, helping to avoid an increase in binary size. + */ .flash.rodata_noload (NOLOAD) : { - /* - This is a symbol marking the flash.rodata end, this can be used for mmu driver to maintain virtual address - We don't need to include the noload rodata in this section - */ - _rodata_reserved_end = ABSOLUTE(.); - . = ALIGN (4); + /** + * This symbol marks the end of flash.rodata. It can be utilized by the MMU + * driver to maintain the virtual address. + * NOLOAD rodata may not be included in this section. + */ + _rodata_reserved_end = ADDR(.flash.tbss); + mapping[rodata_noload] } > default_rodata_seg /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : { - . = ALIGN(4); - - _iram_text_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _iram_text_end) } > iram0_0_seg .iram0.data : { - . = ALIGN(16); - _iram_data_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_data_start) mapping[iram0_data] @@ -298,8 +312,7 @@ SECTIONS .iram0.bss (NOLOAD) : { - . = ALIGN(16); - _iram_bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_bss_start) mapping[iram0_bss] @@ -307,25 +320,32 @@ SECTIONS } > iram0_0_seg /** - * This section needs to be placed at the end of the IRAM0, - * which will be released along with dram0_bt_data and dram0_bt_bss when Bluetooth is no longer in use + * This section needs to be placed at the end of the IRAM0, which will be + * released along with dram0_bt_data and dram0_bt_bss when Bluetooth is no + * longer in use. */ .iram0.bt.text : { - . = ALIGN(16); - _iram_bt_text_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_bt_text_start) + mapping[iram0_bt_text] - . = ALIGN(16); - _iram_end = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_end) } > iram0_0_seg - /* Marks the end of data, bss and possibly rodata */ + /* Marks the end of data, bss and possibly rodata */ .dram0.heap_start (NOLOAD) : { - . = ALIGN (16); - _heap_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _heap_start) } > dram0_0_seg + + /** + * Discarding .rela.* sections results in the following mapping: + * .rela.text.* -> .text.* + * .rela.data.* -> .data.* + * And so forth... + */ + /DISCARD/ : { *(.rela.*) } } ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), diff --git a/components/esp_system/ld/esp32c3/sections.ld.in b/components/esp_system/ld/esp32c3/sections.ld.in index 1c1a48af61..f5962dd6f0 100644 --- a/components/esp_system/ld/esp32c3/sections.ld.in +++ b/components/esp_system/ld/esp32c3/sections.ld.in @@ -17,17 +17,16 @@ SECTIONS */ .rtc.text : { - . = ALIGN(4); - _rtc_fast_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_fast_start) mapping[rtc_text] - *rtc_wake_stub*.*(.literal .text .literal.* .text.*) + *rtc_wake_stub*.*(.text .text.*) *(.rtc_text_end_test) - /* 16B padding for possible CPU prefetch and 4B alignment for PMS split lines */ + /* Padding for possible CPU prefetch + alignment for PMS split lines */ . += _esp_memprot_prefetch_pad_size; - . = ALIGN(4); + . = ALIGN(_esp_memprot_align_size); _rtc_text_end = ABSOLUTE(.); } > rtc_iram_seg @@ -39,14 +38,13 @@ SECTIONS */ .rtc.force_fast : { - . = ALIGN(4); - _rtc_force_fast_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_fast_start) mapping[rtc_force_fast] *(.rtc.force_fast .rtc.force_fast.*) - . = ALIGN(4) ; - _rtc_force_fast_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_force_fast_end) } > rtc_data_seg /** @@ -62,6 +60,7 @@ SECTIONS mapping[rtc_data] *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) + _rtc_data_end = ABSOLUTE(.); } > rtc_data_location @@ -69,6 +68,7 @@ SECTIONS .rtc.bss (NOLOAD) : { _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*) *rtc_wake_stub*.*(COMMON) @@ -85,11 +85,11 @@ SECTIONS */ .rtc_noinit (NOLOAD): { - . = ALIGN(4); - _rtc_noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_noinit_start) + *(.rtc_noinit .rtc_noinit.*) - . = ALIGN(4) ; - _rtc_noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_noinit_end) } > rtc_data_location /** @@ -99,27 +99,32 @@ SECTIONS */ .rtc.force_slow : { - . = ALIGN(4); - _rtc_force_slow_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_slow_start) + *(.rtc.force_slow .rtc.force_slow.*) - . = ALIGN(4) ; - _rtc_force_slow_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_force_slow_end) } > rtc_slow_seg /** * This section holds RTC data that should have fixed addresses. - * The data are not initialized at power-up and are retained during deep sleep. + * The data are not initialized at power-up and are retained during deep + * sleep. */ .rtc_reserved (NOLOAD): { - . = ALIGN(4); - _rtc_reserved_start = ABSOLUTE(.); - /* New data can only be added here to ensure existing data are not moved. - Because data have adhered to the end of the segment and code is relied on it. - >> put new data here << */ + ALIGNED_SYMBOL(4, _rtc_reserved_start) + + /** + * New data can only be added here to ensure existing data are not moved. + * Because data have adhered to the end of the segment and code is relied + * on it. + * >> put new data here << + */ *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) + _rtc_reserved_end = ABSOLUTE(.); } > rtc_reserved_seg @@ -149,9 +154,8 @@ SECTIONS ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); KEEP(*(.exception_vectors_table.text)); KEEP(*(.exception_vectors.text)); - . = ALIGN(4); - _invalid_pc_placeholder = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _invalid_pc_placeholder) /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); @@ -184,7 +188,6 @@ SECTIONS mapping[dram0_data] _data_end = ABSOLUTE(.); - . = ALIGN(4); } > dram0_0_seg /** @@ -195,51 +198,61 @@ SECTIONS */ .noinit (NOLOAD): { - . = ALIGN(4); - _noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _noinit_start) + *(.noinit .noinit.*) - . = ALIGN(4) ; - _noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _noinit_end) } > dram0_0_seg /* Shared RAM */ .dram0.bss (NOLOAD) : { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_start) - /* ldgen places all bss-related data to mapping[dram0_bss] (See esp_system/app.lf). */ + /** + * ldgen places all bss-related data to mapping[dram0_bss] + * (See components/esp_system/app.lf). + */ mapping[dram0_bss] - . = ALIGN (8); - _bss_end = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_end) } > dram0_0_seg - ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.") + ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), + "DRAM segment data does not fit.") .flash.text : { _stext = .; - _instruction_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.text start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the start of flash.text. + * This can be used by the MMU driver to maintain the virtual address. + */ + _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); mapping[flash_text] - *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.stub) + *(.gnu.linkonce.t.*) + *(.gnu.warning) *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.fini.literal) - *(.fini) - *(.gnu.version) - /** CPU will try to prefetch up to 16 bytes of - * of instructions. This means that any configuration (e.g. MMU, PMS) must allow - * safe access to up to 16 bytes after the last real instruction, add - * dummy bytes to ensure this - */ + /** + * CPU will try to prefetch up to 16 bytes of of instructions. + * This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add + * dummy bytes to ensure this + */ . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); - _instruction_reserved_end = ABSOLUTE(.); /* This is a symbol marking the flash.text end, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the flash.text end. + * This can be used for MMU driver to maintain virtual address. + */ + _instruction_reserved_end = ABSOLUTE(.); _etext = .; /** @@ -251,32 +264,40 @@ SECTIONS } > default_code_seg /** - * This dummy section represents the .flash.text section but in default_rodata_seg. + * Dummy section represents the .flash.text section but in default_rodata_seg. * Thus, it must have its alignment and (at least) its size. */ .flash_rodata_dummy (NOLOAD): { _flash_rodata_dummy_start = .; - /* Start at the same alignment constraint than .flash.text */ - . = ALIGN(ALIGNOF(.flash.text)); - /* Create an empty gap as big as .flash.text section */ - . = . + SIZEOF(.flash.text); - /* Prepare the alignment of the section above. Few bytes (0x20) must be - * added for the mapping header. */ - . = ALIGN(_esp_mmu_block_size) + 0x20; + + . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); + + /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ + . = ALIGN(_esp_mmu_page_size) + 0x20; } > default_rodata_seg .flash.appdesc : ALIGN(0x10) { - _rodata_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.rodata start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark flash.rodata start. + * This can be used for mmu driver to maintain virtual address + */ + _rodata_reserved_start = ABSOLUTE(.); _rodata_start = ABSOLUTE(.); - *(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */ - *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */ + /* !DO NOT PUT ANYTHING BEFORE THIS! */ - /* Create an empty gap within this section. Thanks to this, the end of this + /* Should be the first. App version info. */ + *(.rodata_desc .rodata_desc.*) + /* Should be the second. Custom app version info. */ + *(.rodata_custom_desc .rodata_custom_desc.*) + + /** + * Create an empty gap within this section. Thanks to this, the end of this * section will match .flash.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. */ + * will be merged when creating the final bin image. + */ . = ALIGN(ALIGNOF(.flash.rodata)); } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) @@ -290,122 +311,124 @@ SECTIONS *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) - __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); - *(.xt_except_table) *(.gcc_except_table .gcc_except_table.*) *(.gnu.linkonce.e.*) - *(.gnu.version_r) - . = (. + 7) & ~ 3; - /* - * C++ constructor and destructor tables - * Don't include anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt. + /** + * C++ constructor tables. * - * RISC-V gcc is configured with --enable-initfini-array so it emits an .init_array section instead. - * But the init_priority sections will be sorted for iteration in ascending order during startup. - * The rest of the init_array sections is sorted for iteration in descending order during startup, however. - * Hence a different section is generated for the init_priority functions which is iterated in - * ascending order during startup. The corresponding code can be found in startup.c. + * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. + * + * RISC-V gcc is configured with --enable-initfini-array so it emits + * .init_array section instead. But the init_priority sections will be + * sorted for iteration in ascending order during startup. + * The rest of the init_array sections is sorted for iteration in descending + * order during startup, however. Hence a different section is generated for + * the init_priority functions which is iterated in ascending order during + * startup. The corresponding code can be found in startup.c. */ - __init_priority_array_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __init_priority_array_start) KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) __init_priority_array_end = ABSOLUTE(.); - __init_array_start = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, __init_array_start) KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) __init_array_end = ABSOLUTE(.); - KEEP (*crtbegin.*(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - /* C++ exception handlers table: */ - __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); - *(.xt_except_desc) - *(.gnu.linkonce.h.*) - __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); - *(.xt_except_desc_end) - *(.dynamic) - *(.gnu.version_d) + /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - soc_reserved_memory_region_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) KEEP (*(.reserved_memory_address)) soc_reserved_memory_region_end = ABSOLUTE(.); + /* System init functions registered via ESP_SYSTEM_INIT_FN */ - _esp_system_init_fn_array_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) _esp_system_init_fn_array_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); - /* Literals are also RO data. */ - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(.flash.tls)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.rodata, .flash.tls) - - .flash.tls : ALIGN(8) - { - _thread_local_start = ABSOLUTE(.); - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) - _thread_local_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(.eh_frame)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.tls, .eh_frame) - - /* 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 - ASSERT_SECTIONS_GAP(.eh_frame, .eh_frame_hdr) + ASSERT_SECTIONS_GAP(.flash.rodata, .eh_frame_hdr) - /* 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 : { - __eh_frame_hdr = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __eh_frame_hdr) + KEEP (*(.eh_frame_hdr)) + __eh_frame_hdr_end = ABSOLUTE(.); + . = ALIGN(ALIGNOF(.eh_frame)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) + + .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 + ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) + + .flash.tdata : + { + _thread_local_data_start = ABSOLUTE(.); + + *(.tdata .tdata.* .gnu.linkonce.td.*) + + . = ALIGN(ALIGNOF(.flash.tbss)); + _thread_local_data_end = ABSOLUTE(.); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + + .flash.tbss (NOLOAD) : + { + _thread_local_bss_start = ABSOLUTE(.); + + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + + _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg - /* - This section is a place where we dump all the rodata which aren't used at runtime, - so as to avoid binary size increase - */ + /** + * This section contains all the rodata that is not used + * at runtime, helping to avoid an increase in binary size. + */ .flash.rodata_noload (NOLOAD) : { - /* - This is a symbol marking the flash.rodata end, this can be used for mmu driver to maintain virtual address - We don't need to include the noload rodata in this section - */ - _rodata_reserved_end = ABSOLUTE(.); - . = ALIGN (4); + /** + * This symbol marks the end of flash.rodata. It can be utilized by the MMU + * driver to maintain the virtual address. + * NOLOAD rodata may not be included in this section. + */ + _rodata_reserved_end = ADDR(.flash.tbss); + mapping[rodata_noload] } > default_rodata_seg /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : { - /* iram_end_test section exists for use by Memprot unit tests only */ - *(.iram_end_test) - /* ESP32-C3 memprot requires 16B padding for possible CPU prefetch and 512B alignment for PMS split lines */ + /* Padding for possible CPU prefetch + alignment for PMS split lines */ . += _esp_memprot_prefetch_pad_size; . = ALIGN(_esp_memprot_align_size); + + /* iram_end_test section exists for use by memprot unit tests only */ + *(.iram_end_test) + _iram_text_end = ABSOLUTE(.); } > iram0_0_seg .iram0.data : { - . = ALIGN(16); - _iram_data_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_data_start) mapping[iram0_data] @@ -414,22 +437,27 @@ SECTIONS .iram0.bss (NOLOAD) : { - . = ALIGN(16); - _iram_bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_bss_start) mapping[iram0_bss] _iram_bss_end = ABSOLUTE(.); - . = ALIGN(16); - _iram_end = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_end) } > iram0_0_seg - /* Marks the end of data, bss and possibly rodata */ + /* Marks the end of data, bss and possibly rodata */ .dram0.heap_start (NOLOAD) : { - . = ALIGN (16); - _heap_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _heap_start) } > dram0_0_seg + + /** + * Discarding .rela.* sections results in the following mapping: + * .rela.text.* -> .text.* + * .rela.data.* -> .data.* + * And so forth... + */ + /DISCARD/ : { *(.rela.*) } } ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), diff --git a/components/esp_system/ld/esp32c5/beta3/sections.ld.in b/components/esp_system/ld/esp32c5/beta3/sections.ld.in index 1de281f3ff..c18b9510f2 100644 --- a/components/esp_system/ld/esp32c5/beta3/sections.ld.in +++ b/components/esp_system/ld/esp32c5/beta3/sections.ld.in @@ -17,18 +17,16 @@ SECTIONS */ .rtc.text : { - . = ALIGN(4); - _rtc_fast_start = ABSOLUTE(.); - _rtc_text_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_fast_start) + ALIGNED_SYMBOL(4, _rtc_text_start) + *(.rtc.entry.text) mapping[rtc_text] - *rtc_wake_stub*.*(.literal .text .literal.* .text.*) + *rtc_wake_stub*.*(.text .text.*) *(.rtc_text_end_test) - . = ALIGN(4); - _rtc_text_end = ABSOLUTE(.); } > lp_ram_seg @@ -39,15 +37,13 @@ SECTIONS */ .rtc.force_fast : { - . = ALIGN(4); - _rtc_force_fast_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_fast_start) mapping[rtc_force_fast] *(.rtc.force_fast .rtc.force_fast.*) - . = ALIGN(4) ; - _rtc_force_fast_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_fast_end) } > lp_ram_seg /** @@ -63,6 +59,7 @@ SECTIONS mapping[rtc_data] *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) + _rtc_data_end = ABSOLUTE(.); } > lp_ram_seg @@ -70,6 +67,7 @@ SECTIONS .rtc.bss (NOLOAD) : { _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*) *rtc_wake_stub*.*(COMMON) @@ -86,11 +84,11 @@ SECTIONS */ .rtc_noinit (NOLOAD): { - . = ALIGN(4); - _rtc_noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_noinit_start) + *(.rtc_noinit .rtc_noinit.*) - . = ALIGN(4) ; - _rtc_noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_noinit_end) } > lp_ram_seg /** @@ -100,27 +98,32 @@ SECTIONS */ .rtc.force_slow : { - . = ALIGN(4); - _rtc_force_slow_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_slow_start) + *(.rtc.force_slow .rtc.force_slow.*) - . = ALIGN(4) ; - _rtc_force_slow_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_force_slow_end) } > lp_ram_seg /** * This section holds RTC data that should have fixed addresses. - * The data are not initialized at power-up and are retained during deep sleep. + * The data are not initialized at power-up and are retained during deep + * sleep. */ .rtc_reserved (NOLOAD): { - . = ALIGN(4); - _rtc_reserved_start = ABSOLUTE(.); - /* New data can only be added here to ensure existing data are not moved. - Because data have adhered to the end of the segment and code is relied on it. - >> put new data here << */ + ALIGNED_SYMBOL(4, _rtc_reserved_start) + + /** + * New data can only be added here to ensure existing data are not moved. + * Because data have adhered to the end of the segment and code is relied + * on it. + * >> put new data here << + */ *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) + _rtc_reserved_end = ABSOLUTE(.); } > rtc_reserved_seg @@ -150,9 +153,8 @@ SECTIONS ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); KEEP(*(.exception_vectors_table.text)); KEEP(*(.exception_vectors.text)); - . = ALIGN(4); - _invalid_pc_placeholder = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _invalid_pc_placeholder) /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); @@ -164,15 +166,12 @@ SECTIONS /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : { - . = ALIGN(4); - - _iram_text_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _iram_text_end) } > iram0_0_seg .iram0.data : { - . = ALIGN(16); - _iram_data_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_data_start) mapping[iram0_data] @@ -181,14 +180,12 @@ SECTIONS .iram0.bss (NOLOAD) : { - . = ALIGN(16); - _iram_bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_bss_start) mapping[iram0_bss] _iram_bss_end = ABSOLUTE(.); - . = ALIGN(16); - _iram_end = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_end) } > iram0_0_seg /** @@ -215,7 +212,6 @@ SECTIONS mapping[dram0_data] _data_end = ABSOLUTE(.); - . = ALIGN(4); } > dram0_0_seg /** @@ -226,24 +222,25 @@ SECTIONS */ .noinit (NOLOAD): { - . = ALIGN(4); - _noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _noinit_start) + *(.noinit .noinit.*) - . = ALIGN(4) ; - _noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _noinit_end) } > dram0_0_seg /* Shared RAM */ .dram0.bss (NOLOAD) : { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_start) - /* ldgen places all bss-related data to mapping[dram0_bss] (See esp_system/app.lf). */ + /** + * ldgen places all bss-related data to mapping[dram0_bss] + * (See components/esp_system/app.lf). + */ mapping[dram0_bss] - . = ALIGN(4); - _bss_end = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_end) } > dram0_0_seg ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.") @@ -251,26 +248,34 @@ SECTIONS .flash.text : { _stext = .; - _instruction_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.text start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the start of flash.text. + * This can be used by the MMU driver to maintain the virtual address. + */ + _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); mapping[flash_text] - *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.stub) + *(.gnu.linkonce.t.*) + *(.gnu.warning) *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.fini.literal) - *(.fini) - *(.gnu.version) - /** CPU will try to prefetch up to 16 bytes of - * of instructions. This means that any configuration (e.g. MMU, PMS) must allow - * safe access to up to 16 bytes after the last real instruction, add - * dummy bytes to ensure this - */ + /** + * CPU will try to prefetch up to 16 bytes of of instructions. + * This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add + * dummy bytes to ensure this + */ . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); - _instruction_reserved_end = ABSOLUTE(.); /* This is a symbol marking the flash.text end, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the flash.text end. + * This can be used for MMU driver to maintain virtual address. + */ + _instruction_reserved_end = ABSOLUTE(.); _etext = .; /** @@ -282,32 +287,40 @@ SECTIONS } > default_code_seg /** - * This dummy section represents the .flash.text section but in default_rodata_seg. + * Dummy section represents the .flash.text section but in default_rodata_seg. * Thus, it must have its alignment and (at least) its size. */ .flash_rodata_dummy (NOLOAD): { _flash_rodata_dummy_start = .; - /* Start at the same alignment constraint than .flash.text */ - . = ALIGN(ALIGNOF(.flash.text)); - /* Create an empty gap as big as .flash.text section */ - . = . + SIZEOF(.flash.text); - /* Prepare the alignment of the section above. Few bytes (0x20) must be - * added for the mapping header. */ - . = ALIGN(_esp_mmu_block_size) + 0x20; + + . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); + + /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ + . = ALIGN(_esp_mmu_page_size) + 0x20; } > default_rodata_seg .flash.appdesc : ALIGN(0x10) { - _rodata_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.rodata start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark flash.rodata start. + * This can be used for mmu driver to maintain virtual address + */ + _rodata_reserved_start = ABSOLUTE(.); _rodata_start = ABSOLUTE(.); - *(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */ - *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */ + /* !DO NOT PUT ANYTHING BEFORE THIS! */ - /* Create an empty gap within this section. Thanks to this, the end of this + /* Should be the first. App version info. */ + *(.rodata_desc .rodata_desc.*) + /* Should be the second. Custom app version info. */ + *(.rodata_custom_desc .rodata_custom_desc.*) + + /** + * Create an empty gap within this section. Thanks to this, the end of this * section will match .flash.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. */ + * will be merged when creating the final bin image. + */ . = ALIGN(ALIGNOF(.flash.rodata)); } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) @@ -321,113 +334,121 @@ SECTIONS *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) - __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); - *(.xt_except_table) *(.gcc_except_table .gcc_except_table.*) *(.gnu.linkonce.e.*) - *(.gnu.version_r) - . = (. + 7) & ~ 3; - /* - * C++ constructor and destructor tables - * Don't include anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt. + /** + * C++ constructor tables. * - * RISC-V gcc is configured with --enable-initfini-array so it emits an .init_array section instead. - * But the init_priority sections will be sorted for iteration in ascending order during startup. - * The rest of the init_array sections is sorted for iteration in descending order during startup, however. - * Hence a different section is generated for the init_priority functions which is iterated in - * ascending order during startup. The corresponding code can be found in startup.c. + * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. + * + * RISC-V gcc is configured with --enable-initfini-array so it emits + * .init_array section instead. But the init_priority sections will be + * sorted for iteration in ascending order during startup. + * The rest of the init_array sections is sorted for iteration in descending + * order during startup, however. Hence a different section is generated for + * the init_priority functions which is iterated in ascending order during + * startup. The corresponding code can be found in startup.c. */ - __init_priority_array_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __init_priority_array_start) KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) __init_priority_array_end = ABSOLUTE(.); - __init_array_start = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, __init_array_start) KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) __init_array_end = ABSOLUTE(.); - KEEP (*crtbegin.*(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - /* C++ exception handlers table: */ - __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); - *(.xt_except_desc) - *(.gnu.linkonce.h.*) - __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); - *(.xt_except_desc_end) - *(.dynamic) - *(.gnu.version_d) + /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - soc_reserved_memory_region_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) KEEP (*(.reserved_memory_address)) soc_reserved_memory_region_end = ABSOLUTE(.); + /* System init functions registered via ESP_SYSTEM_INIT_FN */ - _esp_system_init_fn_array_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) _esp_system_init_fn_array_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); - /* Literals are also RO data. */ - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(.flash.tls)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.rodata, .flash.tls) - - .flash.tls : ALIGN(8) - { - _thread_local_start = ABSOLUTE(.); - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) - _thread_local_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(.eh_frame)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.tls, .eh_frame) - - /* 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 - ASSERT_SECTIONS_GAP(.eh_frame, .eh_frame_hdr) + ASSERT_SECTIONS_GAP(.flash.rodata, .eh_frame_hdr) - /* 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 : { - __eh_frame_hdr = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __eh_frame_hdr) + KEEP (*(.eh_frame_hdr)) + __eh_frame_hdr_end = ABSOLUTE(.); + . = ALIGN(ALIGNOF(.eh_frame)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) + + .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 + ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) + + .flash.tdata : + { + _thread_local_data_start = ABSOLUTE(.); + + *(.tdata .tdata.* .gnu.linkonce.td.*) + + . = ALIGN(ALIGNOF(.flash.tbss)); + _thread_local_data_end = ABSOLUTE(.); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + + .flash.tbss (NOLOAD) : + { + _thread_local_bss_start = ABSOLUTE(.); + + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + + _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg - /* - This section is a place where we dump all the rodata which aren't used at runtime, - so as to avoid binary size increase - */ + /** + * This section contains all the rodata that is not used + * at runtime, helping to avoid an increase in binary size. + */ .flash.rodata_noload (NOLOAD) : { - /* - This is a symbol marking the flash.rodata end, this can be used for mmu driver to maintain virtual address - We don't need to include the noload rodata in this section - */ - _rodata_reserved_end = ABSOLUTE(.); - . = ALIGN (4); + /** + * This symbol marks the end of flash.rodata. It can be utilized by the MMU + * driver to maintain the virtual address. + * NOLOAD rodata may not be included in this section. + */ + _rodata_reserved_end = ADDR(.flash.tbss); + mapping[rodata_noload] } > default_rodata_seg - /* Marks the end of data, bss and possibly rodata */ + /* Marks the end of data, bss and possibly rodata */ .dram0.heap_start (NOLOAD) : { - . = ALIGN (16); - _heap_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _heap_start) } > dram0_0_seg + + /** + * Discarding .rela.* sections results in the following mapping: + * .rela.text.* -> .text.* + * .rela.data.* -> .data.* + * And so forth... + */ + /DISCARD/ : { *(.rela.*) } } ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), diff --git a/components/esp_system/ld/esp32c5/mp/sections.ld.in b/components/esp_system/ld/esp32c5/mp/sections.ld.in index fcb2f4755b..c18b9510f2 100644 --- a/components/esp_system/ld/esp32c5/mp/sections.ld.in +++ b/components/esp_system/ld/esp32c5/mp/sections.ld.in @@ -17,20 +17,16 @@ SECTIONS */ .rtc.text : { - . = ALIGN(4); - _rtc_fast_start = ABSOLUTE(.); - _rtc_text_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_fast_start) + ALIGNED_SYMBOL(4, _rtc_text_start) + *(.rtc.entry.text) mapping[rtc_text] - *rtc_wake_stub*.*(.literal .text .literal.* .text.*) + *rtc_wake_stub*.*(.text .text.*) *(.rtc_text_end_test) - /* 16B padding for possible CPU prefetch and 4B alignment for PMS split lines */ - . += _esp_memprot_prefetch_pad_size; - . = ALIGN(4); - _rtc_text_end = ABSOLUTE(.); } > lp_ram_seg @@ -41,15 +37,13 @@ SECTIONS */ .rtc.force_fast : { - . = ALIGN(4); - _rtc_force_fast_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_fast_start) mapping[rtc_force_fast] *(.rtc.force_fast .rtc.force_fast.*) - . = ALIGN(4) ; - _rtc_force_fast_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_fast_end) } > lp_ram_seg /** @@ -65,6 +59,7 @@ SECTIONS mapping[rtc_data] *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) + _rtc_data_end = ABSOLUTE(.); } > lp_ram_seg @@ -72,6 +67,7 @@ SECTIONS .rtc.bss (NOLOAD) : { _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*) *rtc_wake_stub*.*(COMMON) @@ -88,11 +84,11 @@ SECTIONS */ .rtc_noinit (NOLOAD): { - . = ALIGN(4); - _rtc_noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_noinit_start) + *(.rtc_noinit .rtc_noinit.*) - . = ALIGN(4) ; - _rtc_noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_noinit_end) } > lp_ram_seg /** @@ -102,27 +98,32 @@ SECTIONS */ .rtc.force_slow : { - . = ALIGN(4); - _rtc_force_slow_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_slow_start) + *(.rtc.force_slow .rtc.force_slow.*) - . = ALIGN(4) ; - _rtc_force_slow_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_force_slow_end) } > lp_ram_seg /** * This section holds RTC data that should have fixed addresses. - * The data are not initialized at power-up and are retained during deep sleep. + * The data are not initialized at power-up and are retained during deep + * sleep. */ .rtc_reserved (NOLOAD): { - . = ALIGN(4); - _rtc_reserved_start = ABSOLUTE(.); - /* New data can only be added here to ensure existing data are not moved. - Because data have adhered to the end of the segment and code is relied on it. - >> put new data here << */ + ALIGNED_SYMBOL(4, _rtc_reserved_start) + + /** + * New data can only be added here to ensure existing data are not moved. + * Because data have adhered to the end of the segment and code is relied + * on it. + * >> put new data here << + */ *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) + _rtc_reserved_end = ABSOLUTE(.); } > rtc_reserved_seg @@ -152,9 +153,8 @@ SECTIONS ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); KEEP(*(.exception_vectors_table.text)); KEEP(*(.exception_vectors.text)); - . = ALIGN(4); - _invalid_pc_placeholder = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _invalid_pc_placeholder) /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); @@ -166,18 +166,12 @@ SECTIONS /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : { - /* ESP32-C5 memprot requires 16B padding for possible CPU prefetch and 512B alignment for PMS split lines */ - . += _esp_memprot_prefetch_pad_size; - . = ALIGN(_esp_memprot_align_size); - /* iram_end_test section exists for use by memprot unit tests only */ - *(.iram_end_test) - _iram_text_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _iram_text_end) } > iram0_0_seg .iram0.data : { - . = ALIGN(16); - _iram_data_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_data_start) mapping[iram0_data] @@ -186,14 +180,12 @@ SECTIONS .iram0.bss (NOLOAD) : { - . = ALIGN(16); - _iram_bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_bss_start) mapping[iram0_bss] _iram_bss_end = ABSOLUTE(.); - . = ALIGN(16); - _iram_end = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_end) } > iram0_0_seg /** @@ -220,7 +212,6 @@ SECTIONS mapping[dram0_data] _data_end = ABSOLUTE(.); - . = ALIGN(4); } > dram0_0_seg /** @@ -231,24 +222,25 @@ SECTIONS */ .noinit (NOLOAD): { - . = ALIGN(4); - _noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _noinit_start) + *(.noinit .noinit.*) - . = ALIGN(4) ; - _noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _noinit_end) } > dram0_0_seg /* Shared RAM */ .dram0.bss (NOLOAD) : { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_start) - /* ldgen places all bss-related data to mapping[dram0_bss] (See esp_system/app.lf). */ + /** + * ldgen places all bss-related data to mapping[dram0_bss] + * (See components/esp_system/app.lf). + */ mapping[dram0_bss] - . = ALIGN(4); - _bss_end = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_end) } > dram0_0_seg ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.") @@ -256,26 +248,34 @@ SECTIONS .flash.text : { _stext = .; - _instruction_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.text start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the start of flash.text. + * This can be used by the MMU driver to maintain the virtual address. + */ + _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); mapping[flash_text] - *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.stub) + *(.gnu.linkonce.t.*) + *(.gnu.warning) *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.fini.literal) - *(.fini) - *(.gnu.version) - /** CPU will try to prefetch up to 16 bytes of - * of instructions. This means that any configuration (e.g. MMU, PMS) must allow - * safe access to up to 16 bytes after the last real instruction, add - * dummy bytes to ensure this - */ + /** + * CPU will try to prefetch up to 16 bytes of of instructions. + * This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add + * dummy bytes to ensure this + */ . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); - _instruction_reserved_end = ABSOLUTE(.); /* This is a symbol marking the flash.text end, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the flash.text end. + * This can be used for MMU driver to maintain virtual address. + */ + _instruction_reserved_end = ABSOLUTE(.); _etext = .; /** @@ -287,32 +287,40 @@ SECTIONS } > default_code_seg /** - * This dummy section represents the .flash.text section but in default_rodata_seg. + * Dummy section represents the .flash.text section but in default_rodata_seg. * Thus, it must have its alignment and (at least) its size. */ .flash_rodata_dummy (NOLOAD): { _flash_rodata_dummy_start = .; - /* Start at the same alignment constraint than .flash.text */ - . = ALIGN(ALIGNOF(.flash.text)); - /* Create an empty gap as big as .flash.text section */ - . = . + SIZEOF(.flash.text); - /* Prepare the alignment of the section above. Few bytes (0x20) must be - * added for the mapping header. */ - . = ALIGN(_esp_mmu_block_size) + 0x20; + + . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); + + /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ + . = ALIGN(_esp_mmu_page_size) + 0x20; } > default_rodata_seg .flash.appdesc : ALIGN(0x10) { - _rodata_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.rodata start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark flash.rodata start. + * This can be used for mmu driver to maintain virtual address + */ + _rodata_reserved_start = ABSOLUTE(.); _rodata_start = ABSOLUTE(.); - *(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */ - *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */ + /* !DO NOT PUT ANYTHING BEFORE THIS! */ - /* Create an empty gap within this section. Thanks to this, the end of this + /* Should be the first. App version info. */ + *(.rodata_desc .rodata_desc.*) + /* Should be the second. Custom app version info. */ + *(.rodata_custom_desc .rodata_custom_desc.*) + + /** + * Create an empty gap within this section. Thanks to this, the end of this * section will match .flash.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. */ + * will be merged when creating the final bin image. + */ . = ALIGN(ALIGNOF(.flash.rodata)); } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) @@ -326,113 +334,121 @@ SECTIONS *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) - __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); - *(.xt_except_table) *(.gcc_except_table .gcc_except_table.*) *(.gnu.linkonce.e.*) - *(.gnu.version_r) - . = (. + 7) & ~ 3; - /* - * C++ constructor and destructor tables - * Don't include anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt. + /** + * C++ constructor tables. * - * RISC-V gcc is configured with --enable-initfini-array so it emits an .init_array section instead. - * But the init_priority sections will be sorted for iteration in ascending order during startup. - * The rest of the init_array sections is sorted for iteration in descending order during startup, however. - * Hence a different section is generated for the init_priority functions which is iterated in - * ascending order during startup. The corresponding code can be found in startup.c. + * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. + * + * RISC-V gcc is configured with --enable-initfini-array so it emits + * .init_array section instead. But the init_priority sections will be + * sorted for iteration in ascending order during startup. + * The rest of the init_array sections is sorted for iteration in descending + * order during startup, however. Hence a different section is generated for + * the init_priority functions which is iterated in ascending order during + * startup. The corresponding code can be found in startup.c. */ - __init_priority_array_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __init_priority_array_start) KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) __init_priority_array_end = ABSOLUTE(.); - __init_array_start = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, __init_array_start) KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) __init_array_end = ABSOLUTE(.); - KEEP (*crtbegin.*(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - /* C++ exception handlers table: */ - __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); - *(.xt_except_desc) - *(.gnu.linkonce.h.*) - __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); - *(.xt_except_desc_end) - *(.dynamic) - *(.gnu.version_d) + /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - soc_reserved_memory_region_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) KEEP (*(.reserved_memory_address)) soc_reserved_memory_region_end = ABSOLUTE(.); + /* System init functions registered via ESP_SYSTEM_INIT_FN */ - _esp_system_init_fn_array_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) _esp_system_init_fn_array_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); - /* Literals are also RO data. */ - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(.flash.tls)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.rodata, .flash.tls) - - .flash.tls : ALIGN(8) - { - _thread_local_start = ABSOLUTE(.); - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) - _thread_local_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(.eh_frame)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.tls, .eh_frame) - - /* 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 - ASSERT_SECTIONS_GAP(.eh_frame, .eh_frame_hdr) + ASSERT_SECTIONS_GAP(.flash.rodata, .eh_frame_hdr) - /* 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 : { - __eh_frame_hdr = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __eh_frame_hdr) + KEEP (*(.eh_frame_hdr)) + __eh_frame_hdr_end = ABSOLUTE(.); + . = ALIGN(ALIGNOF(.eh_frame)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) + + .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 + ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) + + .flash.tdata : + { + _thread_local_data_start = ABSOLUTE(.); + + *(.tdata .tdata.* .gnu.linkonce.td.*) + + . = ALIGN(ALIGNOF(.flash.tbss)); + _thread_local_data_end = ABSOLUTE(.); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + + .flash.tbss (NOLOAD) : + { + _thread_local_bss_start = ABSOLUTE(.); + + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + + _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg - /* - This section is a place where we dump all the rodata which aren't used at runtime, - so as to avoid binary size increase - */ + /** + * This section contains all the rodata that is not used + * at runtime, helping to avoid an increase in binary size. + */ .flash.rodata_noload (NOLOAD) : { - /* - This is a symbol marking the flash.rodata end, this can be used for mmu driver to maintain virtual address - We don't need to include the noload rodata in this section - */ - _rodata_reserved_end = ABSOLUTE(.); - . = ALIGN (4); + /** + * This symbol marks the end of flash.rodata. It can be utilized by the MMU + * driver to maintain the virtual address. + * NOLOAD rodata may not be included in this section. + */ + _rodata_reserved_end = ADDR(.flash.tbss); + mapping[rodata_noload] } > default_rodata_seg - /* Marks the end of data, bss and possibly rodata */ + /* Marks the end of data, bss and possibly rodata */ .dram0.heap_start (NOLOAD) : { - . = ALIGN (16); - _heap_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _heap_start) } > dram0_0_seg + + /** + * Discarding .rela.* sections results in the following mapping: + * .rela.text.* -> .text.* + * .rela.data.* -> .data.* + * And so forth... + */ + /DISCARD/ : { *(.rela.*) } } ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), diff --git a/components/esp_system/ld/esp32c6/sections.ld.in b/components/esp_system/ld/esp32c6/sections.ld.in index fdc2aa8d66..2af3405154 100644 --- a/components/esp_system/ld/esp32c6/sections.ld.in +++ b/components/esp_system/ld/esp32c6/sections.ld.in @@ -17,19 +17,17 @@ SECTIONS */ .rtc.text : { - . = ALIGN(4); - _rtc_fast_start = ABSOLUTE(.); - _rtc_text_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_fast_start) + ALIGNED_SYMBOL(4, _rtc_text_start) + *(.rtc.entry.text) mapping[rtc_text] - *rtc_wake_stub*.*(.literal .text .literal.* .text.*) + *rtc_wake_stub*.*(.text .text.*) *(.rtc_text_end_test) - . = ALIGN(4); - - _rtc_text_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_text_end) } > lp_ram_seg /** @@ -39,14 +37,13 @@ SECTIONS */ .rtc.force_fast : { - . = ALIGN(4); - _rtc_force_fast_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_fast_start) mapping[rtc_force_fast] *(.rtc.force_fast .rtc.force_fast.*) - . = ALIGN(4) ; - _rtc_force_fast_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_force_fast_end) } > lp_ram_seg /** @@ -62,6 +59,7 @@ SECTIONS mapping[rtc_data] *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) + _rtc_data_end = ABSOLUTE(.); } > lp_ram_seg @@ -69,6 +67,7 @@ SECTIONS .rtc.bss (NOLOAD) : { _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*) *rtc_wake_stub*.*(COMMON) @@ -85,11 +84,11 @@ SECTIONS */ .rtc_noinit (NOLOAD): { - . = ALIGN(4); - _rtc_noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_noinit_start) + *(.rtc_noinit .rtc_noinit.*) - . = ALIGN(4) ; - _rtc_noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_noinit_end) } > lp_ram_seg /** @@ -99,27 +98,32 @@ SECTIONS */ .rtc.force_slow : { - . = ALIGN(4); - _rtc_force_slow_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_slow_start) + *(.rtc.force_slow .rtc.force_slow.*) - . = ALIGN(4) ; - _rtc_force_slow_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_force_slow_end) } > lp_ram_seg /** * This section holds RTC data that should have fixed addresses. - * The data are not initialized at power-up and are retained during deep sleep. + * The data are not initialized at power-up and are retained during deep + * sleep. */ .rtc_reserved (NOLOAD): { - . = ALIGN(4); - _rtc_reserved_start = ABSOLUTE(.); - /* New data can only be added here to ensure existing data are not moved. - Because data have adhered to the end of the segment and code is relied on it. - >> put new data here << */ + ALIGNED_SYMBOL(4, _rtc_reserved_start) + + /** + * New data can only be added here to ensure existing data are not moved. + * Because data have adhered to the end of the segment and code is relied + * on it. + * >> put new data here << + */ *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) + _rtc_reserved_end = ABSOLUTE(.); } > rtc_reserved_seg @@ -149,9 +153,8 @@ SECTIONS ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); KEEP(*(.exception_vectors_table.text)); KEEP(*(.exception_vectors.text)); - . = ALIGN(4); - _invalid_pc_placeholder = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _invalid_pc_placeholder) /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); @@ -163,15 +166,12 @@ SECTIONS /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : { - . = ALIGN(4); - - _iram_text_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _iram_text_end) } > sram_seg .iram0.data : { - . = ALIGN(16); - _iram_data_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_data_start) mapping[iram0_data] @@ -180,14 +180,13 @@ SECTIONS .iram0.bss (NOLOAD) : { - . = ALIGN(16); - _iram_bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_bss_start) mapping[iram0_bss] _iram_bss_end = ABSOLUTE(.); - . = ALIGN(16); - _iram_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(16, _iram_end) } > sram_seg .dram0.data : @@ -205,7 +204,6 @@ SECTIONS mapping[dram0_data] _data_end = ABSOLUTE(.); - . = ALIGN(4); } > sram_seg /** @@ -216,49 +214,58 @@ SECTIONS */ .noinit (NOLOAD): { - . = ALIGN(4); - _noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _noinit_start) + *(.noinit .noinit.*) - . = ALIGN(4) ; - _noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _noinit_end) } > sram_seg /* Shared RAM */ .dram0.bss (NOLOAD) : { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_start) - /* ldgen places all bss-related data to mapping[dram0_bss] (See esp_system/app.lf). */ + /** + * ldgen places all bss-related data to mapping[dram0_bss] + * (See components/esp_system/app.lf). + */ mapping[dram0_bss] - . = ALIGN (8); - _bss_end = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_end) } > sram_seg .flash.text : { _stext = .; - _instruction_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.text start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the start of flash.text. + * This can be used by the MMU driver to maintain the virtual address. + */ + _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); mapping[flash_text] - *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.stub) + *(.gnu.linkonce.t.*) + *(.gnu.warning) *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.fini.literal) - *(.fini) - *(.gnu.version) - /** CPU will try to prefetch up to 16 bytes of - * of instructions. This means that any configuration (e.g. MMU, PMS) must allow - * safe access to up to 16 bytes after the last real instruction, add - * dummy bytes to ensure this - */ + /** + * CPU will try to prefetch up to 16 bytes of of instructions. + * This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add + * dummy bytes to ensure this + */ . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); - _instruction_reserved_end = ABSOLUTE(.); /* This is a symbol marking the flash.text end, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the flash.text end. + * This can be used for MMU driver to maintain virtual address. + */ + _instruction_reserved_end = ABSOLUTE(.); _etext = .; /** @@ -270,32 +277,40 @@ SECTIONS } > default_code_seg /** - * This dummy section represents the .flash.text section but in default_rodata_seg. + * Dummy section represents the .flash.text section but in default_rodata_seg. * Thus, it must have its alignment and (at least) its size. */ .flash_rodata_dummy (NOLOAD): { _flash_rodata_dummy_start = .; - /* Start at the same alignment constraint than .flash.text */ - . = ALIGN(ALIGNOF(.flash.text)); - /* Create an empty gap as big as .flash.text section */ - . = . + SIZEOF(.flash.text); - /* Prepare the alignment of the section above. Few bytes (0x20) must be - * added for the mapping header. */ - . = ALIGN(_esp_mmu_block_size) + 0x20; + + . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); + + /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ + . = ALIGN(_esp_mmu_page_size) + 0x20; } > default_rodata_seg .flash.appdesc : ALIGN(0x10) { - _rodata_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.rodata start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark flash.rodata start. + * This can be used for mmu driver to maintain virtual address + */ + _rodata_reserved_start = ABSOLUTE(.); _rodata_start = ABSOLUTE(.); - *(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */ - *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */ + /* !DO NOT PUT ANYTHING BEFORE THIS! */ - /* Create an empty gap within this section. Thanks to this, the end of this + /* Should be the first. App version info. */ + *(.rodata_desc .rodata_desc.*) + /* Should be the second. Custom app version info. */ + *(.rodata_custom_desc .rodata_custom_desc.*) + + /** + * Create an empty gap within this section. Thanks to this, the end of this * section will match .flash.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. */ + * will be merged when creating the final bin image. + */ . = ALIGN(ALIGNOF(.flash.rodata)); } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) @@ -309,111 +324,119 @@ SECTIONS *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) - __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); - *(.xt_except_table) *(.gcc_except_table .gcc_except_table.*) *(.gnu.linkonce.e.*) - *(.gnu.version_r) - . = (. + 7) & ~ 3; - /* - * C++ constructor and destructor tables - * Don't include anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt. + /** + * C++ constructor tables. * - * RISC-V gcc is configured with --enable-initfini-array so it emits an .init_array section instead. - * But the init_priority sections will be sorted for iteration in ascending order during startup. - * The rest of the init_array sections is sorted for iteration in descending order during startup, however. - * Hence a different section is generated for the init_priority functions which is iterated in - * ascending order during startup. The corresponding code can be found in startup.c. + * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. + * + * RISC-V gcc is configured with --enable-initfini-array so it emits + * .init_array section instead. But the init_priority sections will be + * sorted for iteration in ascending order during startup. + * The rest of the init_array sections is sorted for iteration in descending + * order during startup, however. Hence a different section is generated for + * the init_priority functions which is iterated in ascending order during + * startup. The corresponding code can be found in startup.c. */ - __init_priority_array_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __init_priority_array_start) KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) __init_priority_array_end = ABSOLUTE(.); - __init_array_start = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, __init_array_start) KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) __init_array_end = ABSOLUTE(.); - KEEP (*crtbegin.*(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - /* C++ exception handlers table: */ - __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); - *(.xt_except_desc) - *(.gnu.linkonce.h.*) - __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); - *(.xt_except_desc_end) - *(.dynamic) - *(.gnu.version_d) + /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - soc_reserved_memory_region_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) KEEP (*(.reserved_memory_address)) soc_reserved_memory_region_end = ABSOLUTE(.); + /* System init functions registered via ESP_SYSTEM_INIT_FN */ - _esp_system_init_fn_array_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) _esp_system_init_fn_array_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); - /* Literals are also RO data. */ - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(.flash.tls)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.rodata, .flash.tls) - - .flash.tls : ALIGN(8) - { - _thread_local_start = ABSOLUTE(.); - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) - _thread_local_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(.eh_frame)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.tls, .eh_frame) - - /* 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 - ASSERT_SECTIONS_GAP(.eh_frame, .eh_frame_hdr) + ASSERT_SECTIONS_GAP(.flash.rodata, .eh_frame_hdr) - /* 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 : { - __eh_frame_hdr = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __eh_frame_hdr) + KEEP (*(.eh_frame_hdr)) + __eh_frame_hdr_end = ABSOLUTE(.); + . = ALIGN(ALIGNOF(.eh_frame)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) + + .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 + ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) + + .flash.tdata : + { + _thread_local_data_start = ABSOLUTE(.); + + *(.tdata .tdata.* .gnu.linkonce.td.*) + + . = ALIGN(ALIGNOF(.flash.tbss)); + _thread_local_data_end = ABSOLUTE(.); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + + .flash.tbss (NOLOAD) : + { + _thread_local_bss_start = ABSOLUTE(.); + + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + + _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg - /* - This section is a place where we dump all the rodata which aren't used at runtime, - so as to avoid binary size increase - */ + /** + * This section contains all the rodata that is not used + * at runtime, helping to avoid an increase in binary size. + */ .flash.rodata_noload (NOLOAD) : { - /* - This is a symbol marking the flash.rodata end, this can be used for mmu driver to maintain virtual address - We don't need to include the noload rodata in this section - */ - _rodata_reserved_end = ABSOLUTE(.); - . = ALIGN (4); + /** + * This symbol marks the end of flash.rodata. It can be utilized by the MMU + * driver to maintain the virtual address. + * NOLOAD rodata may not be included in this section. + */ + _rodata_reserved_end = ADDR(.flash.tbss); + mapping[rodata_noload] } > default_rodata_seg - /* Marks the end of data, bss and possibly rodata */ + /* Marks the end of data, bss and possibly rodata */ .dram0.heap_start (NOLOAD) : { - . = ALIGN (16); - _heap_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _heap_start) } > sram_seg + + /** + * Discarding .rela.* sections results in the following mapping: + * .rela.text.* -> .text.* + * .rela.data.* -> .data.* + * And so forth... + */ + /DISCARD/ : { *(.rela.*) } } diff --git a/components/esp_system/ld/esp32h2/sections.ld.in b/components/esp_system/ld/esp32h2/sections.ld.in index f69d925ddd..2af3405154 100644 --- a/components/esp_system/ld/esp32h2/sections.ld.in +++ b/components/esp_system/ld/esp32h2/sections.ld.in @@ -17,19 +17,17 @@ SECTIONS */ .rtc.text : { - . = ALIGN(4); - _rtc_fast_start = ABSOLUTE(.); - _rtc_text_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_fast_start) + ALIGNED_SYMBOL(4, _rtc_text_start) + *(.rtc.entry.text) mapping[rtc_text] - *rtc_wake_stub*.*(.literal .text .literal.* .text.*) + *rtc_wake_stub*.*(.text .text.*) *(.rtc_text_end_test) - . = ALIGN(4); - - _rtc_text_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_text_end) } > lp_ram_seg /** @@ -39,14 +37,13 @@ SECTIONS */ .rtc.force_fast : { - . = ALIGN(4); - _rtc_force_fast_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_fast_start) mapping[rtc_force_fast] *(.rtc.force_fast .rtc.force_fast.*) - . = ALIGN(4) ; - _rtc_force_fast_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_force_fast_end) } > lp_ram_seg /** @@ -62,6 +59,7 @@ SECTIONS mapping[rtc_data] *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) + _rtc_data_end = ABSOLUTE(.); } > lp_ram_seg @@ -69,6 +67,7 @@ SECTIONS .rtc.bss (NOLOAD) : { _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*) *rtc_wake_stub*.*(COMMON) @@ -85,11 +84,11 @@ SECTIONS */ .rtc_noinit (NOLOAD): { - . = ALIGN(4); - _rtc_noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_noinit_start) + *(.rtc_noinit .rtc_noinit.*) - . = ALIGN(4) ; - _rtc_noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_noinit_end) } > lp_ram_seg /** @@ -99,27 +98,32 @@ SECTIONS */ .rtc.force_slow : { - . = ALIGN(4); - _rtc_force_slow_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_slow_start) + *(.rtc.force_slow .rtc.force_slow.*) - . = ALIGN(4) ; - _rtc_force_slow_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_force_slow_end) } > lp_ram_seg /** * This section holds RTC data that should have fixed addresses. - * The data are not initialized at power-up and are retained during deep sleep. + * The data are not initialized at power-up and are retained during deep + * sleep. */ .rtc_reserved (NOLOAD): { - . = ALIGN(4); - _rtc_reserved_start = ABSOLUTE(.); - /* New data can only be added here to ensure existing data are not moved. - Because data have adhered to the end of the segment and code is relied on it. - >> put new data here << */ + ALIGNED_SYMBOL(4, _rtc_reserved_start) + + /** + * New data can only be added here to ensure existing data are not moved. + * Because data have adhered to the end of the segment and code is relied + * on it. + * >> put new data here << + */ *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) + _rtc_reserved_end = ABSOLUTE(.); } > rtc_reserved_seg @@ -149,9 +153,8 @@ SECTIONS ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); KEEP(*(.exception_vectors_table.text)); KEEP(*(.exception_vectors.text)); - . = ALIGN(4); - _invalid_pc_placeholder = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _invalid_pc_placeholder) /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); @@ -163,15 +166,12 @@ SECTIONS /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : { - . = ALIGN(4); - - _iram_text_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _iram_text_end) } > sram_seg .iram0.data : { - . = ALIGN(16); - _iram_data_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_data_start) mapping[iram0_data] @@ -180,14 +180,13 @@ SECTIONS .iram0.bss (NOLOAD) : { - . = ALIGN(16); - _iram_bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_bss_start) mapping[iram0_bss] _iram_bss_end = ABSOLUTE(.); - . = ALIGN(16); - _iram_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(16, _iram_end) } > sram_seg .dram0.data : @@ -205,7 +204,6 @@ SECTIONS mapping[dram0_data] _data_end = ABSOLUTE(.); - . = ALIGN(4); } > sram_seg /** @@ -216,48 +214,57 @@ SECTIONS */ .noinit (NOLOAD): { - . = ALIGN(4); - _noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _noinit_start) + *(.noinit .noinit.*) - . = ALIGN(4) ; - _noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _noinit_end) } > sram_seg /* Shared RAM */ .dram0.bss (NOLOAD) : { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_start) - /* ldgen places all bss-related data to mapping[dram0_bss] (See esp_system/app.lf). */ + /** + * ldgen places all bss-related data to mapping[dram0_bss] + * (See components/esp_system/app.lf). + */ mapping[dram0_bss] - . = ALIGN (8); - _bss_end = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_end) } > sram_seg .flash.text : { _stext = .; + /** + * Mark the start of flash.text. + * This can be used by the MMU driver to maintain the virtual address. + */ _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); mapping[flash_text] - *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.stub) + *(.gnu.linkonce.t.*) + *(.gnu.warning) *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.fini.literal) - *(.fini) - *(.gnu.version) - /** CPU will try to prefetch up to 16 bytes of - * of instructions. This means that any configuration (e.g. MMU, PMS) must allow - * safe access to up to 16 bytes after the last real instruction, add - * dummy bytes to ensure this - */ + /** + * CPU will try to prefetch up to 16 bytes of of instructions. + * This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add + * dummy bytes to ensure this + */ . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); + /** + * Mark the flash.text end. + * This can be used for MMU driver to maintain virtual address. + */ _instruction_reserved_end = ABSOLUTE(.); _etext = .; @@ -270,32 +277,40 @@ SECTIONS } > default_code_seg /** - * This dummy section represents the .flash.text section but in default_rodata_seg. + * Dummy section represents the .flash.text section but in default_rodata_seg. * Thus, it must have its alignment and (at least) its size. */ .flash_rodata_dummy (NOLOAD): { _flash_rodata_dummy_start = .; - /* Start at the same alignment constraint than .flash.text */ - . = ALIGN(ALIGNOF(.flash.text)); - /* Create an empty gap as big as .flash.text section */ - . = . + SIZEOF(.flash.text); - /* Prepare the alignment of the section above. Few bytes (0x20) must be - * added for the mapping header. */ - . = ALIGN(_esp_mmu_block_size) + 0x20; - _rodata_reserved_start = .; + + . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); + + /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ + . = ALIGN(_esp_mmu_page_size) + 0x20; } > default_rodata_seg .flash.appdesc : ALIGN(0x10) { + /** + * Mark flash.rodata start. + * This can be used for mmu driver to maintain virtual address + */ + _rodata_reserved_start = ABSOLUTE(.); _rodata_start = ABSOLUTE(.); - *(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */ - *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */ + /* !DO NOT PUT ANYTHING BEFORE THIS! */ - /* Create an empty gap within this section. Thanks to this, the end of this + /* Should be the first. App version info. */ + *(.rodata_desc .rodata_desc.*) + /* Should be the second. Custom app version info. */ + *(.rodata_custom_desc .rodata_custom_desc.*) + + /** + * Create an empty gap within this section. Thanks to this, the end of this * section will match .flash.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. */ + * will be merged when creating the final bin image. + */ . = ALIGN(ALIGNOF(.flash.rodata)); } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) @@ -309,102 +324,119 @@ SECTIONS *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) - __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); - *(.xt_except_table) *(.gcc_except_table .gcc_except_table.*) *(.gnu.linkonce.e.*) - *(.gnu.version_r) - . = (. + 7) & ~ 3; - /* - * C++ constructor and destructor tables - * Don't include anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt. + /** + * C++ constructor tables. * - * RISC-V gcc is configured with --enable-initfini-array so it emits an .init_array section instead. - * But the init_priority sections will be sorted for iteration in ascending order during startup. - * The rest of the init_array sections is sorted for iteration in descending order during startup, however. - * Hence a different section is generated for the init_priority functions which is iterated in - * ascending order during startup. The corresponding code can be found in startup.c. + * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. + * + * RISC-V gcc is configured with --enable-initfini-array so it emits + * .init_array section instead. But the init_priority sections will be + * sorted for iteration in ascending order during startup. + * The rest of the init_array sections is sorted for iteration in descending + * order during startup, however. Hence a different section is generated for + * the init_priority functions which is iterated in ascending order during + * startup. The corresponding code can be found in startup.c. */ - __init_priority_array_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __init_priority_array_start) KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) __init_priority_array_end = ABSOLUTE(.); - __init_array_start = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, __init_array_start) KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) __init_array_end = ABSOLUTE(.); - KEEP (*crtbegin.*(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - /* C++ exception handlers table: */ - __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); - *(.xt_except_desc) - *(.gnu.linkonce.h.*) - __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); - *(.xt_except_desc_end) - *(.dynamic) - *(.gnu.version_d) + /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - soc_reserved_memory_region_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) KEEP (*(.reserved_memory_address)) soc_reserved_memory_region_end = ABSOLUTE(.); - _esp_system_init_fn_array_start = ABSOLUTE(.); - KEEP (*(SORT(.esp_system_init_fn) SORT(.esp_system_init_fn.*))) + + /* System init functions registered via ESP_SYSTEM_INIT_FN */ + ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) + KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) _esp_system_init_fn_array_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); - /* Literals are also RO data. */ - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(.flash.tls)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.rodata, .flash.tls) - - .flash.tls : ALIGN(8) - { - _thread_local_start = ABSOLUTE(.); - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) - _thread_local_end = ABSOLUTE(.); - _rodata_reserved_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(.eh_frame)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.tls, .eh_frame) - - /* 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 - ASSERT_SECTIONS_GAP(.eh_frame, .eh_frame_hdr) + ASSERT_SECTIONS_GAP(.flash.rodata, .eh_frame_hdr) - /* 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 : { - __eh_frame_hdr = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __eh_frame_hdr) + KEEP (*(.eh_frame_hdr)) + __eh_frame_hdr_end = ABSOLUTE(.); + . = ALIGN(ALIGNOF(.eh_frame)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) + + .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 + ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) + + .flash.tdata : + { + _thread_local_data_start = ABSOLUTE(.); + + *(.tdata .tdata.* .gnu.linkonce.td.*) + + . = ALIGN(ALIGNOF(.flash.tbss)); + _thread_local_data_end = ABSOLUTE(.); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + + .flash.tbss (NOLOAD) : + { + _thread_local_bss_start = ABSOLUTE(.); + + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + + _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg + /** + * This section contains all the rodata that is not used + * at runtime, helping to avoid an increase in binary size. + */ .flash.rodata_noload (NOLOAD) : { - . = ALIGN (4); + /** + * This symbol marks the end of flash.rodata. It can be utilized by the MMU + * driver to maintain the virtual address. + * NOLOAD rodata may not be included in this section. + */ + _rodata_reserved_end = ADDR(.flash.tbss); + mapping[rodata_noload] } > default_rodata_seg - /* Marks the end of data, bss and possibly rodata */ + /* Marks the end of data, bss and possibly rodata */ .dram0.heap_start (NOLOAD) : { - . = ALIGN (16); - _heap_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _heap_start) } > sram_seg + + /** + * Discarding .rela.* sections results in the following mapping: + * .rela.text.* -> .text.* + * .rela.data.* -> .data.* + * And so forth... + */ + /DISCARD/ : { *(.rela.*) } } diff --git a/components/esp_system/ld/esp32p4/sections.ld.in b/components/esp_system/ld/esp32p4/sections.ld.in index 873cdf87fe..318b068875 100644 --- a/components/esp_system/ld/esp32p4/sections.ld.in +++ b/components/esp_system/ld/esp32p4/sections.ld.in @@ -18,18 +18,15 @@ SECTIONS */ .rtc.text : { - . = ALIGN(4); - _rtc_fast_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_fast_start) arrays[rtc_text] mapping[rtc_text] - *rtc_wake_stub*.*(.literal .text .literal.* .text.*) + *rtc_wake_stub*.*(.text .text.*) *(.rtc_text_end_test) - . = ALIGN(4); - - _rtc_text_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_text_end) } > lp_ram_seg /** @@ -39,16 +36,14 @@ SECTIONS */ .rtc.force_fast : { - . = ALIGN(4); - _rtc_force_fast_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_fast_start) arrays[rtc_force_fast] mapping[rtc_force_fast] *(.rtc.force_fast .rtc.force_fast.*) - . = ALIGN(4) ; - _rtc_force_fast_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_fast_end) } > lp_ram_seg /** @@ -65,6 +60,7 @@ SECTIONS mapping[rtc_data] *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) + _rtc_data_end = ABSOLUTE(.); } > lp_ram_seg @@ -72,6 +68,7 @@ SECTIONS .rtc.bss (NOLOAD) : { _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*) *rtc_wake_stub*.*(COMMON) @@ -89,11 +86,11 @@ SECTIONS */ .rtc_noinit (NOLOAD): { - . = ALIGN(4); - _rtc_noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_noinit_start) + *(.rtc_noinit .rtc_noinit.*) - . = ALIGN(4) ; - _rtc_noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_noinit_end) } > lp_ram_seg /** @@ -103,27 +100,32 @@ SECTIONS */ .rtc.force_slow : { - . = ALIGN(4); - _rtc_force_slow_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_slow_start) + *(.rtc.force_slow .rtc.force_slow.*) - . = ALIGN(4) ; - _rtc_force_slow_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_force_slow_end) } > lp_ram_seg /** * This section holds RTC data that should have fixed addresses. - * The data are not initialized at power-up and are retained during deep sleep. + * The data are not initialized at power-up and are retained during deep + * sleep. */ .rtc_reserved (NOLOAD): { - . = ALIGN(4); - _rtc_reserved_start = ABSOLUTE(.); - /* New data can only be added here to ensure existing data are not moved. - Because data have adhered to the end of the segment and code is relied on it. - >> put new data here << */ + ALIGNED_SYMBOL(4, _rtc_reserved_start) + + /** + * New data can only be added here to ensure existing data are not moved. + * Because data have adhered to the end of the segment and code is relied + * on it. + * >> put new data here << + */ *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) + _rtc_reserved_end = ABSOLUTE(.); } > rtc_reserved_seg @@ -155,7 +157,6 @@ SECTIONS mapping[tcm_text] _tcm_text_end = ABSOLUTE(.); - } > tcm_idram_seg .tcm.data : @@ -166,9 +167,6 @@ SECTIONS mapping[tcm_data] _tcm_data_end = ABSOLUTE(.); - - . = ALIGN(4); - } > tcm_idram_seg .iram0.text : @@ -178,9 +176,8 @@ SECTIONS ASSERT(ABSOLUTE(.) % 0x40 == 0, "vector address must be 64 byte aligned"); KEEP(*(.exception_vectors_table.text)); KEEP(*(.exception_vectors.text)); - . = ALIGN(4); - _invalid_pc_placeholder = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _invalid_pc_placeholder) /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); @@ -193,15 +190,12 @@ SECTIONS /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : { - . = ALIGN(4); - - _iram_text_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _iram_text_end) } > sram_low .iram0.data : { - . = ALIGN(16); - _iram_data_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_data_start) arrays[iram0_data] mapping[iram0_data] @@ -211,15 +205,14 @@ SECTIONS .iram0.bss (NOLOAD) : { - . = ALIGN(16); - _iram_bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _iram_bss_start) arrays[iram0_bss] mapping[iram0_bss] _iram_bss_end = ABSOLUTE(.); - . = ALIGN(16); - _iram_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(16, _iram_end) } > sram_low .dram0.data : @@ -238,7 +231,6 @@ SECTIONS mapping[dram0_data] _data_end = ABSOLUTE(.); - . = ALIGN(4); } > sram_low /** @@ -249,37 +241,45 @@ SECTIONS */ .noinit (NOLOAD): { - . = ALIGN(4); - _noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _noinit_start) + *(.noinit .noinit.*) - . = ALIGN(4) ; - _noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _noinit_end) } > sram_low .flash.text : { _stext = .; - _instruction_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.text start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the start of flash.text. + * This can be used by the MMU driver to maintain the virtual address. + */ + _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); arrays[flash_text] mapping[flash_text] - *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.stub) + *(.gnu.linkonce.t.*) + *(.gnu.warning) *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.fini.literal) - *(.fini) - *(.gnu.version) - /** CPU will try to prefetch up to 16 bytes of - * of instructions. This means that any configuration (e.g. MMU, PMS) must allow - * safe access to up to 16 bytes after the last real instruction, add - * dummy bytes to ensure this - */ + /** + * CPU will try to prefetch up to 16 bytes of of instructions. + * This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add + * dummy bytes to ensure this + */ . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); - _instruction_reserved_end = ABSOLUTE(.); /* This is a symbol marking the flash.text end, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the flash.text end. + * This can be used for MMU driver to maintain virtual address. + */ + _instruction_reserved_end = ABSOLUTE(.); _etext = .; /** @@ -291,32 +291,40 @@ SECTIONS } > text_seg_low /** - * This dummy section represents the .flash.text section but in default_rodata_seg. + * Dummy section represents the .flash.text section but in default_rodata_seg. * Thus, it must have its alignment and (at least) its size. */ .flash_rodata_dummy (NOLOAD): { _flash_rodata_dummy_start = .; - /* Start at the same alignment constraint than .flash.text */ - . = ALIGN(ALIGNOF(.flash.text)); - /* Create an empty gap as big as .flash.text section */ - . = . + SIZEOF(.flash.text); - /* Prepare the alignment of the section above. Few bytes (0x20) must be - * added for the mapping header. */ - . = ALIGN(_esp_mmu_block_size) + 0x20; + + . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); + + /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ + . = ALIGN(_esp_mmu_page_size) + 0x20; } > rodata_seg_low .flash.appdesc : ALIGN(0x10) { - _rodata_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.rodata start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark flash.rodata start. + * This can be used for mmu driver to maintain virtual address + */ + _rodata_reserved_start = ABSOLUTE(.); _rodata_start = ABSOLUTE(.); - *(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */ - *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */ + /* !DO NOT PUT ANYTHING BEFORE THIS! */ - /* Create an empty gap within this section. Thanks to this, the end of this + /* Should be the first. App version info. */ + *(.rodata_desc .rodata_desc.*) + /* Should be the second. Custom app version info. */ + *(.rodata_custom_desc .rodata_custom_desc.*) + + /** + * Create an empty gap within this section. Thanks to this, the end of this * section will match .flash.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. */ + * will be merged when creating the final bin image. + */ . = ALIGN(ALIGNOF(.flash.rodata)); } > rodata_seg_low ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) @@ -331,149 +339,159 @@ SECTIONS *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) - __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); - *(.xt_except_table) *(.gcc_except_table .gcc_except_table.*) *(.gnu.linkonce.e.*) - *(.gnu.version_r) + . = ALIGN(ALIGNOF(.flash.init_array)); } > rodata_seg_low + ASSERT_SECTIONS_GAP(.flash.rodata, .flash.init_array) .flash.init_array : { - . = (. + 7) & ~ 3; - /* - * C++ constructor and destructor tables - * Don't include anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt. + /** + * C++ constructor tables. * - * RISC-V gcc is configured with --enable-initfini-array so it emits an .init_array section instead. - * But the init_priority sections will be sorted for iteration in ascending order during startup. - * The rest of the init_array sections is sorted for iteration in descending order during startup, however. - * Hence a different section is generated for the init_priority functions which is iterated in - * ascending order during startup. The corresponding code can be found in startup.c. + * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. + * + * RISC-V gcc is configured with --enable-initfini-array so it emits + * .init_array section instead. But the init_priority sections will be + * sorted for iteration in ascending order during startup. + * The rest of the init_array sections is sorted for iteration in descending + * order during startup, however. Hence a different section is generated for + * the init_priority functions which is iterated in ascending order during + * startup. The corresponding code can be found in startup.c. */ - __init_priority_array_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __init_priority_array_start) KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) __init_priority_array_end = ABSOLUTE(.); - __init_array_start = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, __init_array_start) KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) __init_array_end = ABSOLUTE(.); - KEEP (*crtbegin.*(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - /* C++ exception handlers table: */ - __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); - *(.xt_except_desc) - *(.gnu.linkonce.h.*) - __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); - *(.xt_except_desc_end) - *(.dynamic) - *(.gnu.version_d) + /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - soc_reserved_memory_region_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) KEEP (*(.reserved_memory_address)) soc_reserved_memory_region_end = ABSOLUTE(.); + /* System init functions registered via ESP_SYSTEM_INIT_FN */ - _esp_system_init_fn_array_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) _esp_system_init_fn_array_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); - /* Literals are also RO data. */ - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(.flash.tls)); - } > rodata_seg_low - ASSERT_SECTIONS_GAP(.flash.init_array, .flash.tls) - - .flash.tls : ALIGN(8) - { - _thread_local_start = ABSOLUTE(.); - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) - _thread_local_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(.eh_frame)); - } > rodata_seg_low - ASSERT_SECTIONS_GAP(.flash.tls, .eh_frame) - - /* 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)); } > rodata_seg_low - ASSERT_SECTIONS_GAP(.eh_frame, .eh_frame_hdr) + ASSERT_SECTIONS_GAP(.flash.init_array, .eh_frame_hdr) - /* 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 : { - __eh_frame_hdr = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __eh_frame_hdr) + KEEP (*(.eh_frame_hdr)) + __eh_frame_hdr_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(.flash.rodata)); + . = ALIGN(ALIGNOF(.eh_frame)); + } > rodata_seg_low + ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) + + .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)); + } > rodata_seg_low + ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) + + .flash.tdata : + { + _thread_local_data_start = ABSOLUTE(.); + + *(.tdata .tdata.* .gnu.linkonce.td.*) + + . = ALIGN(ALIGNOF(.flash.tbss)); + _thread_local_data_end = ABSOLUTE(.); + } > rodata_seg_low + ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + + .flash.tbss (NOLOAD) : + { + _thread_local_bss_start = ABSOLUTE(.); + + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + + _thread_local_bss_end = ABSOLUTE(.); } > rodata_seg_low - /* - This section is a place where we dump all the rodata which aren't used at runtime, - so as to avoid binary size increase - */ + /** + * This section contains all the rodata that is not used + * at runtime, helping to avoid an increase in binary size. + */ .flash.rodata_noload (NOLOAD) : { - /* - This is a symbol marking the flash.rodata end, this can be used for mmu driver to maintain virtual address - We don't need to include the noload rodata in this section - */ - _rodata_reserved_end = ABSOLUTE(.); - . = ALIGN (4); + /** + * This symbol marks the end of flash.rodata. It can be utilized by the MMU + * driver to maintain the virtual address. + * NOLOAD rodata may not be included in this section. + */ + _rodata_reserved_end = ADDR(.flash.tbss); + arrays[rodata_noload] mapping[rodata_noload] } > rodata_seg_low .dram0.bss (NOLOAD) : { - . = ALIGN(4); - _bss_start_low = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _bss_start_low) - /* ldgen places all bss-related data to mapping[dram0_bss] (See esp_system/app.lf). */ + /** + * ldgen places all bss-related data to mapping[dram0_bss] + * (See components/esp_system/app.lf). + */ arrays[dram0_bss] mapping[dram0_bss] - . = ALIGN(4); - _bss_end_low = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _bss_end_low) } > sram_low .dram1.bss (NOLOAD) : { - . = ALIGN(4); - _bss_start_high = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _bss_start_high) - /* ldgen places all bss-related data to mapping[dram0_bss] (See esp_system/app.lf). */ + /** + * ldgen places all bss-related data to mapping[dram0_bss] + * (See components/esp_system/app.lf). + */ mapping[dram0_bss] - . = ALIGN(4); - _bss_end_high = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _bss_end_high) } > sram_high - /* Marks the end of data, bss and possibly rodata */ + /* Marks the end of data, bss and possibly rodata */ .dram0.heap_start_low (NOLOAD) : { - . = ALIGN (16); - _heap_start_low = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _heap_start_low) } > sram_low - /* Marks the end of data, bss and possibly rodata */ + /* Marks the end of data, bss and possibly rodata */ .dram1.heap_start_high (NOLOAD) : { - . = ALIGN (16); - _heap_start_high = ABSOLUTE(.); + ALIGNED_SYMBOL(16, _heap_start_high) } > sram_high + + /** + * Discarding .rela.* sections results in the following mapping: + * .rela.text.* -> .text.* + * .rela.data.* -> .data.* + * And so forth... + */ + /DISCARD/ : { *(.rela.*) } } diff --git a/components/esp_system/ld/esp32s2/sections.ld.in b/components/esp_system/ld/esp32s2/sections.ld.in index 119f29eb46..f177a766fe 100644 --- a/components/esp_system/ld/esp32s2/sections.ld.in +++ b/components/esp_system/ld/esp32s2/sections.ld.in @@ -6,67 +6,75 @@ #include "ld.common" -/* Default entry point: */ +/** + * Added to maintain compatibility: there is no iram0 data section to place + * _coredump_iram_XXX symbols that are defined in espcoredump's linker.lf + */ +_coredump_iram_start = 0; +_coredump_iram_end = 0; + +/* Default entry point */ ENTRY(call_start_cpu0); SECTIONS { - /* RTC fast memory holds RTC wake stub code, - including from any source file named rtc_wake_stub*.c - */ + /** + * RTC fast memory holds RTC wake stub code, + * including from any source file named rtc_wake_stub*.c + */ .rtc.text : { - _rtc_text_start = ABSOLUTE(.); - . = ALIGN(4); - - _rtc_code_start = .; + ALIGNED_SYMBOL(4, _rtc_text_start) mapping[rtc_text] *rtc_wake_stub*.*(.literal .text .literal.* .text.*) - _rtc_code_end = .; - /* possibly align + add 16B for CPU dummy speculative instr. fetch */ - . = ((_rtc_code_end - _rtc_code_start) == 0) ? ALIGN(0) : ALIGN(4) + 16; + /* Padding for possible CPU prefetch + alignment for PMS split lines */ + . += _esp_memprot_prefetch_pad_size; + . = ALIGN(_esp_memprot_align_size); _rtc_text_end = ABSOLUTE(.); } > rtc_iram_seg - /* - This section is required to skip rtc.text area because rtc_iram_seg and - rtc_data_seg are reflect the same address space on different buses. - */ + /** + * This section is required to skip rtc.text area because rtc_iram_seg and + * rtc_data_seg are reflect the same address space on different buses. + */ .rtc.dummy : { _rtc_dummy_start = ABSOLUTE(.); _rtc_fast_start = ABSOLUTE(.); + . = SIZEOF(.rtc.text); + _rtc_dummy_end = ABSOLUTE(.); } > rtc_data_seg - /* This section located in RTC FAST Memory area. - It holds data marked with RTC_FAST_ATTR attribute. - See the file "esp_attr.h" for more information. - */ + /** + * This section located in RTC FAST Memory area. + * It holds data marked with RTC_FAST_ATTR attribute. + * See the file "esp_attr.h" for more information. + */ .rtc.force_fast : { - . = ALIGN(4); - _rtc_force_fast_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_fast_start) mapping[rtc_force_fast] *(.rtc.force_fast .rtc.force_fast.*) - . = ALIGN(4) ; - _rtc_force_fast_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_force_fast_end) } > rtc_data_seg - /* RTC data section holds RTC wake stub - data/rodata, including from any source file - named rtc_wake_stub*.c and the data marked with - RTC_DATA_ATTR, RTC_RODATA_ATTR attributes. - The memory location of the data is dependent on - CONFIG_ESP32S2_RTCDATA_IN_FAST_MEM option. - */ + /** + * RTC data section holds RTC wake stub + * data/rodata, including from any source file + * named rtc_wake_stub*.c and the data marked with + * RTC_DATA_ATTR, RTC_RODATA_ATTR attributes. + * The memory location of the data is dependent on + * CONFIG_ESP32S2_RTCDATA_IN_FAST_MEM option. + */ .rtc.data : { _rtc_data_start = ABSOLUTE(.); @@ -74,6 +82,7 @@ SECTIONS mapping[rtc_data] *rtc_wake_stub*.*(.data .rodata .data.* .rodata.*) + _rtc_data_end = ABSOLUTE(.); } > rtc_data_location @@ -81,6 +90,7 @@ SECTIONS .rtc.bss (NOLOAD) : { _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.*(.bss .bss.*) *rtc_wake_stub*.*(COMMON) @@ -89,49 +99,56 @@ SECTIONS _rtc_bss_end = ABSOLUTE(.); } > rtc_data_location - /* This section holds data that should not be initialized at power up - and will be retained during deep sleep. - User data marked with RTC_NOINIT_ATTR will be placed - into this section. See the file "esp_attr.h" for more information. - The memory location of the data is dependent on - CONFIG_ESP32S2_RTCDATA_IN_FAST_MEM option. - */ + /** + * This section holds data that should not be initialized at power up + * and will be retained during deep sleep. + * User data marked with RTC_NOINIT_ATTR will be placed + * into this section. See the file "esp_attr.h" for more information. + * The memory location of the data is dependent on + * CONFIG_ESP32S2_RTCDATA_IN_FAST_MEM option. + */ .rtc_noinit (NOLOAD): { - . = ALIGN(4); - _rtc_noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_noinit_start) + *(.rtc_noinit .rtc_noinit.*) - . = ALIGN(4) ; - _rtc_noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_noinit_end) } > rtc_data_location - /* This section located in RTC SLOW Memory area. - It holds data marked with RTC_SLOW_ATTR attribute. - See the file "esp_attr.h" for more information. - */ + /** + * This section located in RTC SLOW Memory area. + * It holds data marked with RTC_SLOW_ATTR attribute. + * See the file "esp_attr.h" for more information. + */ .rtc.force_slow : { - . = ALIGN(4); - _rtc_force_slow_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_slow_start) + *(.rtc.force_slow .rtc.force_slow.*) - . = ALIGN(4) ; - _rtc_force_slow_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_force_slow_end) } > rtc_slow_seg /** * This section holds RTC data that should have fixed addresses. - * The data are not initialized at power-up and are retained during deep sleep. + * The data are not initialized at power-up and are retained during deep + * sleep. */ .rtc_reserved (NOLOAD): { - . = ALIGN(4); - _rtc_reserved_start = ABSOLUTE(.); - /* New data can only be added here to ensure existing data are not moved. - Because data have adhered to the end of the segment and code is relied on it. - >> put new data here << */ + ALIGNED_SYMBOL(4, _rtc_reserved_start) + + /** + * New data can only be added here to ensure existing data are not moved. + * Because data have adhered to the end of the segment and code is relied + * on it. + * >> put new data here << + */ *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) + _rtc_reserved_end = ABSOLUTE(.); } > rtc_reserved_seg @@ -160,7 +177,6 @@ SECTIONS _iram_start = ABSOLUTE(.); /* Vectors go to IRAM */ _vector_table = ABSOLUTE(.); - /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */ . = 0x0; KEEP(*(.WindowVectors.text)); . = 0x180; @@ -191,25 +207,24 @@ SECTIONS *(.entry.text) *(.init.literal) *(.init) + _init_end = ABSOLUTE(.); } > iram0_0_seg .iram0.text : { - /* Code marked as runnning out of IRAM */ + /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); mapping[iram0_text] - /* Added to maintain compability, there are no iram0 data section to put - * sections:iram_coredump entry defined in espcoredump's linker.lf file */ - _coredump_iram_start = 0; - _coredump_iram_end = 0; + /* Padding for possible CPU prefetch + alignment for PMS split lines */ + . += _esp_memprot_prefetch_pad_size; + . = ALIGN(_esp_memprot_align_size); - /* align + add 16B for CPU dummy speculative instr. fetch */ - . = ALIGN(_esp_memprot_align_size) + _esp_memprot_prefetch_pad_size; /* iram_end_test section exists for use by memprot unit tests only */ *(.iram_end_test) + _iram_text_end = ABSOLUTE(.); } > iram0_0_seg @@ -232,71 +247,70 @@ SECTIONS mapping[dram0_data] _data_end = ABSOLUTE(.); - . = ALIGN(4); } > dram0_0_seg - /*This section holds data that should not be initialized at power up. - The section located in Internal SRAM memory region. The macro _NOINIT - can be used as attribute to place data into this section. - See the esp_attr.h file for more information. - */ + /** + * This section holds data that should not be initialized at power up. + * The section located in Internal SRAM memory region. The macro _NOINIT + * can be used as attribute to place data into this section. + * See the "esp_attr.h" file for more information. + */ .noinit (NOLOAD): { - . = ALIGN(4); - _noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _noinit_start) + *(.noinit .noinit.*) - . = ALIGN(4) ; - _noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _noinit_end) } > dram0_0_seg - /* external memory bss, from any global variable with EXT_RAM_BSS_ATTR attribute*/ + /* External Memory BSS. (Variables with EXT_RAM_BSS_ATTR attribute). */ .ext_ram.bss (NOLOAD) : { - _ext_ram_bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _ext_ram_bss_start) mapping[extern_ram] - . = ALIGN(4); - _ext_ram_bss_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _ext_ram_bss_end) } > extern_ram_seg /* Shared RAM */ .dram0.bss (NOLOAD) : { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_start) + /** + * ldgen places all bss-related data to mapping[dram0_bss] + * (See components/esp_system/app.lf). + */ mapping[dram0_bss] - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.share.mem) - *(.gnu.linkonce.b.*) - - . = ALIGN (8); - _bss_end = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_end) } > dram0_0_seg .flash.appdesc : ALIGN(0x10) { - _rodata_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.rodata start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark flash.rodata start. + * This can be used for mmu driver to maintain virtual address + */ + _rodata_reserved_start = ABSOLUTE(.); _rodata_start = ABSOLUTE(.); - *(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */ - *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */ + /* !DO NOT PUT ANYTHING BEFORE THIS! */ - /* Create an empty gap within this section. Thanks to this, the end of this + /* Should be the first. App version info. */ + *(.rodata_desc .rodata_desc.*) + /* Should be the second. Custom app version info. */ + *(.rodata_custom_desc .rodata_custom_desc.*) + + /** + * Create an empty gap within this section. Thanks to this, the end of this * section will match .flah.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. */ + * will be merged when creating the final bin image. + */ . = ALIGN(ALIGNOF(.flash.rodata)); - } >default_rodata_seg + } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) .flash.rodata : ALIGN(0x10) @@ -308,133 +322,146 @@ SECTIONS *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) - __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + + /* C++ exception handlers table. */ + ALIGNED_SYMBOL(4, __XT_EXCEPTION_TABLE_) *(.xt_except_table) *(.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 - Make a point of not including anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt - */ - __init_array_start = ABSOLUTE(.); - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .ctors SORT(.ctors.*))) - __init_array_end = ABSOLUTE(.); - KEEP (*crtbegin.*(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - /* C++ exception handlers table: */ - __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __XT_EXCEPTION_DESCS_) *(.xt_except_desc) *(.gnu.linkonce.h.*) __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); *(.xt_except_desc_end) - *(.dynamic) - *(.gnu.version_d) - /* Addresses of memory regions reserved via - SOC_RESERVE_MEMORY_REGION() */ - soc_reserved_memory_region_start = ABSOLUTE(.); + + 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); + + /** + * C++ constructor tables. + * + * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. + */ + ALIGNED_SYMBOL(4, __init_array_start) + KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .ctors SORT(.ctors.*))) + __init_array_end = ABSOLUTE(.); + + /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ + ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) KEEP (*(.reserved_memory_address)) soc_reserved_memory_region_end = ABSOLUTE(.); + /* System init functions registered via ESP_SYSTEM_INIT_FN */ - _esp_system_init_fn_array_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) _esp_system_init_fn_array_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + /* Literals are also RO data. */ _lit4_start = ABSOLUTE(.); *(*.lit4) *(.lit4.*) *(.gnu.linkonce.lit4.*) _lit4_end = ABSOLUTE(.); - . = ALIGN(4); - _thread_local_start = ABSOLUTE(.); + + /* TLS data. */ + ALIGNED_SYMBOL(4, _thread_local_start) *(.tdata) *(.tdata.*) *(.tbss) *(.tbss.*) _thread_local_end = ABSOLUTE(.); - . = ALIGN(4); - } >default_rodata_seg + } > default_rodata_seg _flash_rodata_align = ALIGNOF(.flash.rodata); - /* - This section is a place where we dump all the rodata which aren't used at runtime, - so as to avoid binary size increase - */ + /** + * This section contains all the rodata that is not used + * at runtime, helping to avoid an increase in binary size. + */ .flash.rodata_noload (NOLOAD) : { - /* - This is a symbol marking the flash.rodata end, this can be used for mmu driver to maintain virtual address - We don't need to include the noload rodata in this section - */ + /** + * This symbol marks the end of flash.rodata. It can be utilized by the MMU + * driver to maintain the virtual address. + * NOLOAD rodata may not be included in this section. + */ _rodata_reserved_end = ABSOLUTE(.); - . = ALIGN (4); + mapping[rodata_noload] } > default_rodata_seg .flash.text : { _stext = .; - _instruction_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.text start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the start of flash.text. + * This can be used by the MMU driver to maintain the virtual address. + */ + _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); mapping[flash_text] - *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.stub) + *(.gnu.warning) + *(.gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.fini.literal) - *(.fini) - *(.gnu.version) - /** CPU will try to prefetch up to 16 bytes of - * of instructions. This means that any configuration (e.g. MMU, PMS) must allow - * safe access to up to 16 bytes after the last real instruction, add - * dummy bytes to ensure this - */ + /** + * CPU will try to prefetch up to 16 bytes of of instructions. + * This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, + * add dummy bytes to ensure this. + */ . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); - _instruction_reserved_end = ABSOLUTE(.); /* This is a symbol marking the flash.text end, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the flash.text end. + * This can be used for MMU driver to maintain virtual address. + */ + _instruction_reserved_end = ABSOLUTE(.); _etext = .; - /* Similar to _iram_start, this symbol goes here so it is - resolved by addr2line in preference to the first symbol in - the flash.text segment. - */ + /** + * Similar to _iram_start, this symbol goes here so it is + * resolved by addr2line in preference to the first symbol in + * the flash.text segment. + */ _flash_cache_start = ABSOLUTE(0); - } >default_code_seg + } > default_code_seg /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : { - . = ALIGN (4); - _iram_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _iram_end) } > iram0_0_seg /* Marks the end of data, bss and possibly rodata */ .dram0.heap_start (NOLOAD) : { - . = ALIGN (8); /* Lowest possible start address for the heap */ - _heap_low_start = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _heap_low_start) } > dram0_0_seg - /** This section will be used by the debugger and disassembler to get more information - * about raw data present in the code. - * Indeed, it may be required to add some padding at some points in the code - * in order to align a branch/jump destination on a particular bound. - * Padding these instructions will generate null bytes that shall be - * interpreted as data, and not code by the debugger or disassembler. - * This section will only be present in the ELF file, not in the final binary - * For more details, check GCC-212 - */ + /** + * This section will be used by the debugger and disassembler to get more + * information about raw data present in the code. + * Indeed, it may be required to add some padding at some points in the code + * in order to align a branch/jump destination on a particular bound. + * Padding these instructions will generate null bytes that shall be + * interpreted as data, and not code by the debugger or disassembler. + * This section will only be present in the ELF file, not in the final binary + * For more details, check GCC-212 + */ .xt.prop 0 : { KEEP (*(.xt.prop .gnu.linkonce.prop.*)) diff --git a/components/esp_system/ld/esp32s3/memory.ld.in b/components/esp_system/ld/esp32s3/memory.ld.in index 855affba74..ba229c649b 100644 --- a/components/esp_system/ld/esp32s3/memory.ld.in +++ b/components/esp_system/ld/esp32s3/memory.ld.in @@ -118,6 +118,8 @@ MEMORY extern_ram_seg(RWX) : org = 0x3c000020 , len = 0x2000000-0x20 } +_diram_i_start = SRAM_DIRAM_I_START; + #if CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE /* static data ends at defined address */ _heap_start = SRAM_DRAM_ORG + DRAM0_0_SEG_LEN; diff --git a/components/esp_system/ld/esp32s3/sections.ld.in b/components/esp_system/ld/esp32s3/sections.ld.in index 5e86deb7ae..553c4f2e25 100644 --- a/components/esp_system/ld/esp32s3/sections.ld.in +++ b/components/esp_system/ld/esp32s3/sections.ld.in @@ -9,8 +9,6 @@ /* Default entry point */ ENTRY(call_start_cpu0); -_diram_i_start = 0x40378000; - SECTIONS { /** @@ -19,9 +17,9 @@ SECTIONS */ .rtc.text : { - . = ALIGN(4); - _rtc_fast_start = ABSOLUTE(.); - _rtc_text_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_fast_start) + ALIGNED_SYMBOL(4, _rtc_text_start) + *(.rtc.entry.text) mapping[rtc_text] @@ -29,9 +27,9 @@ SECTIONS *rtc_wake_stub*.*(.literal .text .literal.* .text.*) *(.rtc_text_end_test) - /* 16B padding for possible CPU prefetch and 4B alignment for PMS split lines */ + /* Padding for possible CPU prefetch + alignment for PMS split lines */ . += _esp_memprot_prefetch_pad_size; - . = ALIGN(4); + . = ALIGN(_esp_memprot_align_size); _rtc_text_end = ABSOLUTE(.); } > rtc_iram_seg @@ -43,14 +41,13 @@ SECTIONS */ .rtc.force_fast : { - . = ALIGN(4); - _rtc_force_fast_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_fast_start) mapping[rtc_force_fast] *(.rtc.force_fast .rtc.force_fast.*) - . = ALIGN(4) ; - _rtc_force_fast_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_force_fast_end) } > rtc_data_seg /** @@ -68,6 +65,7 @@ SECTIONS mapping[rtc_data] *rtc_wake_stub*.*(.data .rodata .data.* .rodata.*) + _rtc_data_end = ABSOLUTE(.); } > rtc_data_location @@ -75,6 +73,7 @@ SECTIONS .rtc.bss (NOLOAD) : { _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.*(.bss .bss.*) *rtc_wake_stub*.*(COMMON) @@ -88,15 +87,16 @@ SECTIONS * and will be retained during deep sleep. * User data marked with RTC_NOINIT_ATTR will be placed * into this section. See the file "esp_attr.h" for more information. - * The memory location of the data is dependent on CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM option. + * The memory location of the data is dependent on + * CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM option. */ .rtc_noinit (NOLOAD): { - . = ALIGN(4); - _rtc_noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_noinit_start) + *(.rtc_noinit .rtc_noinit.*) - . = ALIGN(4) ; - _rtc_noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_noinit_end) } > rtc_data_location /** @@ -106,27 +106,32 @@ SECTIONS */ .rtc.force_slow : { - . = ALIGN(4); - _rtc_force_slow_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _rtc_force_slow_start) + *(.rtc.force_slow .rtc.force_slow.*) - . = ALIGN(4) ; - _rtc_force_slow_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _rtc_force_slow_end) } > rtc_slow_seg /** * This section holds RTC data that should have fixed addresses. - * The data are not initialized at power-up and are retained during deep sleep. + * The data are not initialized at power-up and are retained during deep + * sleep. */ .rtc_reserved (NOLOAD): { - . = ALIGN(4); - _rtc_reserved_start = ABSOLUTE(.); - /* New data can only be added here to ensure existing data are not moved. - Because data have adhered to the end of the segment and code is relied on it. - >> put new data here << */ + ALIGNED_SYMBOL(4, _rtc_reserved_start) + + /** + * New data can only be added here to ensure existing data are not moved. + * Because data have adhered to the end of the segment and code is relied + * on it. + * >> put new data here << + */ *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) + _rtc_reserved_end = ABSOLUTE(.); } > rtc_reserved_seg @@ -185,6 +190,7 @@ SECTIONS *(.entry.text) *(.init.literal) *(.init) + _init_end = ABSOLUTE(.); } > iram0_0_seg @@ -220,7 +226,6 @@ SECTIONS mapping[dram0_data] _data_end = ABSOLUTE(.); - . = ALIGN(4); } > dram0_0_seg /** @@ -231,62 +236,61 @@ SECTIONS */ .noinit (NOLOAD): { - . = ALIGN(4); - _noinit_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _noinit_start) + *(.noinit .noinit.*) - . = ALIGN(4) ; - _noinit_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _noinit_end) } > dram0_0_seg /* Shared RAM */ .dram0.bss (NOLOAD) : { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_start) + /** + * ldgen places all bss-related data to mapping[dram0_bss] + * (See components/esp_system/app.lf). + */ mapping[dram0_bss] - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.share.mem) - *(.gnu.linkonce.b.*) - - . = ALIGN (8); - _bss_end = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _bss_end) } > dram0_0_seg - ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.") + ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), + "DRAM segment data does not fit.") .flash.text : { _stext = .; - _instruction_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.text start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the start of flash.text. + * This can be used by the MMU driver to maintain the virtual address. + */ + _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); mapping[flash_text] - *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.stub) + *(.gnu.warning) + *(.gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.fini.literal) - *(.fini) - *(.gnu.version) - /** CPU will try to prefetch up to 16 bytes of - * of instructions. This means that any configuration (e.g. MMU, PMS) must allow - * safe access to up to 16 bytes after the last real instruction, add - * dummy bytes to ensure this - */ + /** + * CPU will try to prefetch up to 16 bytes of of instructions. + * This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add + * dummy bytes to ensure this + */ . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); - _instruction_reserved_end = ABSOLUTE(.); /* This is a symbol marking the flash.text end, this can be used for mmu driver to maintain virtual address */ + /** + * Mark the flash.text end. + * This can be used for MMU driver to maintain virtual address. + */ + _instruction_reserved_end = ABSOLUTE(.); _etext = .; /** @@ -298,34 +302,42 @@ SECTIONS } > default_code_seg /** - * This dummy section represents the .flash.text section but in default_rodata_seg. + * Dummy section represents the .flash.text section but in default_rodata_seg. * Thus, it must have its alignment and (at least) its size. */ .flash_rodata_dummy (NOLOAD): { _flash_rodata_dummy_start = ABSOLUTE(.); - /* Start at the same alignment constraint than .flash.text */ - . = ALIGN(ALIGNOF(.flash.text)); - /* Create an empty gap as big as .flash.text section */ - . = . + SIZEOF(.flash.text); - /* Prepare the alignment of the section above. Few bytes (0x20) must be - * added for the mapping header. */ - . = ALIGN(_esp_mmu_block_size) + 0x20; + + . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); + + /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ + . = ALIGN(_esp_mmu_page_size) + 0x20; } > default_rodata_seg .flash.appdesc : ALIGN(0x10) { - _rodata_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.rodata start, this can be used for mmu driver to maintain virtual address */ + /** + * Mark flash.rodata start. + * This can be used for mmu driver to maintain virtual address + */ + _rodata_reserved_start = ABSOLUTE(.); _rodata_start = ABSOLUTE(.); - *(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */ - *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */ + /* !DO NOT PUT ANYTHING BEFORE THIS! */ - /* Create an empty gap within this section. Thanks to this, the end of this + /* Should be the first. App version info. */ + *(.rodata_desc .rodata_desc.*) + /* Should be the second. Custom app version info. */ + *(.rodata_custom_desc .rodata_custom_desc.*) + + /** + * Create an empty gap within this section. Thanks to this, the end of this * section will match .flah.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. */ + * will be merged when creating the final bin image. + */ . = ALIGN(ALIGNOF(.flash.rodata)); - } >default_rodata_seg + } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) .flash.rodata : ALIGN(0x10) @@ -337,81 +349,90 @@ SECTIONS *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) - __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + + /* C++ exception handlers table. */ + ALIGNED_SYMBOL(4, __XT_EXCEPTION_TABLE_) *(.xt_except_table) *(.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 */ - /* Don't include anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt */ - __init_array_start = ABSOLUTE(.); - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .ctors SORT(.ctors.*))) - __init_array_end = ABSOLUTE(.); - KEEP (*crtbegin.*(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - /* C++ exception handlers table: */ - __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, __XT_EXCEPTION_DESCS_) *(.xt_except_desc) *(.gnu.linkonce.h.*) __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); *(.xt_except_desc_end) - *(.dynamic) - *(.gnu.version_d) + + 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); + + /** + * C++ constructor tables. + * + * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. + */ + ALIGNED_SYMBOL(4, __init_array_start) + KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .ctors SORT(.ctors.*))) + __init_array_end = ABSOLUTE(.); + /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - soc_reserved_memory_region_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) KEEP (*(.reserved_memory_address)) soc_reserved_memory_region_end = ABSOLUTE(.); + /* System init functions registered via ESP_SYSTEM_INIT_FN */ - _esp_system_init_fn_array_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) _esp_system_init_fn_array_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + /* Literals are also RO data. */ _lit4_start = ABSOLUTE(.); *(*.lit4) *(.lit4.*) *(.gnu.linkonce.lit4.*) _lit4_end = ABSOLUTE(.); - . = ALIGN(4); - _thread_local_start = ABSOLUTE(.); + + /* TLS data. */ + ALIGNED_SYMBOL(4, _thread_local_start) *(.tdata) *(.tdata.*) *(.tbss) *(.tbss.*) _thread_local_end = ABSOLUTE(.); - . = ALIGN(4); } > default_rodata_seg _flash_rodata_align = ALIGNOF(.flash.rodata); - /* - This section is a place where we dump all the rodata which aren't used at runtime, - so as to avoid binary size increase - */ + /** + * This section contains all the rodata that is not used + * at runtime, helping to avoid an increase in binary size. + */ .flash.rodata_noload (NOLOAD) : { - /* - This is a symbol marking the flash.rodata end, this can be used for mmu driver to maintain virtual address - We don't need to include the noload rodata in this section - */ + /** + * This symbol marks the end of flash.rodata. It can be utilized by the MMU + * driver to maintain the virtual address. + * NOLOAD rodata may not be included in this section. + */ _rodata_reserved_end = ABSOLUTE(.); - . = ALIGN (4); + mapping[rodata_noload] } > default_rodata_seg /** - * This section is required to skip flash rodata sections, because `extern_ram_seg` - * and `drom0_0_seg` are on the same bus + * Dummy section to skip flash rodata sections. + * Because to `extern_ram_seg` and `drom0_0_seg` are on the same bus */ .ext_ram.dummy (NOLOAD): { - . = ORIGIN(extern_ram_seg) + (_rodata_reserved_end - _flash_rodata_dummy_start); + . = ORIGIN(extern_ram_seg); + . = . + (_rodata_reserved_end - _flash_rodata_dummy_start); . = ALIGN (0x10000); } > extern_ram_seg @@ -419,61 +440,61 @@ SECTIONS .ext_ram.bss (NOLOAD) : { _ext_ram_bss_start = ABSOLUTE(.); + mapping[extern_ram] - . = ALIGN(4); - _ext_ram_bss_end = ABSOLUTE(.); + + ALIGNED_SYMBOL(4, _ext_ram_bss_end) } > extern_ram_seg /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : { - /* iram_end_test section exists for use by memprot unit tests only */ - *(.iram_end_test) - /* ESP32-S3 memprot requires 16B padding for possible CPU prefetch and 256B alignment for PMS split lines */ + /* Padding for possible CPU prefetch + alignment for PMS split lines */ . += _esp_memprot_prefetch_pad_size; . = ALIGN(_esp_memprot_align_size); + + /* iram_end_test section exists for use by memprot unit tests only */ + *(.iram_end_test) + _iram_text_end = ABSOLUTE(.); } > iram0_0_seg .iram0.data : { - . = ALIGN(4); - _iram_data_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _iram_data_start) mapping[iram0_data] - _iram_data_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _iram_data_end) } > iram0_0_seg .iram0.bss (NOLOAD) : { - . = ALIGN(4); - _iram_bss_start = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _iram_bss_start) mapping[iram0_bss] _iram_bss_end = ABSOLUTE(.); - . = ALIGN(4); - _iram_end = ABSOLUTE(.); - } > iram0_0_seg + ALIGNED_SYMBOL(4, _iram_end) + } > iram0_0_seg /* Marks the end of data, bss and possibly rodata */ .dram0.heap_start (NOLOAD) : { - . = ALIGN (8); /* Lowest possible start address for the heap */ - _heap_low_start = ABSOLUTE(.); + ALIGNED_SYMBOL(8, _heap_low_start) } > dram0_0_seg - /** This section will be used by the debugger and disassembler to get more information - * about raw data present in the code. - * Indeed, it may be required to add some padding at some points in the code - * in order to align a branch/jump destination on a particular bound. - * Padding these instructions will generate null bytes that shall be - * interpreted as data, and not code by the debugger or disassembler. - * This section will only be present in the ELF file, not in the final binary - * For more details, check GCC-212 - */ + /** + * This section will be used by the debugger and disassembler to get more + * information about raw data present in the code. + * Indeed, it may be required to add some padding at some points in the code + * in order to align a branch/jump destination on a particular bound. + * Padding these instructions will generate null bytes that shall be + * interpreted as data, and not code by the debugger or disassembler. + * This section will only be present in the ELF file, not in the final binary + * For more details, check GCC-212 + */ .xt.prop 0 : { KEEP (*(.xt.prop .gnu.linkonce.prop.*)) diff --git a/components/esp_system/ld/ld.common b/components/esp_system/ld/ld.common index f5ec5ff726..7a1b6360f8 100644 --- a/components/esp_system/ld/ld.common +++ b/components/esp_system/ld/ld.common @@ -24,9 +24,9 @@ #endif #if CONFIG_APP_BUILD_TYPE_RAM -#define _esp_mmu_block_size 0 +#define _esp_mmu_page_size 0 #else -#define _esp_mmu_block_size CONFIG_MMU_PAGE_SIZE +#define _esp_mmu_page_size CONFIG_MMU_PAGE_SIZE #endif #if CONFIG_SOC_RTC_MEM_SUPPORTED @@ -54,3 +54,7 @@ #define ASSERT_SECTIONS_GAP(PREV_SECTION, NEXT_SECTION) \ ASSERT((ADDR(NEXT_SECTION) == ADDR(PREV_SECTION) + SIZEOF(PREV_SECTION)), \ QUOTED_STRING(The gap between PREV_SECTION and NEXT_SECTION must not exist to produce the final bin image.)) + +#define ALIGNED_SYMBOL(X, SYMBOL) \ +\n . = ALIGN(X); \ +\n SYMBOL = ABSOLUTE(.); diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c index eb13f9e7f0..ea2e46c41d 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c @@ -335,28 +335,35 @@ FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, u LOW ADDRESS |---------------------------| Linker Symbols | Section | -------------- - | .flash.tls | - 0x0|---------------------------| <- _thread_local_start - | .tbss | ^ - | | | - | 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 TLS area size and round up to multiple of 16 bytes. - extern char _thread_local_start, _thread_local_end; - const uint32_t tls_area_size = ALIGNUP(16, (uint32_t)&_thread_local_end - (uint32_t)&_thread_local_start); + 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 aligned to 16-bytes 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); // Save tls start address *ret_threadptr_reg_init = (uint32_t)uxStackPointer; diff --git a/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c b/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c index c8842b98b3..18aa79db67 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c +++ b/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c @@ -192,28 +192,35 @@ FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, u LOW ADDRESS |---------------------------| Linker Symbols | Section | -------------- - | .flash.tls | - 0x0|---------------------------| <- _thread_local_start - | .tbss | ^ - | | | - | 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 TLS area size and round up to multiple of 16 bytes. - extern char _thread_local_start, _thread_local_end; - const uint32_t tls_area_size = ALIGNUP(16, (uint32_t)&_thread_local_end - (uint32_t)&_thread_local_start); + 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 aligned to 16-bytes 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); // Save tls start address *ret_threadptr_reg_init = (uint32_t)uxStackPointer;