[在创建裸机可执行文件时,出现此错误:
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 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'
其中aarch64-linux-gnu-gcc
是Ubuntu 19.10的gcc-9-aarch64-linux-gnu
软件包的GCC版本9.2.1。
我后来还在Ubuntu 18.04 GCC 7.5.0上进行了尝试,并且在那里工作了,所以最好了解一下两者之间的变化。
.skip 16
有效,但.skip 32
无效。
我知道对裸机对象使用非裸机交叉编译器并不理想,但是任何人都可以指出我是否可以进行某些命令行选项或代码修改以使链接正常工作?
如果该工具链无法做到这一点,那么有人可以阐明原因吗?特别是哪个GCC构建配置选项使这不可能?
我实际上在aarch64
周围有一个described here crosstool-NG工具链,并且与该工具链一起使用,因此实际上可能是该工具链的问题。
[我知道R_AARCH64_PREL32
记录在:https://static.docs.arm.com/ihi0044/g/aaelf32.pdf,并且我对重新定位有一个大致的了解:What does this GCC error "... relocation truncated to fit..." mean?,但是这个比我现在想深入了解的要多。
此外,如果我将入口点移动到更实际的设置中,则:
notmain.S
.global _start
_start:
bl entry
main.c
void entry(void) {}
未出现问题。
作为一种可以让我在不完全了解情况的情况下进行编译的解决方法,您可以添加:
-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
选项。