53

我有c++filt命令去破坏符号,相反的工具是什么工具来破坏符号名称?

如果我想调用dlsym()一个错位的 C++ 函数名,这将很有用。我宁愿不对代码中的名称进行硬编码,因为由于使用了新的编译器版本或新的编译器品牌,或者目前由于为多个平台编译,它可能会随着时间的推移而改变。

是否有一种编程方式可以在运行时获取表示 C++ 函数的字符串,以便代码独立于编译器?一种可能的方法是在编译时调用一个实用程序,该实用程序为正在使用的编译器执行名称修改,并将适当的修改后的 C++ 符号名称插入到字符串中dlsym()以供使用。

这是我在此站点上找到的最接近解决方案的解决方案,该解决方案是通过使用固定的 C 样式名称间接到您希望的库中定义的 C++ 符号来完成的dlsym(),但如果您无法控制该库的内容提供,这不是一个选项。

4

4 回答 4

7

这就是 g++ 破坏名称的方式。您可能会在您的程序中实施这些修改规则。

另一个(疯狂的)解决方案是列出您要使用的库中的所有符号(如果您了解格式,这并不难),将它们全部解开,然后在该列表中搜索您的函数名称。这种方法的优点是拆解更容易,因为有一个函数调用来做到这一点:abi::__cxa_demangle,来自 cxxabi.h 头文件。

于 2015-08-23T03:37:45.367 回答
5

您可以通过查看 .so 您正在查看的符号表来获得所需的内容:其他人已经回答了此问题 Returning a shared library symbol table

但是,如果符号太多……那可能行不通。
所以这是一个疯狂的想法。买者自负!

一个潜在的解决方案是:

  1. 创建一个包含一个名称的存根文件:您想要的名称:void myfunction() { }

  2. 编译该文件(使用 -fPIC 和 -shared 所以它是一个动态库)

  3. 在该特定文件上调用 dlopen/dlsym

  4. 遍历符号(应该只有一个想要的符号加上您可以过滤的其他常规垃圾)。遍历符号很笨拙,但您可以做到: 返回共享库符号表

  5. dlclose() 释放它(从你的符号中丢失存根)

  6. 用 dlopen 打开你想要的文件

基本上,你会从你的代码中调用编译器,它会创建一个 .so 你可以查看,取出唯一的值,然后卸载那个 .so 以便你可以加载你想要的那个。

这很疯狂。

于 2015-08-21T21:29:52.417 回答
2

名称修饰是特定于实现的。

名称修饰没有标准,因此最好的办法是找到一个编译器来为您完成。

名称修改

如果您希望手动执行此操作,此处有一个表格可以帮助您

于 2015-08-19T16:24:20.667 回答
1

比第一次发布的更简单的方法。编写一个小 C++ 程序,例如:

#include <stdlib.h>

extern int doit(const char *toto, bool is);

int main(int argc, char *argv[])
{
  exit(doit (argv[0], true));
}

构建它

# g++ -S test.cpp

并从汇编源代码中提取符号名称

# cat test.s | grep call | grep doit | awk '{print $2}'

你得到:

rcoscali@srjlx0001:/tmp/TestC++$ cat test.s | grep call | grep doit | awk '{print $2}'
_Z4doitPKcb
rcoscali@srjlx0001:/tmp/TestC++$ 

重整的doit符号是_Z4doitPKcb 使用您计划使用的编译器,因为每个编译器都有自己的名称重整规则(正如之前所说的,从一个编译器到另一个编译器,这些规则可能会改变)。

玩得开心 !

于 2016-06-25T12:51:37.127 回答