0

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

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

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

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. 我怎样才能解决这个问题?

4

2 回答 2

1

-fPIC仅当 asm 由编译器生成而不是手工编写时,重新编译才适用。它对 asm 如何组装成机器代码没有影响。

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

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

唯一需要的更改是lea bar(%rip), %rdxRIP 相关的 LEA 而不是mov $imm32, %r/m64. (movabs 可以,但更大,通常更慢。)

或者,如果您实际上打算构建-static并创建一个可执行文件,该可执行文件将在地址空间的低 32 位中的固定地址加载,您应该使用mov $bar, %edx5 字节mov $imm32, %r32编码而不是 7 字节mov $sign_extended_imm32, %r/m64或 7 字节执法机构。另请参阅x86-64 中 movq 和 movabsq 之间的区别

于 2018-11-14T04:57:42.063 回答
1

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

现在-fPIC-fPIE都是编译器专用标志,不会传递给汇编器。您需要在汇编代码中显式使用特定于 PIC 的助记符,而不是依赖于位置的调用和分支,例如,而不是

movq $bar, %rdx

利用

movq bar@GOTPCREL(%rip), %rdx

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

于 2018-11-14T04:20:08.087 回答