链接脚本.relocate节的第一个符号,_srelocate,是不正确(GCC漏洞?) [英] Linker script .relocate section's first symbol, _srelocate, is incorrect (GCC Bug?)

查看:603
本文介绍了链接脚本.relocate节的第一个符号,_srelocate,是不正确(GCC漏洞?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题

我的问题是,当我使用的,其目的是在code放入RAM的移居部分下面的脚本被充满虚假的数据。

我的问题是:


  1. 为什么比 _etext 符号越大 _srelocate 符号4个字节?难道他们不应该是一样的吗?


  2. 此外,如果答案为1是NO,我不应该从 _etext + 4 复制到 _srelocate


背景和相关的code

我与爱特梅尔ATSAM3N4X系列处理器(了ARM Cortex M3)的工作,愿与我的链接脚本和 .relocate 部分初始化。

这样做的原因是, _etext 符号大于 _srelocate 符号少4个字节。

下面的链接器脚本是由Atmel Studio 6中产生(默认脚本,如果你想在 RAM / ROM 符号位置看到 Apendix 的问题)。

  / * ------------------------------------ ----------------------------------------
 * SAM软件包许可证
 * ------------------------------------------------- ---------------------------
 *版权所有(C)2012 Atmel公司
 *
 * 版权所有。
 *
 *再分发和使用源代码和二进制的形式,有或无
 *变形例中,则允许使满足下列条件:
 *
 * - 源$ C ​​$ C的再分发必须保留以上版权声明,
 *此条件列表及以下免责声明。
 *
 * Atmel公司的名称,不得使用宣传或推销衍生产品
 *该软件没有事先书面许可。
 *
 *免责声明:本软件提供了由ATMEL原样任何EX $ P $干燥综合征或
 *默示的担保,包括但不限于,的暗示担保
 *适销性,特定目的和不侵权ARE
 *承担责任。在任何情况下ATMEL对任何直接,间接,
 *偶然,特殊,惩戒性的或后果性损害(包括但
 *仅限于替代商品或服务的采购;使用损失,数据,
 *或利润损失;或业务中断)但是造成和任何理论的
 *责任,不论是合同,严格责任或侵权(包括
 *疏忽或其它)承担任何责任出了使用本软件,
 *即使已被告知发生此类损害的可能性。
 * ------------------------------------------------- ---------------------------
 * // *节定义* /
截面
{
    的.text:
    {
        。 = ALIGN(4);
        _sfixed =。
        KEEP(*(向量.vectors。*))
        *(文本的.text。* .gnu.linkonce.t。*)
        *(glue_7t)*(。glue_7)
        *(rodata .RODATA * .gnu.linkonce.r。*)
        *(* ARM.extab .gnu.linkonce.armextab。*)        / *载体C的构造,并在这两个用户$ C C C的析构函数
           和C库。这也提供了C ++ code支持。 * /
        。 = ALIGN(4);
        KEEP(*(INIT))
        。 = ALIGN(4);
        __ preinit_array_start =。
        KEEP(*(preinit_array))
        __ preinit_array_end =。        。 = ALIGN(4);
        __init_array_start =。
        KEEP(*(SORT(.init_array。*)))
        KEEP(*(init_array))
        __init_array_end =。        。 = ALIGN(为0x4);
        KEEP(* crtbegin.o(.ctors))
        KEEP(*(EXCLUDE_FILE(* crtend.o).ctors))
        KEEP(*(SORT(.ctors。*)))
        KEEP(* crtend.o(.ctors))        。 = ALIGN(4);
        KEEP(*(FINI))        。 = ALIGN(4);
        __fini_array_start =。
        KEEP(*(fini_array))
        KEEP(*(SORT(.fini_array。*)))
        __fini_array_end =。        KEEP(* crtbegin.o(.dtors))
        KEEP(*(EXCLUDE_FILE(* crtend.o).dtors))
        KEEP(*(SORT(.dtors。*)))
        KEEP(* crtend.o(.dtors))        。 = ALIGN(4);
        _efixed =。 / *文字节结束* /
    }>随机存取存储器    。 = ALIGN(4);
    _etext =。    .relocate:AT(_etext)
    {
        。 = ALIGN(4);
        _srelocate =。
        *(。ramfunc .RAMFUNC *);
        *(数据的.data *);
        。 = ALIGN(4);
        _erelocate =。
    }>随机存取存储器    / * .bss段是用于未初始化的数据* /
    .bss段(NOLOAD):
    {
        。 = ALIGN(4);
        _sbss =。 ;
        _szero =。
        *(BSS的.bss。*)
        *(共同)
        。 = ALIGN(4);
        _ebss =。 ;
        _ezero =。
    }>随机存取存储器    / *堆栈段* /
    .STACK(NOLOAD):
    {
        。 = ALIGN(8);
        _sstack =。
        。 =。 + STACK_SIZE;
        。 = ALIGN(8);
        _estack =。
    }>随机存取存储器    / * .ARM.exidx进行排序,所以在自己的输出部分中去。 * /
    PROVIDE_HIDDEN(__exidx_start =。);
    .ARM.exidx:
    {
      *(* ARM.exidx .gnu.linkonce.armexidx。*)
    }>随机存取存储器
    PROVIDE_HIDDEN(__exidx_end =。);    。 = ALIGN(4);
    _end =。 ;
}

我用纳米来看看有什么符号值分别为,我已经包括以下这些:

  2000115c一个_etext
20001160Ð_srelocate
200015c8Ð_erelocate

现在,爱特梅尔Studio 6中自动生成我的项目,并给了我一个 Reset_Handler()的副本 .relocate _etext 部分 _srelocate 并清除的.bss 部分。该项目来了有两个连接器脚本,一个是基于FLASH的执行,一个是基于RAM code。默认值是基于FLASH code,但我改变了对基于RAM链接脚本(上面提供),并跑进问题。

初​​始化code那份从FLASH中的 .relocate 部分RAM也是自动生成的,当我改变链接脚本我并没有改变它。它看起来是这样的:

 无效Reset_Handler(无效)
{
    uint32_t的* PSRC,* pDest,尺寸;    / *初始化移居段* /
    PSRC =安培; _etext;
    pDest =安培; _srelocate;    如果(PSRC!= pDest){
        对于(; pDest<&安培; _erelocate;){
            * pDest ++ = * PSRC ++;
        }
    }    / *清除零段* /
    对于(pDest =安培; _szero; pDest<&安培; _ezero;){
        * pDest ++ = 0;
    }    / *设置矢量表基址* /
    PSRC =(uint32_t的*)及_sfixed;
    SCB-> VTOR =((uint32_t的)PSRC和放大器; SCB_VTOR_TBLOFF_Msk);    如果(((uint32_t的)PSRC&GT = IRAM_ADDR)及及((uint32_t的)PSRC&所述; IRAM_ADDR + IRAM_SIZE)){
        SCB-> VTOR | =(1UL)LT;< SCB_VTOR_TBLBASE_Pos;
    }    / *初始化C库* /
    __libc_init_array();    / *分公司主要功能* /
    主要();    /* 无限循环 */
    而(1);
}

编辑1:

使用 objdump的-t codeFile.elf> codeFile.symbols ,我发现我的 .relocate 部分的开始,这似乎表明, _srelocate 并不真正指向的开头 .relocate

  2000115c克邻.relocate 00000000 .hidden __TMC_END__

这是什么符号?

我看着它,并在GCC 4.7中发现这个bug,但如果在我的版本的固定或不想不通。

我的编译器是臂无 - EABI - 海合会,并指出其版本 4.7.0 ...
该链接器是臂无 - EABI-LD 且版本 2.22

编辑2:

我做这个一些研究,它被记录在<一个href=\"http://stackoverflow.com/questions/17605794/what-are-linker-symbols-tmc-end-and-tmc-list-for\">this相关SO质疑我问。请看它为好,因为它解释说,这个问题是一个 GCC错误

Apendix

的链接描述文件存储布局

  OUTPUT_FORMAT(ELF32-littlearm,ELF32-littlearm,ELF32-littlearm)
OUTPUT_ARCH(ARM)
SEARCH_DIR(。)/ *内存空间定义* /
记忆
{
    ROM(RX):ORIGIN = 0x00400000,长度= 0x00040000 / *闪光,256K * /
    RAM(RWX):ORIGIN = 0x20000000,长度= 0x00006000 / * SRAM,24K * /
}/ *应用程序使用的堆栈大小。注意:您需要调整* /
STACK_SIZE = DEFINED(STACK_SIZE)? STACK_SIZE:为0x800;


解决方案

我早就发现了这个答案我自己的问题,但它似乎仍然在我的编辑有点不清楚所以请允许我在这里正式化。

问题是,由于GCC中错误连接器插入一个额外的 TMC_END 符号占用4字节在我的 _etext _srelocate 符号之间。这是不正确,因为这个符号无关与code,我正在写,我也不使用此功能。我发现,在我的<一说明了这href=\"http://stackoverflow.com/questions/17605794/what-are-linker-symbols-tmc-end-and-tmc-list-for\">other SO质疑。

解决方法:

Atmel的样本code,正确地假定,如果你的code已经不多了闪存的 _srelocate 符号的地址和 _etext 符号的地址将是不同的,有开始 0x20的地址为0x004 ... ,另一个..

如果您code正在运行的RAM,这意味着你有一个引导程序的有关章节的副本到正确的内​​存位置,因此 _etext 符号的地址也将驻留在内存和等于 _srelocate 符号的地址。

因此​​爱特梅尔正在努力确保该 _srelocate 部分始终驻留在内存中。

由于GCC的bug的解决办法是改变code,以检查 _srelocate 符号的地址已经在RAM中,像这样的:

  //我不记得什么#定义爱特梅尔用于SRAM,所以我只是要
//使用这个对我的例子的目的。
#定义SRAM_START_ADDRESS 0x20000000无效Reset_Handler(无效)
{
    uint32_t的* PSRC,* pDest,尺寸;    / *初始化移居段* /
    PSRC =安培; _etext; //既可以是闪存或SRAM根据您的配置。
    pDest =安培; _srelocate; //总是在SRAM或者有事情有些奇怪?    如果((使用intptr_t)PSRC≤(使用intptr_t)SRAM_START_ADDRESS){//&所述;&所述;&所述;&下;更改code此处&lt;&LT;&LT;&LT;
        //我们在这里只输入,如果PSRC指向在Flash中的位置。
        //如果是这样的话,我们需要将内存从闪存复制到SRAM。
        对于(; pDest&LT;&安培; _erelocate;){
            * pDest ++ = * PSRC ++;
        }
    }    / *清除零段* /
    对于(pDest =安培; _szero; pDest&LT;&安培; _ezero;){
        * pDest ++ = 0;
    }    / *设置矢量表基址* /
    PSRC =(uint32_t的*)及_sfixed;
    SCB-&GT; VTOR =((uint32_t的)PSRC和放大器; SCB_VTOR_TBLOFF_Msk);    如果(((uint32_t的)PSRC&GT = IRAM_ADDR)及及((uint32_t的)PSRC&所述; IRAM_ADDR + IRAM_SIZE)){
        SCB-&GT; VTOR | =(1UL)LT;&LT; SCB_VTOR_TBLBASE_Pos;
    }    / *初始化C库* /
    __libc_init_array();    / *分公司主要功能* /
    主要();    /* 无限循环 */
    而(1);
}

这工作了我的情况。从我所看到的这个错误是固定和修复已被收归所以它是不太可能你将它固定在你的工作室爱特梅尔

Problem

My problem is that when I use the following script which is intended to place the Code into RAM the relocate section gets filled with bogus data.

My question is:

  1. Why is the _srelocate symbol 4 bytes greater than the _etext symbol? Shouldn't they be the same?

  2. Also, if the answer to 1. is NO, shouldn't I be copying from _etext + 4 to _srelocate?

Background and relevant code

I'm working with an Atmel ATSAM3N4X series processor (an ARM Cortex M3) and would like a little help with my linker script and .relocate section initialization.

The reason for this is that the _etext symbol is 4 bytes less than the _srelocate symbol.

The following linker script is the default script generated by Atmel Studio 6 (if you want the ram/rom symbol locations see the Apendix to the question).

/* ----------------------------------------------------------------------------
 *         SAM Software Package License
 * ----------------------------------------------------------------------------
 * Copyright (c) 2012, Atmel Corporation
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the disclaimer below.
 *
 * Atmel's name may not be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ----------------------------------------------------------------------------
 */

/* Section Definitions */
SECTIONS
{
    .text :
    {
        . = ALIGN(4);
        _sfixed = .;
        KEEP(*(.vectors .vectors.*))
        *(.text .text.* .gnu.linkonce.t.*)
        *(.glue_7t) *(.glue_7)
        *(.rodata .rodata* .gnu.linkonce.r.*)
        *(.ARM.extab* .gnu.linkonce.armextab.*)

        /* Support C constructors, and C destructors in both user code
           and the C library. This also provides support for C++ code. */
        . = ALIGN(4);
        KEEP(*(.init))
        . = ALIGN(4);
        __preinit_array_start = .;
        KEEP (*(.preinit_array))
        __preinit_array_end = .;

        . = ALIGN(4);
        __init_array_start = .;
        KEEP (*(SORT(.init_array.*)))
        KEEP (*(.init_array))
        __init_array_end = .;

        . = ALIGN(0x4);
        KEEP (*crtbegin.o(.ctors))
        KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
        KEEP (*(SORT(.ctors.*)))
        KEEP (*crtend.o(.ctors))

        . = ALIGN(4);
        KEEP(*(.fini))

        . = ALIGN(4);
        __fini_array_start = .;
        KEEP (*(.fini_array))
        KEEP (*(SORT(.fini_array.*)))
        __fini_array_end = .;

        KEEP (*crtbegin.o(.dtors))
        KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
        KEEP (*(SORT(.dtors.*)))
        KEEP (*crtend.o(.dtors))

        . = ALIGN(4);
        _efixed = .;            /* End of text section */
    } > ram

    . = ALIGN(4);
    _etext = .;

    .relocate : AT (_etext)
    {
        . = ALIGN(4);
        _srelocate = .;
        *(.ramfunc .ramfunc.*);
        *(.data .data.*);
        . = ALIGN(4);
        _erelocate = .;
    } > ram

    /* .bss section which is used for uninitialized data */
    .bss (NOLOAD) :
    {
        . = ALIGN(4);
        _sbss = . ;
        _szero = .;
        *(.bss .bss.*)
        *(COMMON)
        . = ALIGN(4);
        _ebss = . ;
        _ezero = .;
    } > ram

    /* stack section */
    .stack (NOLOAD):
    {
        . = ALIGN(8);
        _sstack = .;
        . = . + STACK_SIZE;
        . = ALIGN(8);
        _estack = .;
    } > ram

    /* .ARM.exidx is sorted, so has to go in its own output section.  */
    PROVIDE_HIDDEN (__exidx_start = .);
    .ARM.exidx :
    {
      *(.ARM.exidx* .gnu.linkonce.armexidx.*)
    } > ram
    PROVIDE_HIDDEN (__exidx_end = .);

    . = ALIGN(4);
    _end = . ;
}

I used nm to see what the symbol values were and I've included them below:

2000115c A _etext
20001160 D _srelocate
200015c8 D _erelocate

Now, Atmel Studio 6 auto-generated my project and gave me a Reset_Handler() that copies the .relocate section from _etext to _srelocate and clears the .bss section. The project came with two linker scripts, one for FLASH based execution and one for RAM based code. The default is the FLASH based code but I changed that to the RAM based linker script (provided above), and ran into the problem.

The initialization code that copies the .relocate section from FLASH to RAM is also auto-generated and I haven't changed it when I changed linker scripts. It looks like this:

void Reset_Handler(void)
{
    uint32_t *pSrc, *pDest, Size;

    /* Initialize the relocate segment */
    pSrc = &_etext;
    pDest = &_srelocate;

    if (pSrc != pDest) {
        for (; pDest < &_erelocate;) {
            *pDest++ = *pSrc++;
        }
    }

    /* Clear the zero segment */
    for (pDest = &_szero; pDest < &_ezero;) {
        *pDest++ = 0;
    }

    /* Set the vector table base address */
    pSrc = (uint32_t *) & _sfixed;
    SCB->VTOR = ((uint32_t) pSrc & SCB_VTOR_TBLOFF_Msk);

    if (((uint32_t) pSrc >= IRAM_ADDR) && ((uint32_t) pSrc < IRAM_ADDR + IRAM_SIZE)) {
        SCB->VTOR |= (1UL) << SCB_VTOR_TBLBASE_Pos;
    }

    /* Initialize the C library */
    __libc_init_array();

    /* Branch to main function */
    main();

    /* Infinite loop */
    while (1);
}

Edit 1:

Using objdump -t CodeFile.elf > CodeFile.symbols, I have found this symbol at the start of my .relocate section which seems to suggest that _srelocate doesn't truly point to the beginning of .relocate.

    2000115c g     O .relocate  00000000 .hidden __TMC_END__

What is this symbol?

I've looked it up and found this bug in GCC 4.7 but can't figure out if it is fixed or not in my version.

My compiler is arm-none-eabi-gcc and states its version as 4.7.0... The linker is arm-none-eabi-ld and its version is 2.22.

Edit 2:

I have done some research about this and it is recorded in this related SO question that I asked. Please look at it as well, as it explains that the problem is a GCC bug.

Apendix

Memory Layout for Linker Scripts

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)

/* Memory Spaces Definitions */
MEMORY
{
    rom (rx)  : ORIGIN = 0x00400000, LENGTH = 0x00040000 /* flash, 256K */
    ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00006000 /* sram, 24K */
}

/* The stack size used by the application. NOTE: you need to adjust  */
STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : 0x800 ;

解决方案

I had long ago discovered the answer to my own question but it seems that it is still a little unclear in my edits so allow me to formalize it here.

The issue is that due to a bug in GCC the linker inserts an additional TMC_END symbol taking up 4 bytes in between my _etext and _srelocate symbols. This is incorrect because this symbol has nothing to do with the code that I'm writing and I'm not even using this functionality. I had discovered and explained this in my other SO question.

Workaround:

Atmel's sample code, rightly, assumes that if your code is running out of Flash memory your _srelocate symbol's address and _etext symbol's address will be different, one having an address starting with 0x004... and the other with 0x20....

If your code is running out of RAM, this means that you have a bootloader that copies the relevant sections into the correct memory location, hence the _etext symbol's address will also reside in RAM and be equal to the _srelocate symbol's address.

Therefore Atmel is trying to make sure that the _srelocate section always resides in RAM.

Due to the bug in GCC the solution was to change the code to check if the _srelocate symbol's address is already in RAM, like this:

// I can't remember what #define Atmel has for SRAM so I'm just going to
// use this one for the purposes of my example.
#define SRAM_START_ADDRESS 0x20000000

void Reset_Handler(void)
{
    uint32_t *pSrc, *pDest, Size;

    /* Initialize the relocate segment */
    pSrc = &_etext;      // Could either be in Flash or SRAM depending on your configuration.
    pDest = &_srelocate; // Always in SRAM or there's something strange going on...

    if ((intptr_t)pSrc < (intptr_t)SRAM_START_ADDRESS) { // <<<< Changed code here <<<<
        // We enter here only if pSrc is pointing to a location in Flash.
        // If that's the case, we need to copy the memory from Flash to SRAM.
        for (; pDest < &_erelocate;) {
            *pDest++ = *pSrc++;
        }
    }

    /* Clear the zero segment */
    for (pDest = &_szero; pDest < &_ezero;) {
        *pDest++ = 0;
    }

    /* Set the vector table base address */
    pSrc = (uint32_t *) & _sfixed;
    SCB->VTOR = ((uint32_t) pSrc & SCB_VTOR_TBLOFF_Msk);

    if (((uint32_t) pSrc >= IRAM_ADDR) && ((uint32_t) pSrc < IRAM_ADDR + IRAM_SIZE)) {
        SCB->VTOR |= (1UL) << SCB_VTOR_TBLBASE_Pos;
    }

    /* Initialize the C library */
    __libc_init_array();

    /* Branch to main function */
    main();

    /* Infinite loop */
    while (1);
}

And that worked for my situation. From what I can see this bug was fixed and the fix has since been reverted so it is unlikely that you will have it fixed in your Atmel Studio.

这篇关于链接脚本.relocate节的第一个符号,_srelocate,是不正确(GCC漏洞?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆