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

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

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

/* Stabs debugging sections.  */
  .stab          0 : { *(.stab) }
  .stabstr       0 : { *(.stabstr) }
  .stab.excl     0 : { *(.stab.excl) }
  .stab.exclstr  0 : { *(.stab.exclstr) }
  .stab.index    0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment       0 : { *(.comment) }
  .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the beginning
     of the section so we begin them at 0.  */
  /* DWARF 1.  */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }
  /* GNU DWARF 1 extensions.  */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  /* DWARF 1.1 and DWARF 2.  */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  /* DWARF 2.  */
  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }

  //snip several more of these, until...

  .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }
  .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }

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

[13] .stab             PROGBITS        00000000 009a6c 00009c 0c     14   0  4
  [14] .stabstr          STRTAB          00000000 009b08 00014d 00      0   0  1
 
   ...

  [16] .debug_aranges    PROGBITS        00000000 009cb0 0005f0 00      0   0  8
  [17] .debug_info       PROGBITS        00000000 00a2a0 0110c9 00      0   0  1
  [18] .debug_abbrev     PROGBITS        00000000 01b369 00401d 00      0   0  1
  [19] .debug_line       PROGBITS        00000000 01f386 0063ed 00      0   0  1
  [20] .debug_frame      PROGBITS        00000000 025774 00097c 00      0   0  4
  [21] .debug_str        PROGBITS        00000000 0260f0 001f29 01  MS  0   0  1
  [22] .debug_line_str   PROGBITS        00000000 028019 0000b3 01  MS  0   0  1
  [23] .debug_loclists   PROGBITS        00000000 0280cc 00221c 00      0   0  1
  [24] .debug_rnglists   PROGBITS        00000000 02a2e8 000495 00      0   0  1
  [25] .ARM.attributes   ARM_ATTRIBUTES  00000000 02a77d 00002e 00      0   0  1

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

uqzxnwby

uqzxnwby1#

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

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

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

相关问题