| Using Microsoft Windows Debugger (WinDbg) |
Updated: 2/19/2005
|
This tutorial shows how to begin using the Microsoft Windows Debugger (WinDbg) to debug 32-bit assembly language programs running in Protected mode. You can download the Microsoft Debugging Tools for Windows from the Microsoft Windows Debugging Web site: http://www.microsoft.com/whdc/devtools/debugging/default.mspx. There is a link on the same Web page to the Microsoft knowledge base articles relating to debugging tools. The Microsoft Windows Debugger (WinDbg) can be used to debug both user-mode and kernel-mode programs. It uses Microsoft Visual Studio debug symbol formats for source-level debugging. It displays function names and variables for any modules compiled usign the COFF (common object file format) linker option. It permits you to do the following:
That's only one side of what it does. It is also a kernel-mode debugger that debugs the intricate interfaces between applications and MS-Windows. And it's free.
Now it's time to do something useful. We will assume that you've already set up your integrated editor (such as TextPad or JCreator) with the necessary commands to build and debug programs. If you haven't one that, click here. Load the Source ProgramOpen AddSub2.asm from the \Examples\ch03 directory and insert a new line of code at the beginning of main: int 3 ; required for WinDbg debugger The comment, of course, is optional. The INT 3 instruction is called a breakpoint because it forces your program to pause execution and transfer control to the debugger. If we didn't include this instruction, AddSub2 would just run to completion without giving us a chance to use the debugger. We're about to run WinDbg and tell it to load and run the AddSub2 program. AddSub2 will be a child process running under WinDbg. When AddSub2 begins to execute, we use the INT 3 instruction to return control to WinDbg so we can view the source code, trace individual statements, examine variables, and so on. Save the program and build it (Tools | Build 32-bit MASM). Debug the ProgramSelect the WinDbg command from your editor's Tools menu. You may have renamed the command to something like "Debug 32-bit MASM". If you've set up your Tools menu correctly, WinDbg will run. The program's console output window (probably all black) will be overlaid on top of the debugger. This window lets us know that AddSub2 has begun to execute. Click behind it to bring the the debugger to the top. Your debugger will look something like this:
I cheated a bit and brought the source code window up to the front to make it look better. You can do the same by selecting its name from the Window menu. Source WindowThe Source window displays the program's source file. Note that the main PROC statement is highlighted. Actually, execution has really paused on the INT 3 instruction. We will return to this window in a moment, when we begin to trace the program. Command WindowThe Command window gives you a detailed history of each DLL and EXE file that has been loaded and executed from the moment we launched WinDbg. The last line in the Command window indicates that the INT 3 instruction in the AddSub2 program just executed. Disassembly WindowThe Disassembly window displays a raw listing of the program's code. There's some extra stuff at the beginning that you can ignore. The relevant part begins at the label AddSub2!main, where it displays the address, machine code, and assembly language for each program instruction:
When variables are displayed, their names are appended to the module name, as in AddSub2!val1. Note that the offset of each variable apears next to its name. Note also that the exit statement in the AddSub2 source file has been translated into a call to the ExitProcess function. This is explained more fully at the bottom of page 75 in the book. Register WindowThe Register window seems to order the register names in an odd way, but you can fix that. Click on the Customize... button at the top of the window. If you want, you can replace the contents of this window with the following register list: eax ebx ecx edx esi edi ebp eip esp cf sf zf of df af pf The last seven are flags: Carry, Sign, Zero, Overflow, Direction, Aux Carry, Parity. Any registers not named in the list are automatically appended to the window. This is what the top part of the Register window looks like, with the new register list:
Step Through the Program (F10)We can step through the program using the F10 key. Try it now, and watch the highlight bar in the Source window move from statement to statement. Look at the Register window as you do this, and note that certain register names turn red immediately after they have been modified. The AddSub2 program modifies the EAX and EIP registers quite a bit, as you can see. Note also that a corresponding highlight bar moves in the Disassembly window. This bar is tracking your program's execution through the machine code displayed there. You can use this window to check the address of each instruction as it executes. When you execute the call DumpRegs statement, click on the program's output window and note that the register dump has appeared. When you reach the exit statement and press F10, WinDbg exits and returns to your text editor. WorkspaceWe have set up WinDbg to automatically save your program's workspace (configuration) when closing the debugger. Then, if you open the same program in WinDbg again, the setup of your various debugger windows will be the same. Each workspace is stored in the system registry, in the following path:
Unfortunately, each new program creates its own Workspace. If you want the Register window to display registers in a particular order, for example, you will have to customize it for each new program. Watch WindowRun WinDbg again. This time we will display the values of the variables as the program executes. With the debugger on the screen, select Watch from the View menu. The Watch window is like an electronic spreadsheet that displays the name and value of selected variables. As you step through a program, you can see the watch variables change value. Click just below the Name column, and type: val1. Notice that its starting value (1000h) is displayed in the Watch window. Do the same for val2 and val3 on the next two lines of the Watch window. Click in the Value column of the Watch window and change the value of a variable. That's really useful if you discover a program bug and you just want to continue stepping through the program. Select Offsets from the Watch window's toolbar to add a column that displays each variable's offset. This is useful because you often need to check the offset of a variable when you use indirect addressing. Memory WindowA memory window is great for displaying a raw dump of a range of memory locations. Select Memory from the View menu, and type in 40400 into the Virtual (address) field. In the Display format field, select Long Hex from the dropdown list:
If you change the Display format to long, you can view the memory dump as a series of 32-bit decimal integers. Just for fun, experiment with some of the available formats. Restarting a ProgramFinally, if you have already stepped through part of a program and you want to start over, select Restart from the Debug menu. The program is reloaded into memory, so any changes previously made to variables in the Watch window are undone. Running WinDbg from a Command PromptIf you want to run WinDbg from the Windows Command prompt, you must set the system PATH variable to the location of windbg.exe. It can usually be found in the C:\Program Files\Debugging Tools for Windows directory. In Windows XP, set the path by right-clicking on My Computer, select Properties, select Advanced, select Environment Variables. In the upper pane (user variables), select PATH and click on Edit. In the Variable value box, move to the end, type a semicolon, and enter the full path to the directory containing windbg.exe (for example, C:\Program Files\Debugging Tools for Windows). Here's a sample screen snapshot:
Next, open a command prompt and navigate to the directory containing your program's EXE file. Suppose you want to debug the AddSub2.exe program; the following command does the trick: windbg -QY -g -G addsub2.exe (-QY auto-saves the debugger's workspace file. -g skips over the MS-Windows startup code that launches your program. -G skips the MS-Windows cleanup code that executes after your program has ended.) For more information about debugging options, press F1 in WinDbg and look for the topic command-line options under Reference.) This ends your first introduction to WinDbg. Enjoy! |