How to prevent “main.o:(.eh_frame+0x1c): relocation truncated to fit: R_AARCH64_PREL32 against `.text'” when creating an aarch64 baremetal program?

三世轮回 提交于 2020-04-07 07:39:53

问题


When playing with creating baremetal executables, I hit this error:

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

I then managed to create a minimal reproduction example:

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 = .;
}

Compilation command:

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 is GCC version 9.2.1 from Ubuntu 19.10's gcc-9-aarch64-linux-gnu package.

I later also tried on Ubuntu 18.04 GCC 7.5.0, and there it worked, so it would be good to understand what changed in between.

.skip 16 works, but .skip 32 does not.

I know that it is not ideal to use a non-baremetal cross compiler for baremetal stuff, but can anyone point out if there is some command line option or code modification I could make to make the link work?

And if this is not possible with that toolchain, can someone clarify why? Which GCC build configuration option in particular makes this impossible?

I actually had an aarch64 crosstool-NG toolchain lying around described here and it works with that one, so it could actually be a problem with the toolchain.

I know that R_AARCH64_PREL32 is documented at: https://static.docs.arm.com/ihi0044/g/aaelf32.pdf and I have a general understanding of relocaiton: What does this GCC error "... relocation truncated to fit..." mean? but this one is a bit more than what I'd like to dig into right now.

Also, if I move the entry point to assembly in a more realistic setup:

notmain.S

.global _start
_start:
    bl entry

main.c

void entry(void) {}

the problem did not occur.


回答1:


As a workaround that allows it to compile without me fully understanding the situation, you can add:

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

which removes the .eh_frame frame from which the failing relocation was coming from: Why GCC compiled C program needs .eh_frame section?

I then noticed the binary doesn't work because _start has the C function prologue and touches stack first thing, and I can't find an amazing solution for that: Creating a C function without compiler generated prologue/epilogue & RET instruction? (-O3? :-) We need to invent a -fno-stack option).



来源:https://stackoverflow.com/questions/60817268/how-to-prevent-main-o-eh-frame0x1c-relocation-truncated-to-fit-r-aarch64

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!