【发布时间】:2020-10-15 14:11:31
【问题描述】:
目前我正在尝试修补 ELF 可执行对象文件。
我正在使用原始的 hello-world 应用程序测试我的实用程序。打补丁后一切似乎都很好,但在执行时,应用程序出现了段错误。
修补时,我还插入了一个新的共享对象依赖项。为了了解出了什么问题,我同时设法将共享对象链接到我的测试应用程序中。这样我就会收到格式正确的g++-made 结果,我可以将其与我的算法结果(或多或少)进行比较。
我遇到的问题是,在执行期间,我修改后的 hello-world 应用程序无法调用 std::cout 例程,因为 std::ostream::sentry::sentry(std::ostream&) ctor 失败;我设法使用gdb 解决了这个问题。在调试并与格式良好的结果进行比较时,我设法找出了问题所在。看来std::cout / _ZSt4cout 重定位绑定符号有点被滥用。尽管两个结果在.dynamic 部分中具有完全相同的DT_NEEDED 条目(顺序也相同),并且尽管它们在.dynsym 部分中都有一个std::cout 的导入符号条目,并相应地修改了@ 987654331@ 和 .gnu.hash 内容, - 尽管有这些, - std::ios_base::Init::Init() 函数在解析 std::cout 对象时,对这两个结果的操作不同。对于格式良好的结果 - 在 hello-world 应用程序的 .bss 部分中的正确条目上,而对于我的算法结果 - 在 @987654338 中的 std::cout 条目上(如 readelf 实用程序验证) 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 实用程序表明一切都正确)?
当然,glibc 和 libstdc++ 版本和相同,两个 hello-world 应用程序都在相同的g++ 版本下编译。 .bss 部分正确驻留,所有部分和段都设置了正确的标志。
【问题讨论】: