windbg:获取在UnhandledExceptionFilter中创建的minidump的堆栈跟踪

时间:2011-03-30 22:39:26

标签: windbg minidump

我通过执行以下操作设置未处理的异常过滤器: SetUnhandledExceptionFilter(UnhandledException)

在我的UnhandledException函数中,我使用MiniDumpWriteDump编写了一个minidump:

  

MiniDumpWriteDump(GetCurrentProcess(),   GetCurrentProcessId(),hFile,   MiniDumpNormal,excpInfo? & eInfo:   NULL,NULL,NULL);

当我查看WinDbg中的堆栈跟踪时,我看不到多少:

0:023> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
15e7e7dc 08f00150 08f00a78 08f00000 08f00150 ntdll!ZwGetContextThread+0x12
15e7e7fc 777d301e 6f00016e 00000044 627e056a 0x8f00150
15e7e890 777d2ffa 777d2bf2 00000000 00650000 ntdll!RtlInterlockedFlushSList+0x889
15e7e894 777d2bf2 00000000 00650000 077e1b88 ntdll!RtlInterlockedFlushSList+0x865
15e7e8b4 772b14d1 08f00000 00000000 077e0c48 ntdll!RtlInterlockedFlushSList+0x45d
15e7e8d0 777ce023 077e1b88 08f00138 00000001 kernel32!HeapFree+0x14
15e7e8e8 777d48c6 777bfafa 777d419a ffffffff ntdll!RtlFreeHeap+0x7e
15e7e914 777e9ed7 ffffffff 15e7e938 15e7e944 ntdll!RtlImageNtHeader+0xe2
15e7e93c 777e9e49 00010000 00000000 08c70000 ntdll!RtlDestroyHeap+0x139
15e7e958 75d5458e 08f00000 00000000 08ccfe46 ntdll!RtlDestroyHeap+0xab
15e7e9c4 777ce023 104d9250 104d91f0 104d9250 KERNELBASE!HeapDestroy+0xe
00000000 00000000 00000000 00000000 00000000 ntdll!RtlFreeHeap+0x7e

MiniDumpWriteDump文档提到strack trace可能不太好,但我真的不明白我应该怎么做: http://msdn.microsoft.com/en-us/library/ms680360%28v=vs.85%29.aspx

任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:2)

您无法从当前正在执行的线程获取可靠的调用堆栈。为了从转储文件获取调用堆栈,WinDbg从转储文件中提取线程上下文记录(CONTEXT结构,它基本上是线程的所有寄存器的快照)。基于寄存器(特别是RIP和RSP)和符号,它可以遍历堆栈并提取调用堆栈。对于运行线程,无法获得一致的CONTEXT结构,因为它会更改每条指令。

您在MSDN上查看的链接提到了为当前正在执行的线程获取一致的CONTEXT的简单方法。代码如下所示:

   __try
   {
      RaiseException(0, 0, 0, 0);
   }
   __except (
      MyStackTraceFilter(GetExceptionInformation()->ContextRecord)))
   {
      // do nothing in the handler
   }

这里的工作是在MyStackTraceFilter中完成的 - 你必须提供这个功能。输入参数将是您可以依赖的CONTEXT记录 - 当引发exceptin时特定时间的当前线程的快照。实际上,您可以编写代码来在MyStackTraceFilter中遍历堆栈,并获得正在运行的线程的良好调用堆栈。如果您只对调用堆栈感兴趣,这可能会为您解决。

在大多数情况下,可以从不一致的CONTEXT结构中获得“更好”的调用堆栈。如果您可以依赖RSP / esp或多或少是正确的,那么您所做的就是

  • 转储堆栈(x64为“dds esp”或x64为“dqs rsp”)
  • 尝试猜测异常前的最后一个堆栈帧在哪里
  • 使用命令'k BasePtr StackPtr InstructionPtr'转储调用堆栈

答案 1 :(得分:1)

如果您从未处理的异常过滤器调用MinidumpWriteDump,那么您应该有一个有效的EXCEPTION_POINTERS来传入MINIDUMP_EXCEPTION_INFORMATION参数。如果你已经这样做了,那么minidump将包含一个异常流,它包含一个特殊的CONTEXT,它表示崩溃线程的状态。在WinDBG中加载这样的转储时,它将显示以下消息:   此转储文件存储在其中的异常例外。   存储的异常信息可以通过.ecxr。

访问

您需要输入.ecxr命令来加载该上下文,以便从该点开始显示堆栈跟踪。