Skip to content

esp: add linker fragment file #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 4, 2024
Merged

Conversation

erhankur
Copy link
Contributor

@erhankur erhankur commented Jun 29, 2024

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
Copy link
Contributor Author

@georgik fyi

@erhankur erhankur force-pushed the fix_linker_gap_errors branch from 9d9e567 to 7357b9c Compare June 29, 2024 01:46
@erhankur erhankur force-pushed the fix_linker_gap_errors branch from 7357b9c to 856171d Compare June 29, 2024 08:54
@erhankur erhankur changed the title esp: add linker fragment file to locate custom swift sections to prop… esp: add linker fragment file Jun 29, 2024
@Lapshin
Copy link

Lapshin commented Jun 29, 2024

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

@rauhul
Copy link
Collaborator

rauhul commented Jul 1, 2024

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
Copy link
Contributor Author

erhankur commented Jul 2, 2024

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

  • Modify the sections.ld.in files: One solution is to manually place sections in the proper locations by editing the sections.ld.in file for each target. You can refer to the patch I created for the ESP32-C6. However, this requires changes to the ESP-IDF.

  • Custom Linker Fragment File: The approach I took in this PR is to locate custom sections without modifying the IDF linker files. I created a linker fragment file inside the example's main directory to avoid modifying IDF linker files for each possible target. You can find more details here

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
Copy link
Collaborator

rauhul commented Jul 3, 2024

@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.

@erhankur
Copy link
Contributor Author

erhankur commented Jul 4, 2024

@rauhul We, Espressif, are completely fine with making the necessary modifications to the IDF. However, it is better to see the big picture first to avoid back-and-forth changes.

@rauhul
Copy link
Collaborator

rauhul commented Jul 4, 2024

I suspect we will need to tweak this file in the future as the swift compiler behavior changes but that's ok. Let's merge it :)

@rauhul rauhul merged commit 2eb2975 into apple:main Jul 4, 2024
@erhankur erhankur deleted the fix_linker_gap_errors branch July 4, 2024 19:35
@erhankur
Copy link
Contributor Author

erhankur commented Jul 4, 2024

@rauhul thanks for merging.

I suspect we will need to tweak this file in the future as the swift compiler behavior changes but that's ok. Let's merge it :)

I believe it is easier to change this file rather than the IDF :)

@erhankur
Copy link
Contributor Author

erhankur commented Nov 4, 2024

@rauhul @kubamracek This question remained unanswered.

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

If they could be dropped, we wouldn’t need a linker fragment file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants