创建aarch64裸机程序时如何防止“main.o:(.eh_frame+0x1c): relocation truncated to fit: R_AARCH64_PREL32 against ‘.text’”?

2023-12-01

在创建裸机可执行文件时,我遇到了以下错误:

main.o:(.eh_frame+0x1c): relocation truncated to fit: R_AARCH64_PREL32 against `.text'
collect2: error: ld returned 1 exit status

然后我设法创建了一个最小的复制示例:

main.c

void _start(void) {}

不是主程序

.skip 32

link.ld

ENTRY(_start)
SECTIONS
{
  .text : {
    */bootloader.o(.text)
    *(.text)
    *(.rodata)
    *(.data)
    *(COMMON)
  }
  .bss : { *(.bss) }
  heap_low = .;
  . = . + 0x1000000;
  heap_top = .;
  . = . + 0x1000000;
  stack_top = .;
}

编译命令:

aarch64-linux-gnu-gcc \
-save-temps \
-T link.ld \
-Wall \
-Werror \
-Wextra \
-Wl,--section-start=.text=0x80000000 \
-Xassembler -march=all \
-fno-pie \
-ggdb3 \
-no-pie \
-nostartfiles \
-nostdlib \
-static \
-o 'main.out' \
-pedantic \
notmain.S \
'main.c'

where aarch64-linux-gnu-gcc是 Ubuntu 19.10 的 GCC 版本 9.2.1gcc-9-aarch64-linux-gnu包裹。

后来我也在 Ubuntu 18.04 GCC 7.5.0 上进行了尝试,并且它成功了,所以最好了解一下之间发生了什么变化。

.skip 16有效,但是.skip 32才不是。

我知道使用非裸机交叉编译器来处理裸机内容并不理想,但是任何人都可以指出是否可以进行一些命令行选项或代码修改来使链接正常工作?

如果该工具链无法实现这一点,有人可以澄清原因吗?哪个 GCC 构建配置选项特别使这成为不可能?

我实际上有一个aarch64crosstool-NG 工具链随处可见此处描述它适用于那个,所以这实际上可能是工具链的问题。

我知道R_AARCH64_PREL32记录于:https://static.docs.arm.com/ihi0044/g/aaelf32.pdf我对搬迁有一个大概的了解:这个 GCC 错误“...重定位被截断以适合...”是什么意思?但这比我现在想深入研究的内容要多一些。

另外,如果我将入口点移至更实际的设置中的程序集:

不是主程序

.global _start
_start:
    bl entry

main.c

void entry(void) {}

问题没有发生。


作为一种允许它在我完全了解情况的情况下进行编译的解决方法,您可以添加:

-fno-unwind-tables -fno-asynchronous-unwind-tables

这消除了.eh_frame失败的重定位来自的框架:为什么GCC编译的C程序需要.eh_frame部分?

然后我注意到二进制文件不起作用,因为_start首先有 C 函数序言和触摸堆栈,但我找不到一个令人惊奇的解决方案:创建一个没有编译器生成的序言/尾声和 RET 指令的 C 函数? (-O3? :-) 我们需要发明一个-fno-stack选项)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

创建aarch64裸机程序时如何防止“main.o:(.eh_frame+0x1c): relocation truncated to fit: R_AARCH64_PREL32 against ‘.text’”? 的相关文章

随机推荐