我正在开发可以作为插件加载到另一个程序中的共享库(.so)。该程序由一组其他库组成。其中一个库,称为 libA.so,导出自己的实现 ::operator new() 和 ::operator delete()。但我不想使用 new 和 delete 的这种实现,而是使用自己的实现(与我的库静态链接)。一切正常,但 libA.so 具有返回指向已分配内存的指针的功能,我应该通过从 libA.so 调用 operator delete 来释放它。所以,我需要来自 libA.so 的 _ZdlPv 符号的地址。
我正在使用函数 dlsym 获取 _ZdlPv 的地址:dlsym(RTLD_DEFAULT, "_ZdlPv")。我自己的操作符删除(_ZdlPv 符号)实现在我的共享库中的动态符号表中不存在,所以我希望获得在 libA.so 中定义的操作符 delete() 的地址。
但是我从 dlsym 函数得到了完全错误的结果——它返回驻留在其他库 libB.so 中的地址。并且 libB.so 不包含 _ZdlPv 符号的定义,但它需要此符号(在该库中未定义)。dlsym() 返回的地址指向 libB.so 的 .MIPS.stubs 部分。看起来这有点像 PLT(但在 MIPS 架构上——是的,我正在为 MIPS 开发)。当我使用 dlsym 返回的地址调用函数时——线程终止。很难调试...
这里有错吗?为什么 dlsym() 对我不起作用?据我所知, $gp 寄存器保存指向“全局链接表”的指针。每个共享库都有自己的链接表?从存根部分调用函数,gp 应该有正确的值——对吧?当我从其他库(libB.so)的存根部分调用代码时——我用不正确的 $gp 值调用它,因为这个线程崩溃了?
但是为什么 dlsym() 返回指向其他 (libB.so) 库的存根部分中的代码的指针?这是因为我的库的存根部分不包含 _ZdlPv 符号,因为它不存在于我的库的动态符号表中?
如果我的假设是正确的,我不明白,如何在 MIPS 平台上使用 dlsym() 从其他库调用仲裁函数?