首页 > 解决方案 > ELF补丁,绑定问题

问题描述

目前我正在尝试修补 ELF 可执行对象文件。

我正在使用原始的 hello-world 应用程序测试我的实用程序。打补丁后一切似乎都很好,但是在执行时,应用程序会出现段错误。

修补时,我还插入了一个新的共享对象依赖项。为了了解出了什么问题,我同时设法将共享对象链接到我的测试应用程序中。这样我就会收到格式g++正确的结果,我可以将其与我的算法结果(或多或少)进行比较。

我遇到的问题是,在执行过程中,我修改后的 hello-world 应用程序无法调用std::cout例程,因为std::ostream::sentry::sentry(std::ostream&)ctor 失败了;我设法使用gdb. 在调试并与格式良好的结果进行比较时,我设法找出了问题所在。似乎符号std::cout/_ZSt4cout重定位绑定被滥用了。尽管这两个结果在该部分中具有完全相同的DT_NEEDED条目(也以相同的顺序),并且尽管它们在该部分中.dynamic都有一个导入符号条目,并进行了相应的修改和内容,但-尽管所有这些-功能,当解决std::cout.dynsym.gnu.version.gnu.hashstd::ios_base::Init::Init()std::cout对象,对这两种结果的操作方式不同。对于格式正确的结果 - 在.bsshello-world 应用程序部分中的正确条目上,而对于我的算法结果 - 在共享库部分中的std::cout条目(如readelfutil 验证) 。.gotlibstdc++

最后但并非最不重要的一点是,当使用该LD_DEBUG=bindings选项执行时,我收到以下格式正确结果的输出(添加std::cin/_ZSt3cin用于对比):

...
     10067: binding file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] to ./hello_world_wellformed [0]: normal symbol `_ZSt4cout' [GLIBCXX_3.4]
     10067: binding file /home/user/Documents/Test/libmyexternal.so [0] to ./hello_world_wellformed [0]: normal symbol `_ZSt4cout' [GLIBCXX_3.4]
     10067: binding file ./hello_world_wellformed [0] to /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]: normal symbol `_ZSt4cout' [GLIBCXX_3.4]
...
     10067: binding file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] to ./hello_world_wellformed [0]: normal symbol `_ZSt3cin' [GLIBCXX_3.4]
     10067: binding file ./hello_world_wellformed [0] to /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]: normal symbol `_ZSt3cin' [GLIBCXX_3.4]
...

而对于算法修改的结果:

...
     10027: binding file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] to /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]: normal symbol `_ZSt4cout' [GLIBCXX_3.4]
     10027: binding file /home/user/Documents/Test/libmyexternal.so [0] to /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]: normal symbol `_ZSt4cout' [GLIBCXX_3.4]
     10027: binding file ./hello_world_algotest  [0] to /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]: normal symbol `_ZSt4cout' [GLIBCXX_3.4]
...
     10027: binding file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] to /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]: normal symbol `_ZSt3cin' [GLIBCXX_3.4]
     10027: binding file ./hello_world_algotest [0] to /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]: normal symbol `_ZSt3cin' [GLIBCXX_3.4]
...

我该如何解决这个问题或这种行为可能是什么原因?如何处理glibclibstdc++处理这种情况以及如何修改算法的应用程序的std::cout条目对库来说变得“不可见”(尽管readelfobjdumpnmutils 表明一切都是正确的)?

自然,两者的版本glibclibstdc++版本相同,两个 hello-world 应用程序都编译在相同的g++版本下。.bss部分正确驻留,所有部分和段都设置了适当的标志。

标签: linuxgccbindingg++elf

解决方案


挖掘glibc源代码,使用gdb(并且丢失了几天),我达到了_dl_lookup_symbol_xdo_lookup_x函数,定义在dl-lookup.c; 通过的参数向我展示了(格式良好的结果和算法派生的结果之间)的区别在于哈希值。好吧,我忘记了 GNU 哈希表被错误地修改了。添加导入功能后,您必须更改 GNU 哈希表索引(幸运的是,您不必重建整个哈希表,只需更新索引即可;不要忘记,添加导入功能时,您仍然需要更改.dynsym 和 GNU 版本表内容)(对整个 GNU 散列概念的一个非常酷的解释可以在这里看到:https ://flapenguin.me/elf-dt-gnu-hash)。顺便说一句,我发现并修复了一个带有过时 .bss 部分编号的错误(由于部分重建而发生)。


推荐阅读