【问题标题】:Getting mangled name from demangled name从 demangled 名称中获取 mangled 名称
【发布时间】:2023-03-13 00:02:02
【问题描述】:

有什么方法可以从 g++ 中的 demangled name 中取回 mangled name。

例如,我的名称是func(char*, int),我应该怎么做才能恢复名称,即_Z4funcPci

我的问题是特定于 g++ 的。

【问题讨论】:

  • @H2CO3:很好的链接,但是有什么方法可以知道它是否是最新的和权威的?该域名似乎是温尼伯大学的一个网站。
  • @j_random_hacker 美国技术大学有不在官方网站上放垃圾的好习惯。
  • @H2CO3:在该页面链接到的内容页面上:“此文档于 1999 年 8 月 27 日生成”。另外,如果我记得的话,温尼伯在加拿大:-P
  • @j_random_hacker 正确。我应该说“美国人”。好吧,那我们试着找一个更新的版本吧。
  • @j_random_hacker 也是,这个related SO Q/A 指向同一个站点:)

标签: c++ g++ name-mangling


【解决方案1】:

您可以简单地使用 g++ 编译一个带有您需要的签名的空函数并从中提取名称。例如:

echo "int f1(char *, int) {} " | g++ -x c++ -S - -o- | grep "^_.*:$" | sed -e 's/:$//'

给出输出

_Z2f1Pci

这是我认为你需要的。确保包含任何相关的头文件,因为它们会影响符号被破坏的方式。

【讨论】:

  • 好方法。并使用c++filt 作为另一个方向。
  • 这并不总是那么容易。假设你有像IFS::Profiler::create(IFS::Handle hdl) 这样的名字。
  • 完全“没那么容易”。如果未声明任何提及的数据结构,则编译失败。其中一些在您的代码中,其中一些来自标头。
【解决方案2】:

基于 Bojan Nikolic 的方法,这里有一个更好的脚本:

mangle.bash:

IFS='::' read -a array <<< "$1"

indexes=("${!array[@]}")

prefix=""
middle=""
suffix=""
rettype=""
if [ -z "$2" ]; then
    rettype="void"
fi


for index in "${indexes[@]}"
do
    #echo "$index ${array[index]}"
    if [ $index == ${indexes[-1]} ]; then
    #echo "last"
    middle="$rettype ${array[index]};"
    elif [ -n "${array[index]}" ]; then
    #echo "not empty"
    prefix="${prefix}struct ${array[index]}{"
    suffix="${suffix}};"
    fi
done

#echo "$prefix$middle$suffix $rettype $1{}"
echo "$prefix$middle$suffix $rettype $1{}" | g++ -x c++ -S - -o- | grep "^_.*:$" | sed -e 's/:$//'

用途:

$ ./mangle.bash "abc::def::ghi()"
_ZN3abc3def3ghiEv
$ ./mangle.bash "abc::def::ghi(int i, char c)"
_ZN3abc3def3ghiEic
$ ./mangle.bash "abc::def::def(int i, char c)" constr
_ZN3abc3defC2Eic
$ ./mangle.bash "abc::def::~def()" destr
_ZN3abc3defD2Ev

但是关于构造函数和析构函数,记住有 C0 C1 C2 和 D0 D1 D2 。

【讨论】:

  • Cam 你解释一下你的脚本如何接受第二个参数(constr/destr)?我真的不能在代码中看到它(我只看到 $1)。另外,什么是 C0、C1 和 C2 ctors/dtors?
  • 请原谅我的无知...为什么更好?
  • @jww 尝试使用原始脚本获取 abc::def::ghi() 的错误名称
  • 该脚本仅适用于内置类型的参数。拥有自定义类型后,您需要在临时 C++ 代码的头文件中包含声明。
  • 此解决方案仍然不完整,因为您不处理复杂的参数类型。我认为在一般情况下包含必要的标题是不可避免的。
【解决方案3】:

最糟糕的是,有时您无法破坏一个名称,因为您必须获得多个结果。

参见https://reverseengineering.stackexchange.com/q/4323/4398(VFT 中有多个析构函数,它们都被解构为ClassName::~ClassName())。 (构造函数也是如此,我见过C0和C2构造函数。)

另一方面,该答案引用了 Itanium ABI:https://refspecs.linuxbase.org/cxxabi-1.75.html#mangling-type,其中指定了 mangling。

itanium-abi Haskell 包:它对我不起作用(2014 年 5 月)

有一个 Haskell 包 http://hackage.haskell.org/package/itanium-abi 这保证了拆解和拆解,但我只能运行拆解:

在 Ubuntu Precise 上安装:

sudo aptitude install ghc
sudo aptitude install cabal-install
cabal update
cabal install itanium-abi

然后你运行ghci 并在import ABI.Itaniumimport Data.Either 之后得到:

Prelude ABI.Itanium Data.Either> cxxNameToText $ head (rights [ demangleName "_ZTI13QSystemLocale" ])
"typeinfo for QSystemLocale"

mangleName,但它需要DecodedName,它是一个数据结构而不是一个字符串,并且该数据结构仅由demangleName 生成(除非我忽略了某些东西)。希望这会在未来的某个版本中变得更好。

clang 代码

我没有尝试the clang code

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-06
    • 1970-01-01
    • 1970-01-01
    • 2012-08-29
    • 2011-04-03
    • 2018-12-16
    • 1970-01-01
    • 2017-07-23
    相关资源
    最近更新 更多