我有一个闭源 Linux 库 libfoo,它可以调用另一个闭源库 libbar 以获取其他(主要是不需要的)功能。但是,出于道德原因,我不能使用 libbar,所以我试图制作一个虚拟库 libfakebar,它“实现”尽可能少的 libbar,同时仍然可以用作替代品(即,尽可能接近尽可能多地收集存根)。
我最初尝试简单地通过 libbar 从 libbar 中提取定义的符号,nm -D --defined-only libbar.so
并且只为这些符号创建存根,参考可用的公共文档以获得适当的函数签名。但是,当 libfoo 尝试进行不基于符号的调用时,这会失败。具体来说,它调用BarInstance()
libbar 以获取指向 C++ 类实例的指针,向该指针添加一个看似任意的值,然后使用在新地址处找到的值作为指向它调用的下一个函数的指针。这是一个演示此示例的示例:
callq 0x7fff97158300 <BarInstance@plt>
mov (%rax),%r8
lea 0x96c165(%rip),%rcx # 0x7fff97b50e65
mov %ebp,%edx
mov %r12d,%esi
mov %rax,%rdi
callq *0x28(%r8)
我无法理解这应该如何有意义或成为“合法”代码。值得注意的是,如果我BarInstance()
返回一组指向存根函数而不是类实例的指针,libfoo 会毫无怨言地运行,并且一切“正常”。不幸的是,它不足以满足我的最低功能要求,因为我需要的至少一个功能不适用于上述存根,而且 libfoo 的奇怪调用行为并不能帮助我了解更多可能需要加在哪里。
我不确定这会产生什么影响,但似乎 libbar 是使用 GCC 的-fvisibility=hidden
. 我一直无法弄清楚上述调用行为的确切含义,因此我需要在 libfakebar 中做什么才能正确复制 libfoo 代码按预期工作所需的任何内容 - 这里发生了什么?