从 Windows错误报告获取的转储通常在错误线程上设置无用的当前上下文,并在WerpReportFault中设置深层堆栈.可以使用.ecxr检索异常时的实际上下文 – 它还以这样的方式设置上下文,即同一线
我正在构建一个自动转储分析工具,它使用IDebugControl :: GetStackTrace来获取错误线程的堆栈.我可以使用IDebugControl4 :: GetStoredEventInformation检索存储的异常上下文.如果我使用存储的上下文中的EBP / RBP,ESP / RSP,EIP / RIP值与GetStackTrace,我得到正确的堆栈.但是,我宁愿复制.ecxr命令的作用,设置“正确”状态,直到切换线程.我尝试使用IDebugAdvanced :: SetThreadContext,但它似乎是转储目标的非法操作,并以0x8000FFFF失败.
我试图通过调试WinDbg实例找出.ecxr的作用,看起来.ecxr是在dbgeng!DotEcxr中实现的.但是,通过跟踪它(使用wt),我无法理解它如何重置当前线程的上下文.它似乎没有调用任何COM调试客户端接口方法,并且不使用IDebugAdvanced :: SetThreadContext.
关于如何在转储文件中设置线程上下文的任何建议都将非常感激.作为最后的手段,我总是可以使用IDebugControl :: Execute并简单地调用.ecxr命令,但我更喜欢更程序化的方法.
.ecxr memcopies上下文记录设置范围,你可以使用它
EXT_COMMAND( setscope, "setscope", "{;e,d=@$ip;!setscope;}" ) { m_Symbols3->SetScopeFromStoredEvent(); }
在这次通话之后,如果你做k等,那将是最后设定的背景
:\>cdb -z oktest.dmp Microsoft (R) Windows Debugger Version 10.0.10586.567 X86 This dump file has a breakpoint exception stored in it. The stored exception information can be accessed via .ecxr. 0:000> k ChildEBP RetAddr 0007fb1c 7c940442 ntdll!DbgBreakPoint 0007fc94 7c9210af ntdll!LdrpInitializeProcess+0xffa 0007fd1c 7c90e457 ntdll!_LdrpInitialize+0x183 00000000 00000000 ntdll!KiUserApcDispatcher+0x7 0:000> .load setscope 0:000> !setscope 0:000> k *** Stack trace for last set context - .thread/.cxr resets it ChildEBP RetAddr 0007fb1c 7c940442 ntdll!DbgBreakPoint 0007fc94 7c9210af ntdll!LdrpInitializeProcess+0xffa 0007fd1c 7c90e457 ntdll!_LdrpInitialize+0x183 00000000 00000000 ntdll!KiUserApcDispatcher+0x7 0:000>
完整的扩展代码,包括getstacktrace和outputstacktrace
#include <codeanalysis\warnings.h> #pragma warning( push ) #pragma warning ( disable : ALL_CODE_ANALYSIS_WARNINGS ) #include <engextcpp.cpp> #pragma warning( pop ) class EXT_CLASS : public ExtExtension { public: EXT_COMMAND_METHOD(setscope); }; EXT_DECLARE_GLOBALS(); EXT_COMMAND( setscope, "setscope", "{;e,d=@$ip;!setscope;}" ) { m_Symbols3->SetScopeFromStoredEvent(); DEBUG_STACK_FRAME Frames[0x20] = {0}; ULONG FramesFilled = NULL; m_Control->GetStackTrace(0,0,0,Frames,0x20,&FramesFilled); m_Control->OutputStackTrace(DEBUG_OUTCTL_THIS_CLIENT,Frames,FramesFilled,0x1fff); }
执行kvf和setcope
0:000> kVf *** Stack trace for last set context - .thread/.cxr resets it # Memory ChildEBP RetAddr Args to Child 00 0007fb1c 7c940442 00000000 00000000 00000000 ntdll!DbgBreakPoint (FPO: [0,0,0]) 01 178 0007fc94 7c9210af 0007fd30 7c900000 0007fce0 ntdll!LdrpInitializeProcess+0xffa (FPO: [Non-Fpo]) 02 88 0007fd1c 7c90e457 0007fd30 7c900000 00000000 ntdll!_LdrpInitialize+0x183 (FPO: [Non-Fpo]) 03 00000000 00000000 00000000 00000000 00000000 ntdll!KiUserApcDispatcher+0x7 0:000> !setscope # Memory ChildEBP RetAddr Args to Child 00 0007fb1c 7c940442 00000000 00000000 00000000 ntdll!DbgBreakPoint (FPO: [0,0,0]) 01 178 0007fc94 7c9210af 0007fd30 7c900000 0007fce0 ntdll!LdrpInitializeProcess+0xffa (FPO: [Non-Fpo]) 02 88 0007fd1c 7c90e457 0007fd30 7c900000 00000000 ntdll!_LdrpInitialize+0x183 (FPO: [Non-Fpo]) 03 00000000 00000000 00000000 00000000 00000000 ntdll!KiUserApcDispatcher+0x7