Data Breakpoints

Usually, people put breakpoints on an instruction. These breakpoints are set by replacing the first byte of an instruction with the ‘int 3’ instruction (0xcc). When the processor executes the ‘int 3’ instruction, it causes the OS to generate STATUS_BREAKPOINT exception, and your program stops.

There is another type of breakpoint that the debugger can also set for you – a data breakpoint. Data breakpoints fire when data is changed. To set one, go to Debug->New Breakpoint, then switch to the ‘Data’ tab.

There are really two types of data breakpoints that the native debugger supports – hardware data breakpoints, and emulated data breakpoints. Hardware data breakpoints are the useful ones. They are implemented with the debug registers of the processor. Unlike emulated breakpoints, these are fast and reliable. On the downside, the processor doesn’t have many of them. Also, all data breakpoints (including hardware breakpoints) won’t fire when the memory is written from kernel mode. With emulated breakpoints, the debugger uses instruction breakpoints to try and break when a variable is changed. However, this is a very challenging operation, and doesn’t always work. This also slows down the execution of your program, sometimes dramatically. Because of the problems with emulated breakpoints, this feature is likely going to be removed in a future product. One thing we would like to do is expose all the breakpoint register features of the processor. This would let you set a breakpoint on data read, write and execute instead of just write.

Now that you know the difference between a hardware and emulated breakpoint, here is how you set a hardware breakpoint:

  1. Determine what address you want to watch

  2. Open the new breakpoint dialog, and switch to the data tab

  3. Enter the address that you want to watch in the variable column

  4. The context is ignored. You can clear this if you want.

  5. Set the item count. If you are using an address, this should be the number of bytes (example: 4 for a DWORD)

One downside to data breakpoints are that they are only supported for native debugging. Maybe sometime they will work for managed. In some ways, this is a much harder feature for managed because the GC moves objects around in memory. I think data breakpoints are probably far less important for managed code since there is no heap corruption, and properties allow setting a breakpoint on the set function instead.

Comments (8)
  1. Data breakpoints are also supported in Windbg/Cdb (the platform debuggers) using the "ba" breakpoint type (break on access). You can break on reads, writes or execution of a specific piece of memory. See the debugger help for more info… Suffice to say this is a _very_ powerful tool when debugging hard to understand problems.

  2. I’ll throw my voice in (and I know a lot of other MVPs agree) on that data breakpoints would be extremely useful for managed code. That was one feature I looked for when I got Whibey.

  3. Pavel Lebedinsky says:

    > data breakpoints are probably far less important for managed code since there is no heap corruption…

    That’s of course assuming that there are no memory corrupting bugs in the runtime/OS (which is mostly – but not 100% – true) and that the user didn’t screw up his P/Invoke declarations (which happens quite often unfortunately).

    Luckily we still have cdb/windbg (as Josh noted), and they are far better tools for debugging this kind of problems anyway.

  4. On my web site, at“> , I have a helper class, CBreakpoint, that makes it easier to deal with hardware breakpoints. It gives you access, at *compile* time, to the Intel CPU’s hardware breakpoint registers.

    The way it works is, after your code sets breakpoint, if you happen to hit that breakpoint, Visual Studio will stop. Visual Studio might actually be a little puzzled at this point — it got an EXCEPTION_SINGLE_STEP from the OS, but isn’t sure why — but nonetheless it does the right thing, luckily.

    The nice things about this approach are:

    1. It avoids the issues with Visual Studio’s emulated breakpoints. In Visual Studio, if you try to set a hardware breakpoint on a local variable, you’re probably going to get an emulated one. With this class, it’s easy to get the real thing.

    2. Your breakpoint will automatically be removed when your instance of CBreakpoint goes out of scope. (If you want it to stick around, make your CBreakpoint instance a global, or a static local.)

    3. Makes it easier to specify exactly what you want your hardware breakpoint to be watching. In Visual Studio it can sometimes be a little hard to tell if you’re setting it at the right place. E.g. if you have "char* p", and you set a hardware breakpoint on "p", are you setting it on the address of p, or the address of the char to which it points? Hard to tell. Also, it can be hard to tell how many bytes you are watching (in the above example, are you watching four bytes or one byte?).

    See“> for source.

    P.S. I worked as a developer on the Visual Studio debugger in the early-to-mid 90s. Hello up there!

  5. Gregg Miskelly says:

    I wouldn’t say that cdb/ntsd is a better tool for debugging much of anything. If you need a data breakpoint on an address, there is nothing stopping you from using Visual Studio to native-only debug your managed or mixed code.

Comments are closed.

Skip to main content