在尝试创建裸机可执行文件时,我遇到了这个错误:
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) {}notmain.S
.skip 32link.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'其中aarch64-linux-gnu-gcc是Ubuntu19.10的gcc-9-aarch64-linux-gnu包中的GCC 9.2.1版本。
我后来也尝试了Ubuntu18.04,GCC 7.5.0,它在那里工作,所以它将很好地理解在这两者之间发生了什么变化。
.skip 16可以工作,但.skip 32不能。
我知道使用非裸机交叉编译器来处理裸机并不理想,但是有没有人能指出有没有什么命令行选项或者代码修改可以让链接正常工作呢?
如果这个工具链不能做到这一点,有人能解释一下原因吗?具体是哪个GCC构建配置选项让这一切变得不可能?
实际上,我在described here周围有一个aarch64 crosstool NG工具链,它可以与它一起工作,所以它实际上可能是工具链的一个问题。
我知道R_AARCH64_PREL32的文档在:https://static.docs.arm.com/ihi0044/g/aaelf32.pdf上,我对relocaiton:What does this GCC error "... relocation truncated to fit..." mean?有一个大致的理解,但这篇文章比我现在想要深入研究的要多一点。
此外,如果我将入口点移动到更逼真的设置中的装配:
notmain.S
.global _start
_start:
bl entrymain.c
void entry(void) {}未出现问题。
发布于 2020-03-24 04:05:49
作为一种解决方法,允许我在不完全了解情况的情况下进行编译,您可以添加:
-fno-unwind-tables -fno-asynchronous-unwind-tables这将删除失败的位置调整所来自的.eh_frame帧:Why GCC compiled C program needs .eh_frame section?
然后我注意到二进制文件不能工作,因为_start有C函数的前言,并且首先触及堆栈,而我找不到一个令人惊讶的解决方案:Creating a C function without compiler generated prologue/epilogue & RET instruction? (-O3?:-)我们需要发明一个-fno-stack选项)。
https://stackoverflow.com/questions/60817268
复制相似问题