apple / swift-embedded-examples

A collection of example projects using Embedded Swift
Apache License 2.0
556 stars 30 forks source link

esp: add linker fragment file #26

Open erhankur opened 4 days ago

erhankur commented 4 days ago

With the help of linker fragment files, it is possible to specify custom placements at the component level within ESP-IDF.

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/linker-script-generation.html

erhankur commented 4 days ago

@georgik fyi

Lapshin commented 4 days ago

Should not .got* sections be dropped? (Because they usually using for dynamic linking)

rauhul commented 1 day ago

Do you mind adding some comments and additional context so we can better understand why this file is helpful? I'm not too familiar with the idf so background really helps.

erhankur commented 1 day ago

Do you mind adding some comments and additional context so we can better understand why this file is helpful? I'm not too familiar with the idf so background really helps.

@rauhul , in IDF 5.3 and later branches, we have added assertions in the linker files to avoid gaps between memory regions. When building Swift examples, additional sections such as .swift_modhash, .got and .got.plt are introduced, which eventually cause assertion errors due to their placement in the ELF file.

riscv32-esp-elf-readelf -S build/main.elf

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .rtc.text         PROGBITS        50000000 049d1c 000000 00   W  0   0  1
  [ 2] .rtc.force_fast   PROGBITS        50000000 049d1c 000000 00   W  0   0  1
  [ 3] .rtc_noinit       PROGBITS        50000000 049d1c 000000 00   W  0   0  1
  [ 4] .rtc.force_slow   PROGBITS        50000000 049d1c 000000 00   W  0   0  1
  [ 5] .rtc_reserved     NOBITS          50003fe8 049fe8 000018 00  WA  0   0  8
  [ 6] .iram0.text       PROGBITS        40800000 001000 00c9c8 00  AX  0   0 256
  [ 7] .iram0.text_end   NOBITS          4080c9c8 00d9c8 000000 00  WA  0   0  1
  [ 8] .iram0.data       NOBITS          4080c9c8 00d9c8 000008 00  WA  0   0  1
  [ 9] .iram0.bss        PROGBITS        4080c9d0 049d1c 000000 00   W  0   0  1
  [10] .dram0.data       PROGBITS        4080c9d0 00d9d0 001921 00  WA  0   0 16
  [11] .noinit           NOBITS          4080e2f1 00f2f1 000003 00  WA  0   0  1
  [12] .dram0.bss        NOBITS          4080e300 00f2f1 0013a8 00  WA  0   0 16
  [13] .flash.text       PROGBITS        42000020 010020 016768 00  AX  0   0  2
  [14] .flash_rodat[...] NOBITS          42000020 027020 018000 00  WA  0   0  1
  [15] .flash.appdesc    PROGBITS        42018020 03f020 000100 00   A  0   0 16
  [16] .swift_modhash    PROGBITS        42018120 03f120 000010 00  Ao  0   0  1
  [17] .flash.rodata     PROGBITS        42018130 03f130 00abdc 00  WA  0   0 16
  [18] .got              PROGBITS        42022d0c 049d0c 000008 04  WA  0   0  4
  [19] .got.plt          PROGBITS        42022d14 049d14 000008 04  WA  0   0  4
  [20] .eh_frame_hdr     PROGBITS        42022d1c 049d1c 000000 00   W  0   0  1
  [21] .eh_frame         PROGBITS        42022d1c 049d1c 000000 00   W  0   0  1
  [22] .flash.tdata      PROGBITS        42022d1c 049d1c 000000 00   W  0   0  1
  [23] .dram0.heap_start NOBITS          4080f6a8 00f2f1 000008 00  WA  0   0  1
  [24] .debug_aranges    PROGBITS        00000000 049d20 005988 00      0   0  8
  ....
  [35] .comment          PROGBITS        00000000 36a2c4 000060 01  MS  0   0  1
  [36] .riscv.attributes RISCV_ATTRIBUTE 00000000 36a324 000057 00      0   0  1
  [37] .symtab           SYMTAB          00000000 36a37c 013700 10     38 2595  4
  [38] .strtab           STRTAB          00000000 37da7c 0111ce 00      0   0  1
  [39] .shstrtab         STRTAB          00000000 38ec4a 0001f3 00      0   0  1

For example, we have ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata), meaning there must not be any other section between .flash.appdesc and .flash.rodata. But as you can see:

  [15] .flash.appdesc    PROGBITS        42018020 03f020 000100 00   A  0   0 16
  [16] .swift_modhash    PROGBITS        42018120 03f120 000010 00  Ao  0   0  1
  [17] .flash.rodata     PROGBITS        42018130 03f130 00abdc 00  WA  0   0 16

Similarly, the .got and .got.plt sections cause ASSERT_SECTIONS_GAP(.flash.rodata, .eh_frame_hdr) to fail.

Solutions

This way, we can manage the sections effectively and avoid assertion errors without making changes to the ESP-IDF itself.

I hope it is clear now.

And one question from our side:

Should not .got* sections be dropped? (Because they usually using for dynamic linking)

rauhul commented 57 minutes ago

@erhankur I think it makes sense, but I'm a little concerned how we will handle the Swift compiler adding or removing sections in the future. Maintaining and understanding this sort of file is a big ask for even experienced users and I'm wondering if we can somehow do better.

Maybe @kubamracek has thoughts.