我正在DebugExtensionProvideValue
我的扩展中实现,所以我可以提供自定义伪寄存器。它在 CDB 中运行良好,最初在 WinDbg 中运行良好,但在停止调试并打开新的可执行文件后,发生了一些事情,WinDbg 最终处于奇怪的不可用状态。
当您触发问题时,WinDbg 会将此消息打印到命令窗口:
无法传递回调,3131
发生这种情况后,WinDbg 似乎在命令窗口中两次打印所有输出!
我的扩展代码很简单:
EXTERN_C HRESULT CALLBACK DebugExtensionProvideValue(PDEBUG_CLIENT Client, ULONG Flags, IN PCWSTR Name, OUT PULONG64 Value, OUT PULONG64 TypeModBase, OUT PULONG TypeId, OUT PULONG TypeFlags)
{
HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
if (!Name || !Value || !TypeFlags)
{
hr = E_INVALIDARG;
}
else if (0 == lstrcmpiW(Name, L"$$test"))
{
*Value = 0xDeadCafeBabeBeefULL;
*TypeFlags = DEBUG_EXT_PVTYPE_IS_VALUE;
if (TypeId) *TypeId = 0; // Where are these types defined?
if (TypeModBase) *TypeModBase = 0;
hr = S_OK;
}
#if 0 // <-- ** Setting this to != 0 fixes the problem **
Client->Release(); // This does not feel right but it does seem to be required!
#endif
return hr;
}
EXTERN_C HRESULT CALLBACK DebugExtensionQueryValueNames(PDEBUG_CLIENT Client, ULONG Flags, OUT PWSTR Buffer, ULONG BufferChars, OUT PULONG BufferNeeded)
{
static const WCHAR pseregs[] = L"$$test\0";
if (BufferNeeded) *BufferNeeded = ARRAYSIZE(pseregs);
memcpy(Buffer, pseregs, min(sizeof(pseregs), BufferChars*sizeof(*Buffer)));
return ARRAYSIZE(pseregs) > BufferChars ? S_FALSE : S_OK;
}
EXTERN_C HRESULT CALLBACK DebugExtensionInitialize(OUT PULONG Version, OUT PULONG Flags)
{
*Version = DEBUG_EXTENSION_VERSION(1, 0), *Flags = 0;
return S_OK;
}
重现问题看起来像这样:
0:000> $$ Press Ctrl+E to open a executable, I'm going to open WinVer.exe
0:000> .load c:\test\myext.dll
0:000> ?@$$test
Evaluate expression: -2401039830915039505 = deadcafe`babebeef
0:000> $$ Press Shift+F5 to stop debugging
0:000> $$ Press Ctrl+E and open a executable again, WinDbg will now print "Unable to deliver callback, 3131"
我能够想出一个似乎确实有效的解决方法,但它只是感觉不对,因为我必须发布一个我从未 QI'ed 或 AddRef'ed 的接口。在我最少量的测试中,这个 hack 似乎从来没有崩溃过,并且通过查看 IDebugClients refcount,它在多次调用中似乎是正确的。
据我所知,您无法停止调试并在 CDB 中像这样打开一个新的 .exe,因此问题似乎只能发生在 WinDbg 中。
我做错了什么还是 DbgEng 中有错误?