编译 GAS 代码未检测到 -fPIC 选项
Compiling GAS code doesn't detect -fPIC option
我正在尝试使用 GCC gnu 编译器为项目编译一些 GAS 代码。以下是我的编译方式:
gcc -c boot.s -o boot.o -fPIC
在我使用 -fPIC
参数编译我的 kernel.c 文件后,我尝试使用此命令 link 它:
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 代码。我该如何解决这个问题?
首先你可能需要 -fPIE
而不是 -fPIC
。 -fPIE
允许编译器生成更高效的代码,但只能用于作为主要可执行文件(而非共享库)一部分的代码。
现在 -fPIC
和 -fPIE
都是编译器专用标志,不会传递给汇编程序。您需要在汇编代码中明确使用特定于 PIC 的助记符,而不是位置相关的调用和分支,例如,而不是
movq $bar, %rdx
使用
movq bar@GOTPCREL(%rip), %rdx
(通常为了获得我需要的语法,我只是 运行 gcc -fPIE -S -o-
在匹配的 C 片段上)。
Recompile with -fPIC
仅适用于 asm 由编译器生成,而不是手工编写的情况。它对 asm 如何汇编成机器代码没有影响。
问题是您的 PIE 可执行文件无法与 32 位绝对地址链接。 (您的意思是制作 PIE 而不是静态位置相关的可执行文件)?
您不需要完整的共享库内容来引用另一个库或主要可执行文件中的符号(如@yugr 的回答显示了如何做)。您的独立内核甚至可能 没有 GOT 或 PLT,绝对不应该将它们用于内部符号。
唯一需要的更改是 lea bar(%rip), %rdx
,一个 RIP 相关的 LEA 而不是 mov $imm32, %r/m64
。 (movabs 可以工作,但更大而且通常更慢。)
或者,如果您实际上打算使用 -static
构建并创建一个将加载到地址 space 低 32 位固定地址的可执行文件,您应该使用 mov $bar, %edx
以获得 5 字节 mov $imm32, %r32
编码而不是 7 字节 mov $sign_extended_imm32, %r/m64
或 7 字节 LEA。另见
我正在尝试使用 GCC gnu 编译器为项目编译一些 GAS 代码。以下是我的编译方式:
gcc -c boot.s -o boot.o -fPIC
在我使用 -fPIC
参数编译我的 kernel.c 文件后,我尝试使用此命令 link 它:
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 代码。我该如何解决这个问题?
首先你可能需要 -fPIE
而不是 -fPIC
。 -fPIE
允许编译器生成更高效的代码,但只能用于作为主要可执行文件(而非共享库)一部分的代码。
现在 -fPIC
和 -fPIE
都是编译器专用标志,不会传递给汇编程序。您需要在汇编代码中明确使用特定于 PIC 的助记符,而不是位置相关的调用和分支,例如,而不是
movq $bar, %rdx
使用
movq bar@GOTPCREL(%rip), %rdx
(通常为了获得我需要的语法,我只是 运行 gcc -fPIE -S -o-
在匹配的 C 片段上)。
Recompile with -fPIC
仅适用于 asm 由编译器生成,而不是手工编写的情况。它对 asm 如何汇编成机器代码没有影响。
问题是您的 PIE 可执行文件无法与 32 位绝对地址链接。 (您的意思是制作 PIE 而不是静态位置相关的可执行文件)?
您不需要完整的共享库内容来引用另一个库或主要可执行文件中的符号(如@yugr 的回答显示了如何做)。您的独立内核甚至可能 没有 GOT 或 PLT,绝对不应该将它们用于内部符号。
唯一需要的更改是 lea bar(%rip), %rdx
,一个 RIP 相关的 LEA 而不是 mov $imm32, %r/m64
。 (movabs 可以工作,但更大而且通常更慢。)
或者,如果您实际上打算使用 -static
构建并创建一个将加载到地址 space 低 32 位固定地址的可执行文件,您应该使用 mov $bar, %edx
以获得 5 字节 mov $imm32, %r32
编码而不是 7 字节 mov $sign_extended_imm32, %r/m64
或 7 字节 LEA。另见