C++的name mangling
C++是允许函数重载的,也就引出了编译器的name mangling(名字修饰)机制,其目的是给同名的重载函数不同的签名。
例如,对于如下代码:1
2
3
4
5
6
7
8int test(int a,int b)
{
return a+b;
}
int test(int a){
return a;
}
使用g++编译成so后,使用nm -a (ldd -r命令也可以)查看so中的符号:
发现两个test函数名字变为Z4testi和Z4testii, 这就是name mangling机制产生的。其中_Z是一个前缀,4表示函数名长度(test长度为4),i表示参数类型。
C++的name mangling遵循一定的规则,因此是可逆的,即通过符号还原出原来的函数定义。这个工具就叫c++filt。
c++filt
对于上述例子中的符号我们使用c++filt
可以看到还原出来我们定义的函数。
当然,工程中的函数并没有我们给出的例子中那么简单,例如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、逆向等场景中非常有用,可以帮助我们很快的还原符号,定位代码。
参考资料: