In Visual Studio while debugging a C++ project, some data breakpoints never hit.
So I wrote some code for testing:
#include <iostream>
#include <stdint.h>
void test(uint32_t* p)
{
*p = 0;
// set a data breakpoint on p
*((char*)p + 2) = 0x1;
std::cout << *p << std::endl;
}
uint32_t* alloc(size_t offset)
{
char* p = new char[sizeof(uint32_t) + offset];
p = p + offset;
return (uint32_t*)p;
}
int main()
{
test(alloc(0)); // test #1
test(alloc(2)); // test #2
}
As you see, in function test, the value of *p will be zeroed first, then it will be changed implicitly, I got a litte-endian CPU so it must be 65536.
If you set a data breakpoint on p (4 bytes) to detect the changing, you'll get two different results: hit or not. It depends on the address of that p pointed at.
In my testing code above, test #1 will hit and test #2 will not, the difference between #1 and #2 are the addresses returned by alloc(0) and alloc(2).
This article How to: Set a Data Breakpoint on MSDN does not talk about this.
Does data breakpoint not work on an unaligned address ?
The data breakpoints are set with the assistance of the CPU, using the debug registers on x86; about them, the Intel manual says (§17.2.5):
Breakpoint address registers (debug registers
DR0
throughDR3
) and theLENn
fields for each breakpoint define a range of sequential byte addresses for a data or I/O breakpoint. TheLENn
fields permit specification of a 1-, 2-, 4- , or 8-byte range, beginning at the linear address specified in the corresponding debug register (DRn). Two-byte ranges must be aligned on word boundaries; 4-byte ranges must be aligned on doubleword boundaries. I/O addresses are zero-extended (from 16 to 32 bits, for comparison with the breakpoint address in the selected debug register). These requirements are enforced by the processor; it uses LENn field bits to mask the lower address bits in the debug registers. Unaligned data or I/O breakpoint addresses do not yield valid results.
(emphasis added)
So, the limitation is in hardware.