Continuing on with my series on useful WinDbg commands, the next group I'd like to discuss are breakpoint commands. In particular, I'd like to discuss bl, bp, bu and bm as well as the meta-command .bpcmds. Let's first look at the command format.
bl [/L] [Breakpoints]
[~Thread] bp [ID] [Options] [Address [Passes]] ["CommandString"]
[~Thread] bu[ID] [Options] [Address [Passes]] ["CommandString"]
[~Thread] bm [Options] SymbolPattern [Passes] ["CommandString"]
bl is by far the most used command when debugging in WinDbg. The only purpose this command serves is to output the current list of breakpoints. To view the documentation for bl, type ".hh bl" at the WinDbg command line. Let's take a look at an example output for the bl command. After a debugging session, a list of breakpoints might look like the following.
0 eu 0001 (0001) 0:0001 (MyDLL!Start)
1 eu 0001 (0001) 0:0001 (@@masm(`MyDLL!test.cpp:84+`))
2 du 0001 (0001) 0:0001 (MyDLL!Initialize)
6 eu 0001 (0001) 0:0001 (@@masm(`MyDLL!test.cpp:92+`))
The structure for the output is quite simple. Each row is a separate breakpoint.
So, if we take apart the first row, we have:
Breakpoint index. Note that this index is used to enable/disable breakpoints using (be/bd) i.e. be 0 to enable breakpoint 0 or bd 0 to disable the breakpoint.
Breakpoint flags. This signifies that the breakpoint is enabled (e) and unresolved (u). An unresolved breakpoint is one that does not match a symbol reference in any currently loaded module. Note, to see the current symbol references, use x (more on this later).
The breakpoint is active on the first pass through the code and the code has not yet been executed under the debugger. This information is indicated by a value of 1 (0001) in the "passes remaining" counter and a value of 1 ((0001)) in the initial passes counter.
Associated process and thread ID. The process is 0, and the thread ID is 0001. If thread is given as three asterisks ("***"), this breakpoint is not a thread-specific breakpoint (all threads will hit).
Breakpoint location. It is stored within the MyDLL module at the Start function.
Although bl accepts the /L flag which forces the command to always display the addresses instead of line numbers and source code, unless you are doing some insane hacker assembly debugging, you will probably never need to use this flag. In most cases, the naked bl command (with no args) perfectly suffices.
Stay tuned for my next blog to learn more about breakpoints. In the next blog, I'll be discussing the second most widely used command in WinDbg, the bp command.