ELF目标文件和共享对象之间的ELF头差异是什么?

19
首先,我从技术角度而不是库代码用户的角度来提出这个问题。一个例子是共享对象包含程序头文件而普通对象文件则不包含。还有哪些区别?
至于我的问题目的,我正在尝试确定需要从共享对象文件中删除哪些内容才能使链接器将其视为普通对象文件并尝试将其重新定位和静态链接到生成的可执行文件中,而不是将其识别为共享库并生成 DT_NEEDED 引用。这反过来是将共享库转换为可以静态链接的东西的第一步(但可能需要进一步的工作来使重定位可满足)。

不是针对你的问题的答案,但你可能会发现ld命令中的-r选项很有用。 - bdonlan
如果它们不完全符合您的要求,它们可能会有所帮助:http://statifier.sourceforge.net/(将共享库直接链接到二进制文件)和http://libraryopt.sourceforge.net/(拆分共享库,删除不需要的符号并重新构建它们)...也许两者的组合? - technosaurus
谢谢提供的想法,但我使用statifier没有取得好的结果,并且我意识到需要进行机械转换(尽管可能有些痛苦,并且可能无法处理某些具有非标准加载段的非常奇怪的库),以将共享库转换为单个可重定位的.o文件,以进行静态链接。 - R.. GitHub STOP HELPING ICE
1个回答

11
你会发现的一个主要区别是,在最终链接阶段,许多C库组件被静态链接到库中,形成了INIT和FINI等符号。这些是在程序头中用DT_INIT和DT_FINI条目指定的;你需要将它们转换为静态构造函数/析构函数条目。在转换为.o时,DT_NEEDED条目将丢失;你需要手动重新添加它们。
最终链接阶段生成的PLT需要与最终输出文件合并,或者转换回普通重定位;这不容易,因为PLT只是代码。GOT也是一个问题;它位于与.text段相对固定的偏移量处,并包含对数据成员的指针。然而,它还包含指向_DYNAMIC结构的指针,每个库或可执行文件只能有一个。而且你不能改变GOT中的偏移量,因为它们直接从代码引用。
因此,将.so转换回真正的.o是非常困难的;在转换为PLT/GOT时信息已经丢失了。更好的方法可能是修改C库的动态链接器,以支持将已经映射到内存中的共享库作为静态图像进行链接。也就是说,你可以通过将.so转换为页面对齐的只读部分来将其转换为.o;然后将其传递给动态链接器以重新映射适当的权限并执行正常的共享库初始化。然后添加一个静态构造函数来调用C库以初始化共享库。最后,添加适当的导出符号以对应于共享库的.text段中的动态符号。
但这种方法的一个问题是,在伪solib初始化静态构造函数之前可能会运行静态构造函数。在这种情况下,它们不能尝试调用solib中的函数,否则你可能会崩溃,因为solib尚未初始化。这可能可以通过使导出的符号指向一个确保先初始化solib的跳板函数来避免(不过对于数据符号而言不太容易!)。

你可能会发现,这个之前的问题对你有些帮助。


3
然而,最重要的是需要更改类型(Elf_Ehdr.e_type)。 (EXEC / DYN与REL不同) - jørgensen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接