let's say I run arm-none-eabi-objcopy firmwared.elf -O ihex firmware.hex
Assume the binary was generated with the following linker script:
ENTRY(Reset_Handler)
MEMORY
{
FLASH (RX) : ORIGIN = 0x08020000, LENGTH = 896K
SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 512K
BKPSRAM (RW) : ORIGIN = 0x40024000, LENGTH = 4K
}
_estack = 0x20080000;
SECTIONS
{
.isr_vector :
{
. = ALIGN(4);
_isr_vector = .;
KEEP(*(.isr_vector))
. = ALIGN(4);
} > FLASH
.firmware_header_vector :
{
. = ALIGN(4);
KEEP(*(.firmware_header_vector))
. = ALIGN(4);
} > FLASH
.text :
{
. = ALIGN(4);
_stext = .;
*(.Reset_Handler)
*(.text)
*(.text*)
*(.rodata)
*(.rodata*)
*(.glue_7)
*(.glue_7t)
KEEP(*(.init))
KEEP(*(.fini))
. = ALIGN(4);
_etext = .;
} > FLASH
.ARM.extab :
{
. = ALIGN(4);
*(.ARM.extab)
*(.gnu.linkonce.armextab.*)
. = ALIGN(4);
} > FLASH
.exidx :
{
. = ALIGN(4);
PROVIDE(__exidx_start = .);
*(.ARM.exidx*)
. = ALIGN(4);
PROVIDE(__exidx_end = .);
} > FLASH
.preinit_array :
{
PROVIDE(__preinit_array_start = .);
KEEP(*(.preinit_array*))
PROVIDE(__preinit_array_end = .);
} > FLASH
.init_array :
{
PROVIDE(__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array*))
PROVIDE(__init_array_end = .);
} > FLASH
.fini_array :
{
PROVIDE(__fini_array_start = .);
KEEP(*(.fini_array*))
KEEP(*(SORT(.fini_array.*)))
PROVIDE(__fini_array_end = .);
} > FLASH
_sidata = .;
.data_x : AT(_sidata) /* LMA address is _sidata (in FLASH) */
{
. = ALIGN(4);
_sdata = .; /* data section VMA address */
*(.data*)
. = ALIGN(4);
_edata = .;
} > SRAM
.firmware_header (_sidata + SIZEOF(.data_x)):
{
. = ALIGN(4);
KEEP(*(.firmware_header))
. = ALIGN(4);
} > FLASH
.eth (NOLOAD) :
{
. = ALIGN(4);
KEEP(*(.RxDecripSection))
KEEP(*(.TxDescripSection))
KEEP(*(.RxarraySection))
KEEP(*(.TxarraySection))
. = ALIGN(4);
} > SRAM
.bss :
{
. = ALIGN(4);
_sbss = .;
PROVIDE(__bss_start__ = _sbss);
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
PROVIDE(__bss_end__ = _ebss);
} > SRAM
PROVIDE(end = .);
.heap (NOLOAD) :
{
. = ALIGN(4);
PROVIDE(__heap_start__ = .);
KEEP(*(.heap))
. = ALIGN(4);
PROVIDE(__heap_end__ = .);
} > SRAM
.reserved_for_stack (NOLOAD) :
{
. = ALIGN(4);
PROVIDE(__reserved_for_stack_start__ = .);
KEEP(*(.reserved_for_stack))
. = ALIGN(4);
PROVIDE(__reserved_for_stack_end__ = .);
} > SRAM
.battery_backed_sram (NOLOAD) :
{
. = ALIGN(4);
KEEP(*(.battery_backed_sram))
. = ALIGN(4);
} > BKPSRAM
/DISCARD/ :
{
*(.ARM.attributes)
}
}
This results in a readelf output of:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .isr_vector PROGBITS 08020000 010000 0001f8 00 WA 0 0 4
[ 2] .firmware_header_ PROGBITS 080201f8 0101f8 000004 00 WA 0 0 4
[ 3] .text PROGBITS 08020200 010200 021b44 00 AX 0 0 64
[ 4] .ARM.extab PROGBITS 08041d44 042728 000000 00 W 0 0 1
[ 5] .exidx ARM_EXIDX 08041d44 031d44 000008 00 AL 3 0 4
[ 6] .init_array INIT_ARRAY 08041d4c 031d4c 000008 04 WA 0 0 4
[ 7] .fini_array FINI_ARRAY 08041d54 031d54 000004 04 WA 0 0 4
[ 8] .data_x PROGBITS 20000000 040000 0009c8 00 WA 0 0 8
[ 9] .firmware_header PROGBITS 08042720 042720 000008 00 WA 0 0 4
[10] .eth NOBITS 200009c8 0509c8 0030a0 00 WA 0 0 4
[11] .bss NOBITS 20003a68 0509c8 045da4 00 WA 0 0 4
[12] .heap PROGBITS 2004980c 042728 000000 00 W 0 0 1
[13] .reserved_for_sta PROGBITS 2004980c 042728 000000 00 W 0 0 1
[14] .battery_backed_s NOBITS 40024000 044000 00000c 00 WA 0 0 4
[15] .comment PROGBITS 00000000 042728 000075 01 MS 0 0 1
[16] .debug_frame PROGBITS 00000000 0427a0 00144c 00 0 0 4
[17] .stab PROGBITS 00000000 043bec 000084 0c 18 0 4
[18] .stabstr STRTAB 00000000 043c70 000117 00 0 0 1
[19] .symtab SYMTAB 00000000 043d88 009b00 10 20 1787 4
[20] .strtab STRTAB 00000000 04d888 0042bb 00 0 0 1
[21] .shstrtab STRTAB 00000000 051b43 0000e6 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
y (purecode), p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x010000 0x08020000 0x08020000 0x21d58 0x21d58 RWE 0x10000
LOAD 0x040000 0x20000000 0x08041d58 0x009c8 0x009c8 RW 0x10000
LOAD 0x042720 0x08042720 0x08042720 0x00008 0x00008 RW 0x10000
LOAD 0x0509c8 0x200009c8 0x08042720 0x00000 0x48e44 RW 0x10000
LOAD 0x044000 0x40024000 0x40024000 0x00000 0x0000c RW 0x10000
Section to Segment mapping:
Segment Sections...
00 .isr_vector .firmware_header_vector .text .exidx .init_array .fini_array
01 .data_x
02 .firmware_header
03 .eth .bss
04 .battery_backed_sram
How does objcopy know not to insert sections such as .bss in to the output image? I know that it computes this on the fly, and I'm assuming this mechanism is driven through the section to segment mapping, but I cannot find any explanation as to how it actually performs the segment to section mapping. The elf file stores no information about which segments are flash, and yet somehow objcopy knows that it should not copy .bss into the output file. How?