在gcc目标机器上,当想要编译共享库时,需要指定-fpic或-fPIC来使事情正常工作。这是因为默认情况下使用的是绝对寻址,它适用于完全控制自己地址空间的可执行文件,但不适用于可以加载到可执行文件地址空间中任何位置的共享库。
然而,现代内核现在正在实现地址空间随机化,并且许多现代架构支持PC相对寻址。这似乎使绝对寻址不可用(地址空间随机化)或不需要(PC相对寻址)。
我也注意到clang没有-fPIC选项,这使得我不再需要它。
现在-fpic是多余的,还是需要生成单独的.o文件,一个用于静态库,一个用于共享库?
答案 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(但不对其使用的共享库)