我在一个大型应用程序上工作,并且经常使用 WinDbg 根据客户提供的 DMP 文件来诊断问题。我已经为 WinDbg 编写了一些小扩展,这些扩展对于从 DMP 文件中提取信息非常有用。在我的扩展代码中,我发现自己以同样的方式一遍又一遍地手动取消引用 c++ 类对象。例如:
Address = GetExpression("somemodule!somesymbol");
ReadMemory(Address, &addressOfPtr, sizeof(addressOfPtr), &cb);
// get the actual address
ReadMemory(addressOfObj, &addressOfObj, sizeof(addressOfObj), &cb);
ULONG offset;
ULONG addressOfField;
GetFieldOffset("somemodule!somesymbolclass", "somefield", &offset);
ReadMemory(addressOfObj+offset, &addressOfField, sizeof(addressOfField), &cb);
这很好用,但是随着我编写了更多的扩展,具有更强大的功能(并在我们的应用程序 DMP 文件中访问更复杂的对象),我渴望有一个更好的解决方案。我当然可以访问我们自己的应用程序的源代码,所以我认为应该有一种方法可以将对象从 DMP 文件中复制出来,并使用该内存在调试器扩展中创建一个实际的对象,我可以在该对象上调用函数(通过从我们的应用程序中链接 dll)。这将省去我用手从 DMP 中取出东西的麻烦。
这甚至可能吗?我尝试了一些显而易见的事情,比如在扩展中创建一个新对象,然后直接从 DMP 文件中用一个大的 ReadMemory 覆盖它。这似乎将数据放在正确的字段中,但当我尝试调用函数时吓坏了。我想我错过了一些东西......也许c ++会带来一些我不知道的vtable funky-ness?我的代码与此类似:
SomeClass* thisClass = SomeClass::New();
ReadMemory(addressOfObj, &(*thisClass), sizeof(*thisClass), &cb);
跟进:看起来可能来自 EngExtCpp 的 ExtRemoteTyped 是我想要的?有没有人成功使用过这个?我需要谷歌搜索一些示例代码,但运气不佳。
跟进 2:我正在对此进行两种不同的调查。
1) 我正在研究 ExtRemoteTyped,但看起来这个类实际上只是 ReadMemory/GetFieldOffset 调用的助手。是的,这将有助于加快速度,但在从 DMP 文件重新创建对象时并没有真正的帮助。虽然文档很薄,所以我可能会误解一些东西。2) 我也在考虑尝试使用 ReadMemory 用 DMP 文件中的数据覆盖在我的扩展中创建的对象。但是,我没有像上面那样使用 sizeof(*thisClass) ,而是认为我只会挑选数据元素,而保持 vtables 不变。