Gcc 如何预防;main.o:(.eh#u frame+;0x1c):根据`.text'&引用;创建aarch64裸金属程序时?

Gcc 如何预防;main.o:(.eh#u frame+;0x1c):根据`.text'&引用;创建aarch64裸金属程序时?,gcc,arm,ld,arm64,bare-metal,Gcc,Arm,Ld,Arm64,Bare Metal,在创建裸金属可执行文件时,我遇到了以下错误: 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) {} void entry(void) {} 诺曼 .skip 32 .global _start

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

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) {}
void entry(void) {}
诺曼

.skip 32
.global _start
_start:
    bl entry
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
crosstool NG工具链,它与这个工具链一起工作,因此它实际上可能是工具链的一个问题

我知道,
R\u AARCH64\u PREL32
被记录在:中,我对relocation有一个大致的了解:但这一点比我现在想深入了解的要多一些

此外,如果在更真实的设置中将入口点移动到assembly:

诺曼

.skip 32
.global _start
_start:
    bl entry
main.c

void _start(void) {}
void entry(void) {}

问题没有出现。

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

-fno-unwind-tables -fno-asynchronous-unwind-tables
这将删除失败的重新定位来自的
.eh_帧
帧:


然后我注意到二进制文件不起作用,因为
\u start
有C函数序言,第一件事就是触及堆栈,我找不到一个令人惊讶的解决方案:(
-O3
?:-)我们需要发明一个
-fno堆栈
选项)。

您没有提供
m5\u exit.C
@Frant谢谢,在最小化过程中出错,现已修复:-)我经常使用arm anywhere linux anywhere for baremetal,没有问题,这取决于您的代码/设计。因此,您希望能够在内存空间中的任何位置启动,即使它与baremetal并不相关?混淆了问题所在。@old_timer是的,符号名
\u start
是任意的,可以是任何东西,但理想情况下会标记为ELF入口点,我的模拟器可以解析并设置为初始PC,否则,我不得不考虑什么是默认的输入PC。问题是它没有链接,所以我没有二进制运行:-)