编译GAS代码未检测到-fPIC选项

时间:2018-11-13 23:47:32

标签: gcc assembly gas position-independent-code

我正在尝试使用GCC gnu编译器为项目编译一些GAS代码。这是我的编译方式:

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

使用-fPIC参数编译kernel.c文件后,尝试使用以下命令将其链接:

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

它带有:

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

这使我认为它不是用-fPIC编译GAS代码。我该如何解决?

2 个答案:

答案 0 :(得分:1)

首先,您可能需要-fPIE而不是-fPIC-fPIE允许编译器生成更有效的代码,但只能用于主要可执行文件(而非共享库)中的代码。

现在-fPIC-fPIE都是仅编译器标志,并且不会传递给汇编器。您需要在汇编代码中显式使用PIC专有的助记符,而不是位置相关的调用和分支,例如代替

movq $bar, %rdx

使用

movq bar@GOTPCREL(%rip), %rdx

(通常要获得所需的语法,我只需在匹配的C代码段上运行gcc -fPIE -S -o-)。

答案 1 :(得分:1)

使用-fPIC进行重新编译仅在asm是由编译器生成而不是手工编写的情况下适用。它对如何将asm汇编为机器代码没有影响。

问题是您的PIE可执行文件无法与32位绝对地址链接。 (您的意思是制作PIE而不是静态的位置相关可执行文件)吗?

您不需要完整的共享库内容即可引用另一个库或主可执行文件中的符号(例如@yugr的答案显示了操作方法)。您的独立内核甚至可能没有 GOT或PLT,并且绝对不应将其用于内部符号。

唯一需要更改的是lea bar(%rip), %rdx,这是相对于RIP的LEA,而不是mov $imm32, %r/m64 。 (运动样本可以起作用,但更大但通常更慢。)

或者,如果您实际上打算使用-static进行构建并创建一个将在地址空间的低32位中的固定地址处加载的可执行文件,则应使用mov $bar, %edx获得5字节mov $imm32, %r32编码,而不是7字节mov $sign_extended_imm32, %r/m64或7字节LEA。另请参见Difference between movq and movabsq in x86-64