Reputation: 77
I want to interpret COMDAT symbol of COFF file The COMDAT symbol is
?make@DNameStatusNode@@SAPAV1@W4DNameStatus@@@Z
How can I interpret it as
(public: static class DNameStatusNode * __cdecl DNameStatusNode::make(enum DNameStatus))
Thanks.
Upvotes: 2
Views: 388
Reputation: 4339
That would be a "decorated" (mangled) C++ function name as generated by Visual Studio (and VS-compatible Windows compilers), not specifically a COMDAT symbol.
The easiest way would be to run the symbol through UNDNAME.EXE
, a utility that comes with Visual Studio. Barring that, you could use the UnDecorateSymbolName()
function in the library Dbghelp.dll
, or the undocumented internal function __unDName()
(which, to my knowledge, is what UNDNAME
uses); I assume you're at least somewhat familiar with this function, considering that DName
is one of its helper classes. [Note that while these tools are mostly accurate, they falter in a few cases (such as pointer const
-ness, certain C++/CLI symbols, or function-local classes declared in extern "C"
functions (including main()
).]
If all else fails, you can also attempt to demangle the name by hand, which would require familiarity with the mangling scheme itself; if you aren't privy to MS-internal information, this can take a significant amount of experimentation and/or research, but is the most accurate way. There are a few simple guidelines that can help with that, though:
?
. If not, the ?
will be preceded by special modifiers (such as __imp_
for __declspec(dllimport)
or ?@
for CodeView), with the name proper starting at the ?
.?
, the segment up to and including the @@
is the entity's qualified name, broken up into separate component names (first the symbol name, then every containing scope's name; namespace scope and class scope are treated identically for this step of the mangling process); each of the component names making up the qualified name is immediately followed by a single @
, which acts as a terminator for that name, and the full name is terminated by a standalone @
(normally creating a double @@
). Read it from right to left, replacing any single @
with the scope operator ::
and stopping at the second @
in the double @@
. [Note that there are also cases where this rule isn't followed, and that templated entity names are really weird. Also note that when a user-defined type (enum, class, struct, union) is encountered during type information, its qualified name will be used according to normal qualified name mangling rules, with the exceptions that 1) it will be preceded with an identifier instead of a question mark1, and 2) the name will be abbreviated if possible2.]
?x
, where x
is a number or capital letter preceded by 0-2 underscores; note that these names act as special abbreviations2, and as such, are not terminated with a single @
. Due to this, special member entities will have a name like ??_FCLS@@QAEXXZ
(default constructor closure for class ::CLS
), and special non-member entities will have names terminated with a single @
instead of a double @@
(such as ??_H@YGXPAXIHP6EPAX0@Z@Z
, the vector constructor iterator; note that ??_H@
is its fully-qualified name, and everything after that is type information).@@
contains all relevant type information, and is very hard to explain without going into a lot of detail. I would suggest using a resource such as Agner Fog's "Calling conventions for different C++ compilers and operating systems" PDF and/or the Wikiversity page "Visual C++ name mangling" as a reference; while their information isn't 100% accurate, it's accurate enough to read most mangled names you'll come across.Hope this helps.
1: One of the following will be used to indicate the type of UDT:
W4
[Note that this technically represents enum : int
, but for some reason the compiler mangles all enum types as W4
and stores underlying type information elsewhere.]V
U
T
It will be followed by the UDT's qualified name, which terminates with a @@
as usual.
class CL; // Is: VCL@@
struct ST; // Is: UST@@
enum EN; // Is: W4EN@@
union UN; // Is: TUN@@
namespace X { class CL; } // Is: VCL@X@@
2: If any of the component names in a UDT's qualified name has already been encountered while mangling the symbol (whether as part of the symbol's qualified name, or as part of a parameter's qualified name (reading parameters from left to right)), and it was one of the first 10 names encountered, both the name and its terminating @
will be abbreviated into a digit representing that previously-used name. Abbreviations are zero-indexed, with the symbol's actual name being counted as name 0
.
namespace Y {
void func(X::CL param);
// Is: ?func@Y@@YAXVCL@X@@@Z
}
namespace X {
void func(CL param);
// Is: ?func@Y@@YAXVCL@1@@Z
// "X@" is replaced with "1".
}
As mentioned, certain special entities (operators, certain internal helper functions, and certain internal helper objects) also use name abbreviation rules, using special abbreviations hard-coded into the compiler; interestingly most of the non-operator
entities have internal names, which are distinct from the abbreviations. As with normal abbreviations, these special abbreviations expand to a name and its terminating @
; due to this, the special abbreviation will be immediately followed by either the qualified-name-terminating second @
, or by any containing scopes.
// Containing scopes example, with 'scalar deleting destructor':
class CL {
public:
~CL();
};
CL::~CL() {} // Non-trivial destructor.
// If an instance of the above class is deleted with "delete", the compiler will create
// hidden member functions 'scalar deleting destructor' and 'vector deleting destructor'.
// The former will have this mangled symbol:
// ??_GCL@@QAEPAXI@Z
// Note that there's no '@' between '?_G' (function name) & 'CL@' (containing scope name).
// Global example, with 'vector constructor iterator':
class CL {
public:
CL();
};
CL::CL() {} // Non-trivial constructor.
CL cls[3]; // Create an array of class with non-trivial ctor.
// The compiler uses the 'vector constructor iterator' to create the array and initialise
// each instance.
// It has the mangled symbol:
// ??_H@YGXPAXIHP6EPAX0@Z@Z
// Note that there's no '@' between '?_H' (function name) & '@' (qualified name terminator).
Upvotes: 1