KernelDebugRef - Using Kernel Debugger Commands
Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation
There are many Kernel Debugger commands that allow you to control execution of the system under test.
Most commands are one or two characters, with one-character options. The semicolon character (;) is the command separator, and the comma (,) or a blank is the operand separator.
When the syntax of the command is shown, the following conventions are used:
- Arguments between square brackets ([]) are optional.
- A vertical bar (|) indicates that either argument is acceptable.
The definitions of some of the arguments used in the commands are as follows:
- <range> = <addr> [<word>] | [<addr>] [L <word>]
- <addr> = [. | #][<word>:]<word> | %<dword>
- <list> = <byte>, <byte>, ... | "string"
- <string> = "char" | 'char'
- <dword>, <word>, <byte> = evaluate to the size indicated in the symbols <>
Some examples of how to use the debugger follow:
- ##?
This command gets you a help screen, and .? gets you a help screen for the extended commands.
- ##.P
This command displays all of the processes running in the system. The left-hand column of this display shows the slot number, which is important for the .ss command.
When you set a breakpoint in an application, the current debugger context must be changed to that process. For example, if you press Ctrl+C and you interrupt while BAR.EXE is executing, but you want to set a breakpoint in FOO.EXE, you must change the debugger context to FOO.EXE.
- ##SS [slot number]
Type .p, find out the slot number of FOO.EXE, and type .ss [slot number]. Now you can set breakpoints in FOO.EXE. Because .DLLs have no process associated with them, in order to set a breakpoint in a .DLL you need to be in the context of an application that is dynamically linked to that .DLL.
- ##BP [addr]
This sets a break point at the address [addr]. [addr] can be symbolic or numerical. For 32-bit applications, this is a 32-bit address. For 16-bit applications, this is a 16-bit address.
- ##BC [bp number]
- ##BD [bp number]
- ##BC *
- ##BD *
BC [bp number] clears a breakpoint, while BD disables it. BC * clears all breakpoints, while BD * disables all breakpoints.
- ##DA [addr]
- ##DB [addr]
- ##DW [addr]
- ##DD [addr]
The above commands stand for dump ASCII, dump byte, dump word, and dump doubleword respectively, and display memory starting at address [addr]. DW [addr] L 20 would display hex 20 words starting at [addr].
- ##E [addr]
This allows you to edit memory (change memory contents) at [addr].
- ##K
This gives a stack-frame backtrace of the current application (even at ring 0).
- ##.K [slot number]
This gives a stack-frame backtrace of the thread in this slot. If you are in ring 0, this causes a ring-3 backtrace.
- ##DD SS:ESP
This dumps the stack data at the current top of the stack. ESP always points to the last value pushed onto the stack.
- ##DD SS:EBP
This is what links C stack-frames together at any time. The EBP register points to the location on the stack where the old EBP is saved. After EBP is located on the stack, you get the return address and then the parameters passed to the function that is currently executing. References to [EBP+n] refer to passed parameters, while references to [EBP-n] refer to local variables.
- ##G
This means go or execute.
- ##R
This dumps the register set. To set a register, type r [reg] = value. For example, r EAX = 6 puts 6 into register EAX. To re-execute some code or to jump ahead in the code, reset the instruction pointer by typing r EIP=[addr].
- ##P
This steps through the code using the INT 3 type of stepping to step over function calls.
Note: If a function exits to an address other than the return address (where the INT 3 is waiting), you might get unexpected results. Keep track of what happens within the conditional jump and looping constructs of your program.
- ##T
This single-steps through the code. This does not use the INT 3 type of stepping as p does, but actually steps into any call to a function.