To start up a process and attach to the new process for debugging, one
can use:
ntsd [-o] ProgramName [Arguments]
or
windbg [-o] ProgramName [Arguments]
For windbg, one also has the File | Open Executable menu item which
for the same purpose. Although on local drives (like C:), you can often
put in a relative path name, the correct syntax is to use a full path
name -- in the case of network drives, the path name should not be a drive
letter, but must specify the machine,
e.g. \\msc.uky.edu\t\Users\Inslab\CS470-001\user_name\myprog.exe and not
just u:\myprog.exe.
By default, the debugger will start the process and stop at an initial
breakpoint as soon as it is loaded. Usually, one sets a breakpoint
at the main routine and starts execution so as to skip over the
process initialization code.
III. Basic Debugger Commands
The program being debugged is either running or stopped. If it
is running, it can be stopped by using Ctrl-C (for ntsd) or Ctrl-Break (for
windbg) or the windbg Debug | Break menu item.
If the program is stopped, one can start it running:
Command | Operation |
Go | Start execution |
Step Into | Execute a single instruction |
Step Over | Execute a single subroutine |
Step Out | Execute until the end of the current subroutine |
These commands can be invoked in a number of ways:
Command | ntsd | windbg menu | windbg shortcut |
Go | g | Debug | Go | F5 |
Step Into | t | Debug | Step Into | F8 or F11 |
Step Over | p | Debug | Step Over | F10 |
Step Out | g @$ra | Debug | Step Out | shift-F11 |
The steps are either C source code steps or assembly language instruction
steps depending on whether or not Source Mode is in effect. In windbg,
when there is source code available to the debugger, e.g. after you reach
main, steps will be C source code steps, and the source will be displayed in
a separate window. To go to assembly mode, issue the l-t command;
the l+t turns on source mode again. The ASM label on the status
line is grayed out when you are in source mode; you can also see this
in the menus as Debug | Source Mode.
Breakpoints are either code or data locations where execution will stop
just before the code at the location is executed or when the data location
is accessed. The location can be specified by virtual adddress, by
module andd routine offsets, or by source file and line number (when in
source mode).
Command | Operation |
BL (Breakpoint List) | List the current breakpoints and their status |
BP (Set Breakpoint) | Set a new code breakpoint |
BA (Break on Access) | Set a new data breakpoint |
BC (Breakpoint Clear) | Remove a breakpoint |
BD (Breakpoint Disable | Temporarily disable a breakpoint |
BE (Breakpoint Enable | Re-enable a disabled breakpoint |
Here are some examples:
bp 41112c
bp main
bp main+2c
bp `fact.c:15`
Reading and Writing Memory: The Display Memory command
can display memory contents. The command is !dd or !db
depending on whether you want the display unit to be double words or bytes.
To Enter Values command can be used to change values. The command is
!ed or !eb depending on whether it is a double word or a byte
address. There are also commands for moving, filling, comparing, or
searching blocks of memory.
These commands take addresses as parameters. So, to get a value
of a global variable, simply use the Evaluate Expression command as in
? variable_name
to get the address and then use the display memory command to get the
value. The dv command can be used to display addresses of
local variables; but you need to toggle verbose mode on before it
gives the addresses (Ctrl-V in ntsd or Alt-Ctrl-V in windbg).
There are many more formats for displaying memory. For example
dc displays memory as both double words as well as ANSI characters.
Also, the u command disassembles code. (Try it on some code
as well as on some data so you can recognize code when you see it.)
Although many of the commands take an address as a parameter, you
can often simply repeat the command without the address parameter and
it will continue from where it was previously.
Registers: Every time the debugger stops the program, the
values of the registers are displayed. However, you can also use
the r command to display the values of the registers. For example:
0:000> r
eax=00410e20 ebx=7ffdf000 ecx=00409ab8 edx=00000003 esi=00000000 edi=000aec00
eip=0040105a esp=0012ff84 ebp=0012ffc0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000206
fact2!main:
0040105a 55 push ebp
You can also use it to set values of registers as in
r eax=12c
(If you want to set the default radix to be base 10, then use the
command: n 10. Then r eax=12 will set the eax register
to the value 0xc.)
Setting values of the flags in EFLAGS has a special syntax, e.g. to
set the carry bit, you use:
r cf=1
Stack Backtrace: One can get information about the contents
of the stack in several forms:
Command | Description |
K (Display Stack) | ebp, return address, and function name |
KP (Display Stack Parameters) | Adds parameters to the list |
KD (Display Stack Data) | Raw data in the stack |