代码之家  ›  专栏  ›  技术社区  ›  sparklewhiskers

LD链接器:目标地址对齐,但不是ROM中的地址

  •  2
  • sparklewhiskers  · 技术社区  · 15 年前

    .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对齐。因此,我的复制到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++
    

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

    .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
    

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

    克里斯

    2 回复  |  直到 15 年前
        1
  •  3
  •   sparklewhiskers    15 年前

    通过使用不同形式的“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中,因为它是只读的。在我的系统上,flash无法处理浮点常量所需的访问类型,因此我确实需要将其复制到RAM中,即使它不会被修改)。

        2
  •  -1
  •   user3923658    10 年前

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

    .section_name是要对齐的输出节的名称,可以是任何合法名称。冒号左侧的ALIGN语句影响VMA对齐,冒号右侧的ALIGN语句影响LMA对齐。在您的情况下,您希望vma_校准=lma_校准=4。请参阅GNU链接器参考手册的第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--
    }