Я хочу интерпретировать символ COMDAT файла COFF
Символ COMDAT
?make@DNameStatusNode@@SAPAV1@W4DNameStatus@@@Z
Как я могу интерпретировать это как
(public: static class DNameStatusNode * __cdecl DNameStatusNode::make(enum DNameStatus))
Благодарю.
Это будет «украшенное» (искаженное) имя функции C ++, сгенерированное Visual Studio (и VS-совместимыми компиляторами Windows), а не символ COMDAT.
Самый простой способ — провести символ через UNDNAME.EXE
утилита, которая поставляется с Visual Studio. За исключением этого, вы можете использовать UnDecorateSymbolName()
функция в библиотеке Dbghelp.dll
или недокументированная внутренняя функция __unDName()
(что, насколько мне известно, это то, что UNDNAME
использует); Я предполагаю, что вы хотя бы немного знакомы с этой функцией, учитывая, что DName
является одним из его вспомогательных классов. [Обратите внимание, что хотя эти инструменты в основном точны, в некоторых случаях они дают сбой (например, указатель const
-ness, определенные символы C ++ / CLI или функционально-локальные классы, объявленные в extern "C"
функции (в том числе main()
).]
Если ничего не помогает, вы также можете попытаться раскрутить имя вручную, что потребует знакомства с самой схемой искажения; если вы не знакомы с внутренней информацией MS, это может потребовать значительных экспериментов и / или исследований, но это наиболее точный способ. Есть несколько простых рекомендаций, которые могут помочь с этим:
?
, Если нет, то ?
будут предшествовать специальные модификаторы (такие как __imp_
за __declspec(dllimport)
или же ?@
для CodeView), с правильным именем, начинающимся с ?
,?
, сегмент до @@
является квалифицированным именем объекта, разбитым на отдельные имена компонентов (сначала имя символа, затем каждое, содержащее имя области действия; область действия пространства имен и класса обрабатываются одинаково для этого этапа процесса искажения); за каждым из имен компонентов, составляющих квалифицированное имя, сразу же следует один @
, который действует как терминатор для этого имени, а полное имя завершается автономным @
(обычно создает двойной @@
). Прочитайте это справа налево, заменяя любой @
с оператором области ::
и останавливаясь на втором @
в двойном @@
, [Обратите внимание, что есть также случаи, когда это правило не соблюдается, и что шаблоны имен объектов действительно странно. Также обратите внимание, что когда пользовательский тип (enum, class, struct, union) встречается во время информации о типе, его квалифицированное имя будет использоваться в соответствии с обычными правилами квалифицированного именования, за исключением того, что 1) ему будет предшествовать идентификатор вместо знака вопроса1, и 2) имя будет сокращено, если это возможно2.]
?x
, где x
является цифрой или заглавной буквой, которой предшествуют 0-2 подчеркивания; обратите внимание, что эти имена действуют как специальные сокращения2, и, как таковые, являются не заканчивается одним @
, В связи с этим, специальные субъекты-члены будут иметь имя, подобное ??_FCLS@@QAEXXZ
(закрытие конструктора по умолчанию для class ::CLS
), и специальные объекты, не являющиеся членами, будут иметь имена, оканчивающиеся одним @
вместо двойного @@
(такие как ??_H@YGXPAXIHP6EPAX0@Z@Z
итератор векторного конструктора; Обратите внимание, что ??_H@
это его полное имя, и все, что после этого является информацией о типе).@@
содержит всю соответствующую информацию о типе, и очень трудно объяснить, не вдаваясь в много подробно. Я бы предложил использовать в качестве справочного материала такой ресурс, как «Соглашения о вызовах для различных компиляторов и операционных систем C ++» Агнера Фога, и / или страницу Викиверситета «Искаженное имя в Visual C ++»; хотя их информация не на 100% точна, она достаточно точна, чтобы прочитать большинство искаженных имен, с которыми вы столкнетесь.Надеюсь это поможет.
1: Одно из следующего будет использоваться для указания типа UDT:
W4
[Обратите внимание, что это технически представляет enum : int
, но по какой-то причине компилятор искажает все типы перечислений как W4
и хранит информацию о базовом типе в другом месте.]V
U
T
За ним последует квалифицированное имя UDT, которое заканчивается @@
по-прежнему.
class CL; // Is: VCL@@
struct ST; // Is: UST@@
enum EN; // Is: W4EN@@
union UN; // Is: TUN@@
namespace X { class CL; } // Is: VCL@X@@
2: Если какое-либо из имен компонентов в квалифицированном имени UDT уже встречалось при перетаскивании символа (либо как часть квалифицированного имени символа, либо как часть квалифицированного имени параметра (чтение параметров слева направо)), и оно был одним из первых 10 встреченных имен, как имя, так и его окончание @
будет сокращено до цифры, представляющей это ранее использованное имя. Сокращения индексируются нулями, а фактическое имя символа считается именем 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".
}
Как уже упоминалось, некоторые специальные объекты (операторы, определенные внутренние вспомогательные функции и определенные внутренние вспомогательные объекты) также используют правила сокращений имен, используя специальные сокращения, жестко запрограммированные в компиляторе; интересно, что большинствоoperator
сущности имеют внутренние имена, которые отличаются от сокращений. Как и в случае обычных сокращений, эти специальные сокращения расширяются до имени и его окончания @
; из-за этого за специальной аббревиатурой сразу же будет следовать либо завершение квалифицированного имени, либо @
или любыми содержащимися областями.
// 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).