linux - 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.hash
std::ios_base::Init::Init()
std::cout
对象,对这两种结果的操作方式不同。对于格式正确的结果 - 在.bss
hello-world 应用程序部分中的正确条目上,而对于我的算法结果 - 在共享库部分中的std::cout
条目(如readelf
util 验证) 。.got
libstdc++
最后但并非最不重要的一点是,当使用该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]
...
我该如何解决这个问题或这种行为可能是什么原因?如何处理glibc
和libstdc++
处理这种情况以及如何修改算法的应用程序的std::cout
条目对库来说变得“不可见”(尽管readelf
、objdump
和nm
utils 表明一切都是正确的)?
自然,两者的版本glibc
和libstdc++
版本相同,两个 hello-world 应用程序都编译在相同的g++
版本下。.bss
部分正确驻留,所有部分和段都设置了适当的标志。
解决方案
挖掘glibc
源代码,使用gdb
(并且丢失了几天),我达到了_dl_lookup_symbol_x
和do_lookup_x
函数,定义在dl-lookup.c
; 通过的参数向我展示了(格式良好的结果和算法派生的结果之间)的区别在于哈希值。好吧,我忘记了 GNU 哈希表被错误地修改了。添加导入功能后,您必须更改 GNU 哈希表索引(幸运的是,您不必重建整个哈希表,只需更新索引即可;不要忘记,添加导入功能时,您仍然需要更改.dynsym 和 GNU 版本表内容)(对整个 GNU 散列概念的一个非常酷的解释可以在这里看到:https ://flapenguin.me/elf-dt-gnu-hash)。顺便说一句,我发现并修复了一个带有过时 .bss 部分编号的错误(由于部分重建而发生)。
推荐阅读
- netlogo - 如何找出特定海龟(Netlogo)在每个滴答声中调用的程序?
- c# - 检索结果集并将其缓存到我的应用程序中
- web-config - web.config 和 cscfg 文件之间的区别?
- javascript - 有没有办法从 Google 自定义搜索 API 获取网站的完整标题?
- r - 使用 r 将凹多边形变成凸多边形
- r - R中switch()中带引号和不带引号的键之间的区别?
- azure - Azure Log Insights - 如何聚合每小时的事件
- python - 为什么此 tn.write("ip address 1.1.1.1 255.255.255.255") 行“检测到无效输入”?
- java - 如果对象的字段变量=方法的参数,我如何从对象数组中删除对象
- python - 使用多处理池时更新对象的成员变量