我没有找到任何关于“-fno-pie”和“-no-pie”之间区别的有用信息。它们是 gcc 标志还是 ld 标志?它们是否都需要?
我找到了一段使用这些行的 makefile:
CC = @gcc -fno-pie -no-pie
LD = @gcc -fno-pie -no-pie
所以它使用 gcc 进行链接而不是直接调用 ld 但我不明白标志之间的区别以及它们是否都是编译和链接阶段所必需的
TLDR;
-fno-pie
是“代码生成选项”,而 -no-pie
是“链接器选项”。你两者都需要。
-fno-pie
告诉GCC你不想做一个PIE。如果您不是在制作 PIE,那么您正在制作一个共享对象(使用-shared
)或一个普通的可执行文件。-fno-pie
告诉 GCC 可以将像 &foo
这样的表达式翻译成像 mov eax, OFFSET FLAT foo
.-fpie
/-fno-pie
在组装说明方面做了什么。
像
mov eax, OFFSET FLAT foo
这样的指令会创建一个 R_X86_64_32
重定位,当编译器确保地址始终适合 32 位(即低于 4GiB)时,此重定位用于 64 位程序。-fno-pie
doesn't 阻止 GCC 将 -pie
传递给链接器。R_X86_64_32
重定位,并且仍然被指示制作一个 PIE 可执行文件。重定位承诺地址将低于 4GiB,但 -pie
标志承诺可执行文件将被加载到任何地方,包括 4GiB 以上。要告诉链接器您确实不想链接 PIE 可执行文件,您需要将
-no-pie
传递给 GCC。
您可以在编译文件时将
-v
传递给 GCC,以查看传递给 collect2
(链接器的包装器)的选项。-fno-pie
的存在,-pie
仍然传递给collect2
.-no-pie
添加到 GCC 将在 -pie
命令行中抑制 collect2
。
注意:较旧的发行版构建了 GCC 而没有默认为
-fpie -pie
.