(Cortex M4) ELF 文件中的部分对齐错误

问题描述 投票:0回答:1

我们在 Cortex M4 MCU 上遇到了一个奇怪的问题。如果在正确的部分使用 ST-LINK 加载二进制文件,则编译后的固件可以工作,但使用 C-Lion 和 OpenOcd,FW 加载操作还会加载 FLASH 中的 ELF 标头并损坏引导加载程序使用的标志区域。

MCU Flash 大小为 512 kB - 总共 256 页(每页 2kB),布局如下:

+-------- 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                           |
|                                                           |
+-----------------------------------------------------------+

App FW必须从

0x0800 8500
开始加载,用ST-LINK加载.bin是正确的,但是在C-Lion中加载FW,代码是从
0x0800 8500
开始正确加载的,但也错误地加载了ELF 文件加载于
0x0800 5000

使用readelf分析ELF文件,显示以下信息:

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.

看起来链接器尝试将代码对齐到 4kB 而不是 2kB。 有办法强制链接器将代码对齐到2kB吗?

使用相同的链接描述文件为 CortexM7 处理器编译固件,具有 2MB 闪存和不同的闪存分区,在这种情况下,闪存分区与 4kB 对齐兼容。

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) }
}

代码是用

xpack-arm-none-eabi-gcc-13.3.1-1.1
工具链编译的。

gcc arm clion cortex-m openocd
1个回答
0
投票

我找到了解决方案! 我的问题是重复的:使用 OpenOcd 刷新 ELF 文件会导致 ELF 标头写入 Flash 搜索解决方案我发现了这个:如何更改 ELF 中代码段的对齐方式

解决方案是将最小页面大小减小到 2kB,添加链接器选项:

-z max-page-size=2048

之后 ELF 格式正确,C-Lion/OpenOCD 可以正确加载代码。 改变后的ELF为:

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.

© www.soinside.com 2019 - 2024. All rights reserved.