Question

I set unhandled exception filter by doing: SetUnhandledExceptionFilter(UnhandledException)

and in my UnhandledException function, I write out a minidump using MiniDumpWriteDump:

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

When I look at the stack trace in WinDbg, I don't see much:

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

The MiniDumpWriteDump documentation mentions that the strack trace may not be good, but I don't really understand what I should do about it: http://msdn.microsoft.com/en-us/library/ms680360%28v=vs.85%29.aspx

Any help appreciated!

Was it helpful?

Solution

You cannot get reliable call stack from thread which is currently executing. To get call stack from the dump file, WinDbg extracts thread context record from the dump file (CONTEXT structure, which is basically snapshot of all registers for the thread). Based on the registers (specifically RIP and RSP) and symbols it can walk the stack and extract the call stack. For running thread, there is no way to get consistent CONTEXT structure, because it changes every instruction.

The link you looked at on MSDN mentioned easy way to get consistent CONTEXT for the currently executing thread. The code looks like this:

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

Here the work is done in MyStackTraceFilter -- you have to provide this function. Input parameter would be CONTEXT record you can rely on - a snapshot for current thread at specific time when exceptin is raised. You can actually write code to walk the stack inside the MyStackTraceFilter and you get nice call stack of the running thread. This might be workaround for you if you only interested in call stack.

In most cases it is possible to get a 'better' call stack from inconsistend CONTEXT structure. If you can rely that RSP/esp is more or less correct, then what you do is

  • dump the stack ("dds esp" for x86 or "dqs rsp" for x64)
  • try to guess where was the last stack frame before exception
  • use command 'k BasePtr StackPtr InstructionPtr' to dump the call stack

OTHER TIPS

If you're calling MinidumpWriteDump from an unhandled exception filter then you should have a valid EXCEPTION_POINTERS to pass in the MINIDUMP_EXCEPTION_INFORMATION parameter. If you've done that then the minidump will contain an exception stream that contains a special CONTEXT which represents the state of the crashing thread. When you load a dump like this in WinDBG it will display the message: This dump file has an exception of interest stored in it. The stored exception information can be accessed via .ecxr.

You need to enter the .ecxr command to load that context so you can display the stack trace starting from that point.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top