#include "stdafx.h"
int _tmain( int argc, _TCHAR* argv[])
{
int * p = NULL;
p[0] = 10;
return 0;
}
* This source code was highlighted with Source Code Highlighter .
#include "stdafx.h"
#include <windows.h>
#include <io.h>
LONG WINAPI CustomUnhandledExceptionFilter( PEXCEPTION_POINTERS pExInfo )
{
_tprintf( TEXT( "Exception!" ) );
return EXCEPTION_EXECUTE_HANDLER;
}
int _tmain( int argc, _TCHAR* argv[])
{
LPTOP_LEVEL_EXCEPTION_FILTER hOldFilter = SetUnhandledExceptionFilter( CustomUnhandledExceptionFilter );
int * p = NULL;
p[0] = 10;
SetUnhandledExceptionFilter( hOldFilter );
return 0;
}
* This source code was highlighted with Source Code Highlighter .
#include <dbghelp.h>
LONG WINAPI CustomUnhandledExceptionFilter( PEXCEPTION_POINTERS pExInfo )
{
HANDLE hFile;
hFile = CreateFile( TEXT( "c:\\minidump.dmp" ), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if ( NULL == hFile || INVALID_HANDLE_VALUE == hFile )
return EXCEPTION_EXECUTE_HANDLER;
MINIDUMP_EXCEPTION_INFORMATION eInfo;
eInfo.ThreadId = GetCurrentThreadId();
eInfo.ExceptionPointers = pExInfo;
eInfo.ClientPointers = FALSE;
MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), hFile,
MiniDumpNormal, &eInfo, NULL, NULL);
CloseHandle( hFile );
return EXCEPTION_EXECUTE_HANDLER;
}
* This source code was highlighted with Source Code Highlighter .
!analyze -v
FAULTING_IP:
CrashHandler! Wmain + 11 [d: \ work \ crashhandler \ crashhandler.cpp @ 35]
00401091 c7010a000000 mov dword ptr [ecx], 0Ah
EXCEPTION_RECORD: ffffffff - (.exr 0xffffffffffffffff)
ExceptionAddress: 00401091 (CrashHandler! Wmain + 0x00000011)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter [0]: 00000001
Parameter [1]: 00000000
Attempt to write to address 00000000
PROCESS_NAME: CrashHandler.exe
ADDITIONAL_DEBUG_TEXT:
Use the '! Findthebuild' command to search for the target build information.
If the build information is available, run '! Find thebuild -s; .reload 'set symbol path and load symbols.
FAULTING_MODULE: 75bf0000 kernel32
DEBUG_FLR_IMAGE_TIMESTAMP: 4bb07e29
MODULE_NAME: CrashHandler
ERROR_CODE: (NTSTATUS) 0xc0000005 - EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - EXCEPTION_PARAMETER1: 00000001
EXCEPTION_PARAMETER2: 00000000
WRITE_ADDRESS: 00000000
FOLLOWUP_IP:
CrashHandler! Wmain + 11 [d: \ work \ crashhandler \ crashhandler.cpp @ 35]
00401091 c7010a000000 mov dword ptr [ecx], 0Ah
FAULTING_THREAD: 0000109c
BUGCHECK_STR: APPLICATION_FAULT_NULL_POINTER_WRITE_WRONG_SYMBOLS
PRIMARY_PROBLEM_CLASS: NULL_POINTER_WRITE
DEFAULT_BUCKET_ID: NULL_POINTER_WRITE
LAST_CONTROL_TRANSFER: from 0040120d to 00401091
STACK_TEXT:
0018ff44 0040120d 00000001 003c2dc0 003c3c90 CrashHandler! Wmain + 0x11 [d: \ work \ crashhandler \ crashhandler.cpp @ 35]
0018ff88 75c03677 7efde000 0018ffd4 773b9d72 CrashHandler! __ tmainCRTStartup + 0x10f [f: \ dd \ vctools \ crt_bld \ self_x86 \ crt \ src \ crtexe.c @ 583]
WARNING: Stack unwind information not available. Following frames may be wrong.
0018ff94 773b9d72 7efde000 6819a792 00000000 kernel32! BaseThreadInitThunk + 0x12
0018ffd4 773b9d45 00401355 7efde000 00000000 ntdll! RtlInitializeExceptionChain + 0x63
0018ffec 00000000 00401355 7efde000 00000000 ntdll! RtlInitializeExceptionChain + 0x36
STACK_COMMAND: ~ 0s; .ecxr; kb
FAULTING_SOURCE_CODE:
31: int * p = NULL;
32: p [0] = 10;
33:
34: SetUnhandledExceptionFilter (hOldFilter);
> 35:
36: return 0;
37:}
38:
SYMBOL_STACK_INDEX: 0
SYMBOL_NAME: CrashHandler! Wmain + 11
FOLLOWUP_NAME: MachineOwner
IMAGE_NAME: CrashHandler.exe
BUCKET_ID: WRONG_SYMBOLS
FAILURE_BUCKET_ID: NULL_POINTER_WRITE_c0000005_CrashHandler.exe! Wmain
In this listing there is everything to understand what happened with our program.
in the EXCEPTION_RECORD section there is information about the exception, in the STACK_TEXT section you will receive a drop stack with addresses, function names, source codes and code lines.
Now you can take the exe file of your program and the dbghelp.dll file, transfer it to another computer, and run it there. Take the minidump.dmp file from there and again parse this file on your work computer. And the result will be the same. This is postmortem debugging.
In the next section I will give some tips.Further development
In the example above, we made a primitive program that, when dropped, collects its own dump and was able to parse this dump in order to get a stack of crashes. And now a few sensible thoughts on the organization of work with this kind of things.
- Common sense dictates to us that directly the handler for unhandled exceptions should be placed in a separate dll for reuse in your programs. To register a handler, it would be good to make a class, an instance of which is created on the stack at the entry point of your application (then we will be able to set our handler in the constructor and remove in the destructor
- In addition to the dump, you can also create a file with information about the exception by manually parsing the data structures in the callback of the DumpWriteDump function (read the help to this function for clarity). And in general, you can even fasten an archiver to the dump collector to reap everything, but do not forget to insert a reentrant protection into the handler (in case an exception occurs during the processing of an exception)
- To obtain reliable data on the drop stack, we need to have debugging symbols from all modules that have been loaded by the application. To do this, you should deploy the debug information server, about how to do this, I wrote in my article: habrahabr.ru/blogs/development/89094/#habracut
- The dbghelp.dbg library has long been bundled with Windows, with Visual Studio, etc. therefore, in order not to fence dll-hell, distribute it along with your application and load exactly the copy you need.
Where to dig further
If you liked this article and you want to use Postmortem Debugging, then you should study the following:
- Help from Debugging Tools For Windows, from the SDK and from the WinDbg debugger
- Oleg Starodumov’s blog , debuginfo.com , has useful articles and utilities.
- Look at the old, but very useful implementation of the dump collection library www.codeproject.com/KB/debug/XCrashReportPt1.aspx (there are 4 parts)
- Read John Robbins debug books, as well as his blog (his nickname is Bugslayer).
Well, fantasize. For example, one of my former colleague, a very competent specialist, made a library that collected ladies, sent them to a special mailbox of the company. A robot hung on this mailbox, which parsed the dumps, looked for familiar components on the stack, and sent letters with dumps to the programmers responsible for these modules. If I am not mistaken by this method, he even wrote an article in the RSDN Journal.
Good luck and a reckless code to you, if you have any questions - ask, discuss.
Source: https://habr.com/ru/post/89220/
All Articles