Re: MI: reporting of multiple breakpoints

Eli Zaretskii
2006-02-18T11:34:33Z

> Date: Fri, 17 Feb 2006 16:37:50 -0500
> From: Paul Koning <pkoning@equallogic.com>
> Cc: eliz@gnu.org, ghost@cs.msu.su, gdb@sources.redhat.com
>
> The fact that some hardware may take the exception with PC pointing at
> 422 is not a valid reason to do otherwise. It's conceivable that it's
> unavoidable, if the hardware doesn't distinguish watchpoint from
> breakpoint exceptions.

No, it's not a hardware limitation, it's a ``limitation'' (I think
it's rather a feature) of _any_ reasonable implementation of
watchpoints, even software watchpoints: a watchpoint _always_ breaks
_after_ the instruction that writes to the watched location. It
cannot be any other way, because no debugger and no hardware can
possibly know whether an instruction will write to an arbitrary
location before running that instruction.

Therefore, when a watchpoint triggers, we will _always_ be after the
instruction already executed. The only hardware-specific aspect here
is whether the value of PC as reported by the target reflects that
fact, but that's a quirk of the hardware, not of the reality (I think
GDB fixes $pc to always behave as if the PC were after the instruction,
to reflect the reality). In reality, the faulting instruction is
always behind us, and we already are at the next instruction. In your
example, the next instruction is the one where the user put the
breakpoint, so we are _exactly_ at the place where it should break.

In other words, if line 421 writes to a watched location, then when
the watchpoint triggers, we are already after line 421, i.e. at line
422 (since, as I wrote earlier, there's no location between those two
lines where we could be).

> But, for example, on MIPS the two are
> distinct. So if I get a watch exception at PC 0x12340, I know that
> the instruction that caused the watch is 0x1233c, which is line 421,
> so that's what should be reported.

We know this on x86 as well, but this is a different issue. Knowing
that the instruction at 0x1233c wrote to a watched address says nothing
about _where_ is the PC of the program at the time we are told that.

> The instruction that caused the exception is NOT the break, first of
> all because it's at 0x12340 which is not the instruction address that
> caused the exception, and second because the exception type (watch
> exception) cannot be produced by a break instruction.

You seem to suggest that we back up one instruction after a watchpoint
triggers. Is that true? If so, I think it's not a good idea, since
(1) we'd have the watchpoint trigger again when we continue after
that, and (2) the user who knows (as they all should, IMHO) that a
watchpoint always triggers _after_ the code that wrote to the data
will be utterly confused by that.

> Maybe you find it confusing because you're trying to reason about this
> at the machine code level. Look at the source line level instead.

I hope I explained above that on both levels we should see the same
conceptual picture: a watchpoint always triggers _after_ the code was
executed. By contrast, a breakpoint always triggers _before_ the code
is executed.

> If you watch foo, you should be told about watchpoint stops at lines
> that touch foo. You should not be told about breaks in other lines.

Again, this is mixing two subtly different aspects: one is where in
the code was the instruction that wrote to the watched location, the
other is where (i.e. at what PC) is the debuggee when we report the
watchpoint.

> If you hit at watchpoint in line 421, and you continue, and you had
> defined a breakpoint in line 422, you would expect that breakpoint to
> fire because 422 != 421.

And if you continue, what instruction will be the first one to be
executed, in your scheme? It cannot be the first instruction of line
422, since the breakpoint should have triggered before that. And it
cannot be the last instruction of line 421, because that would trigger
the same watchpoint again. And there's no instruction in between
those two, so what can GDB do if we accept your views? The only thing
it can do is not move at all, i.e. not resume the inferior, but
instead generate a breakpoint event out of thin air. Is that what you
are saying we should do?