Crash Handlers Riddhiman Ghosh Debugging Applications for

Download Report

Transcript Crash Handlers Riddhiman Ghosh Debugging Applications for

Crash
Handlers
Riddhiman Ghosh
Debugging Applications for
.NET and Windows
John Robbins
Goal
From “prevention” to “cure”. How to
deal with a program that has
crashed?
How to pinpoint sources of errors in
programs that are running outside
the debugger and on-site?
2
Outline
• Exceptions
– C++ Exceptions
– Structured Exception Handling
• Crashes
– Custom Crash Handlers
– Bugslayer Crash Utils
– Minidumps
• Code Samples
3
Types of Exception Handling
• C++ Exception Handling
• Structured Exception
Handling (SEH)
The two have different approaches to exception
handling.
4
C++ Exceptions
try, catch, throw
void someFunc()
{
try
{
//exception block
throw 100;
}
catch(int& exc)
{
//exception handler
cout<<"Caught Exception "<<exc;
}
}
5
Structured Exception Handling
• Is provided by the Operating System
and is independent of programming
language.
• Deals directly with crashes such as
access violations, stack overflows,
invalid handles, no memory, etc.
• We can use SEH through C/C++ using
the __try/__except/__finally keywords.
6
Structured Exception Handling
void someFunc()
{
__try
{
//exception block
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
//exception handler
cout<<"Caught Exception "<<exc;
}
__finally
{
//termination block
//release resources
}
}
7
Structured Exception Handling
• The parameter of __except is called an
“exception filter” that specifies how the
exception is supposed to be handled.
• 3 possible values:
– EXCEPTION_EXECUTION_HANDLER
– EXCEPTION_CONTINUE_EXECUTION
– EXCEPTION_CONTINUE_SEARCH
8
Structured Exception Handling
• EXCEPTION_EXECUTION_HANDLER
– Indicates that the code in the __except block
should be used to handle the exception.
• EXCEPTION_CONTINUE_EXECUTION
– Allows the exception to be ignored.
• EXCEPTION_CONTINUE_SEARCH
– Passes the exception up the call chain to the next
__except block. The OS will continue looking for
a suitable exception handler.
9
Structured Exception Handling
• The exception filter can be a complex
expression.
__try
{
//exception block
throw 100;
}
__except( EXCEPTION_INT_DIVIDE_BY_ZER0 ==
GetExceptionCode()
? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH )
{
//exception handler
...
}
10
Structured Exception Handling
• GetExceptionCode can only be called in
exception filters, else compiler error.
• GetExceptionInformation – returns a
pointer to an EXCEPTION_POINTERS
structure that completely describes the reason
for the crash and the state of the CPU at the
time of the crash.
typedef struct _EXCEPTION_POINTERS
{
PEXCEPTION_RECORD ExceptionRecord;
PCONTEXT ContextRecord;
} EXCEPTION_POINTERS,
*PEXCEPTION_POINTERS;
11
Structured Exception Handling
• RaiseException
– SEH is not limited to crashes – you can
create your own exceptions with
RaiseException.
– Custom error codes are limited to a single
unsigned integer
12
Structured Exception Handling
• Vectored Exception Handling
– An advanced feature of SEH that first
appeared in Windows XP and Windows Server
2003.
– Allows global notification for every exception
that occurs, making it possible to log and
monitor all exceptions being generated by your
application, even from third-party library code.
– If your application crashed in front of a
customer due to an unhandled exception,
you’d like to know where it came from.
13
… and never the twain shall meet!
• A serious limitation of SEH is the fact that
SEH and C++ exception handling don’t
mix very well.
• C++ exceptions are implemented
internally using SEH.
• The compiler complains if you use the two
indiscriminately together .
• Unlike C++, SEH does not call
destructors for objects created on the
stack.
14
SEH vs. C++ Exceptions
Robbins:
“Avoid C++ exception handling”
• C++ exception handling is not a “clean feature” of the
language, and has not been architected well. E.g. there
is no ANSI standard class that contains information
about an exception for consisting handling of generic
errors.
• Unlike SEH, C++ exception handling does not handle
hard crashes automatically. Translation functions
between SEH and C++, such as
_set_se_translator don’t really work.
15
SEH vs. C++ Exceptions
Robbins:
“Avoid C++ exception handling”
• C++ exception handling comes with a much larger
overhead, and should not be used in performancesensitive applications. C++ uses SEH internally to
implement exceptions.
16
SEH vs. C++ Exceptions
Robbins:
“Absolutely, positively, never, ever use
catch(…)”
• catch(…)block can catch any type of exception, but
since there is no parameter to this function, you have
no way of knowing what was thrown, how you got
there and why. Without this information the only
logical and safe thing to do is to terminate.
17
SEH vs. C++ Exceptions
Robbins:
“Absolutely, positively, never, ever use
catch(…)”
• More seriously, catch(…)eats not only C++ exceptions
but also SEH exceptions, since C++ uses SEH internally.
• Not only do you not know how you’ve reached the catch
block, you’ve probably silently eaten up a hard error such
as an access violation, and you know nothing about how
to handle it. Your program may crash later, obscuring any
causal relationship to the real cause of the crash from 18
you.
When your program crashes…
•When an exception is raised, “exception unwinding”
takes place, in search of a suitable handler.
•If “no one” is ready to handle the exception the
program crashes.
19
When your program crashes…
•Actually there is always an exception handler. If none
is explicitly provided, the OS always sneaks in a
default exception handler. It is this handler generates
the “Application Error” dialog box as shown and
allows you to terminate/debug the program on a
“crash”.
20
When your program crashes…
• The default “Application Error” dialog
box is hardly useful.
• To get to the bottom of a crash we need
more information.
• We can create our own dialog boxes and
handlers to obtain the information we
want, at the same time presenting a
friendlier interface to the user – “Crash
Handlers”
21
Crash Handlers
“Crash Handlers” = “Proactive
Debugging”
• With a crash handler its possible to get control
right as the application dies, and log vital
information about the crash:
– the processor context
– the memory
– the state of all objects live at the time of the crash
• This may look like too much information to
log, but helps replicate conditions that led to a
crash.
22
Crash Handlers
• SetUnhandledExceptionFilter
– This API function allows you to specify an
exception filter function (the crash handler)
that will be called whenever an unhandled
exception occurs in the process.
– This API call takes in a pointer to a
function that will be called in case of an
unhandled exception.
23
Crash Handlers
• SetUnhandledExceptionFilter
– The exception filter function receives a
pointer to EXCEPTION_POINTERS that
gives information about the exception.
– Any exception handling code can be placed
in this callback function. Check the reason
of the exception – the stack is damaged do
not make function calls or calls to libraries
like CRT or MFC.
24
Crash Handlers
• SetUnhandledExceptionFilter
– Avoid memory allocations on the heap in
the handler
– There is only one global crash handler per
process. This handler will be called
irrespective of which module of the process
caused the crash.
25
Bugslayer Utilities
• Robbins’ bugslayerutil.dll includes the easy-touse CrashHandler API
– SetCrashHandlerFilter: simply call this function to set
your own exception filter function
– GetRegisterString – a that function reads an
EXCEPTION_POINTERS structure to return formatted
register string
– GetFaultReason – returns a complete description of the
crash. Shows the process, the reason for the exception, the
module that caused the exception, the address of the
exception and if symbol information is available, the
function, the source file and the line number where the
crash occurred
26
Bugslayer Utilities
– GetFirstStackTraceString and
GetNextStackTraceString functions let you
walk the stack. You first call the
GetFirstStackTraceString function and keep
calling GetNextStackTraceString till it returns
false, to walk the entire stack.
27
Minidumps
• An alternative to extracting crash information from an
EXCEPTION_POINTERS structure is to use minidumps, also called crash
dumps.
• A minidump contains the entire state of the application at the time of
the crash.
• The Windows API provides:
BOOL MiniDumpWriteDump(
HANDLE hProcess,
DWORD ProcessId,
HANDLE hFile,
MINIDUMP_TYPE DumpType,
/*dump type*/
PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, /*pointer to EXCEPTION_POINTERS*/
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, /*usually NULL*/
PMINIDUMP_CALLBACK_INFORMATION CallbackParam /*usually NULL*/
);
28
Minidumps
• Dump (.DMP) files can be loaded into a debugger
such as Visual Studio. The source and symbols, if
available, for the dump file are automatically loaded.
• Its like being there when the crash occurred;
debugging a dump is almost like live debugging.
• In bugslayerutil Robbins uses
MiniDumpWriteDump to give us a function that we can
use to snap out a dump at any time during program
execution.
29
Summary
• SEH provides a powerful, language
independent means of exception handling.
• Avoid using C++ exceptions. Never use the
catch(…) construct.
• Crash Handlers are very effective debugging
tools – provide detailed information on the
crash, and help replicate crash conditions for
troubleshooting.
30
Summary
• Crash Handlers can obtain exception
information using GetExceptionInformation,
or use crash dumps which contain detailed
application state at the time of the crash.
• BugslayerUtil provides an easy to use
interface to add crash handler and dumping
functionality to our applications.
31
References
• Robbins, J. Debugging Applications for .NET and Windows ,
Microsoft Press, 2003
• Pietrek, M. "A Crash Course on the Depths of Win32 Structured
Exception Handling," Microsoft Systems Journal, January 1997.
http://www.microsoft.com/msj/0197/exception/exception.htm
• Gershnik, E. “Visual C++ Exception-Handling Instrumentation,”
Windows Developer Magazine, December 2002
http://www.windevnet.com/documents/s=7697/win0212a/0212a.htm
• Microsoft Developer Network
32