如何使用c++filt工具解析被name mangling过的符号? (符号解码)

c++kquote>c++filt 不生效主因是符号未正确 mangling 或 ABI 不匹配:C 符号(extern “C”)、MSVC ABI、缺 _Z 前缀、含空格未加引号等;正确用法需带前缀、单引号包裹,必要时指定 –format。

如何使用c++filt工具解析被name mangling过的符号? (符号解码)

直接用 c++filt 就能还原大多数 GCC/Clang 编译器生成的 mangled 符号,但必须注意输入格式、ABI 版本和模板实例化细节,否则会输出原样或报错。

为什么 c++filt 有时不生效?

常见原因不是工具坏了,而是符号本身没被正确 mangling,或用了非默认 ABI:

  • 符号来自 C 代码(如加了 extern "C")——c++filt 不处理,直接原样输出
  • Clang 默认用 Itanium ABI,但若编译时加了 -fms-extensions 或目标是 Windows(MSVC ABI),c++filt 默认不支持
  • 符号开头缺 _Z(Itanium 标准前缀),比如只粘贴了 4func 这种片段,c++filt 无法识别
  • 符号含空格或特殊字符未转义,shell 直接截断,应加引号

如何正确传入符号并获取可读名?

最稳妥的方式是:确保符号完整、带前缀、用单引号包裹,并显式指定 ABI(如有必要):

c++filt '_Z3fooi'
c++filt --format=gnu-v3 '_ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKSt7__cxx1112basic_stringIS4_S5_T1_E'

关键点:

立即学习C++免费学习笔记(深入)”;

  • Linux/macOS 下符号通常以 _Z 开头(如 _Z3fooifoo(int)),必须保留
  • --format=gnu-v3 是默认值,一般不用写;但若怀疑是旧版 GCC(如 3.x)产出,可加 --format=gnu
  • 批量处理时用 c++filt -n(no strip underscores)避免误删下划线,尤其对内联命名空间有用

从二进制文件里提取并解码符号的典型流程

不能只靠 c++filt 单独工作,它不读文件,需配合 nmobjdumpreadelf

nm -C a.out | grep 'T '     # -C 已启用 demangle,但可能不准

更可靠的是先提取 raw 符号再过滤:

Copy.ai

Copy.ai

Copy.ai 是一个人工智能驱动的文案生成器

下载

nm --defined-only --demangle=none a.out | awk '$2 == "T" {print $3}' | c++filt

说明:

  • --demangle=none 强制 nm 输出原始 mangled 名(避免双重解码)
  • $2 == "T" 只取文本段定义的函数符号(排除调试符号或弱符号)
  • 管道进 c++filt 才做最终解析,可控性高

容易被忽略的模板与匿名命名空间问题

模板实例化和匿名命名空间会导致符号极长,且 c++filt 输出可能仍含编译器内部标识:

c++filt '_ZN1A3fooIiEEvT_'

结果可能是:A::foo(int) —— 注意末尾的 (int) 是参数类型,不是调用,别误以为是函数调用表达式。

匿名命名空间符号(如 _ZN12_GLOBAL__N_13barEv)解码后显示为 (anonymous namespace)::bar(),括号是 c++filt 的约定表示,不是 C++ 语法。

真正麻烦的是带 std:: 内部实现细节的符号(比如 __cxx11),它们在不同 libstdc++ 版本间不兼容,c++filt 能显示但不代表 ABI 兼容。

https://www.php.cn/faq/1996143.html

发表回复

Your email address will not be published. Required fields are marked *