2016-08-30 2 views
5

Дампы, полученные из отчетов об ошибках Windows, обычно имеют бесполезный текущий контекст, установленный в ветке с ошибкой, с глубиной стека в WerpReportFault. Фактический контекст во время исключения можно получить с помощью .ecxr, который также устанавливает контекст таким образом, что последующие команды в одном потоке (например, k) возвращают «правильную» информацию.Получение трассировки стека из хранимого контекста исключений в minidump (аналогично .ecxr; k)

Я создаю инструмент для автоматического анализа дампа, который использует IDebugControl::GetStackTrace для получения стека дефектной нити. Я могу получить сохраненный контекст исключения, используя IDebugControl4::GetStoredEventInformation. Если я использую значения EBP/RBP, ESP/RSP, EIP/RIP из сохраненного контекста с GetStackTrace, я получаю правильный стек. Однако я бы скорее повторил то, что делает команда .ecxr, установив «правильное» состояние до тех пор, пока нить не будет переключена. Я пробовал использовать IDebugAdvanced::SetThreadContext, но, похоже, это незаконная операция для целей дампа и с ошибкой 0x8000FFFF.

Я попытался выяснить, что делает .ecxr, отлаживая экземпляр WinDbg, и он выглядит как .ecxr реализован в dbgeng!DotEcxr. Однако, отслеживая его (с wt), я не смог понять, как он сбрасывает контекст текущего потока. Во всяком случае, он не вызывает каких-либо методов интерфейса отладки COM-клиента и не использует IDebugAdvanced::SetThreadContext.

Любые предложения о том, как установить контекст потока в файле дампа, будут высоко оценены. В крайнем случае, я всегда могу использовать IDebugControl::Execute и просто вызывать команду .ecxr, но я бы предпочел более программный подход.

ответ

2

.ecxr memcopies контекстной записи

, чтобы установить область вы можете использовать этот

EXT_COMMAND(setscope, "setscope", "{;e,[email protected]$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,[email protected]$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 и setscope

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 
+0

Awesome. Похоже, именно то, что мне нужно. –

1

Я думаю, что нет никакой магии пути в dbgeng сохранить контекст регистров и использовать его в каждом последующем вызове API, но если вы получаете контекст исключения из IDebugControl4 :: GetStoredEventInformation () Я считаю, что вы предпочитаете IDebugControl4 :: GetContextStackTrace() вместо того, чтобы обманывать GetStackTrace().

Смежные вопросы