Data breakpoints

Data breakpoints are one of the most helpful debugger features when trying to hunt for memory overwrites/ninja variable modifications. In majority of cases it’s enough to set them up from debugger, however, there are situations when it’s not possible. Sometimes breaking into debugger changes program behavior (I had this problem just yesterday), sometimes we don’t want to catch every variable access, just some of them (as others are legal). In situations like that we need to set data breakpoints from code.

Imagine the following scenario. We have our Hero structure, with m_VitalityPoints member variable. The only places where it can be modified are ApplyDamage & Regenerate methods. However, for some reason, in unknown circumstances it’s being modified outside those functions. Setting data breakpoint from debugger doesn’t give us much, now it triggers every frame, on every Regenerate call. Wouldn’t it be cool to disable breakpoints for “legal” accesses? It’s possible to do via debug registers. (Disclaimer: I’m talking Windows/x86 here, for other platforms consult their SDK, in many cases it’s a matter of calling one function).

We can trace up to 4 different memory locations at any given moment. Exact behavior is controlled via DR7 register, addresses are stored in DR0-DR3. If you’re interested in a more comprehensive description/implementation see CodeProject article by Michael Chourdakis. I used it as an entry point for my version, however there is a little bit too much thread manipulation for my taste. My implementations boils down to one function (which pretty much maps 1:1 to a certain other gamedev platform): SetDataBreakpoint (+ template helper).

In case of our initial example, here’s how we disable & enable data breakpoint for m_VitalityPoints:

1 void Hero::Regenerate()
2 {
3     SetDataBreakpoint(m_VitalityPoints, DataBreakpoint::NONE); // Disable
4     m_VitalityPoints += m_RegenerationPerTick;
5     SetDataBreakpoint(m_VitalityPoints, DataBreakpoint::WRITE); // Enable again
6 }
7 //... similar code for ApplyDamage
Now, it’s safe for “our” functions to modify m_VitalityPoints, but as soon as it’s modified (or even touched, if we use DataBreakpoint::READWRITE access trigger) by other code - it breaks into debugger.

Code can be downloaded here: header & MSVC/Win32 implementation. Will not compile as-is, but adapting it to your codebase should be a matter of minutes.

Old comments

Review-Medicus Dual Hinge Driver | Life By Design Over 50 2010-03-17 07:36:08

[…] Data breakpoints | .mischief.mayhem.soap. […]

Gregory 2010-03-01 10:44:42

Nifty, does someone know the equivalent calls for Linux and Mac?

ent 2010-02-27 16:05:30

Wow, didn’t know about this. Thanks for the info!

More Reading
Older// Adding layers
comments powered by Disqus