3

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.

Ciro Santilli
  • 3,693
  • 1
  • 18
  • 44
  • You did not provide the content for `m5_exit.c`. – Frant Mar 23 '20 at 16:57
  • @Frant thanks, got it wrong during the minimization, fixed now :-) – Ciro Santilli Mar 23 '20 at 17:14
  • I use the arm-whatever-linux-whatever for baremetal quite often, no issues, depends on your code/design. – old_timer Mar 23 '20 at 17:52
  • so you want to be able to put _start anywhere in the memory space, even though it is not really relevant to baremetal? confused as to what the issue is. – old_timer Mar 23 '20 at 17:56
  • @old_timer yes, the symbol name `_start` is arbitrary, could be anything, but ideally will be marked as the ELF entry point, which my emulator can parse and set as the initial PC, otherwise I'd have to think what's the default entry PC. The problem is that it does not link and so I have no binary to run :-) – Ciro Santilli Mar 23 '20 at 18:49
  • you could provide an actual bootstrap at the entry point and can be as simple as a branch to main, which would resemble a real binary and allow your simulation to work. does the problem occur when your application starts to resemble something real? – old_timer Mar 23 '20 at 21:30
  • @old_timer updated question with that, it did not occur in that case. Maybe it only happens when the entry point is in C? I would still like to understand why. – Ciro Santilli Mar 24 '20 at 08:01

1 Answers1

2

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).

Ciro Santilli
  • 3,693
  • 1
  • 18
  • 44