0

I am trying to compile some GAS code for a project using the GCC gnu compiler. Here is how I am compiling it:

gcc -c boot.s -o boot.o -fPIC

After I compile my kernel.c file with the -fPIC argument, I try to link it with this command:

gcc -N -T linker.ld -o Slack\ Berry.bin -ffreestanding -nostdlib kernel.o boot.o -lgcc

It comes up with:

/usr/bin/ld: boot.o: relocation R_X86_64_32 against '.multiboot' can not be used when making a PIE object; recompile with -fPIC

This leads me to think that it is not compiling my GAS code with -fPIC. How can I fix this?

yugr
  • 19,769
  • 3
  • 51
  • 96

2 Answers2

1

First of all you probly need -fPIE rather than -fPIC. -fPIE allows compiler to generate more efficient code but can only be used for code that's part of main executable (not shared library).

Now both -fPIC and -fPIE are compiler-only flags and are not passed to assembler. You'll need to explicitly use PIC-specific mnemonics in your assembly code instead of position-dependent calls and branches e.g instead of

movq $bar, %rdx

use

movq bar@GOTPCREL(%rip), %rdx

(normally to get the syntax I need I just run gcc -fPIE -S -o- on matching C snippet).

yugr
  • 19,769
  • 3
  • 51
  • 96
  • The OP is making a PIE, not a shared library; they don't need the GOT or PLT for internal static symbols. The only change needed is `lea bar(%rip), %rdx`, a RIP-relative LEA instead of a `mov $imm32, %r64`. (movabs would work to, but be larger and usually slower.) – Peter Cordes Nov 14 '18 at 04:52
  • @PeterCordes Thanks, I'll make an update. I think the question should be updated as well. – yugr Nov 14 '18 at 05:22
  • Why, what do you think is missing in the question? It has `-ffreestanding -nostdlib`, and has names like `boot.o` and mentions multiboot. Also the error message mentions making a PIE executable. Seems pretty clear to me that the OP wasn't actually trying to make a shared library. (This is not the first question about this error message when making an executable from asm, either, so I wasn't at all expecting the question to be about actually making shared libs. Usually it's just PIE requiring relocatable-anywhere code catching people by surprise.) – Peter Cordes Nov 14 '18 at 11:50
  • @PeterCordes Well, why not make things more explicit if possible? – yugr Nov 14 '18 at 15:59
  • I guess maybe. I missed that they had actually compiled their `kernel.c` with `-fPIC`, so the code probably does depend on a PLT and GOT unless they carefully used `__attribute__((hidden))`. You definitely don't want to go through the GOT / PLT for calls / references within the same object. – Peter Cordes Nov 14 '18 at 16:05
  • 1
    @PeterCordes Yup, I developed [ShlibVisibilityChecker](https://github.com/yugr/ShlibVisibilityChecker) specifically for that. Sadly I found that package maintainers usually don't care much about getting rid of spurious GOT/PLT references... – yugr Nov 14 '18 at 17:08
1

Recompile with -fPIC only applies if the asm was generated by a compiler, not written by hand. It has no effect on how asm is assembled into machine code.

The problem is that your PIE executable can't be linked with 32-bit absolute addresses. (Did you mean to make a PIE instead of a static position-dependent executable)?

You don't need the full shared-library stuff for referencing symbols in another library or the main executable (like @yugr's answer shows how to do). Your freestanding kernel may not even have a GOT or PLT, and definitely shouldn't use them for internal symbols.

The only change needed is lea bar(%rip), %rdx, a RIP-relative LEA instead of a mov $imm32, %r/m64. (movabs would work to, but be larger and usually slower.)

Or, if you actually meant to build with -static and create an executable that will be loaded at a fixed address in the low 32 bits of address space, you should use mov $bar, %edx to get a 5-byte mov $imm32, %r32 encoding instead of 7-byte mov $sign_extended_imm32, %r/m64 or a 7-byte LEA. See also Difference between movq and movabsq in x86-64

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847