【问题标题】:Interpret COMDAT symbol of COFF file as human readable function signature将 COFF 文件的 COMDAT 符号解释为人类可读的函数签名
【发布时间】:2015-08-26 20:37:26
【问题描述】:

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

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

如何理解为

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

谢谢。

【问题讨论】:

    标签: c++ symbols coff


    【解决方案1】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-08
      • 1970-01-01
      • 1970-01-01
      • 2017-08-09
      • 1970-01-01
      • 1970-01-01
      • 2013-09-03
      • 1970-01-01
      相关资源
      最近更新 更多