Any object code produced by compiler is usually linked with other pieces of object code by linker. The linker relies on unique object names for identification but C++ (and many modern programming languages) allows different entities to be named with the same identifier as long as they occupy a different namespace. So names should be mangled by compiler before reaching the linker. Linker also needs a great deal of information on each program entity. For example, to correctly link a function it needs its name, the number of arguments and their types, and so on.
C++ decoration can become fairly complex (storing information about classes, templates, namespaces, operator overloading, etc). This section explains the specific manner in which the Microsoft Visual C++ series of compilers mangle symbol names.
? (question mark). Because all mangled C name starts with alphanumeric characters, @ (at-sign) and _ (underscore), C++ name can be distinguished from C name.Structure of mangled name looks like this:
?@?
@
Qualification is written in reversed order. For example myclass::nested::something becomes something@nested@myclass@@.
@.
?. Most of special name is constructor, destructor, operator and internal symbol. Below is a table for known codes.| Code | Meaning with no underline | Meaning with preceding underline | Meaning with two preceding underlines |
|---|---|---|---|
0
| Constructor | operator /= | |
1
| Destructor | operator %= | |
2
| operator new | operator >>= | |
3
| operator delete | operator <<= | |
4
| operator = | operator &= | |
5
| operator >> | operator |= | |
6
| operator << | operator ^= | |
7
| operator ! | 'vftable' | |
8
| operator == | 'vbtable' | |
9
| operator != | 'vcall' | |
A
| operator[] | 'typeof' | 'managed vector constructor iterator' |
B
| operator returntype | 'local static guard' | 'managed vector destructor iterator' |
C
| operator -> | 'string'(Unknown) | 'eh vector copy constructor iterator' |
D
| operator * | 'vbase destructor' | 'eh vector vbase copy constructor iterator' |
E
| operator ++ | 'vector deleting destructor' | |
F
| operator -- | 'default constructor closure' | |
G
| operator - | 'scalar deleting destructor' | |
H
| operator + | 'vector constructor iterator' | |
I
| operator & | 'vector destructor iterator' | |
J
| operator ->* | 'vector vbase constructor iterator' | |
K
| operator / | 'virtual displacement map' | |
L
| operator % | 'eh vector constructor iterator' | |
M
| operator < | 'eh vector destructor iterator' | |
N
| operator <= | 'eh vector vbase constructor iterator' | |
O
| operator > | 'copy constructor closure' | |
P
| operator >= | 'udt returning' (prefix) | |
Q
| operator , | Unknown | |
R
| operator () | RTTI-related code (see below) | |
S
| operator ~ | 'local vftable' | |
T
| operator ^ | 'local vftable constructor closure' | |
U
| operator | | operator new[] | |
V
| operator && | operator delete[] | |
W
| operator || | ||
X
| operator *= | 'placement delete closure' | |
Y
| operator += | 'placement delete[] closure' | |
Z
| operator -= |
Prefix _P is used as ?_PX, though I don't know about it.
Below is RTTI-related code (all starting with _R). Some codes have trailing parameters.
| Code | Meaning | Trailing Parameters |
|---|---|---|
_R0
| type 'RTTI Type Descriptor' | Data type type. |
_R1
| 'RTTI Base Class Descriptor at (a,b,c,d)' | Four encoded numbers: a, b, c and d. |
_R2
| 'RTTI Base Class Array' | None. |
_R3
| 'RTTI Class Hierarchy Descriptor' | None. |
_R4
| 'RTTI Complete Object Locator' | None. |
?$ has template arguments. This kind of name looks like this:
?$@For example, we assume the following prototype.
void __cdecl abc,void*>::xyz(void);
Name of this function can be obtained by the following process:
abc,void*>::xyz xyz@ abc ,void*> @ xyz@ ?$abc@ def void* @ @ xyz@ ?$abc@ V def @ PAX @ @ xyz@ ?$abc@ V ?$def@H@ @ PAX @ @ xyz@?$abc@V?$def@H@@PAX@@
So mangled name for this function is ?xyz@?$abc@V?$def@H@@PAX@@YAXXZ.
?? denotes nested name. Nested name is a name inside local scope but needed to be exported. Its structure looks like the following:
?? again)
For example, ?nested@??func@@YAXXZ@4HA means variable ?nested@@4HA(int nested) inside ?func@@YAXXZ(void __cdecl func(void)). UnDecorateSymbolName function returns int 'void __cdecl func(void)'::nested for this input.
? and unsigned number. UnDecorateSymbolName function returns something like '42' for this kind of input.Exceptionally if numbered namespace starts with ?A it becomes anonymous namespace ('anonymous namespace').
alpha@?1beta@@(beta::'2'::alpha), 0 refers to alpha@, and 1(not 2) refers to beta@.Generally back reference table is kept during mangling process. It means you can use back reference to function name in function arguments (shown later than function name). However, in template argument list back reference table is separately created.
For example, assume ?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@ (std::basic_string). In std::basic_string<...>, 0 refers to basic_string@, 1 refers to ?$char_traits@G@, and 2 refers to std@. This relation doesn't change wherever it is.
0 to 9 represents number 1 to 10.num@ represents hexadecimal number, where num consists of hexadecimal digit A(means 0) to P(means 15). For example BCD@ means number 0x123, that is 291.@ represents number 0.? represents minus sign. Note that both ?@ and @ represents number 0.| Code | Meaning with no underline | Meaning with preceding underline |
|---|---|---|
| ? | Type modifier, Template parameter | |
| $ | Type modifier, Template parameter | __w64 (prefix) |
| 0-9 | Back reference | |
| A | Type modifier (reference) | |
| B | Type modifier (volatile reference) | |
| C | signed char | |
| D | char | __int8 |
| E | unsigned char | unsigned __int8 |
| F | short | __int16 |
| G | unsigned short | unsigned __int16 |
| H | int | __int32 |
| I | unsigned int | unsigned __int32 |
| J | long | __int64 |
| K | unsigned long | unsigned __int64 |
| L | __int128 | |
| M | float | unsigned __int128 |
| 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 | Complex Type (union) | |
| U | Complex Type (struct) | |
| V | Complex Type (class) | |
| W | Enumerate Type (enum) | wchar_t |
| X | void, Complex Type (coclass) | Complex Type (coclass) |
| Y | Complex Type (cointerface) | Complex Type (cointerface) |
| Z | ... (elipsis) |
Actually void for X and elipsis for Z can be used only for terminator of argument list or pointer. Otherwise, X is used as cointerface.
_.
0 to 9 refers to first shown type to 10th shown type in argument list. (It means return type cannot be referred.) Back reference can refer to any non-primitive type, including extended type. Of course back reference can refer to prefixed type such as PAVblah@@(class blah *), but cannot refer to prefixless type — say, Vblah@@ in PAVblah@@.As back reference for name, in template argument list back reference table is separately created. Function argument list has no such scoping rule, though it can be confused sometimes. For example, assume P6AXValpha@@Vbeta@@@Z(void (__cdecl*)(class alpha, class beta)) is first shown non-primitive type. Then 0 refer to Valpha@@, 1 refer to Vbeta@@, and finally 2 refer to function pointer.
$A for __gc, $B for __pin)There is eight type of type modifier:
| none | const | volatile | const volatile | |
|---|---|---|---|---|
| Pointer | P
| Q
| R
| S |
| Reference | A
| B
| ||
| none | ?, $$C
|
For normal type, referred type info is data type. For function, it looks like the following. (It depends on CV-class modifier)
T, U, V, ...)W. It looks like this:
WReal type for enum is represented as the following:
| Code | Corresponding Real Type |
|---|---|
0
| char |
1
| unsigned char |
2
| short |
3
| unsigned short |
4
| int (generally normal "enum") |
5
| unsigned int |
6
| long |
7
| unsigned long |
_O. It looks like this:
_O
You can use multi-dimensional array like _OC_OBH, but only the outmost CV-class modifier is affected. (In this case _OC_OBH means int volatile [][], not int const [][])
The table below is a list of known template parameters. a, b, c represent encoded signed numbers, and x, y, z represent encoded unsigned numbers.
| Code | Meaning |
|---|---|
?x
| anonymous type template parameter x ('template-parameter-x') |
$0a
| integer value a |
$2ab
| real value a × 10b-k+1, where k is number of decimal digits of a |
$Da
| anonymous type template parameter a ('template-parametera') |
$Fab
| 2-tuple {a,b} (unknown) |
$Gabc
| 3-tuple {a,b,c} (unknown) |
$Hx
| (unknown) |
$Ixy
| (unknown) |
$Jxyz
| (unknown) |
$Qa
| anonymous non-type template parameter a ('non-type-template-parametera') |
X (means void, also terminating list)@ (means normal list of data types. Note that N can be zero)Z (means list with trailing elipsis)| Variable | Function | ||||
|---|---|---|---|---|---|
| none | const | volatile | const volatile | ||
| none | A
| B, J
| C, G, K
| D, H, L
| 6, 7 |
| __based() | M
| N
| O
| P
| _A, _B |
| Member | Q, U, Y
| R, V, Z
| S, W, 0
| T, X, 1
| 8, 9 |
| __based() Member | 2
| 3
| 4
| 5
| _C, _D |
| Prefix | Meaning |
|---|---|
E
| type __ptr64 |
F
| __unaligned type |
I
| type __restrict |
CV-class modifier is usually used in reference/pointer type, but it is also used in other place with some restrictions:
0 (means __based(void))2name (means __based(name), where name is qualification without basic name)5 (means no __based())
@ for voidThe following table shows calling convention of function:
| Code | Exported? | Calling Convention |
|---|---|---|
A
| No | __cdecl |
B
| Yes | __cdecl |
C
| No | __pascal |
D
| Yes | __pascal |
E
| No | __thiscall |
F
| Yes | __thiscall |
G
| No | __stdcall |
H
| Yes | __stdcall |
I
| No | __fastcall |
J
| Yes | __fastcall |
K
| No | none |
L
| Yes | none |
M
| No | __clrcall |
Argument list for throw() attribute is same to argument list, but if this list is Z, it means there is no throw() attribute. If you want to use throw() you have to use @ instead.
_ (means __based() property is used)The table below shows code for access level and function type:
| none | static | virtual | thunk | |
|---|---|---|---|---|
| private: | A, B
| C, D
| E, F
| G, H |
| protected: | I, J
| K, L
| M, N
| O, P |
| public: | Q, R
| S, T
| U, V
| W, X |
| none | Y, Z
|
this adjustor property, which means an offset to true this value in some multiple inheritance.
The table below shows code for access level and storage class:
| none | static | virtual | thunk | |
|---|---|---|---|---|
| private: | A, B
| C, D
| E, F
| G, H |
| protected: | I, J
| K, L
| M, N
| O, P |
| public: | Q, R
| S, T
| U, V
| W, X |
| none | Y, Z
|