arm-none-eabi-gcc
's default linker script defines several sections with VMA of 0. Most of these contain debug information:
/* 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)) }
I don't understand what this does, and the explanatory comment on the DWARF sections doesn't help - the sections can't really all have the same start address unless they're all size 0! Plus, the script is assigning address 0 to the sections, not the symbols. And that comment didn't apply to the "Stabs" section...
Using readelf -S
shows that they all theoretically have an address of 0, but also all have different offsets - presumably these offsets are their actual addresses if loaded:
[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
The only idea I have is that virtual address 0 might be considered a special address, which is not taken literally, but instead means that sections with this address will not be loaded into memory (and so will not have a load address) unless the code is being run under a debugger. I have not been able to find any evidence to support this, however.
Can anyone explain to me what is actually happening with these duplicate addresses?
This is explained in the 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.
You should see that the SHF_ALLOC
flag is unset for those sections (no A
in the Flags field of the readelf -S
output) and so they do not reside in the memory image. There is thus no need to specify a start address, so that field is set to zero.
These sections actually do not need to be loaded into memory by exec*
under any circumstances, debugger or not. They are certainly not needed for the programmer to run, and when debugging, the debugger will open and read the binary file to parse out that data, as a separate operation from executing the program.