(Cortex M4) Bad section alignment in ELF file

we have a strange issue on a Cortex M4 MCU. The compiled Firmware works if the binary is loaded with ST-LINK in the correct section, but using C-Lion and OpenOcd, The FW load operation, load also the ELF header in FLASH and corrupt a Flags Area used by a bootloader.

The MCU Flash is 512 kB – 256 pages total (2kB for page), with the following layout:

+-------- 0x0800 0000 - FLASH_BASE -------------------------+
| Bootloader partition                                      |
|                                                           |
+-------- FLAGS_ADDR  0x0800 5000 --------------------------+
| 1 page Flags page                                         |
+-------- APP_ADDR 0x0800 5800 -----------------------------+
|                                                           |
| (APP_NUMPAGES) Application partition                      |
|                                                           |
+-------- BAK_ADDR -----------------------------------------+
|                                                           |
| (APP_NUMPAGES) Application backup                         |
|                                                           |
+-------- NEW_ADDR -----------------------------------------+
|                                                           |
| (APP_NUMPAGES) Update partition                           |
|                                                           |
+-----------------------------------------------------------+

The App FW has to be loaded starting from 0x0800 8500, that’s true loading the .bin with ST-LINK, but loading the FW in C-Lion the code is correctly loaded starting from 0x0800 8500, but also incorrectly the header of ELF file is loaded at 0x0800 5000.

Analyzing the ELF file with readelf, shown the following information:

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        08005800 000800 000194 00   A  0   0  1
  [ 2] .build_info       PROGBITS        08005994 000994 0000a4 00   A  0   0  4
  [ 3] .text             PROGBITS        08005a40 000a40 01f698 00  AX  0   0 16
  [ 4] .rodata           PROGBITS        080250d8 0200d8 002540 00   A  0   0  4
  [ 5] .ARM.extab        PROGBITS        08027618 024398 000000 00   W  0   0  1
  [ 6] .ARM              ARM_EXIDX       08027618 022618 000008 00  AL  3   0  4
  [ 7] .preinit_array    PREINIT_ARRAY   08027620 024398 000000 04  WA  0   0  1
  [ 8] .init_array       INIT_ARRAY      08027620 022620 000038 04  WA  0   0  4
  [ 9] .fini_array       FINI_ARRAY      08027658 022658 000008 04  WA  0   0  4
  [10] .data             PROGBITS        20000000 023000 001398 00  WA  0   0  8
  [11] .bss              NOBITS          20001398 024398 00f740 00  WA  0   0  8
  [12] ._user_heap_stack NOBITS          20010ad8 024398 002000 00  WA  0   0  1
  [13] .ARM.attributes   ARM_ATTRIBUTES  00000000 024398 000030 00      0   0  1
  [14] .comment          PROGBITS        00000000 0243c8 000039 01  MS  0   0  1
  [15] .debug_info       PROGBITS        00000000 024401 1f27e9 00      0   0  1
  [16] .debug_abbrev     PROGBITS        00000000 216bea 020d3e 00      0   0  1
  [17] .debug_aranges    PROGBITS        00000000 237928 00cc90 00      0   0  8
  [18] .debug_rnglists   PROGBITS        00000000 2445b8 009c3c 00      0   0  1
  [19] .debug_line       PROGBITS        00000000 24e1f4 06ef95 00      0   0  1
  [20] .debug_str        PROGBITS        00000000 2bd189 1d4157 01  MS  0   0  1
  [21] .debug_frame      PROGBITS        00000000 4912e0 03a014 00      0   0  4
  [22] .debug_line_str   PROGBITS        00000000 4cb2f4 0001bc 01  MS  0   0  1
  [23] .debug_loclists   PROGBITS        00000000 4cb4b0 001e9b 00      0   0  1
  [24] .symtab           SYMTAB          00000000 4cd34c 00f260 10     25 2637  4
  [25] .strtab           STRTAB          00000000 4dc5ac 01f90f 00      0   0  1
  [26] .shstrtab         STRTAB          00000000 4fbebb 00012b 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),
  D (mbind), y (purecode), p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x08005000 0x08005000 0x22660 0x22660 RWE 0x1000
  LOAD           0x023000 0x20000000 0x08027660 0x01398 0x01398 RW  0x1000
  LOAD           0x000398 0x20001398 0x20001398 0x00000 0x11740 RW  0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .isr_vector .build_info .text .rodata .ARM .init_array .fini_array
   01     .data
   02     .bss ._user_heap_stack

There is no dynamic section in this file.

It seams that the linker try to align the code to 4kB and not to 2kB.
There is a way to force the linker to align the code to 2kB?

The same linkerscript is used to compile FW for a CortexM7 processor, with 2MB of Flash and a different Flash partition, in this case the Flash partition is compatible with 4kB alignment.

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        08040000 001000 0001f8 00   A  0   0  1
  [ 2] .build_info       PROGBITS        080401f8 0011f8 000098 00   A  0   0  4
  [ 3] .text             PROGBITS        08040290 001290 0939d8 00  AX  0   0 16
  [ 4] .rodata           PROGBITS        080d3c68 094c68 025f18 00   A  0   0  8
  [ 5] .ARM.extab        PROGBITS        080f9b80 0beea0 000000 00   W  0   0  1
  [ 6] .ARM              ARM_EXIDX       080f9b80 0bab80 000008 00  AL  3   0  4
  [ 7] .preinit_array    PREINIT_ARRAY   080f9b88 0beea0 000000 04  WA  0   0  1
  [ 8] .init_array       INIT_ARRAY      080f9b88 0bab88 000070 04  WA  0   0  4
  [ 9] .fini_array       FINI_ARRAY      080f9bf8 0babf8 000008 04  WA  0   0  4
  [10] .data             PROGBITS        20000000 0bb000 003ea0 00  WA  0   0  8
  [11] .dma              NOBITS          20078000 0bf000 0030a0 00  WA  0   0  4
  [12] .bss              NOBITS          20003ea0 0beea0 03fca0 00  WA  0   0  8
  [13] ._user_heap_stack NOBITS          20043b40 0beea0 004800 00  WA  0   0  1
  [14] .ARM.attributes   ARM_ATTRIBUTES  00000000 0beea0 00002e 00      0   0  1
  [15] .comment          PROGBITS        00000000 0beece 0000a9 01  MS  0   0  1
  [16] .debug_info       PROGBITS        00000000 0bef77 b262bd 00      0   0  1
  [17] .debug_abbrev     PROGBITS        00000000 be5234 063c2c 00      0   0  1
  [18] .debug_aranges    PROGBITS        00000000 c48e60 02be48 00      0   0  8
  [19] .debug_rnglists   PROGBITS        00000000 c74ca8 025d1f 00      0   0  1
  [20] .debug_line       PROGBITS        00000000 c9a9c7 168d5a 00      0   0  1
  [21] .debug_str        PROGBITS        00000000 e03721 1d9a755 01  MS  0   0  1
  [22] .debug_frame      PROGBITS        00000000 2b9de78 0ca8ac 00      0   0  4
  [23] .debug_line_str   PROGBITS        00000000 2c68724 0001c9 01  MS  0   0  1
  [24] .debug_loclists   PROGBITS        00000000 2c688ed 05e172 00      0   0  1
  [25] .debug_loc        PROGBITS        00000000 2cc6a5f 0002dd 00      0   0  1
  [26] .debug_ranges     PROGBITS        00000000 2cc6d3c 000030 00      0   0  1
  [27] .symtab           SYMTAB          00000000 2cc6d6c 05bbf0 10     28 15989  4
  [28] .strtab           STRTAB          00000000 2d2295c 240e77 00      0   0  1
  [29] .shstrtab         STRTAB          00000000 2f637d3 000149 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),
  D (mbind), y (purecode), p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001000 0x08040000 0x08040000 0xb9c00 0xb9c00 RWE 0x1000
  LOAD           0x0bb000 0x20000000 0x080f9c00 0x03ea0 0x03ea0 RW  0x1000
  LOAD           0x000ea0 0x20003ea0 0x20003ea0 0x00000 0x444a0 RW  0x1000
  LOAD           0x000000 0x20078000 0x20078000 0x00000 0x030a0 RW  0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .isr_vector .build_info .text .rodata .ARM .init_array .fini_array
   01     .data
   02     .bss ._user_heap_stack
   03     .dma

There is no dynamic section in this file.

The linker script is the following, with a different definition for Cortex M4 or Cortex M7:


INCLUDE "hw_linkerdefs.ld"

/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = _LINKER_StartStack;    /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = _LINKER_Min_Heap_Size;      /* required amount of heap  */
_Min_Stack_Size = _LINKER_Min_Stack_Size; /* required amount of stack */

_heap_upper_limit = _estack - _LINKER_Min_Stack_Size;
_dmaAreaStart     = _LINKER_DMA_AREASTART;

/* Specify the memory areas */
/* ensure consistency to SCB->VTOR defined in system_stm32l4xx.c */
/* IMAGETYPE is replaced by cmake into either APP or BOOT*/
MEMORY
{
RAM (xrw)      : ORIGIN = _LINKER_RAM_BASEADDR,            LENGTH = _LINKER_RAM_SIZE
FLASH (rx)     : ORIGIN = _LINKER_APP_FLASHSTART, LENGTH = _LINKER_APP_FLASHSIZE
FLAGSAREA (r)  : ORIGIN = FLAGS_ADDR,                      LENGTH = 1024 
DMARAM (rw)    : ORIGIN = _LINKER_DMA_AREASTART,           LENGTH = _LINKER_DMA_AREASIZE
}

/* Define output sections */
SECTIONS
{

  /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(8);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(8);
  } >FLASH

  /* This is the area reserved for build info */
  .build_info :
  {
    . = ALIGN(8);
    KEEP(*(.build_info_index))
    *(.build_info_area)
    . = ALIGN(8);
  } > FLASH

  /* The program code and other data goes into FLASH */
  .text :
  {
    . = ALIGN(8);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(8);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH

  /* Constant data goes into FLASH */
  .rodata :
  {
    . = ALIGN(8);
    KEEP(*(*.uxTopUsedPriority))
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(8);
  } >FLASH

  .ARM.extab   : 
  { 
  . = ALIGN(8);
  *(.ARM.extab* .gnu.linkonce.armextab.*)
  . = ALIGN(8);
  } >FLASH
  .ARM : {
    . = ALIGN(8);
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
    . = ALIGN(8);
  } >FLASH

  .preinit_array     :
  {
    . = ALIGN(8);
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
    . = ALIGN(8);
  } >FLASH
  
  .init_array :
  {
    . = ALIGN(8);
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
    . = ALIGN(8);
  } >FLASH
  .fini_array :
  {
    . = ALIGN(8);
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
    . = ALIGN(8);
  } >FLASH

  /* used by the startup to initialize data */
  _sidata = LOADADDR(.data);

  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data : 
  {
    . = ALIGN(8);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */

    . = ALIGN(8);
    _edata = .;        /* define a global symbol at data end */
  } >RAM AT> FLASH

  /* This is only useful for the bootloader build in case it includes the default flags area */
  .bootloader_default_flags :
  {
    KEEP(*(.bootloader_default_flags))
  } > FLAGSAREA

  /* this rule places the .dma buffers into the DMA area of RAM */
  .dma (NOLOAD):
  {
    *(.dma)
  } > DMARAM

  
  /* Uninitialized data section */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss secion */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >RAM

  /* User_heap_stack section, used to check that there is enough RAM left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( _end_static_memory = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >RAM

  

  /* Remove information from the standard libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }

  .ARM.attributes 0 : { *(.ARM.attributes) }
}

the code is copiled with xpack-arm-none-eabi-gcc-13.3.1-1.1 toolchanin.

5

I found the Solution!
My problem is a duplication of: Flashing of ELF file using OpenOcd causes the ELF header to be written to Flash
Searching a solution I found this: How to change alignment of code segment in ELF.

The solution is reducing the maximum page size at 2kB adding the linker option: -z max-page-size=2048.

After that the ELF is correctly formatted and C-Lion/OpenOCD can load the code correctly.
The ELF after the change is:

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        08005800 000800 000198 00   A  0   0  1
  [ 2] .build_info       PROGBITS        08005998 000998 0000a8 00   A  0   0  4
  [ 3] .text             PROGBITS        08005a40 000a40 01f258 00  AX  0   0 16
  [ 4] .rodata           PROGBITS        08024c98 01fc98 002420 00   A  0   0  4
  [ 5] .ARM.extab        PROGBITS        080270b8 023b28 000000 00   W  0   0  1
  [ 6] .ARM              ARM_EXIDX       080270b8 0220b8 000008 00  AL  3   0  4
  [ 7] .preinit_array    PREINIT_ARRAY   080270c0 023b28 000000 04  WA  0   0  1
  [ 8] .init_array       INIT_ARRAY      080270c0 0220c0 000038 04  WA  0   0  4
  [ 9] .fini_array       FINI_ARRAY      080270f8 0220f8 000008 04  WA  0   0  4
  [10] .data             PROGBITS        20000000 022800 001328 00  WA  0   0  8
  [11] .bss              NOBITS          20001328 023b28 00f63c 00  WA  0   0  8
  [12] ._user_heap_stack NOBITS          20010964 023b28 002004 00  WA  0   0  1
  [13] .ARM.attributes   ARM_ATTRIBUTES  00000000 023b28 000030 00      0   0  1
  [14] .comment          PROGBITS        00000000 023b58 000039 01  MS  0   0  1
  [15] .debug_info       PROGBITS        00000000 023b91 1f1974 00      0   0  1
  [16] .debug_abbrev     PROGBITS        00000000 215505 020d17 00      0   0  1
  [17] .debug_aranges    PROGBITS        00000000 236220 00cc58 00      0   0  8
  [18] .debug_rnglists   PROGBITS        00000000 242e78 009c0f 00      0   0  1
  [19] .debug_line       PROGBITS        00000000 24ca87 06ece9 00      0   0  1
  [20] .debug_str        PROGBITS        00000000 2bb770 1cc606 01  MS  0   0  1
  [21] .debug_frame      PROGBITS        00000000 487d78 039f0c 00      0   0  4
  [22] .debug_line_str   PROGBITS        00000000 4c1c84 0001bc 01  MS  0   0  1
  [23] .debug_loclists   PROGBITS        00000000 4c1e40 001e9b 00      0   0  1
  [24] .symtab           SYMTAB          00000000 4c3cdc 00ef20 10     25 2604  4
  [25] .strtab           STRTAB          00000000 4d2bfc 01d74e 00      0   0  1
  [26] .shstrtab         STRTAB          00000000 4f034a 00012b 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),
  D (mbind), y (purecode), p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000800 0x08005800 0x08005800 0x21900 0x21900 RWE 0x800
  LOAD           0x022800 0x20000000 0x08027100 0x01328 0x01328 RW  0x800
  LOAD           0x000328 0x20001328 0x20001328 0x00000 0x11640 RW  0x800

 Section to Segment mapping:
  Segment Sections...
   00     .isr_vector .build_info .text .rodata .ARM .init_array .fini_array
   01     .data
   02     .bss ._user_heap_stack

There is no dynamic section in this file.

There are no relocations in this file.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật