locked
MiniDumpWriteDump on Windows 8.1 (VS 2005) not generating debuggable dump RRS feed

  • Question

  • So, first of all: Visual Studio 2005, right? Pretty damn old, but this is for debugging an older product, so the usual corporate stuff, legacy support, etc (new version of the software are using VS 2013, so yay!).

    I'm also running Windows 8.1 Update x64 (but the test machine will be running Win XP SP3) and the version of dbghelp.dll (C:\Windows\System32) is 6.3.9600.17787, and so far all my testing has been done on Win 8.1.

    I'm attempting to write out a dump in a particular non-fatal error situation so I can track down a bug on a remote test machine. It can't be done externally (at least without internal code changes) as the error situation is fleeting so I'm doing it from within the same process as the error. Basically in the error situation, I'm using a __try/__except block (yeah, sorry guys, it's straight C) to dereference a null pointer in order to get the stack trace from the exception information as recommended by the MSDN page on MiniDumpWriteDump.

    I can't seem to get it to generate a dump that I can then use on VS 2005 to load and view the process info. Previously the stack trace (and all associated threads) contained the stack trace that you get when you look at a dump generated with Task Manager on a 64-bit OS instead of using something like ProcDump (from SysInternals).

    I found this article (https://social.msdn.microsoft.com/Forums/en-US/2dfd711f-e81e-466f-a566-4605e78075f6/why-does-minidumpwritedump-fail?forum=windbg), and adding the ContextRecord to the ExceptionPointers member in the MINIDUMP_EXCEPTION_INFORMATION structure helped a little bit. I'm getting functions in the stack trace that come from within the process I'm creating the dump from, but not in the right order as they would actually be called (or rather there are entries higher up that would never be called by the functions they apparently come after), and no entries in the trace from the actual location where I generated the dump (none of the threads are in that location).

    Code:

    int seh_filter(unsigned int code, struct _EXCEPTION_POINTERS* ep, EXCEPTION_POINTERS** pExceptionPointers)
    {
        *pExceptionPointers = ep;
    
        return EXCEPTION_EXECUTE_HANDLER;
    }
    
    void func()
    {
        // snip
    
        // output an application dump
        {
            EXCEPTION_POINTERS* pExceptionPointers;
        
            // intentionally cause an exception to ensure we get a full stack trace from this thread
            __try
            {
                int* ptr = 0;
                *ptr = 4;
            }
            __except(seh_filter(GetExceptionCode(), GetExceptionInformation(), &pExceptionPointers))
            {
                time_t timeNow = time(0);
                struct tm* now = localtime(&timeNow);
                char szTimestamp[100];
                HANDLE hProcess = GetCurrentProcess();
                HANDLE hDmpFile = 0;
                DWORD nProcessId = GetCurrentProcessId();
                DWORD nThreadId = GetCurrentThreadId();
                HANDLE hThread = 0;
                MINIDUMP_EXCEPTION_INFORMATION exceptInfo;
                DWORD miniDumpTypeFlags;
                CONTEXT c;
                BOOL dumpWriteSucceeded = FALSE;
                
                memset(&c, 0, sizeof(c));
                
                c.ContextFlags = CONTEXT_FULL;
                hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, nThreadId);
                GetThreadContext(hThread, &c);
                
                strftime(szTimestamp, sizeof(szTimestamp), "P:/3dx/tmp/ppi_syntax_error_dump_%Y-%m-%d_%H-%M-%S.dmp", now);
                
                hDmpFile = CreateFile(szTimestamp, 
                GENERIC_WRITE,
                0,
                0,
                CREATE_NEW,
                FILE_ATTRIBUTE_NORMAL,
                0);
                
                //pExceptionPointers = GetExceptionInformation();
                
                memset(&exceptInfo, 0, sizeof(exceptInfo));
                exceptInfo.ThreadId = nThreadId;
                exceptInfo.ExceptionPointers = pExceptionPointers;
                exceptInfo.ExceptionPointers->ContextRecord = &c;
                exceptInfo.ClientPointers = TRUE;
                
                miniDumpTypeFlags = MiniDumpWithFullMemory |
                MiniDumpWithDataSegs |
                MiniDumpWithHandleData |
                MiniDumpWithUnloadedModules | 
                MiniDumpWithProcessThreadData;
                
                dumpWriteSucceeded = MiniDumpWriteDump(hProcess, 
                nProcessId, 
                hDmpFile, 
                miniDumpTypeFlags, 
                &exceptInfo,
                0,
                0);
                
                CloseHandle(hDmpFile);
                hDmpFile = 0;
            }
        }
    
        // snip
    }

    And whenever I run the crash dump inside VS2005, the error that is displayed is an unhandled exception in ntdll.dll with an error code "0x00000042: The network resource type is not correct."


    I'm at a loss. And I doing something completely wrong, or have I misunderstood issues with generating and reading dumps relating to x86/x64?

    • Edited by NaimKingston Thursday, April 7, 2016 5:54 AM update with ntdll.dll error code message
    Thursday, April 7, 2016 1:45 AM

Answers

  • Some things which caught my eye

    *pExceptionPointers = ep; 

    https://msdn.microsoft.com/en-us/library/s58ftw19.aspx
    "You can use GetExceptionCode within the exception handler. However, you can use GetExceptionInformation only within the exception filter expression. The information it points to is generally on the stack and is no longer available when control is transferred to the exception handler."
    So would doubt your pExceptionPointers points to valid data, when you write your minidump? Probably overwritten?

    In theory (see above) you already have thread-context through _EXCEPTION_POINTERS* ep, so would think you need not do

    exceptInfo.ExceptionPointers->ContextRecord = &c;
    Your exception pointer is located in the address space of the program, which calls minidumpwritedump, so would assume
    exceptInfo.ClientPointers = FALSE;
    Probably something like
    https://blogs.msdn.microsoft.com/joshpoley/2008/05/19/prolific-usage-of-minidumpwritedump-automating-crash-dump-analysis-part-0/
    in seh_filter - where you get (hopefully) valid _EXCEPTION_POINTERS ep?

    With kind regards


    • Marked as answer by NaimKingston Friday, April 8, 2016 1:00 AM
    Thursday, April 7, 2016 11:32 AM

All replies

  • Some things which caught my eye

    *pExceptionPointers = ep; 

    https://msdn.microsoft.com/en-us/library/s58ftw19.aspx
    "You can use GetExceptionCode within the exception handler. However, you can use GetExceptionInformation only within the exception filter expression. The information it points to is generally on the stack and is no longer available when control is transferred to the exception handler."
    So would doubt your pExceptionPointers points to valid data, when you write your minidump? Probably overwritten?

    In theory (see above) you already have thread-context through _EXCEPTION_POINTERS* ep, so would think you need not do

    exceptInfo.ExceptionPointers->ContextRecord = &c;
    Your exception pointer is located in the address space of the program, which calls minidumpwritedump, so would assume
    exceptInfo.ClientPointers = FALSE;
    Probably something like
    https://blogs.msdn.microsoft.com/joshpoley/2008/05/19/prolific-usage-of-minidumpwritedump-automating-crash-dump-analysis-part-0/
    in seh_filter - where you get (hopefully) valid _EXCEPTION_POINTERS ep?

    With kind regards


    • Marked as answer by NaimKingston Friday, April 8, 2016 1:00 AM
    Thursday, April 7, 2016 11:32 AM
  • That seems to be it!!

    I moved the code to write the dump into the filter, and I get an intelligible stack trace as well as the exact exception that I raised! 

    Friday, April 8, 2016 1:02 AM