2

据我所知,x86 汇编代码在很大程度上受到有限数量的寄存器的限制。

当我了解到在 Linux 上创建 .so 文件时,必须为 gcc 指定 -fPIC 命令行参数才能创建与位置无关的代码,我一开始简直不敢相信。

据我所知,elf 文件格式支持重定位,就像 - 在我看来要好得多 - Windows DLL 系统的工作原理:在 Windows 上,如果有必要,链接器会重定位 DLL 中的所有偏移量。

我认为加载 SO 文件或 DLL 文件所需的时间,以及用于保存不同重定位的 .so 文件的内存量并不像始终缺少整个寄存器那样糟糕,这指向GOT 并拥有所有这些间接跳跃。

我也完全不关心 ALSR 等,因为我只关心库中的代码要尽可能地优化。

1) 为什么 Linux 不支持像 Windows 这样应该产生更高性能代码的更多动态库加载?

到目前为止,我还没有找到真正的解释。像这样的事情,重新定位代码会非常糟糕和缓慢(当然,对于在台式机上加载文字处理器,加载速度有多快很重要,我完全接受这一点。但是对于计算密集型服务器进程(不处理来自互联网的恶意数据),我想拥有我能得到的所有性能和寄存器!

2) 我可以在 Linux 上创建 NOT -fPIC 编译的 SO 文件吗?我可以离开 -fPIC 吗?是否有任何关于该主题的操作指南、手册或项目,并且可以不浪费整个寄存器并仍然动态加载库?

如果我在编译 .so 文件时只删除 -fPIC 会发生什么?

4

1 回答 1

4

如果我-fPIC在编译.so-file 时只删除 会发生什么?

生成的共享对象 ELF 文件将(很可能)在半随机(即不可预测的)页面地址处动态加载(例如,因为mmap系统调用将遇到ASLR)。

并且链接器会产生大量的重定位操作。所以动态链接器ld.so.so

所以在实践中忘记-fPIC共享对象(即动态链接库)通常是一个坏主意,即使它是可能的。

阅读Drepper 的 HowTo do Dynamic Shared Libraries论文和 Wheeler 的Program Library Howto

顺便说一句,与 x86-64 相比,x86(32 位)上的位置无关代码成本更高。但值得付出努力(在 x86 32 位上,PIC 代码可能最多比非 PIC 慢 5% 到 10%)。

于 2013-07-27T18:08:25.450 回答