【问题标题】:LD linker: Target address aligning but not address in ROMLD 链接器:目标地址对齐但不在 ROM 中的地址
【发布时间】:2010-12-16 07:53:51
【问题描述】:

我有一个驻留在闪存中的程序,它将从闪存中运行。在程序的早期,数据段从闪存复制到内存。我正在使用类似(简化)的链接器脚本:

.text      :
{
  *(.text)
} > FLASH
_etext = .;
PROVIDE (etext = .);

.rodata     :
{
  PROVIDE(__COPY_DATA_START__ = .); 
  *(.rodata) 
} > ram AT>flash

PROVIDE (__SDATA2_START__ = .);
.sdata2   :
{ 
  *(.sdata2)
} > ram AT>flash

PROVIDE (__sbss2_start = . );
.sbss2   : { 
  *(.sbss2) 
  . = ALIGN(4)
} > ram AT>flash
PROVIDE (__sbss2_end = . );
PROVIDE (__SBSS2_END__ = .);

.data    :
{
  *(.data)
  *(.gnu.linkonce.d*)
  CONSTRUCTORS
  *(.eh_frame)
} > ram AT>flash
PROVIDE (__END_COPY__ = .);

我希望这些部分在 4 字节边界上对齐(架构是 PowerPC 32 位)。一些数据部分包括子词项。我发现 ALIGN 指令对齐 RAM 中的 VMA 地址,但不对齐 LMA。所以我的 copy-to-ram 例程失败了,因为这两个区域没有逐字节对应。

我的复制程序看起来像

r3 = address in flash of _etext
r4 = address in ram of __COPY_DATA_START__
words to copy = (__END_COPY__ - COPY_DATA_START) / 4

while (words to copy)
  * r4++ = *r3++

当循环到达对齐位时,目标指向一些填充字节,但源数据不包括对齐填充,因此数据太早放入内存中。

我可以从地图文件中看出这一点,因为它看起来像(人为的例子)

.rodata         0x00000000      0xb15 load address 0xfff13000
                0x00000000                PROVIDE (__COPY_DATA_START__, .)

.sdata          0x00000b18      0x10  load address 0xfff13b15  <<< origin 0xb18 is aligned but load address hasn't moved on by the padding bytes

有人知道这个问题的解决方法吗?

谢谢

克里斯

【问题讨论】:

    标签: embedded linker


    【解决方案1】:

    通过使用不同形式的“AT”链接描述文件命令,我取得了一些成功。如果我使用

      _etext = .;
      PROVIDE (etext = .);
      .rodata : AT (_etext)
      { 
    ... contents of section ...
      }
    
      .sdata2 : AT (_etext + SIZEOF(.rodata) + SIZEOF(.gcc_except_table))
      { 
    ... contents of section ...
      } > ram
    
      .sbss2 : AT (_etext + SIZEOF(.rodata) + SIZEOF(.gcc_except_table) + SIZEOF(.sdata2) )
      { 
    ... contents of section ...
        . = ALIGN(16);
      } > ram 
    

    然后它似乎与我预期的一致。 SIZEOF( ) + SIZEOF( ) ... 字符串在文件末尾会变得很长,但至少它可以工作。

    (附加信息:通常您不会将rodata部分复制到ram中,因为它是只读的。在我的系统上,闪存无法处理浮点常量所需的访问类型,因此我确实需要将其复制到RAM,即使它不会被修改)。

    【讨论】:

      【解决方案2】:

      您似乎没有说明您正在使用哪个链接器,但您的脚本看起来像一个 GNU 链接器脚本(所以我假设它是)。要使用 GNU 链接描述文件对齐部分的 VMA 和 LMA,请执行以下操作...

      .section_name ALIGN( vma_alignment ) : ALIGN( lma_alignment ){
        ...section contents
      }
      

      .section_name 是要对齐的输出节的名称,可以是任何合法名称。冒号左侧的 ALIGN 语句影响 VMA 对齐,冒号右侧的 ALIGN 语句影响 LMA 对齐。在您的情况下,您需要 vma_alignment = lma_alignment = 4。请参阅 GNU Linker 参考手册的第 3.6.1 节。

      所以您的整个脚本应该如下所示...

      .text      :
      {
        *(.text)
      } > FLASH
      _etext = .;
      PROVIDE (etext = .);
      
      .rodata ALIGN(4)  : ALIGN(4)
      {
        PROVIDE(__VMA_COPY_DATA_START__ = ADDR(.rodata)); /*The runtime address of .rodata*/
        PROVIDE(__LMA_COPY_DATA_START__ = LOADADDR(.rodata)); /*The load address of .rodata*/
      
        *(.rodata) 
      } > ram AT>flash
      
      PROVIDE (__SDATA2_START__ = .);
      .sdata2   :
      { 
        *(.sdata2)
      } > ram AT>flash
      
      PROVIDE (__sbss2_start = . );
      .sbss2   : { 
        *(.sbss2) 
        . = ALIGN(4)
      } > ram AT>flash
      PROVIDE (__sbss2_end = . );
      PROVIDE (__SBSS2_END__ = .);
      
      .data    :
      {
        *(.data)
        *(.gnu.linkonce.d*)
        CONSTRUCTORS
        *(.eh_frame)
      } > ram AT>flash
       /*
       *align address so that (__END_COPY__ -  __VMA_COPY_DATA_START__) / 4 does not round down.
       *If alignment is not done then the copy routine could potentially drop up to 3 bytes at 
       *the end of the .data section if the section does not end on a multiple of 4 bytes.
       */
      . = ALIGN(4)
      PROVIDE (__END_COPY__ = .);
      

      你的复制程序看起来像......

      r3 = address in flash of __LMA_COPY_DATA_START__
      r4 = address in ram of   __VMA_COPY_DATA_START__
      words_to_copy = (__END_COPY__ -  __VMA_COPY_DATA_START__) / 4
      
      while (words_to_copy){
        * r4++ = *r3++
        words_to_copy--
      }
      

      【讨论】:

      • 这个答案是错误的。冒号后的 ALIGN(x) NOT 设置 LMA 对齐方式。我刚刚用 binutils 2.25 尝试过。
      猜你喜欢
      • 2016-05-16
      • 2023-03-12
      • 1970-01-01
      • 2013-03-20
      • 2018-05-02
      • 2012-04-18
      • 1970-01-01
      • 2011-12-11
      • 2012-06-12
      相关资源
      最近更新 更多