【问题标题】:Create .SO files on Linux without using PIC (position independent code) (x86 32bit)在不使用 PIC(位置无关代码)(x86 32bit)的情况下在 Linux 上创建 .SO 文件
【发布时间】:2013-07-27 17:16:20
【问题描述】:

据我所知,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 会发生什么?

【问题讨论】:

  • 你更关心IA32还是x86-64?任何答案都取决于这种区别。
  • 我关心的是32位代码并调整了问题的标题
  • 对于计算密集型程序,确实值得(出于多种原因)切换到 64 位 linux。

标签: linux assembly dll dynamic-linking relocation


【解决方案1】:

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

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

链接器会产生大量的重定位操作。因此,动态链接器 (ld.so) 将不得不缓慢处理大量重定位,因此必须重写您的文本段(并且不会与使用相同 .so 文件的其他进程有效地只读共享)。

因此在实践中忘记共享对象(即动态链接库)上的-fPIC 通常是个坏主意,即使有可能也是如此。

阅读Drepper's HowTo do Dynamic Shared Libraries 的论文和惠勒的Program Library Howto

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

【讨论】:

  • 谢谢! ld.so 可以做我想做的事,真是太好了。我也读过你在其他地方写的其他东西,但我想知道 ld.so 必须做的工作量在所有场景中是否真的那么重要。例如一个服务器进程,一旦一切都重新定位,问题出在哪里?并且因为没有浪费一个寄存器并且所有跳跃都可以直接而获得高达 10% 的性能,在某些情况下似乎非常值得付出努力。我想知道为什么我没有看到有关 pic 和重定位的文字,其中讨论了有人可能宁愿使用运行时性能而不是快速加载
猜你喜欢
  • 2011-08-19
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2021-10-09
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
相关资源
最近更新 更多