From Unhandled Exception to Debugger Attach

I was always wondering what is happening between an application throws an unhandled exception, and a debugger attached to the process. Apparently the information is right under my nose, but I was blind.

Windows Debugger's documentation about post-mortem debugging has all the details you want to know.

Enabling Postmortem Debugging

The most common application errors are called exceptions. These include access violations, division-by-zero errors, numerical overflows, and many other kinds of errors.

Applications can also cause breakpoint interrupts. These occur when Windows is unable to run the application (for example, when a necessary module cannot be loaded) or when a breakpoint is encountered. Breakpoints can be inserted into the code by a debugger, or invoked through a function such as DbgBreakPoint. In assembly language, a breakpoint interrupt is generated by an int 3 instruction.

Windows can handle user-mode errors in a variety of ways. The following sequence shows the precedence used for error handling:

  1. If a user-mode debugger is currently attached to the faulting process, all errors will cause the target to break into this debugger.

    As long as the user-mode debugger is attached, no other error-handling methods will be used — even if the gn (Go With Exception Not Handled) command is used.

  2. If no user-mode debugger is attached and the executing code has its own exception handling routines (for example, try - except), this exception handling routine will attempt to deal with the error.

  3. If no user-mode debugger is attached, and Windows has an open kernel-debugging connection, and the error is a breakpoint interrupt, Windows will attempt to contact the kernel debugger.

    Kernel debugging connections must be opened during Windows' boot process. If you are using Windows Server 2003 or a later version of Windows and wish to prevent a user-mode interrupt from breaking into the kernel debugger, you can use the KDbgCtrl utility with the -du parameter. For details on how to configure kernel-debugging connections and how to use KDbgCtrl, see Configuring Software on the Target Computer.

    If Windows does attempt to contact a kernel debugger but there is no debugger running at the other end of the connection, Windows will freeze until kernel debugger is activated.

    In the kernel debugger, you can use gh (Go With Exception Handled) to disregard the error and continue running the target. You can use gn (Go With Exception Not Handled) to bypass the kernel debugger and go on to step 4.

  4. If the conditions in steps 1, 2, and 3 do not apply, Windows will activate a debugging tool. Any program can be selected in advance as the tool to use in this situation. The chosen program is referred to as the postmortem debugger. This is also known as the just-in-time debugger or the JIT debugger.

    If the postmortem debugger is a standard user-mode debugger (such as CDB, WinDbg, or Microsoft Visual Studio), this debugger will start up and break into your application.

    If the postmortem debugger is a tool for writing dump files (such as Dr. Watson), a memory dump file will be created, and then the application will be terminated.

Note  If Dr. Watson is activated on Windows XP or a later version of Windows, a message box will appear. This window gives you the option of sending an error report to Microsoft. If you choose Don't Send, a dump file will created and stored on your hard disk. If you choose Send Error Report, a dump file will be created and stored on your hard disk, and will also be transmitted to Microsoft over the internet.

If you have not reconfigured Windows' postmortem settings, Dr. Watson is used as the default postmortem debugger. This setting can be changed programmatically or through the registry; any changes take effect immediately.

  • To change the postmortem debugger to WinDbg, run windbg -I. (The I must be capitalized.) This command will display a success or failure message after it is used. When WinDbg is the postmortem debugger, it will be activated whenever an application crashes.
  • To change the postmortem debugger to CDB, run cdb -iae or cdb -iaec KeyString.. When the -iaec switch is used, KeyString specifies a string to be added to the end of the AeDebug registry key. This command will display no message if it succeeds, but will display a failure message if it fails. When CDB is the postmortem debugger, it will be activated whenever an application crashes.
  • To change the postmortem debugger to NTSD, run ntsd -iae or ntsd -iaec KeyString.. When the -iaec switch is used, KeyString specifies a string to be added to the end of the AeDebug registry key. If KeyString contains spaces, it must be enclosed in quotation marks. This command will display no message if it succeeds, but will display a failure message if it fails. When NTSD is the postmortem debugger, it will be activated whenever an application crashes.
  • To change the postmortem debugger back to Dr. Watson, run drwtsn32 -i. When Dr. Watson is the postmortem debugger, a memory dump file will be written to disk if an application crashes. See Dr. Watson Command-Line Options for details.

Only a system administrator can alter the postmortem settings.

If a postmortem debugger has been installed, you can deliberately break into the debugger from a user-mode application by calling the DebugBreak function.

Editing the Registry

The postmortem debugging settings are stored in the registry. If you wish to control these settings, it is recommended that you use the WinDbg, CDB, NTSD, or Dr. Watson commands described above; these will automatically change the relevant registry keys. If you do need to manually edit the registy, do so very carefully, since improper changes to the registry may render Windows unusable.

On an x86 computer, the postmortem settings are stored in the \\HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AeDebug key.

On an Intel Itanium computer, there are two registry keys used for postmortem debugging:

  1. A failing 64-bit application will be debugged according to the settings stored in the \\HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AeDebug key.
  2. A failing 32-bit application will be debugged according to the settings stored in the \\HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug key. However, if the Debugger value in this key specifies an application in the %windir%\system32 directory, Windows will look in %windir%\syswow64 instead.

When using an Itanium computer, it is often simplest to place identical values in each of these keys. In particular, if you are using WinDbg, CDB, or NTSD as your postmortem debugger, the same version will work for 32-bit and 64-bit user-mode applications on an Itanium computer. See Choosing a 32-bit or 64-bit Debugger Package for details.

There are two registry values that should appear in these keys:

Debugger
This REG_SZ value specifies the debugger that will handle postmortem debugging. The full path to the debugger must be listed, unless the debugger is located in a directory that is in the default path.
Auto
This REG_SZ value is always either 0 or 1. If Auto is set to 0, a message box will be displayed prior to postmortem debugging.

When an unhandled application error occurs, Windows checks to see if the Debugger and Auto registry values exist.

If the Auto value is 0, a message box will appear.

In Windows NT and Windows 2000, the message box will have one of the following formats:

  • If the Debugger value contains the name of a valid debugger or Dr. Watson, the message box will have two buttons: OK and Cancel. If the OK button is pressed, the application will be terminated. If the Cancel button is pressed, the tool specified in the Debugger value will be started.
  • If the Debugger value is empty, the message box will have only an OK button and no debugger will start.

In Windows XP and later versions of Windows, the message box will have one of the following formats:

  • If the Debugger value contains the name of a valid debugger or Dr. Watson, the message box will have three buttons: Send Error Report, Don't Send, and Debug. If the Don't Send button is pressed, the application will be terminated. If the Send Error Report button is pressed, a minidump file will be sent to Microsoft and the application will be terminated. If the Debug button is pressed, the tool specified in the Debugger value will be started. (Note that all of these buttons have different effects than the buttons on the message window for Dr. Watson when the Auto value does not equal 0.)
  • If the Debugger value is empty, the message box will have only the Send Error Report and Don't Send buttons.

If the Auto value equals 1, no message box appears. The debugger referred to in the Debugger value is automatically started.

Registry Examples

The following registry values can be used to set Dr. Watson as the postmortem debugger (this is the default):

Debugger = "drwtsn32 -p %ld -e %ld -g"
Auto = 1

The following values can be used to set WinDbg as the postmortem debugger:

Debugger = "Path \WinDbg -p %ld -e %ld"
Auto = 1

The following values can be used to set CDB as the postmortem debugger:

Debugger = "Path \CDB -p %ld -e %ld -g"
Auto = 1

In these examples, Path is the directory where the debugger is located, -p %ld specifies the process ID that will be debugged, -e %ld provides the event that caused the exception, and -g causes the debugger to skip the initial breakpoint. (Dr. Watson ignores the -g option.)

Security Vulnerabilities

If you are considering enabling postmortem debugging on a computer that you share with other people, see Security During Postmortem Debugging.