mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
fix(ldgen): don't emit intermediate placements without sections
When a symbol needs to be placed to a different target than the one
designated for the object file, the object file is expanded, which
includes the following steps:
1. Creating a new placement for the symbol's input section with the
specified target.
2. Excluding the object placement from the orignal target.
3. Creating a new intermediate placement for the object for the original
target, where its input sections are expanded, excluding the input
section for the symbol.
Let's illustrate the object expansion process with the following example:
[sections:rodata]
entries:
.rodata+
.sdata2+
.srodata+
[scheme:default]
entries:
text -> flash_text
rodata -> flash_rodata
[scheme:noflash]
entries:
text -> iram0_text
rodata -> dram0_data
[mapping:soc_pm]
archive: libsoc.a
entries:
gpio_periph: GPIO_HOLD_MASK (noflash)
gpio_periph section headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000000 00 AX 0 0 2
[ 2] .data PROGBITS 00000000 000034 000000 00 WA 0 0 1
[ 3] .bss NOBITS 00000000 000034 000000 00 WA 0 0 1
[ 4] .rodata.GPIO_HOLD_MASK PROGBITS 00000000 000034 000058 00 A 0 0 4
[ 5] .rodata.GPIO_PIN_MUX_REG PROGBITS 00000000 00008c 000058 00 A 0 0 4
[ 6] .debug_info PROGBITS 00000000 0000e4 0000d8 00 0 0 1
[ 7] .rela.debug_info RELA 00000000 0009d4 000108 0c I 16 6 4
[ 8] .debug_abbrev PROGBITS 00000000 0001bc 000070 00 0 0 1
[ 9] .debug_aranges PROGBITS 00000000 00022c 000018 00 0 0 1
[10] .rela.debug_aranges RELA 00000000 000adc 00000c 0c I 16 9 4
[11] .debug_line PROGBITS 00000000 000244 0001ab 00 0 0 1
[12] .debug_str PROGBITS 00000000 0003ef 00022d 01 MS 0 0 1
[13] .comment PROGBITS 00000000 00061c 000030 01 MS 0 0 1
[14] .note.GNU-stack PROGBITS 00000000 00064c 000000 00 0 0 1
[15] .riscv.attributes RISCV_ATTRIBUTES 00000000 00064c 000044 00 0 0 1
[16] .symtab SYMTAB 00000000 000690 000260 10 17 36 4
[17] .strtab STRTAB 00000000 0008f0 0000e1 00 0 0 1
[18] .shstrtab STRTAB 00000000 000ae8 0000d1 00 0 0 1
1. Creating a new placement
.dram0.data :
{
*libsoc.a:gpio_periph.*(.rodata.GPIO_HOLD_MASK .sdata2.GPIO_HOLD_MASK .srodata.GPIO_HOLD_MASK)
}
2. Excluding the object placement
.flash.rodata :
{
*(EXCLUDE_FILE(*libsoc.a:gpio_periph.*) .rodata.* ...)
}
3. Creating a new intermediate placement
.flash.rodata :
{
*libsoc.a:gpio_periph.*(.rodata.GPIO_PIN_MUX_REG)
}
Now, let's do the same, but also move GPIO_PIN_MUX_REG to noflash with an updated mapping.
[mapping:soc_pm]
archive: libsoc.a
entries:
gpio_periph: GPIO_HOLD_MASK (noflash)
gpio_periph: GPIO_PIN_MUX_REG (noflash)
1. Creating a new placement
.dram0.data :
{
*libsoc.a:gpio_periph.*(.rodata.GPIO_HOLD_MASK .sdata2.GPIO_HOLD_MASK .srodata.GPIO_HOLD_MASK)
*libsoc.a:gpio_periph.*(.rodata.GPIO_PIN_MUX_REG .sdata2.GPIO_PIN_MUX_REG
.srodata.GPIO_PIN_MUX_REG)
}
2. Excluding the object placement
.flash.rodata :
{
*(EXCLUDE_FILE(*libsoc.a:gpio_periph.*) .rodata.* ...)
}
3. Creating a new intermediate placement
.flash.rodata :
{
*libsoc.a:gpio_periph.*
}
The *libsoc.a:gpio_periph.* entity in step 3 no longer has input
sections, as there are no remaining .rodata input sections in the object
file. The linker behavior for this mapping is to include all object
input sections that have not yet been placed as described in
https://sourceware.org/binutils/docs/ld.html#Input-Section-Basics
"If you use a file name without a list of sections, then all sections in
the input file will be included in the output section. This is not
commonly done, but it may by useful on occasion."
The map file for such mapping now contains following input sections
.flash.rodata 0x3c0a0120 0x19b34
*libsoc.a:gpio_periph.*()
.debug_info 0x3c0b95bf 0xd8 esp-idf/soc/libsoc.a(gpio_periph.c.obj)
.debug_abbrev 0x3c0b9697 0x70 esp-idf/soc/libsoc.a(gpio_periph.c.obj)
.debug_aranges
0x3c0b9707 0x18 esp-idf/soc/libsoc.a(gpio_periph.c.obj)
.debug_line 0x3c0b971f 0x1ab esp-idf/soc/libsoc.a(gpio_periph.c.obj)
.debug_str 0x3c0b98ca 0x21a esp-idf/soc/libsoc.a(gpio_periph.c.obj)
0x22d (size before relaxing)
.comment 0x3c0b9ae4 0x30 esp-idf/soc/libsoc.a(gpio_periph.c.obj)
.note.GNU-stack
0x3c0b9ae4 0x0 esp-idf/soc/libsoc.a(gpio_periph.c.obj)
.riscv.attributes
0x3c0b9ae4 0x44 esp-idf/soc/libsoc.a(gpio_periph.c.obj)
This is incorrect, and such intermediate placement should not be
generated. This type of placement can be recognized because it is not
explicitly defined in the mapping and lacks input sections. We can
identify this in the significant function and prevent issuing commands
for such placement.
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
import collections
|
||||
@@ -32,6 +32,7 @@ ROOT = Entity('*')
|
||||
FREERTOS = Entity('libfreertos.a')
|
||||
CROUTINE = Entity('libfreertos.a', 'croutine')
|
||||
TIMERS = Entity('libfreertos.a', 'timers')
|
||||
TEMPERATURE_SENSOR_PERIPH = Entity('libsoc.a', 'temperature_sensor_periph')
|
||||
|
||||
FREERTOS2 = Entity('libfreertos2.a')
|
||||
|
||||
@@ -68,6 +69,9 @@ class GenerationTest(unittest.TestCase):
|
||||
with open('data/libfreertos.a.txt') as objdump:
|
||||
self.entities.add_sections_info(objdump)
|
||||
|
||||
with open('data/libsoc.a.txt') as objdump:
|
||||
self.entities.add_sections_info(objdump)
|
||||
|
||||
with open('data/linker_script.ld') as linker_script:
|
||||
self.linker_script_expect = LinkerScript(linker_script)
|
||||
|
||||
@@ -336,6 +340,48 @@ entries:
|
||||
|
||||
self.compare_rules(expected, actual)
|
||||
|
||||
def test_nondefault_mapping_all_symbols(self):
|
||||
# Test mapping entry different from default for all .rodata.* symbols in the temperature_sensor_periph
|
||||
# object file. There should be exclusion in the default commands for flash_rodata, but
|
||||
# no implicit intermediate object command(X), because there are no .rodata+
|
||||
# symbols left to be placed in dram0_data.
|
||||
#
|
||||
# The X line with entity only(without any input sections) should not be emitted, because
|
||||
# linker would include all not yet placed input sections from the temperature_sensor_periph
|
||||
# object file, including .debug, .comment and other input section.
|
||||
#
|
||||
# flash.rodata
|
||||
# *((EXCLUDE_FILE(*libsoc.a:temperature_sensor_periph.*)) .rodata.* ...) A
|
||||
# # *libsoc.a:temperature_sensor_periph.* X
|
||||
#
|
||||
# Commands placing the entire library in iram should be generated:
|
||||
#
|
||||
# dram0_data
|
||||
# *libsoc.a:temperature_sensor_periph.*(.rodata.temperature_sensor_attribute) B
|
||||
mapping = u"""
|
||||
[mapping:test]
|
||||
archive: libsoc.a
|
||||
entries:
|
||||
temperature_sensor_periph:temperature_sensor_attributes (noflash) # 1
|
||||
"""
|
||||
|
||||
self.add_fragments(mapping)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_rodata = expected['flash_rodata']
|
||||
dram0_data = expected['dram0_data']
|
||||
|
||||
# Generate exclusion in flash_text A
|
||||
flash_rodata[0].exclusions.add(TEMPERATURE_SENSOR_PERIPH)
|
||||
|
||||
# Input section commands in dram0_data for #1 B
|
||||
dram0_data.append(InputSectionDesc(TEMPERATURE_SENSOR_PERIPH,
|
||||
set(['.rodata.temperature_sensor_attributes']),
|
||||
[]))
|
||||
|
||||
self.compare_rules(expected, actual)
|
||||
|
||||
def test_default_symbol_nondefault_lib(self):
|
||||
# Test default symbol mapping with different lib mapping. This should create an implicit intermediate object command.
|
||||
# The significant targets are flash_text, flash_rodata, iram0_text, dram0_data.
|
||||
@@ -571,7 +617,7 @@ entries:
|
||||
|
||||
def test_multiple_symbols_excluded_from_intermediate_command(self):
|
||||
# Test mapping multiple symbols from the same object.
|
||||
# All these symbols must be succesfully excluded from
|
||||
# All these symbols must be successfully excluded from
|
||||
# the intermediate command.
|
||||
#
|
||||
# flash_text
|
||||
|
||||
Reference in New Issue
Block a user