c++filt - 还原so中的函数名

C++的name mangling

C++是允许函数重载的,也就引出了编译器的name mangling(名字修饰)机制,其目的是给同名的重载函数不同的签名。

例如,对于如下代码:

1
2
3
4
5
6
7
8
int test(int a,int b)
{
return a+b;
}

int test(int a){
return a;
}

使用g++编译成so后,使用nm -a (ldd -r命令也可以)查看so中的符号:

upload successful

发现两个test函数名字变为Z4testi和Z4testii, 这就是name mangling机制产生的。其中_Z是一个前缀,4表示函数名长度(test长度为4),i表示参数类型。

C++的name mangling遵循一定的规则,因此是可逆的,即通过符号还原出原来的函数定义。这个工具就叫c++filt。

c++filt

对于上述例子中的符号我们使用c++filt

upload successful

可以看到还原出来我们定义的函数。

当然,工程中的函数并没有我们给出的例子中那么简单,例如Android中有那么多的类和命名空间,其编译生成的符号也是很复杂的,例如

1
2
3
$c++filt __ZN3art7DexFile10OpenMemoryEPKhjRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPKNS_10OatDexFileEPS9_
输出:
art::DexFile::OpenMemory(unsigned char const*, unsigned int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned int, art::MemMap*, art::OatDexFile const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*)

总结

c++filt在hook、逆向等场景中非常有用,可以帮助我们很快的还原符号,定位代码。

参考资料:

  1. https://en.wikipedia.org/wiki/Name_mangling