问题
我的问题是,当我使用以下旨在将代码放入 RAM 的脚本时,重定位部分会充满虚假数据。
我的问题是:
为什么
_srelocate
符号比符号大 4 个字节_etext
?他们不应该是一样的吗?另外,如果 1. 的答案是否定的,我不应该从
_etext + 4
to复制_srelocate
吗?
背景及相关代码
我正在使用 Atmel ATSAM3N4X 系列处理器(ARM Cortex M3),希望对我的链接器脚本和.relocate
部分初始化有所帮助。
原因是_etext
符号比_srelocate
符号少 4 个字节。
以下链接描述文件是 Atmel Studio 6 生成的默认脚本(如果您想要ram
/rom
符号位置,请参阅问题的附录)。
/* ----------------------------------------------------------------------------
* 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
现在,Atmel Studio 6 自动生成了我的项目,并给了我一个Reset_Handler()
复制该.relocate
部分的内容_etext
并_srelocate
清除该.bss
部分。该项目带有两个链接器脚本,一个用于基于 FLASH 的执行,一个用于基于 RAM 的代码。默认是基于 FLASH 的代码,但我将其更改为基于 RAM 的链接器脚本(上面提供),然后遇到了问题。
将部分从 FLASH复制.relocate
到 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 中发现了这个错误,但无法确定它在我的版本中是否已修复。
我的编译器是arm-none-eabi-gcc
并且将它的版本声明为4.7.0
...链接器是arm-none-eabi-ld
并且它的版本是2.22
。
编辑2:
我已经对此进行了一些研究,并记录在我提出的这个相关的 SO 问题中。请同时查看它,因为它解释了问题是GCC 错误。
附录
链接描述文件的内存布局
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 ;