我正在尝试使用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代码。我该如何解决?
答案 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的答案显示了操作方法)。您的独立内核甚至可能没有
唯一需要更改的是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