你会发现一个主要的区别是,在最后的链接阶段,一些C库组件静态链接到库中,形成了INIT和FINI符号等等。这些在程序头中用DT_INIT
和DT_FINI
条目指定;您将需要将这些转换为静态构造函数/析构函数条目。 DT_NEEDED条目将在转换为.o时丢失;您需要手动重新添加它们。
最终链接阶段生成的PLT需要与最终输出文件合并,或者转换回普通重定位;这是不平凡的,因为PLT只是代码。 GOT也是一个问题;它位于.text段的固定相对偏移处,并包含指向数据成员的指针。但是,它也包含一个指向_DYNAMIC结构的指针,其中每个库或可执行文件只能有一个。而且你不能改变GOT中的偏移量,因为它们是直接从代码中引用的。
因此,再次将.so转换为真实的.o是相当困难的;在转换到PLT/GOT时信息丢失了。更好的方法可能是更改C库中的动态链接程序,以支持将已经映射到内存中的共享库链接为静态图像。也就是说,只需将.so转换为.o,然后将其转换为页面对齐的只读部分即可。然后将其传递给动态链接器以重新映射适当的权限并执行正常的共享库初始化。然后添加一个静态构造函数来调用C库来初始化共享库。最后,添加适当的导出符号以对应共享库的.text段中的动态符号。
但是,这种方法的一个问题是,静态构造函数可能会在初始化您的假solib的静态构造函数之前运行。在这种情况下,他们不能尝试从solib调用函数,否则可能会崩溃,因为solib尚未初始化。通过使导出的符号指向蹦床功能可以避免这种情况,从而确保solib首先被初始化(尽管数据符号并不那么容易)。
您可能还会发现this previous question可能对您有些用处。
不是你的问题的答案,但你可能会发现'-r'选项到'ld'有用 – bdonlan
如果他们不是你正在寻找的东西,他们可能至少帮助:http:// statifier。 sourceforge.net/(将共享库直接链接到一个二进制文件)和http://libraryopt.sourceforge.net/(拆分一个共享库,删除不需要的符号并重建它们)...也许这两个组合? – technosaurus
感谢您的想法,但是我没有找到好的结果,并且我意识到应该进行机械转换(尽管中等痛苦,并且可能在一些非标准加载段的非常奇怪的库上失败)将共享库转换为单个用于静态链接的可重定位的'.o'文件。 –