2013-07-11 8 views
2

問題鏈接腳本.relocate節的第一個符號,_srelocate,是不正確的(GCC漏洞?)

我的問題是,當我使用它的目的是將代碼放到RAM以下腳本移居部分得到充斥着虛假數據。

我的問題是:

  1. 爲什麼比_etext符號越大_srelocate符號4個字節?他們不應該一樣嗎?

  2. 此外,如果1.的答案是NO,我不應該從_etext + 4複製到_srelocate

背景和相關代碼

我與愛特梅爾ATSAM3N4X系列處理器(了ARM Cortex M3)合作,並希望與我的鏈接腳本和.relocate段初始化一點幫助。

原因是_etext符號比_srelocate符號少4個字節。

以下鏈接腳本是由Atmel Studio 6中生成的默認腳本(如果你想ram/rom符號位置看到Apendix的問題)。

/* ---------------------------------------------------------------------------- 
*   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 = . ; 
} 

我用nm,看看有什麼符號值分別爲,我已經包括下面這些:

2000115c A _etext 
20001160 D _srelocate 
200015c8 D _erelocate 

現在,愛特梅爾Studio 6中自動生成我的項目,給了我一個Reset_Handler()該副本.relocate_etext_srelocate的部分,並清除.bss部分。該項目帶有兩個鏈接器腳本,一個用於基於FLASH的執行,另一個用於基於RAM的代碼。默認是基於FLASH的代碼,但我將其更改爲基於RAM的鏈接器腳本(上面提供),並且遇到了問題。

.relocate部分從FLASH複製到RAM的初始化代碼也是自動生成的,並且在更改鏈接器腳本時我沒有更改它。它看起來像這樣:

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

編輯1:

使用objdump -t CodeFile.elf > CodeFile.symbols,我發現我的.relocate節的開始,這似乎表明,_srelocate並不真正指向開始這個符號.relocate

2000115c g  O .relocate 00000000 .hidden __TMC_END__ 

是什麼意思?

我查了一下,發現在GCC 4.7中有this bug,但無法弄清楚它在我的版本中是否已修復。

我的編譯器是arm-none-eabi-gcc4.7.0 ... 鏈接器arm-none-eabi-ld且版本2.22指出其版本。

編輯2:

我已經做了一些有關此研究,它被記錄在this related SO question我問。請看看它,因爲它解釋說問題是GCC bug

Apendix鏈接描述文件

內存佈局

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 ; 

回答

2

我早就發現了這個答案我自己的問題,但它似乎還是有點不清楚在我的編輯,以便允許我在這裏正式確定它。

的問題是,由於bug in GCC接頭插入一個額外的TMC_END符號佔用4個字節在我_etext_srelocate符號之間。這是不正確的,因爲這個符號與我正在編寫的代碼無關,我甚至沒有使用這個功能。我發現並在我的other SO question中解釋了這一點。

解決方法:

Atmel的示例代碼,正確地,假設如果你的代碼運行了閃存的你_srelocate符號的地址和_etext符號的地址是不同的,一個有開始0x004...和地址其他與0x20...

如果您的代碼運行的RAM,這意味着你有一個引導程序是副本的相關章節到正確的內存位置,因此_etext符號的地址也將駐留在內存和等於_srelocate符號的地址。

因此,Atmel正試圖確保_srelocate部分始終駐留在RAM中。

由於GCC的bug的解決辦法是修改代碼以檢查_srelocate符號的地址已經在RAM中,這樣的:

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

這工作了我的情況。從我所看到的這個錯誤已經修復,修復已經恢復,因此您不太可能在Atmel Studio中修復它。

+0

您確實列出了編輯1中的錯誤。感謝您發佈您的解決方法。 – Patrick

+0

對不起,它實際上沒有列出,所以我重新編輯我的問題列出它。 – nonsensickle

+0

僅供參考,似乎'SRAM_START_ADDRESS'也是atmel所稱的#define。它在'mpu.h'標題中,所以你可能需要添加MPU ASF包。 –

0

我不知道如果這是你的問題,但如果你使用的是SAM-BA你的代碼複製到SRAM ,SAM-BA引導程序使用SRAM的第一個2048(0x800)字節作爲變量及其堆棧。也許這就是爲什麼你的重定位部分被踩到了(當你複製代碼時有ISR和其他代碼仍在運行,而這些代碼需要自己的SRAM)。

出於這個原因,所有SAM-BA小應用程序示例都被複制到0x20000800。

我不知道除了實現類似於SAM-BA的東西外,您還需要將代碼放在SRAM中,在這種情況下,您還需要自己的一部分SRAM來存儲數據。

下面是小程序的SAM4S16部分鏈接腳本:

/* ---------------------------------------------------------------------------- 
*   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. 
* ---------------------------------------------------------------------------- 
*/ 

/*------------------------------------------------------------------------------ 
*  Linker script for running in internal SRAM on the SAM4S16 
*----------------------------------------------------------------------------*/ 

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

/* Memory Spaces Definitions */ 
MEMORY 
{ 
    romcodesram (W!RX) : ORIGIN = 0x20000000, LENGTH = 0x800 
    sram (W!RX) : ORIGIN = 0x20000800, LENGTH = 0x0001F800 /* sram, 128K - sizeof(romcodesram) */ 
} 

SECTIONS 
{ 
    /* startup code in the .isr_vector */ 
    .text : 
    { 
     . = ALIGN(4); 
     _stext = .; 
     KEEP(*(.isr_vector .isr_vector.*)) 
     *(.mailbox) 
     *(.text .text.*) 
     *(.rodata .rodata.*) 
     *(.ramfunc .ramfunc.*) 
     *(.glue_7) 
     *(.glue_7t) 
     *(.gcc_except_table) 
     *(.rodata .rodata*) 
     *(.gnu.linkonce.r.*) 
     . = ALIGN(4); 
     _etext = .; 
    } > sram 

    /* data */ 
    .data : 
    { 
     . = ALIGN(4); 
     _sidata = .; 
     _sdata = .; 

     *(.data) 
     *(.data.*) 
     . = ALIGN(4); 
     _edata = .; 
    } > sram 

    .bss (NOLOAD) : { 
     _szero = .; 
     *(.bss) 
     . = ALIGN(4); 
     _ezero = .; 
    } >sram 

    /* Stack in SRAM */ 
    _sstack = 0x2001FFF0; 
} 
. = ALIGN(4); 
end = .; 
+0

不,我沒有使用SAM-BA。我正在編譯我自己的應用程序,並使用SAM-ICE通過JTAG加載它。問題在於'_etext'和'_srelocate'符號的內存位置不匹配。 '_etext + 4 == _srelocate'保持爲真。編譯器正在插入一個額外的符號。 – nonsensickle

+0

我明白了。感謝您的答覆。在Atmel Studio發佈的工具鏈的更新版本中是否解決了這個問題? – Patrick

+0

說實話,我還沒有嘗試過。我似乎還沒有添加[[GCC]中的錯誤鏈接(https://sourceware.org/bugzilla/show_bug.cgi?id=13621),它包含在[相關問題](http:// stackoverflow)中。 com/questions/17605794/what-are-linker-symbols-tmc-end-and-tmc-list-for)我問。我確定我在這裏添加了它,但不要猜測。根據Atmel正在使用的特定版本GCC的錯誤狀態,您可能會/可能不會遇到此問題。 – nonsensickle