On Thu, 15 Dec 2016, Andrew Cagney wrote:
> Might a better strategy be to first get the registers exposed, and then, if
> there's still time start to look at an abstract interface?
That's one way of looking at it.
Another way is to consider that watchpoints can be implemented through
careful use of the MMU.
> and now lets consider this simple example, try to watch c.a in:
>
> struct { char c; char a[3]; int32_t i; int64_t j; } c;
>
> Under the proposed model (it looks a lot like gdb's remote protocol's Z
> packet) it's assumed this will allocate one watch-point:
>
> address=&c.a, size=3
So when you register the watchpoint, the kernel adds the address and size
to an internal list and changes the protection of that page. If it's a
write watchpoint, the page is made read-only. If it's a read watchpoint,
it's made invalid.
The userland program runs happily until it tries to access something on
the page with the watchpoint. Then it takes a page fault.
The fault handler checks the fault address against its watchpoint list,
and if there's a match, send a ptrace event and you're done.
If it doesn't match the address, the kernel can either map the address in
and single step, set a breakpoint on the next instruction, or emulate the
instruction, and then protect the page again to wait for the next fault.
It has a bit more overhead than using debug registers, but it scales a lot
better.