public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
From: Pedro Alves <palves@redhat.com>
To: Simon Marchi <simon.marchi@polymtl.ca>,
	Joel Brobecker <brobecker@adacore.com>
Cc: Tim Newsome <tim@sifive.com>, gdb <gdb@sourceware.org>
Subject: Re: gdb requires watchpoints to fire after the write
Date: Wed, 29 Aug 2018 17:29:00 -0000	[thread overview]
Message-ID: <08cf0b78-0fe6-1eda-383f-7d64466d6381@redhat.com> (raw)
In-Reply-To: <f7737cfa92e27db8254934d9efd6f49d@polymtl.ca>

On 08/29/2018 05:02 PM, Simon Marchi wrote:

> I'm just confused by this condition:
> 
>   if (stopped_by_watchpoint
>       && (target_have_steppable_watchpoint
>       || gdbarch_have_nonsteppable_watchpoint (gdbarch)))
> 
> I don't understand why we check for target_have_steppable_watchpoint OR gdbarch_have_nonsteppable_watchpoint, they seem to mean opposite things.

Yeah, it's confusing.

GDB's current "model" is that there are three "kinds" of watchpoints,
wrt to when they trigger and how you can move past them.

Those are: continuable, steppable, and non-steppable.

Continuable watchpoints are like x86's -- those trigger after
the memory access's side effects are fully committed to memory.
I.e., they trap with the PC pointing at the next instruction
already.  Continuing past such a watchpoint is doable
by just normally continuing, hence the name.

Both steppable and nonsteppable watchpoints trap before
the memory access.  I.e, the PC points at the instruction that
is accessing the memory.  So GDB needs to single-step once past
the current instruction in order to make the access effective
and check whether the instruction's side effects change the
watched expression.

Now, in order to step past that instruction, depending on 
architecture, you can have two situations:

- steppable watchpoints: you can single-step with the watchpoint still
  armed, and the watchpoint won't trigger again.

- non-steppable watchpoints: if you try to single-step with the watchpoint
  still armed, you'd trap the watchpoint again and the thread wouldn't
  make any progress.  So GDB needs to temporarily remove the watchpoint
  in order to step past it.

So that's why we have all of target_have_continuable_watchpoint,
target_have_steppable_watchpoint and gdbarch_have_nonsteppable_watchpoint.

Now, the main oddity is that from the definitions above,
we can tell that "continuable" is the same as "!steppable && !nonsteppable",
which makes target_continuable_watchpoint redundant.

Some targets do set "have_continuable_watchpoint" (like x86
in x86-nat.h), but it doesn't seem like target_have_continuable_watchpoint
is checked anywhere nowadays.

The target_have_steppable_watchpoint property is only set by ia64 GNU/Linux
nowadays:

  /* The IA-64 architecture can step over a watch point (without
     triggering it again) if the "dd" (data debug fault disable) bit
     in the processor status word is set.

     This PSR bit is set in
     ia64_linux_nat_target::stopped_by_watchpoint when the code there
     has determined that a hardware watchpoint has indeed been hit.
     The CPU will then be able to execute one instruction without
     triggering a watchpoint.  */
  bool have_steppable_watchpoint () { return 1; }

There's of course also the oddity that target_have_continuable_watchpoint
and target_have_steppable_watchpoint are target methods, while 
gdbarch_have_nonsteppable_watchpoint is a gdbarch method...

We could most probably streamline all of this and come up with a better
design with some thought.  See also the comment in mips-tdep.c:

  /* FIXME: cagney/2003-08-29: The macros target_have_steppable_watchpoint,
     HAVE_NONSTEPPABLE_WATCHPOINT, and target_have_continuable_watchpoint
     need to all be folded into the target vector.  Since they are
     being used as guards for target_stopped_by_watchpoint, why not have
     target_stopped_by_watchpoint return the type of watchpoint that the code
     is sitting on?  */
  set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);

Thanks,
Pedro Alves

  reply	other threads:[~2018-08-29 17:29 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-28 22:08 Tim Newsome
2018-08-29 15:33 ` Simon Marchi
2018-08-29 15:47   ` Joel Brobecker
2018-08-29 15:56     ` Pedro Alves
2018-08-29 16:02     ` Simon Marchi
2018-08-29 17:29       ` Pedro Alves [this message]
2018-08-29 20:13         ` Tim Newsome
2018-08-29 20:58         ` Tom Tromey
2018-08-30  8:05           ` Joel Brobecker
2018-08-31 15:37             ` Pedro Alves
2018-08-31 15:13           ` Pedro Alves

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=08cf0b78-0fe6-1eda-383f-7d64466d6381@redhat.com \
    --to=palves@redhat.com \
    --cc=brobecker@adacore.com \
    --cc=gdb@sourceware.org \
    --cc=simon.marchi@polymtl.ca \
    --cc=tim@sifive.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).