ARM Cortex-M7 长分支在编译时出现错误“relocation truncated to fit: R_ARM_PREL31”
Posted
技术标签:
【中文标题】ARM Cortex-M7 长分支在编译时出现错误“relocation truncated to fit: R_ARM_PREL31”【英文标题】:ARM Cortex-M7 long branch get error "relocation truncated to fit: R_ARM_PREL31" at compiling time 【发布时间】:2019-03-09 07:53:34 【问题描述】:我正在使用 NXP 的 I.MXRT 系列 Cortex-M7 芯片开发嵌入式系统。我需要在 RAM(ITCM) 中重定位一些 C 函数,而不是在 Flash 中。 ITCM 的地址从 0x00000000 开始,Flash 从 0x60000000 开始。因此,位于 Flash 的函数调用位于 ITCM 的函数将执行长分支。但它得到一个编译错误
(.ARM.exidx.itcm.text+0x0):重定位被截断以适应:R_ARM_PREL31 针对 `.itcm.text'
这是我的代码
__attribute__ ((long_call,section(".itcm.text"),noinline))
int foo(int k)
return k + 1;
我的链接脚本
MEMORY
/*
* SPI Flash
*
*
*/
ITCM(xrw) : ORIGIN = 0x00000000, LENGTH = 128K
DTCM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K
RAM (xrw) : ORIGIN = 0x20200000, LENGTH = 256K
FLASH (rx) : ORIGIN = 0x60000000, LENGTH = 4096K
/*************omit***************/
_siitcm = LOADADDR(.itcm.text);
.itcm.text : ALIGN(4)
__itcm_start__ = .;
*(.itcm.text .itcm.text.*)
. = ALIGN(4);
__itcm_end__ = .;
>ITCM AT>FLASH
编译器标志是
arm-none-eabi-gcc -mcpu=cortex-m7 -mthumb $FP_FLAGS -std=c++11 -O3 -munaligned-access -ffunction-sections -fdata-sections -ffreestanding
链接器标志是
"arm-none-eabi-gcc -mcpu=cortex-m7 -mthumb $FP_FLAGS -std=c++11 -O3 -munaligned-access -ffunction-sections -fdata-sections -ffreestanding -T $ MEM_LD_FILE -T $LIBS_LD_FILE -T $SECTIONS_LD_FILE -nostartfiles -Xlinker -gc-sections -u _printf_float -Wl,-Map=$TARGET_MAP --specs=nano.specs"
当分支地址大于0x40000000时似乎会发生错误。那么,如何解决这个问题呢?
/* 第二版 */
我通过添加编译器标志 -fno-exceptions 解决了这个问题。但是不知道为什么?
【问题讨论】:
使用彼此靠近的虚假地址,构建它,查看它使用的地址和说明,这应该可以解释它。 或者实际上只是查看目标文件,因为它无法链接它... 您可以从Exception Handling ABI for the ARM Architecture (ARM IHI 0038B) 中获得一些关于-fno-exceptions
行为的见解,特别是第4.4.2 节“重定位”,其中提到了使用R_ARM_PREL31
进行偏移。 R_ARM_PREL31
是 31 位 2 的补码 - 注意:不是 32 位数字。见ELF for the ARM Architecture (ARM IHI 0044E)
如果您将进入 RAM(ITCM) 的 C 函数编译为 C 而不是 C++,也许会有所帮助?
嗯,31位2的补码的跳转地址确实是+- 0x40000000。但它应该使用一个长分支指令 BLX Ri,它可以根据 ARM 的手册跳转所有 32 位地址空间。其实我也不清楚什么是“搬家”?我的项目包含 C 和 C++ 文件。进入 ITCM 的函数位于外部“C”块中。但我认为链接器是 C++。
【参考方案1】:
ARM-EABI 指定异常胶合代码是 31 位相对的。这意味着所有可以抛出或捕获的 C++(即,具有 C++ 链接,而不是 -fno-exception)将需要位于内存中,距离 .ARM-extab 和 .ARM 不超过 30 位(正负) .exidx 部分或相对偏移量将不足 - 因此错误。
ARM-EABI 很可能利用了 Linux 默认用户空间,即 ARM32 地址空间的 32 位中的低 31 位。
所以,看看你的内存映射。是否有 stash +-30 位来放置 extab/exidx 以最大程度地覆盖您的 .text 内存(XIP 闪存、SDRAM、OCRAM)?您可以(通过链接器脚本)将您的 C++ 限制在所覆盖的区域吗?您可以将非文本(数据、bss 等)放在超出范围的内存中吗? (数据和非 C++ 和 C++-noexception .text 访问不是 REL31 - 只有 C++ 异常是。)
【讨论】:
以上是关于ARM Cortex-M7 长分支在编译时出现错误“relocation truncated to fit: R_ARM_PREL31”的主要内容,如果未能解决你的问题,请参考以下文章
为 ARM NEON 编译时出现未知的 GCC 错误(严重)
我的数码相框.c文件用arm-linux-gcc交叉编译时出现错误,如tgzip.c:309:undefined reference to
安装arm-linux-gcc编译器时出现错误,请大神看看怎么回事
编译linux内核时出现"mkimage" command not found - U-Boot images will not be built错误的解决办法