在Linux上创建.SO文件而不使用PIC(位置无关代码)(x86 32位)

提问

据我所知,x86汇编代码受到有限数量寄存器的限制.

当我在Linux上了解到要创建一个.so文件时,必须为gcc指定-fPIC命令行参数以创建与位置无关的代码,我无法首先相信它.

据我所知,elf文件格式支持重定位,就像 – 在我眼中更好 – Windows DLL系统工作:在Windows上,链接器重定位DLL中的所有偏移,如果有必要的话.

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

对于我想到的应用程序,我也根本不关心ALSR等.我只关心在库中尽可能地优化代码.

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

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

2)我可以在Linux上创建NOT -fPIC编译的SO文件吗?我可以离开-fPIC吗?是否有关于此主题的howto,manual或project,并且可以不浪费整个寄存器并仍然动态加载库?

如果我在编译.so文件时丢弃-fPIC会发生什么?

最佳答案

What happens if I just drop the -fPIC when compiling a .so-file?

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

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

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

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

BTW,position independent code在x86(32位)上比在x86-64上成本高得多.但值得付出努力(可能,PIC代码在x86 32位上比非PIC低5到10%).