When doing live debugging you’ll use breakpoints at some point when tackling a problem.

A simple breakpoint is easy to use; however, when you are on the trenches you might need to use advanced breakpoints that save you a lot of manual work.

For instance, you may need to use a breakpoint that works only one time and changes the assembly code, changing the execution flow of your application. Or you may want to have a breakpoint that logs specific information to a file and then continues the execution.

You can even call a script from your breakpoint!

With breakpoints there’s no limit to creativity! J

 

First let’s start with Breakpoints 101.

 

Note: The Special Command section doesn’t cover all commands and variations. If you want to see all options, check the WinDbg documentation.

 

Options:

 

bp - Sets a new breakpoint at the address of the breakpoint location specified in the command. If the debugger cannot resolve the address expression of the breakpoint location when the breakpoint is set, the bp breakpoint is automatically converted to a bu breakpoint. Use a bp command to create a breakpoint that is no longer active if the module is unloaded.

 

bu - Sets a deferred or unresolved breakpoint. A bu breakpoint is set on a symbolic reference to the breakpoint location specified in the command (not in an address) and is activated whenever the module with the reference is resolved.

bm - Sets a new breakpoint on symbols that match a specified pattern. This command can create more than one breakpoint. By default, after the pattern is matched, bm breakpoints are the same as bu breakpoints. That is, bm breakpoints are deferred breakpoints that are set on a symbolic reference.

 

ba - This breakpoint is triggered when the specified memory is accessed.

 

 

Arguments for all of them:

 

<address/symbol> - Specifies the first byte of the instruction where the breakpoint is set. If you omit Address, the current instruction pointer is used.

 

[/1] - Creates a "one-shot" breakpoint. After this breakpoint is triggered, it is deleted from the breakpoint list.

 

[/c] - MaxCallStackDepth

Activates the breakpoint only when the call stack depth is less than MaxCallStackDepth. You cannot use this option together with /C.

 

[“commands”] - Specifies a list of commands executed every time the breakpoint is encountered the specified number of times. You must enclose the CommandString parameter in quotation marks. Use semicolons to separate multiple commands. Debugger commands in CommandString can include parameters. You can use standard C-control characters (such as \n and \"). Semicolons that are contained in second-level quotation marks (\") are interpreted as part of the embedded quoted string. The CommandString commands are executed only if the breakpoint is reached while the application is executing in response to a g (Go) command. The commands are not executed if you are stepping through the code or tracing past this point. Any command that resumes program execution after a breakpoint (such as g or t) ends the execution of the command list.

 

Arguments for ba only:

e (execute)

Breaks into the debugger when the CPU retrieves an instruction from the specified address.

r (read/write)

Breaks into the debugger when the CPU reads or writes at the specified address.

w (write)

Breaks into the debugger when the CPU writes at the specified address.

 

To see the breakpoints:

 

bl - Lists information about existing breakpoints.

 

 

Example of a basic breakpoint using symbol:

 

bp mtgdi!CGDIThread::InitInstance

 

 

 

Example of a basic breakpoint using address:

 

bp 00414d60

 

 

 

 

Example of setting a breakpoint based on a pattern:

 

bm mtgdi!CGDIThread*

 

 

 

  

 

Example of a one shot breakpoint. It’s deleted after the first hit; you can see it using bl:

 

bp /1 mtgdi!CRectThread::InitInstance

 

 

 

 

Example of a breakpoint using call stack limit:

 

bp /c 6 mtgdi!CBallThread::InitInstance

 

 

 

Example of a breakpoint using commands:

 

bp mtgdi!CBallThread::InitInstance ".echo CALL STACK; kpn 1000; .echo REGISTERS; r; .sleep 0n5000; gc"

 

 

 

 

Example of breaking on access:

 

ba w4 (0x02ed52b0 + 0x080)

 

 

 

 

Bonus example – count how many times a breakpoint was hit:

 

r @$t0 = 0                                    (press Enter)

bp <address/symbol> "r @$t0 = @$t0 + 1; .echo Number of times the breakpoint was hit; ? @$t0; gc"                    (press Enter)

g                                                 (press Enter)

 

 

 

Here you can see scripts that use breakpoints.