2011-07-08 81 views
19

首先,我从技术角度提出这个问题,而不是图书馆代码用户的观点。不同之处在于共享对象包含程序头文件,而普通对象文件则不包含程序头文件。其他的区别是什么?ELF对象文件和共享对象之间的ELF头部区别是什么?

至于我的问题的目的,我试图找出哪些内容需要从共享对象文件中删除,让链接器将其视为一个普通的对象文件,并尝试重新定位和静态链接它插入到生成的可执行文件中,而不是将其标识为共享库并生成DT_NEEDED参考。这反过来又是将共享库原始“转换”为静态链接的第一步(然而,可能需要进一步的工作以使重定位可满足)。

+0

不是你的问题的答案,但你可能会发现'-r'选项到'ld'有用 – bdonlan

+0

如果他们不是你正在寻找的东西,他们可能至少帮助:http:// statifier。 sourceforge.net/(将共享库直接链接到一个二进制文件)和http://libraryopt.sourceforge.net/(拆分一个共享库,删除不需要的符号并重建它们)...也许这两个组合? – technosaurus

+0

感谢您的想法,但是我没有找到好的结果,并且我意识到应该进行机械转换(尽管中等痛苦,并且可能在一些非标准加载段的非常奇怪的库上失败)将共享库转换为单个用于静态链接的可重定位的'.o'文件。 –

回答

11

你会发现一个主要的区别是,在最后的链接阶段,一些C库组件静态链接到库中,形成了INIT和FINI符号等等。这些在程序头中用DT_INITDT_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可能对您有些用处。

+3

然而,最重要的是,类型(Elf_Ehdr.e_type)也需要改变。 (EXEC/DYN与REL) –

相关问题