Windows Exceptions, Part II: Exception Dispatching

August 30th, 2010 by bettermanlu

In previous session, we discussed what happens when a filter returns EXCEPTION_CONTINUE_SEARCH . Returning this value tells the system to continue walking up the call tree looking for additional exception filters. But what happens if every filter returns EXCEPTION_CONTINUE_SEARCH ? In this case, we have what’s called an unhandled exception .

We will focus on user-mode exceptions and see how windows dispatch such exceptions. And we divide the exception into two types: handled exception and unhandled exception . Another thing to make the exception dispathing complicated is that whether the process is debugged or not, i.e, whether there is a debugger attached when the exception happened.

Case 1. Handled exception without debugger attached.

Case 2. Hanlded exception with debugger attached.

Case 3. Unhandled exception without debugger attached.

Case 4. Unhandled excetpion with debugger attached.

If we consider the just-in-time debugger settings, we get another 3 cases.

Case 5. Unhandled exception without just-in-time debugger

Case 6. Unhandled exception with just-in-time debugger (Auto = 0)

Case 7. Unhandled exception with just-in-time debugger (Auto = 1)

Below figure illustrates how windows system dispatches a user-mode exception .

1: WHen an exception occurs, whether it is explicitly raised by software or implicitly raised by hardware, a chain of events begins in the kernel. The CPU hardware transfers cotnrol to the kernel trap handler, which creates a trap frame.  The trap frame allows the system to resume where it left off if the exception is resolved. The trap handler also creates an exception record that contains the reason for the exception and other pertinent information.

2-4:  If the exception occurred in user mode, the exception dispatcher will check whether the application is currently under the control of a debugger; if it is, Windows notifies the attached debugger. The debugger receives the ExceptionInformation member of the EXCEPTION_RECORD structure generated for this exception, and it uses this information to position you at the code instruction that caused the exception to be raised and notify you as to the kind of exception that was raised. This is also called first chance exception . The debugger sees all exceptions before the program does. At this point, the application is suspended and the debugger decides how to handle the exception.

Note that your code can use IsDebuggerPresent to detect whether or not it is running under the control of a debugger.

5-6: If Debugger decides to handle the exception, instead of passing the exception on, this is end. Debugger can choose to terminate the process.

3,7: If debugger decdies to not handle the exception and pass it on, or there is no debugger attached to the process, the exception will be handled by the frame-based handlers.

8-9: If the application’s frame based exception handlers can handle this exception, the process will continue to run normally.

10-12: Otherwise, the exception will be finally tranferred to the windows system which has a default exception handler to handle the so called unhandled exceptions. Again, the exception dispatcher will check whether the application is currently under the control of a debugger; if it is, it will call the debugger again to allow the user to do more debugging. This is called the second-chance notification.

13-16: If the debugger isn’t running, the kernel will start Windows Error Reporting service to notify the user that something wrong happened within the application. If WER doesn’t handle the exception, the kernel executes a default exception handler  that simply terminates the process.

Let’s take a look at what WER really does.

16-21: It first check the registry key to see whether there is a just-in-time debugger registered.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug

Inside this subkey, there is a data value named Debugger , which is typically set to the following value when you install Visual Studio:
“C:\Windows\system32\vsjitdebugger.exe” -p %ld -e %ld

For windbg, it is usually be:

“C:\Program Files\Debugging Tools for Windows\windbg.exe” -p %ld -e %ld -g

There is another data value named Auto , which is 0 or 1. If Auto is set to 1 , WER does not offer any choice to the user and immediately invokes the debugger, otherwise, WER will ask you whether to debug the process or not.

Please note that in step 20: when just-in-time debugger is invoked, the exception is a second-chance one, you can get the information from the output of the above illustrated windbg picture. This is reasonable, because the exception is an unhandled exception, which is passed through the application’s own exception handles and coming here as a second chance exception.

Before we end this session, let me paste some content from windows internals book on how windows dispatches kernel-mode exceptions.

If the exception occurred in kernel mode , the exception dispatcher simply calls a routine to locate a frame-based exception handler that will handle the exception. Because unhandled kernel-mode exceptions are considered fatal operating system errors, you can assume that the dispatcher always finds an exception handler . Some traps, however, do not lead into an exception handler because the kernel always assumes such errors to be fatal—these are errors that could have been caused only by severe bugs in the internal kernel code or by major inconsistencies in driver code (that could have only occurred through deliberate lowlevel system modifications that drivers should not be responsible for). Such fatal errors will result in a bug check with the UNEXPECTED_KERNEL_MODE_TRAP code.

This is it.

Ref:

Windows Internals: Chapter 3 System Mechanisms – Exception Dispatching

Windows via C/C++: Chapter 25 Unhandled Exceptions, Vectored Exception Handling, and C++ Exceptions

Comments are closed.