.data节之前的无法解释的空内存地址

时间:2019-02-12 18:01:15

标签: ld stm32 elf hex-file

我目前正在STM32上编写一个程序,该程序使用一个简单的引导程序和两个子应用程序。子应用程序位于闪存中,引导加载程序将其中一个(代码和数据)加载到RAM存储器中,然后开始执行它。简单地通过遍历闪存中的地址并将数据从这些地址复制到RAM即可完成复制。

最近我遇到了一些奇怪的错误。我试图从全局定义的数组中读取一些数据。我找回错误的值,例如当我尝试阅读array[0]时,我得到了array[1]的值。

我对.elf和.hex文件进行了一些调试和反汇编,我认为我已找到导致此错误的原因。原来,该项目的.elf文件的.ARM节之间没有空格。
令人惊讶的是,.hex文件(我用来刷新STM32板)中没有此空白空间。
这就是我在说的:

  • .elf文件:
2000ee70:   469e        mov lr, r3
2000ee72:   4770        bx  lr

Disassembly of section .ARM:

2000ee74 <__exidx_start>:
2000ee74:   7fff267c    svcvc   0x00ff267c
2000ee78:   00000001    andeq   r0, r0, r1

Disassembly of section .data:

2000ee80 <evnames.5255>:
2000ee80:   00000000    andeq   r0, r0, r0
2000ee84:   08030104    stmdaeq r3, {r2, r8}
  • .hex文件:
 802de70:   4770469e    
 802de74:   7fff267c    svcvc   0x00ff267c
 802de78:   00000001    andeq   r0, r0, r1
 802de7c:   00000000    andeq   r0, r0, r0
 802de80:   08030104    stmdaeq r3, {r2, r8}

显然,地址不同,因为.elf文件中的地址是VMA,而.hex文件中的地址是LMA。
我在这里注意到的是,在.ARM部分之后,下一个内存地址应为2000ee7C,但是出于未知原因,.data部分从2000ee80开始。因此,它们之间只有一个无法解释的空词。但是,.hex文件中不存在此空词。 00000001之后紧跟00000000
因此,基本上,我认为.hex文件的反汇编应输出以下结果:

 802de70:   4770469e    
 802de74:   7fff267c    svcvc   0x00ff267c
 802de78:   00000001    andeq   r0, r0, r1
 802de7c:       <something here>
 802de80:   00000000    andeq   r0, r0, r0
 802de84:   08030104    stmdaeq r3, {r2, r8}

由于这个空的内存空间(在.hex文件中消失了),当我的引导加载程序将数据加载到RAM时,LMA为array[0]的{​​{1}}最终位于地址{{1 }}。

这是我使用的链接脚本的令人讨厌的片段:

2000eec8

我使用以下命令将.o文件链接为一个.elf文件:

2000eec4

我使用以下命令将.elf文件转换为.hex文件:

  /* ARM specific sections, they also go to FLASH and are copied to RAM */
  .ARM.extab : { 
      *(.ARM.extab* .gnu.linkonce.armextab.*) 
  } > RAMAPP AT> FLASH_APP
  .ARM : {
      __exidx_start = .;
      *(.ARM.exidx*)
      __exidx_end = .;
  } > RAMAPP AT> FLASH_APP

  /* Initialized data sections - variables etc.  */
  .data :
  {
      . = ALIGN(4);
      *(.data)           /* .data sections */
      *(.data*)          /* .data* sections */
      . = ALIGN(4);    
  } >RAMAPP AT> FLASH_APP /* Data section is placed in FLASH_APP but its Virtual Memory Address is in RAM_APP */

我尝试尝试使用给arm-none-eabi-gcc -Wl,--gc-sections -mthumb -mthumb-interwork -mcpu=cortex-m4 --specs=nosys.specs -L[path_to_library_files] -T[path_to_ld_file] [long_list_of_object_files] -o [output_elf_file] arm-none-eabi-objcopy -O ihex [elf_file] [output_hex_file] 的参数来摆脱这种填充,例如arm-none-eabi-objcopyarm-none-eabi-gcc,但没有到目前为止成功。

有人知道这个空白来自何处以及如何清除它(或将其包含在.hex文件中)吗?

编辑:根据前两个评论的建议,我已经尝试过:
 *在我的工具链中使用--file-alignment--gap-fill的最新版本,
 * arm-none-eabi-gcc部分的arm-none-eabi-objcopy
 *不将ALIGN(4)节复制到RAM。
不幸的是,这些解决方案都无法解决此问题。

我最近注意到,有时数据在.ARM文件中正确对齐(.ARM部分的第一个地址是紧跟{{1 }} 部分)。它取决于.elf部分恰好结束的地址。我可以通过在代码中添加一些额外的函数调用(导致较大的.data区域)来操纵它,例如:

.ARM

这样,我就确定了:
 *当.ARM部分在地址.text处结束时,2000ee84: 469e mov lr, r3 2000ee86: 4770 bx lr Disassembly of section .ARM: 2000ee88 <__exidx_start>: 2000ee88: 7fff2668 svcvc 0x00ff2668 2000ee8c: 00000001 andeq r0, r0, r1 Disassembly of section .data: 2000ee90 <evnames.5255>: 2000ee90: 00000000 andeq r0, r0, r0 2000ee94: 2001111c andcs r1, r1, ip, lsl r1 部分错误地从.ARM开始(应为0x*******0
 *当.data部分在地址0x*******8处结束时,0x*******4部分错误地从.ARM开始(应为0x*******8
 *当.data部分在地址0x*******0处结束时,0x*******C部分正确地从.ARM开始
 *当0x*******4部分在地址.data处结束时,0x*******8部分的正确位置开始于.ARM

1 个答案:

答案 0 :(得分:0)

好的,事实证明,我不得不在链接描述文件的.data部分添加ALIGN_WITH_INPUT。像这样:

  .data : ALIGN_WITH_INPUT
  {
    . = ALIGN(4);
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
    . = ALIGN(4);    

  } >RAMAPP AT> FLASH_APP

此参数使节的LMA与VMA对齐。 现在.hex文件中的对齐方式与.elf文件中的对齐方式相同。
向Reddit用户FreddieChopin大喊大叫,后者帮助我解决了这个问题。