0

I have an STM32 project involving a linkerscript which is designed to cap off the end of the image with a ".firmware_header" section. The idea is that this header contains the crc of the image, and there should be no content after this point. However, when I do

arm-none-eabi-objcopy firmware.elf -O binary firmware.bin

there exists some data after the last section which for some reason is required for the image to boot. If I zero this mystery block, the image fails to boot. The first question is, from the elf sections I see, there should be no sections after .firmware_header, where is the data coming from? The second question is, why is this data required at boot? My linker script, readelf output, and a screenshot of the mystery data is below.

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

  .firmware_header :
  {
    . = ALIGN(4);
    KEEP(*(.firmware_header))
    . = ALIGN(4);
  } > FLASH

  . = ALIGN(4);
  _sidata = .;

  .data : AT(_sidata)
  {
    . = ALIGN(4);
    _sdata = .;

    PROVIDE(__data_start__ = _sdata);
    *(.data)
    *(.data*)
    . = ALIGN(4);
    _edata = .;

    PROVIDE(__data_end__ = _edata);
  } > 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)
  }
}

arm-none-eabi-readelf -a ./fw.elf:

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x8027c11
  Start of program headers:          52 (bytes into file)
  Start of section headers:          339928 (bytes into file)
  Flags:                             0x5000400, Version5 EABI, hard-float ABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         3
  Size of section headers:           40 (bytes)
  Number of section headers:         25
  Section header string table index: 24

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 043a68 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] .firmware_header  PROGBITS        08041d58 031d58 000008 00  WA  0   0  4
  [ 9] .data             PROGBITS        20000000 040000 0009c8 00  WA  0   0  8
  [10] .RxDecripSection  PROGBITS        200009c8 0409c8 000080 00  WA  0   0  4
  [11] .RxarraySection   PROGBITS        20000a48 040a48 0017d0 00  WA  0   0  4
  [12] .TxDescripSection PROGBITS        20002218 042218 000080 00  WA  0   0  4
  [13] .TxarraySection   PROGBITS        20002298 042298 0017d0 00  WA  0   0  4
  [14] .bss              NOBITS          20003a68 043a68 045da4 00  WA  0   0  4
  [15] .heap             PROGBITS        2004980c 043a68 000000 00   W  0   0  1
  [16] .reserved_for_sta PROGBITS        2004980c 043a68 000000 00   W  0   0  1
  [17] .battery_backed_s NOBITS          40024000 044000 00000c 00  WA  0   0  4
  [18] .comment          PROGBITS        00000000 043a68 000075 01  MS  0   0  1
  [19] .debug_frame      PROGBITS        00000000 043ae0 00144c 00      0   0  4
  [20] .stab             PROGBITS        00000000 044f2c 000084 0c     21   0  4
  [21] .stabstr          STRTAB          00000000 044fb0 000117 00      0   0  1
  [22] .symtab           SYMTAB          00000000 0450c8 009b30 10     23 1790  4
  [23] .strtab           STRTAB          00000000 04ebf8 0042bb 00      0   0  1
  [24] .shstrtab         STRTAB          00000000 052eb3 000122 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 0x21d60 0x21d60 RWE 0x10000
  LOAD           0x040000 0x20000000 0x08041d60 0x03a68 0x4980c RW  0x10000
  LOAD           0x044000 0x40024000 0x40024000 0x00000 0x0000c RW  0x10000

All data after the circled value shouldn't be there. The circled value is the .firmware_header secrion

Clifford
  • 88,407
  • 13
  • 85
  • 165
chris12892
  • 1,634
  • 2
  • 18
  • 36

1 Answers1

1

Turns out this is an issue with the definition of the .data section. It's getting loaded after .firmware_header. Interesting that this wasn't made more clear in readefl, etc output. Solved!

chris12892
  • 1,634
  • 2
  • 18
  • 36
  • 1
    I don't understand what was surprising you ? The section .data is after the section .firmware_header in your linker script, so it makes sense. You were probably confused by the fact that the .data section has different load and execution addresses and readelf displays the execution address. You can also look to the .map file where you see both addresses – Guillaume Petitjean Jul 18 '19 at 13:49