C/C++ 名字修饰
C/C++ 名字修饰
C 语言的名字修饰
C语言并不支持重载,因此C程序中禁止函数与函数同名,也就没有必要做name mangling。但C语言的函数调用协议(calling conventions)五花八门,用某一种调用协议编译的静态库或动态库的函数,如果用另外的调用协议去调用将会导致错误甚至系统崩溃。因此C语言编译器对函数的名字做少量的修饰,用于区别该函数支持哪种调用协议,这可以给编译、链接、特别是库函数的载入提供额外的检查信息。
C语言常用的调用协议有三种:cdecl, stdcall 与 fastcall。
- cdecl 的函数被改名为_name;
- stdcall的函数被改名为_name@X;
- fastcall的函数被改名为@name@X。
其中X是函数形参所占用的字节长度(包括那些用寄存器传递的参数, 如fastcall协议).
1 | int __cdecl foo(int i); // mangled name is _foo; |
注意:Windows 的 64位 Microsoft C 的调用约定中没有前导下划线。
C++ 的名字修饰
C++语言并没有规定一个标准的名字修饰方式,所以各款编译器都使用各自的名字修饰方式。(相同编译器的不同版本也可能使用不同的修饰规则)
GCC/Clang 编译器
MSVC 编译器
Visual C++ 名字修饰符主要包含以下部分:
- 问号前缀;
- 函数名称或不包括类名的方法名称。构造、析构函、运算符重载等具有特定的函数名;
- 如果不是特殊函数名,那么加一个分隔符@;
- 如果是类的方法,那么由所属类开始依次加上类名和父类名,每个类名后面跟一个@符号,所有类名加好后,再加上@Q或者@S(静态方法)。如果不是类的方法,那么直接加上@Y;
- 调用约定代码。对于不属于任何类的函数,C调用约定(__cdecl)的代码为A,__fastcall约定的代码为I,__stdcall 的代码为G,对于类方法,调用约定前会加一个字符A,this调用的代码为E.
- 返回值编码。
- 参数列表编码,以@符号结束。
- 后缀Z。
C++名称修饰组成规律:
- 都是以?开始,以字符Z结束,中间由@符号分割为多个部分。整个名称的长度最长为2048个字节。
- 类的成员函数,其基本结构为:?方法名@类名@@调用约定 返回类型 参数列表 Z。
- 非类的成员函数,其基本结构: ?函数名@@Y调用约定 返回类型 参数列表Z。
特殊函数名:
特殊方法名 | 编码 |
---|---|
构造函数 | ?0 |
析构函数 | ?1 |
重载 new | ?2 |
重载 delete | ?3 |
数据类型:
编码 | 数据类型 |
---|---|
A | Type modifier (reference) |
B | Type modifier (volatile reference) |
D | char |
E | unsigned char |
F | short |
G | unsigned short |
H | int |
I | unsigned int |
J | long |
K | unsigned long |
M | float |
N | double bool |
O | long double Array |
P | Type modifier (pointer) |
Q | Type modifier (const pointer) |
R | Type modifier (volatile pointer) |
S | Type modifier (const volatile pointer) |
T | union |
U | struct |
V | class |
W | enum |
X | void |
预编译宏
GCC/Clang 以及微软都提供了预定义宏,用于获取源码中的方法名。
1 | // GCC 支持: __PRETTY_FUNCTION__ 和 __FUNCTION__ |
修饰解析
- GCC/Clang 编译的符号通过 c++filt 去修饰。
- MSVC 编译的符号使用微软 Visual C++ 中的解析修饰名字的工具软件 undname.exe
查看Visual C++的函数的修饰后的名字:
- 直接用工具软件(如微软开发环境提供的dumpbin)查看obj、exe等二进制文件。使用dumplib查看.obj或.lib文件时,使用”/SYMBOLS”命令行选项。
- 编译时使用”/FA[c|s|u]”编译选项,生成带有丰富注释信息的汇编源程序,其文件扩展名是.cod或者.asm,可以查看每个C/C++函数的修饰名。
参考
https://zh.wikipedia.org/wiki/Visual_C%2B%2B%E5%90%8D%E5%AD%97%E4%BF%AE%E9%A5%B0