Setting Breakpoints

You can set breakpoints using the bp and br commands. With each breakpoint, you can specify breakpoint commands, a string of debugger commands that are executed when a breakpoint is hit. For example, the following command sets a breakpoint that stops execution in the function _MyEntryPoint and displays the registers and stack:

bp _MyEntryPoint+346 "r;k"
 

Semicolons (;) separate commands from one another. All text is converted to uppercase except for text surrounded by single quotation marks ('). Two single quotation marks ('') or two double quotation marks ("") in a row act as an escape character and add one single quotation mark or one double quotation mark to the string. The maximum length of a breakpoint command is 80 characters. If the breakpoint has no breakpoint command string, WDEB386 executes the default (zd) command.

The conditional execution command (j) is very useful in breakpoint commands. This command executes the command list if the expression evaluates to TRUE (nonzero). Otherwise, it continues to the next command in the command line (not including the ones in the command list parameter). If the command list contains more than one command, it must be enclosed in single or double quotation marks. Use a semicolon (;) to separate commands. No quotation marks are required if the command list contains zero or one command. The conditional execution command can be used in breakpoint commands to halt execution when an expression becomes true or in the default command.

Any operator, number, or symbol value can be used in the conditional expression. Always put a zero in front of a hexadecimal number that begins with a nonnumeric character. Doing so will prevent the debugger from treating the number as a symbol and searching all the loaded symbol files. For example, using 0f000 is faster than f000.

For example, the following command stops execution and display registers only if the variable _MyVar is equal to 3 when control enters the _MyEntryPoint function. Otherwise, it displays the current value and continues:

bp _MyEntryPoint "j _MyVar == 3 r;'? "_MyVar=%x" _MyVar;g'"
 
Here are some additional breakpoint examples:
 
##bl
0 d  %c02e9ba0 [VKD_Set_Focus + 33]
1 d  %c012a57c [VKD_VM_Service_Phys]
2 d  W4 %c012c4f8 [VKD_8042_cmd_table + 1e8]
3 e  %c012ad8f [VKD_Chk_BIOS_Toggle_State + 21] "? 'BIOS %X',AL;G"
4 e  %c02ea32d [Hot_Key_Ended + ae] "? 'PriNot %x', DW 0C012BC2D;G"
5 e  %c012aaa4 [Update_Shift_State]  "? '%X %X', DW 0C012BC2D, DW ESP;G"
6 e  %c012a8b1 [Queue_Output + 1] "J DI==8 R;G"
7 e  %c012a8b0 [Queue_Output] "J(AL==38 OR AL==0B8) '?''%X %X %X'',AL,DI,DW ESP;G';G"
 

Breakpoints zero and one are simple breakpoints; nothing much to say.

Breakpoint two is a write breakpoint, established via br w4 %0c012c4f8. This causes the debugger to halt whenever somebody (w)rites to the dword (4) at %c012c4f8. You can also set (r)ead and (e)xecute breakpoints. For read and write breakpoints, you also have to say the size of the object you want to break on, either 1, 2 or 4.

Breakpoint three is a simple command breakpoint. Whenever VKD_Chk_BIOS_Toggle_State+21 is hit, the command "? 'BIOS %X',AL;G" is executed. This command itself is in two parts. The first part is a ? command, which acts like printf. The print format is '%X' which means a hexadecimal value, and the argument is AL. So what the print command does is display the current value of the al register. The second command is G, which tells the debugger to resume execution after doing the requisite printing.

Breakpoint four is a minor extension of breakpoint three. Instead of printing AL, it prints DW 0C012BC2D. As previously noted, the DW operator dereferences the dword at the specified location. So breakpoint four, when hit, displays the current dword value stored at address 0C012BC2D.

Breakpoint five is a minor extension of breakpoint four. A second value is printed, DW ESP. This displays the dword at the top of the stack, which is the address of the caller.

Breakpoint six is a simple conditional breakpoint. When the breakpoint is hit, the expression DI==8 is evaluated. If true, then R is executed (displaying registers); otherwise G is executed (resume execution). In other words, the breakpoint means Stop if DI==8.

Breakpoint seven combines all the tricks. The condition is (AL==38 OR AL==0B8). If the condition is met, then three values are printed, and execution continues. If the condition is not met, then execution continues without printing anything. Note first that quotation marks are used to enclose the commands to be executed if the condition is met. This needs to be done to protect the semicolon embedded within the command string from being interpreted as the end of the J command. Note second that the quotation marks that provide the print format are doubled, because they already live inside the quotation marks that are used to enclose the conditional command.

Debugger breakpoints can be "used" as markers by merely setting a (disabled) breakpoint at an address you will need to refer to frequently. For example:

## bp 12345678 
## bd0 &qquad;assuming that 12345678 was bp0 
## d br0+10 &qquad;    dump at 12345688 
 

If the code containing a breakpoint gets paged out to disk, you cannot remove that breakpoint until it is paged back in.