Re: gdb requires watchpoints to fire after the write

Pedro Alves <[email protected]>
Newsgroups gmane.comp.gdb.devel
Message-ID <[email protected]>
On 08/29/2018 04:47 PM, Joel Brobecker wrote:
>> I don't have experience with many different architectures, but as far as I
>> know, the expectation of the GDB is that the watchpoint is reported after
>> the write.  Otherwise it wouldn't need to save the value of the watched
>> expression.  That's also how software watchpoints seem to work.
>>
>> The easiest way to deal with this would be to match GDB's expectation.  But
>> if you really prefer the behavior of reporting the watchpoint before the
>> event, I suppose it's always possible to teach GDB about this, but it's a
>> less trivial task.  Especially that when you GDB evaluates whether the watch
>> expression has changed value, it would need to consider the not-yet-written
>> value in memory.
>>
>> I'm also curious to know if other architectures work in this way (report the
>> event before the write actually take place).
> 
> I seem to remember some architectures having different behaviors,
> and so we have a couple of entry points in GDB. For architecture-specific
> settings, we have gdbarch_have_nonsteppable_watchpoint. For target-specific
> settings, you would use target_have_steppable_watchpoint. (IIRC)

Yes, the key bit is this here in infrun.c:

  /* If necessary, step over this watchpoint.  We'll be back to display
     it in a moment.  */
  if (stopped_by_watchpoint
      && (target_have_steppable_watchpoint
	  || gdbarch_have_nonsteppable_watchpoint (gdbarch)))
    {
      /* At this point, we are stopped at an instruction which has
         attempted to write to a piece of memory under control of
         a watchpoint.  The instruction hasn't actually executed
         yet.  If we were to evaluate the watchpoint expression
         now, we would get the old value, and therefore no change
         would seem to have occurred.

         In order to make watchpoints work `right', we really need
         to complete the memory write, and then evaluate the
         watchpoint expression.  We do this by single-stepping the
	 target.

	 It may not be necessary to disable the watchpoint to step over
	 it.  For example, the PA can (with some kernel cooperation)
	 single step over a watchpoint without disabling the watchpoint.

	 It is far more common to need to disable a watchpoint to step
	 the inferior over it.  If we have non-steppable watchpoints,
	 we must disable the current watchpoint; it's simplest to
	 disable all watchpoints.

	 Any breakpoint at PC must also be stepped over -- if there's
	 one, it will have already triggered before the watchpoint
	 triggered, and we either already reported it to the user, or
	 it didn't cause a stop and we called keep_going.  In either
	 case, if there was a breakpoint at PC, we must be trying to
	 step past it.  */
      ecs->event_thread->stepping_over_watchpoint = 1;
      keep_going (ecs);
      return;
    }

Thanks,
Pedro Alves
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.