Introduction
We can make a debugger automatically pop up whenever an application crashes. This type of debugger is called a post mortem or JIT Debugger and they can also automatically generate a crash memory dump. Some post mortem debuggers include WinDbg, VS 6.0/NET, and Dr Watson. In this article, we will use the WinDbg debugger and explain how to:
- configure it as a postmortem debugger,
- automatically generate a memory dump file, and
- run through the memory stack of the application when it crashed
To Configure WinDbg as a Postmortem Debugger
- Download the WinDbg from the Microsoft debugger site here.
- Install it in an appropriate directory.
- To change the postmortem debugger to WinDbg, run
WinDbg -I
. (Note that 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.
(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.)
Configure Automatic Memory Dump
To set WinDbg to automatically generate a memory dump file when a program crashes, it is necessary to edit the registry. On an x86 computer, the postmortem settings are stored in the \\HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AeDebug
key. 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 in the default path. Auto
: This REG_SZ
value is always either 0
or 1
. If 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. On 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.
Registry Examples
Prior to change, the registry entry might be:
Debugger = "Path\windbg.exe" -p %ld -e %ld -g
For auto generation of the dump file, modify the registry Debugger
key as shown:
Debugger = "Path\WinDbg.exe" -p %ld –c ".dump /ma /u C:\CrashDump.dmp" -e %ld –g
NOTES
- Be careful with the registry changes. Execute the test.exe to verify that the registry changes are correct. When you run test.exe, the application will automatically bring up the debugger and generate a crashdump.dmp file in the C:\ directory.
-c
option should immediately come after -p %ld
. - Info taken from the “Using Debugging tools for windows” help file.
-c "command"
specifies the initial debugger command to run at start-up. This command must be enclosed in quotation marks. Multiple commands can be separated with semicolons. (If you have a long command list, it may be easier to put them in a script and then use the -c
option with the $<(Run Script File)
command.)
Parameters
You can change the parameters of the command as per your requirements.
Options can be any number of the following:
/o
- Allows the debugger to overwrite a previous dump file with the same name. If this is not included and the file name is in use, the dump file will not be written. /f
- Kernel mode: Causes the debugger to create a complete memory dump
- User mode: Causes the debugger to create a full user dump
Note that, despite their names, the largest minidump file actually contains more information than a full user-mode dump! For example, . dump /mf
or . dump /ma
will create a larger and more complete file than . dump /f
. /m [MiniOptions]
- Causes the debugger to create a Small Memory dump (in kernel mode) or a minidump (in user mode). If neither /f
nor /m
is specified, /m
is the default.
In user mode, /m
can be followed with additional MiniOptions specifying the extra data that should be included in the dump. If no MiniOptions are included, the dump will include module, thread, and stack information, but no additional data. Any of the following MiniOptions can be added to change the contents of the dump file; they are case-sensitive.
MiniOption | Effect |
a | Creates a minidump with all optional additions. The /ma option is equivalent to /mfhuFt — it adds full memory data, handle data, unloaded module information, basic memory information, and thread time information to the minidump. |
f | Adds full memory data to the minidump. All accessible committed pages owned by the target application will be included. |
F | Adds all basic memory information to the minidump. This adds a stream to the minidump that contains all basic memory information, not just information on valid memory. This allows the debugger to reconstruct the complete virtual memory layout of the process when the minidump is being debugged. |
h | Adds data about the handles associated with the target application to the minidump. |
u | Adds unloaded module information to the minidump. This is only available in Windows Server 2003. |
t | Adds additional thread information to the minidump. This includes thread times, which can be displayed by using .ttime (Display Thread Times) when debugging the minidump. |
i | Adds secondary memory to the minidump. Secondary memory is any memory referenced by a pointer on the stack or backing store, plus a small region surrounding this address. |
p | Adds process environment block (PEB) and thread environment block (TEB) data to the minidump. This can be useful if you need access to Windows system information regarding the application's processes and threads. |
w | Adds all committed read-write private pages to the minidump. |
d | Adds all read-write data segments within the executable image to the minidump. |
r | Deletes from the minidump those portions of the stack and store memory that are not useful for recreating the stack trace. Local variables and other data type values are deleted as well. This option does not make the minidump smaller (because these memory sections are simply zeroed), but it is useful if you want to protect the privacy of other applications. |
R | Deletes the full module paths from the minidump. Only the module names will be included. This is a useful option if you want to protect the privacy of the user's directory structure. |
These MiniOptions can only be used when creating a user-mode minidump. They should follow the /m
specifier. /u
- Causes dump file names to have the date, time, and PID appended to them. This ensures that dump file names will be unique. /a
- Causes dumps to be generated for all currently-debugged processes. If /a
is used, the /u
option should be included as well to ensure that each file has a unique name. /b[a]
- Causes a .cab file to be created. If this option is included, FileName is taken to be the CAB file name, not the dump file name. A temporary dump file will be created, this file will be packaged into a CAB, and then the dump file deleted. If the b
option is followed by a
, all symbol and image files will be packaged into the CAB as well. /c "Comment"
- Specifies a comment string that will be written to the dump file. If em>Comment contains spaces, it must be enclosed in double quotes. When the dump file is loaded, the Comment string will be displayed. /kpmf File
(Only when creating a kernel-mode Complete Memory dump) - Specifies a file that contains physical memory page data. FileName
- Specifies the name of the dump file. You can specify a full path and file name or just the file name. If the file name contains spaces, it should be enclosed in quotation marks. If no path is specified, the current directory is used.
Checking the Memory Stack of an Application When It Crashed
Use command KV
for displaying the stack. If the stack is corrupted, then you can manually walk though the stack using the following steps:
lm
- loads all the modules, keep note of address range of all modules dd esp
– dumps the stack. stack has the return addresses of all the functions in the stack. - Guess the module, which would have caused the crash and note its address range.
- Look at the stack dump, and find an address, which is there in the suspected address range.
ln 'address'
- this provides information about the function near that address. u 'address'
- If the function looks suspicious, you can un-assemble the assembly code near that address range. - If you did not find any useful information about the suspected function, repeat steps 4 – 7,
- If you did not find any useful information about the suspected module, repeat steps 3 - 8
Useful Commands in WinDbg
(Taken from the "Using Debugging tools for windows" help file)
- LN (List Nearest Symbols)
The LN command displays the symbols at or near the given address.
- Syntax: LN address
- Parameters:
- address - The address where to begin searching for symbols. The nearest symbols, either before or after address, are displayed
- .dump (Create Dump File)
The .dump
command creates a user-mode or kernel-mode crash .dump
file.
- Syntax:
.dump
Options FileName
- D, DA, DB, DC, Dd, DD, DF, DP, DQ, DU, DW, DYb, DYd (Display Memory)
The D* commands display the contents of memory in the given range.
- Syntax:
- d{a|b|c|d|D|f|p|q|u|w} [range]
- dy{b|d} [range]
- d [range]
- Parameters:
range
- The memory area to display. For more syntax details, see Address and Address Range Syntax. If you omit range
, the command will display memory starting at the ending location of the last display command. If range
is omitted and no previous display command has been used, the display begins at the current instruction pointer.
- U (Unassemble)
The U command displays an assembly translation of the specified program code in memory. This command should not be confused with the ~U (Unfreeze Thread) command.
- Syntax: u [Range]
- Parameters:
Range
- The memory area that contains the instructions to unassemble. If Range
is not specified, the disassembly begins at the current address. If no range size is specified, the default size is eight instructions on an x86 processor and nine instructions on an Itanium processor.
- LM (List Loaded Modules)
The LM command lists the specified loaded modules. The output includes the status and the path to the module.
- Syntax: lm Options [a Address] [m Pattern]
- K, KB, KD, KP, Kp, KV (Display Stack Backtrace)
The K*
commands display the stack frame of the given thread, along with related information.
Reference
- "Using Debugging tools for windows" help file