Reputation: 71
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?
Upvotes: 0
Views: 353
Reputation: 21915
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).
Upvotes: 1
Reputation: 364593
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
Upvotes: 1