Crash Dump Analysis

Microsoft Game Technology Group

December 2005

Introduction

Not all bugs can be found prior to release, which means not all bugs that throw exceptions can be found before release. Microsoft has included in the Platform SDK a function to help developers collect information on exceptions discovered by users. The MiniDumpWriteDump function writes the necessary crash dump information to file without saving the whole process space. This crash dump information file is called a 'minidump'.

The basic options for writing a minidump are as follows:

  1. Do nothing. Windows automatically generates a minidump when ever a program throws an unhandled exception. Automatic generation of a minidump is only available on Windows XP and Windows Vista. If the user allows it, the minidump will be sent to Microsoft, and not the developer, via the Windows Error Reporting (WER) service. Developers can contact the Microsoft Windows Gaming & Graphics developer relations group to arrange for access to the WER service.

    To use the WER service, developers must:

    A custom exception handler won't normally send a minidump to WER. If you implement a custom unhandled exception routine, you can use the ReportFault function in the exception handler to also send an automated minidump to WER. The ReportFault function handles all the issues of connecting to and sending the minidump to WER. It is strongly suggested to implement ReportFault in all custom exception handlers. Not sending minidumps to WER violates the Games for Windows requirements. This article doesn't cover the specifics of ReportFault, but more information can be found in the Implementing the ReportFault() API article.

    For more information on how WER works, read the How Windows Error Reporting Works article, and registration details are explained in ISV Community Center: Windows Error Reporting.

  2. Use Visual Studio. In Visual Studio, select save dump in the in the debug menu. This is only an option for in house testing and debugging.
  3. Add code to your project. Add MiniDumpWriteDump and the appropriate exception handling code to save and send a minidump directly to the developer. This article demonstrates how to implement this option. However, note that MiniDumpWriteDump does not currently work with managed code and is only available on Windows XP or higher.

Thread safety

MiniDumpWriteDump is part of the DBGHELP library. This library is not thread-safe, so any program using MiniDumpWriteDump should synchronize all threads before attempting to call MiniDumpWriteDump.

Writing a minidump with code

The actual implementation is straightforward. The following is a simple example of how to use MiniDumpWriteDump:

#include <dbghelp.h>
#include <shellapi.h>
#include <shlobj.h>

int GenerateDump(EXCEPTION_POINTERS* pExceptionPointers)
{
    BOOL bMiniDumpSuccessful;
    WCHAR szPath[MAX_PATH]; 
    WCHAR szFileName[MAX_PATH]; 
    WCHAR* szAppName = L"AppName";
    WCHAR* szVersion = L"v1.0";
    DWORD dwBufferSize = MAX_PATH;
    HANDLE hDumpFile;
    SYSTEMTIME stLocalTime;
    MINIDUMP_EXCEPTION_INFORMATION ExpParam;

    GetLocalTime( &stLocalTime );
    GetTempPath( dwBufferSize, szPath );

    StringCchPrintf( szFileName, MAX_PATH, L"%s%s", szPath, szAppName );
    CreateDirectory( szFileName, NULL );

    StringCchPrintf( szFileName, MAX_PATH, L"%s%s\\%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp", 
               szPath, szAppName, szVersion, 
               stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, 
               stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, 
               GetCurrentProcessId(), GetCurrentThreadId());
    hDumpFile = CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, 
                FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);

    ExpParam.ThreadId = GetCurrentThreadId();
    ExpParam.ExceptionPointers = pExceptionPointers;
    ExpParam.ClientPointers = TRUE;

    bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), 
                    hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL, NULL);

    return EXCEPTION_EXECUTE_HANDLER;
}


void SomeFunction()
{
    __try
    {
        int *pBadPtr = NULL;
        *pBadPtr = 0;
    }
    __except(GenerateDump(GetExceptionInformation()))
    {
    }
}

This example demonstrates the basic usage of MiniDumpWriteDump and minimum information necessary to call it. It is up to the developer what they decide to call the dump file. However, it is advisable to generate the dump file name from the application name, version number, process id, thread id, day, and time to avoid filename collisions. This will also help keep the minidumps grouped by application and version. It is up to the developer how much or little information is used to differentiate minidump filenames. It should be noted that the pathname was generated using the GetTempPath function with so this will work in least privileged user accounts, and prevent the minidump from taking up hard drive space after it is no longer needed.

If you archive the product during your daily build process, also be sure to include symbols for the build so that if you need to debug an old version of the product, you can. You will also need to take certain steps to maintain full compiler optimizations while generating symbols. This can be done by going to the project settings for the Release configuration and doing the following:

MSDN has more detailed information on the MINIDUMP_EXCEPTION_INFORMATION structure and the MiniDumpWriteDump function.

Using Dumpchk.exe

Dumpchk.exe is a command-line utility that can be used to verify that a dump file was created correctly. If Dumpchk.exe generates an error, then the dump file is corrupt and cannot be analyzed. Dumpchk.exe is included with Windows XP CD-ROM and can be installed to \Program Files\Support Tools folder by installing the Windows XP Support Tools.

The How to Use Dumpchk.exe to Check a Memory Dump File articles provides more details about using the Dumpchk.exe tool.

Analysis of a minidump

Opening a minidump for analysis is as easy as creating one.

  1. Open Visual Studio
  2. Select File->Open->Project
  3. Select the minidump file
  4. Run the debugger

The debugger will create a simulated process. The simulated process will be halted at the instruction that caused the crash.

To get the stack for driver or system level crashes, it might be necessary to setup Visual Studio to point the Microsoft Symbol Server. To point the debugger to the Microsoft Symbol Server, do the following:

  1. Open the Property Pages for the project
  2. Open the Debugging properties folder
  3. Enter "srv*c:\cache*http://msdl.microsoft.com/download/symbols;" in the Symbol Path field. Also append the application's local directory or the build share to the Symbol Path.
  4. Copy the symsrv.dll from the Visual Studio 2003 or 2005 install folder at \Common7\IDE to either System32 folder or the same folder containing devenv.exe.

Developers also need to be aware how their copy-protection scheme might affect the minidump. Most copy-protection schemes have their own descramble tools and it will be up to the developer to learn how to use those tools with MiniDumpWriteDump.

You can also use the Windows Debugging Tools to debug a minidump. WinDbg is a debugger that comes with the Windows Debugging Tool set. WinDbg allows a developer or tester to debug without having to use Visual Studio. After installing, the developer will have to enter the symbol path into WinDbg by going to file, selecting Symbol Path, and entering "srv*c:\cache*http://msdl.microsoft.com/download/symbols;" More information on using the Windows Debugging Tools can be found in the Debugging Tools for Windows Overview.

Summary

The MiniDumpWriteDump API function can be an extremely useful tool in collecting and solving bugs after the product has been released. Writing a custom exception handler that uses the MiniDumpWriteDump API allows the developer to customize the information collection and improve the debugging process. The function is flexible enough to be used in any C++ based project and should be considered part of any project's stability process.