在使用GCC编译时是否还需要使用-fPIC?

时间:2013-12-17 14:52:37

标签: c++ c gcc

在gcc目标机器上,当想要编译共享库时,需要指定-fpic或-fPIC来使事情正常工作。这是因为默认情况下使用的是绝对寻址,它适用于完全控制自己地址空间的可执行文件,但不适用于可以加载到可执行文件地址空间中任何位置的共享库。

然而,现代内核现在正在实现地址空间随机化,并且许多现代架构支持PC相对寻址。这似乎使绝对寻址不可用(地址空间随机化)或不需要(PC相对寻址)。

我也注意到clang没有-fPIC选项,这使得我不再需要它。

现在-fpic是多余的,还是需要生成单独的.o文件,一个用于静态库,一个用于共享库?

5 个答案:

答案 0 :(得分:5)

您仍需要使用-fPIC进行编译。 pc相对寻址无法解决该问题。问题是如何解析外部符号。在动态链接的程序中,分辨率遵循不同的规则,特别是在地址空间随机化时,它在链接时间内无法解析。

clang确实有-fPIC标志,就像gcc一样。

$ cat > foo.c
void foo(void);
void bar(void) { foo(); }
$ gcc -S foo.c && grep call.*foo foo.s
    call    foo
$ gcc -fPIC -S foo.c && grep call.*foo foo.s
    call    foo@PLT
$ clang -S foo.c && grep call.*foo foo.s
    callq   foo
$ clang -fPIC -S foo.c && grep call.*foo foo.s
    callq   foo@PLT
$

答案 1 :(得分:1)

我同意你的观点:在许多情况下-fpic / -fPIC选项几乎是多余的,但我确实使用它们来确保:

  • 可移植性(永远不确定可用的特定操作系统/内核)
  • 向后兼容性:使用这些选项可确保您在旧内核上的行为
  • 习惯 - 难以打破的事情:)
  • 遵守可能需要它的旧代码库

答案 2 :(得分:0)

您永远不需要生成单独的.o个文件。始终指定编译器选项以生成可移植代码(通常为-fPIC)。

在某些系统上,编译器可能配置为强制启用此选项,或默认设置它。但无论如何指定它并没有什么坏处。

注意:人们希望在支持PC相关寻址且表现良好的情况下,-fPIC使用该模式而不是专用额外的寄存器。

答案 3 :(得分:0)

gcc针对许多平台和架构,并非所有平台和架构都像x86架构一样支持原生PIC。在某些情况下,创建PIC意味着额外的开销,这可能是不受欢迎的,您想要或需要的更多是取决于您的项目和您所针对的平台,。

答案 4 :(得分:0)

这取决于目标。默认情况下,某些目标(如x86_64)与位置无关,sp -fpic是noop,对生成的代码没有影响。因此,在这些情况下,您可以省略它并且没有任何变化。默认情况下,其他目标(如x86 32位)不是位置独立的,因此在这些计算机上,如果省略-fpic可执行文件,它将禁用该图像文件的ASLR(但不对其使用的共享库)