在gcc目标机器上,当想要编译共享库时,需要指定-fpic或-fPIC来使事情正常工作 . 这是因为默认使用绝对寻址,它适用于完全控制自己的地址空间的可执行文件,但不适用于可以在可执行文件的地址空间中的任何位置加载的共享库 .
然而,现代内核现在正在实现地址空间随机化,并且许多现代架构支持PC相对寻址 . 这似乎使绝对寻址不可用(地址空间随机化)或不需要(PC相对寻址) .
我还注意到clang没有-fPIC选项,这使我不再需要它 .
那么-fpic现在是多余的,还是需要生成单独的.o文件,一个用于静态库,一个用于共享库?
5 回答
您仍然需要使用-fPIC进行编译 . pc相对寻址无法解决该问题 . 问题是如何解析外部符号 . 在动态链接的程序中,分辨率遵循不同的规则,尤其是在地址空间随机化时,它在链接时间内无法解析 .
并且clang确实像gcc一样拥有-fPIC标志 .
我同意你的观点:在许多情况下-fpic / -fPIC选项几乎是多余的,但我确实使用它们来确保:
可移植性(永远不确定可用的特定OS /内核)
向后兼容性:使用这些选项可确保您在旧内核上的行为
习惯 - 难以打破:)
符合可能需要它的旧代码库
您永远不需要生成单独的
.o
文件 . 始终指定编译器选项以生成可移植代码(通常为-fPIC
) .在某些系统上,编译器可能配置为强制启用此选项,或默认设置它 . 但无论如何指定它并没有什么坏处 .
注意:人们希望在支持PC相关寻址并且表现良好的情况下,
-fPIC
使用该模式而不是专用额外的寄存器 .gcc
针对许多平台和体系结构,并非所有平台和体系结构都像x86体系结构一样支持原生PIC . 在某些情况下,创建PIC意味着额外的开销,这可能是不受欢迎的,您想要或需要的更多是取决于您的项目和您所针对的平台 .这取决于目标 . 默认情况下,某些目标(如x86_64)与位置无关,sp
-fpic
是noop,对生成的代码没有影响 . 因此,在这些情况下,您可以省略它并且没有任何变化 . 默认情况下,其他目标(如x86 32位)不是位置独立的,因此在这些计算机上,如果省略了可执行文件的-fpic
,它将禁用该图像文件的ASLR(但不会禁用它使用的共享库) .