gcc 默认链接器脚本中0的VMA部分重复

vaqhlq81  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(194)

arm-none-eabi-gcc的默认链接器脚本定义了几个VMA为0的部分。其中大部分包含调试信息:

  1. /* Stabs debugging sections. */
  2. .stab 0 : { *(.stab) }
  3. .stabstr 0 : { *(.stabstr) }
  4. .stab.excl 0 : { *(.stab.excl) }
  5. .stab.exclstr 0 : { *(.stab.exclstr) }
  6. .stab.index 0 : { *(.stab.index) }
  7. .stab.indexstr 0 : { *(.stab.indexstr) }
  8. .comment 0 : { *(.comment) }
  9. .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
  10. /* DWARF debug sections.
  11. Symbols in the DWARF debugging sections are relative to the beginning
  12. of the section so we begin them at 0. */
  13. /* DWARF 1. */
  14. .debug 0 : { *(.debug) }
  15. .line 0 : { *(.line) }
  16. /* GNU DWARF 1 extensions. */
  17. .debug_srcinfo 0 : { *(.debug_srcinfo) }
  18. .debug_sfnames 0 : { *(.debug_sfnames) }
  19. /* DWARF 1.1 and DWARF 2. */
  20. .debug_aranges 0 : { *(.debug_aranges) }
  21. .debug_pubnames 0 : { *(.debug_pubnames) }
  22. /* DWARF 2. */
  23. .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
  24. .debug_abbrev 0 : { *(.debug_abbrev) }
  25. .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
  26. .debug_frame 0 : { *(.debug_frame) }
  27. .debug_str 0 : { *(.debug_str) }
  28. .debug_loc 0 : { *(.debug_loc) }
  29. .debug_macinfo 0 : { *(.debug_macinfo) }
  30. //snip several more of these, until...
  31. .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }
  32. .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }

我不明白这是干什么的,DWARF部分的解释性注解也没有帮助--这些部分 * 真的 * 不可能都有相同的起始地址,除非它们的大小都是0!另外,脚本将地址0分配给了这些部分,而不是符号。* 而且 * 该注解不适用于“Stabs”部分...
使用readelf -S表明,理论上它们的地址都是0,但它们的偏移量也各不相同--假设这些偏移量是它们在加载时的实际地址:

  1. [13] .stab PROGBITS 00000000 009a6c 00009c 0c 14 0 4
  2. [14] .stabstr STRTAB 00000000 009b08 00014d 00 0 0 1
  3. ...
  4. [16] .debug_aranges PROGBITS 00000000 009cb0 0005f0 00 0 0 8
  5. [17] .debug_info PROGBITS 00000000 00a2a0 0110c9 00 0 0 1
  6. [18] .debug_abbrev PROGBITS 00000000 01b369 00401d 00 0 0 1
  7. [19] .debug_line PROGBITS 00000000 01f386 0063ed 00 0 0 1
  8. [20] .debug_frame PROGBITS 00000000 025774 00097c 00 0 0 4
  9. [21] .debug_str PROGBITS 00000000 0260f0 001f29 01 MS 0 0 1
  10. [22] .debug_line_str PROGBITS 00000000 028019 0000b3 01 MS 0 0 1
  11. [23] .debug_loclists PROGBITS 00000000 0280cc 00221c 00 0 0 1
  12. [24] .debug_rnglists PROGBITS 00000000 02a2e8 000495 00 0 0 1
  13. [25] .ARM.attributes ARM_ATTRIBUTES 00000000 02a77d 00002e 00 0 0 1

我唯一的想法是虚拟地址0可能被认为是一个特殊的地址,这并不是字面上的意思,而是意味着具有这个地址的部分将不会被加载到内存中(因此将不会有一个加载地址),除非代码在调试器下运行。
有人能给我解释一下这些重复地址到底发生了什么吗?

uqzxnwby

uqzxnwby1#

elf(5) man page中对此进行了说明:

  1. sh_flags
  2. ...
  3. SHF_ALLOC
  4. This section occupies memory during process
  5. execution. Some control sections do not reside in
  6. the memory image of an object file. This attribute
  7. is off for those sections.
  8. sh_addr
  9. If this section appears in the memory image of a process,
  10. this member holds the address at which the section's first
  11. byte should reside. Otherwise, the member contains zero.

您应该看到这些部分的SHF_ALLOC标志未设置(readelf -S输出的Flags字段中没有A),因此它们不驻留在内存映像中。因此,不需要指定起始地址,因此该字段设置为零。
实际上,无论是否调试,这些部分都不需要由exec*加载到内存中。程序员当然不需要运行这些部分,调试时,调试器将打开并读取二进制文件,解析出数据,作为与执行程序不同的操作。

相关问题