2

我想解释 COFF 文件的 COMDAT 符号 COMDAT 符号是

?make@DNameStatusNode@@SAPAV1@W4DNameStatus@@@Z

我怎么能把它解释为

(public: static class DNameStatusNode * __cdecl DNameStatusNode::make(enum DNameStatus))

谢谢。

4

1 回答 1

1

那将是由 Visual Studio(和与 VS 兼容的 Windows 编译器)生成的“修饰的”(损坏的)C++ 函数名称,而不是专门的 COMDAT 符号。

最简单的方法是通过UNDNAME.EXEVisual Studio 附带的实用程序运行符号。除此之外,您可以使用UnDecorateSymbolName()library 中的函数Dbghelp.dll,或未记录的内部函数__unDName()(据我所知,它是什么UNDNAME用途);DName考虑到这是它的帮助类之一,我假设您至少对这个函数有点熟悉。[请注意,虽然这些工具大多是准确的,但在少数情况下它们会动摇(例如指针const性、某些 C++/CLI 符号或在extern "C"函数(包括main())中声明的函数局部类。]

如果一切都失败了,您也可以尝试手动修改名称,这需要熟悉修改方案本身;如果您不了解 MS 内部信息,这可能需要大量的实验和/或研究,但这是最准确的方法。不过,有一些简单的指南可以帮助解决这个问题:

  • 名称几乎总是以前导开头?。如果不是,则?将在前面加上特殊修饰符(例如__imp_for__declspec(dllimport)?@for CodeView),其名称正确以 . 开头?
  • 在前导 之后?,直到并包括 的段@@是实体的限定名称,分解为单独的组件名称(首先是符号名称,然后是每个包含范围的名称;名称空间范围和类范围在处理过程的这一步中被同等对待); 构成限定名称的每个组件名称后面紧跟一个 single @,它充当该名称的终止符,而全名由一个独立名称终止@(通常创建一个 double @@)。从右到左阅读,用@作用域运算符替换任何 single 并在 double::中的第二个处停止。[请注意,也有不遵循此规则的情况,模板实体名称是@@@真的很奇怪。另请注意,当在类型信息期间遇到用户定义的类型(枚举、类、结构、联合)时,将根据正常的限定名修改规则使用其限定名,但以下情况除外:1)它前面会带有一个标识符而不是问号1和 2) 如果可能,名称将被缩写2。]
    • 某些特殊实体(如运算符、内部辅助函数和内部辅助对象)将具有特殊名称,其形式?xx请注意,这些名称充当特殊缩写2,因此,不会以单个 . 结尾@。因此,特殊成员实体将具有类似的名称??_FCLS@@QAEXXZ(默认构造函数闭包class ::CLS),并且特殊的非成员实体将具有以单@而不是双精度结尾的名称@@(例如??_H@YGXPAXIHP6EPAX0@Z@Z,向量构造函数迭代器;请注意,??_H@它的完全-qualified name,之后的所有内容都是类型信息)。
  • 后面的部分包含所有相关的类型信息,如果不深入细节@@就很难解释。我建议使用诸如 Agner Fog 的“不同 C++ 编译器和操作系统的调用约定”PDF 和/或 Wikiversity 页面“Visual C++ name mangling”之类的资源作为参考;虽然他们的信息不是 100% 准确,但它足以准确读取您会遇到的大多数错误名称。

希望这可以帮助。


1 : 以下之一将用于指示 UDT 的类型:

  • 枚举:W4[请注意,这在技术上表示enum : int,但由于某种原因,编译器将所有枚举类型破坏为W4并将底层类型信息存储在其他地方。]
  • 班级:V
  • 结构:U
  • 联盟:T

@@它后面是 UDT 的限定名称,它像往常一样以 a 结尾。

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 个名称之一,名称及其终止符@都将缩写为代表先前使用的名称的数字。缩写是零索引的,符号的实际名称被计为 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".
}

如前所述,某些特殊实体(运算符、某些内部辅助函数和某些内部辅助对象)也使用名称缩写规则,使用硬编码到编译器中的特殊缩写;有趣的是,大多数非operator实体都有内部名称,与缩写不同。与普通缩写一样,这些特殊缩写扩展为名称及其终止@;因此,特殊缩写后将紧跟限定名称终止的 second@或任何包含范围。

// 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).
于 2016-06-17T20:12:38.227 回答