From: Michael Snyder <msnyder@vmware.com>
To: Tom Tromey <tromey@redhat.com>
Cc: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
Subject: Re: RFA: implement "watch -location"
Date: Wed, 11 Aug 2010 22:11:00 -0000 [thread overview]
Message-ID: <4C632000.2060606@vmware.com> (raw)
In-Reply-To: <m38w4c7qne.fsf@fleche.redhat.com>
Syntax quibble. "-location"? Don't we traditionally use command option
syntax such as "print /x"? Hate to be inconsistant...
Also, what about help? Did I miss it? I couldn't see it at a glance.
Tom Tromey wrote:
> This patch steals an idea from Apple's gdb fork, namely "watch -location".
> I wrote this from scratch but in the end it looks pretty similar to what
> they did.
>
> In my experience, I generally don't want gdb's scope-tracking logic for
> watchpoint expressions. Instead, I'm usually just interested in some
> bit of memory. I find myself typing this a lot:
>
> print &expr
> watch *$
>
> This patch adds an option to "watch" to let me do this more directly.
> (FWIW, this is a frequently-asked question on #gdb.)
>
> I did not add an MI option for this (something Apple did do).
> It didn't seem necessary to me.
>
> I also didn't add Python API for this. I'm on the fence about whether
> it is needed.
>
> A doc review is needed, and of course I'd appreciate other comments.
>
> Built and regtested on x86-64 (compile farm).
> New tests included.
>
> Tom
>
> b/gdb/ChangeLog:
> 2010-08-11 Tom Tromey <tromey@redhat.com>
>
> * breakpoint.c (watch_command_1): Add 'just_location' argument.
> (watch_command_wrapper): Update.
> (watch_maybe_just_location): New function.
> (watch_command): Update.
> (rwatch_command_wrapper): Update.
> (rwatch_command): Update.
> (awatch_command_wrapper): Update.
> (awatch_command): Update.
>
> b/gdb/doc/ChangeLog:
> 2010-08-11 Tom Tromey <tromey@redhat.com>
>
> * gdb.texinfo (Set Watchpoints): Document -location option.
>
> b/gdb/testsuite/ChangeLog:
> 2010-08-11 Tom Tromey <tromey@redhat.com>
>
> * gdb.base/watchpoint.exp (test_watchpoint_and_breakpoint): Delete
> watchpoint.
> (test_watch_location): New proc.
> (test_watchpoint_in_big_blob): Delete watchpoint.
> * gdb.base/watchpoint.c (func5): New function.
> (main): Call it.
>
> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
> index 4affe0a..11c88b6 100644
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -98,8 +98,6 @@ static void clear_command (char *, int);
>
> static void catch_command (char *, int);
>
> -static void watch_command (char *, int);
> -
> static int can_use_hardware_watchpoint (struct value *);
>
> static void break_command_1 (char *, int, int);
> @@ -173,12 +171,6 @@ static void hbreak_command (char *, int);
>
> static void thbreak_command (char *, int);
>
> -static void watch_command_1 (char *, int, int);
> -
> -static void rwatch_command (char *, int);
> -
> -static void awatch_command (char *, int);
> -
> static void do_enable_breakpoint (struct breakpoint *, enum bpdisp);
>
> static void stop_command (char *arg, int from_tty);
> @@ -7981,7 +7973,7 @@ watchpoint_exp_is_const (const struct expression *exp)
> hw_read: watch read,
> hw_access: watch access (read or write) */
> static void
> -watch_command_1 (char *arg, int accessflag, int from_tty)
> +watch_command_1 (char *arg, int accessflag, int from_tty, int just_location)
> {
> struct breakpoint *b, *scope_breakpoint = NULL;
> struct expression *exp;
> @@ -8086,7 +8078,15 @@ watch_command_1 (char *arg, int accessflag, int from_tty)
> exp_valid_block = innermost_block;
> mark = value_mark ();
> fetch_subexp_value (exp, &pc, &val, NULL, NULL);
> - if (val != NULL)
> +
> + if (just_location)
> + {
> + exp_valid_block = NULL;
> + val = value_addr (val);
> + release_value (val);
> + value_free_to_mark (mark);
> + }
> + else if (val != NULL)
> release_value (val);
>
> tok = arg;
> @@ -8188,7 +8188,24 @@ watch_command_1 (char *arg, int accessflag, int from_tty)
> b->exp = exp;
> b->exp_valid_block = exp_valid_block;
> b->cond_exp_valid_block = cond_exp_valid_block;
> - b->exp_string = savestring (exp_start, exp_end - exp_start);
> + if (just_location)
> + {
> + struct type *t = value_type (val);
> + CORE_ADDR addr = value_as_address (val);
> + char *name;
> +
> + t = check_typedef (TYPE_TARGET_TYPE (check_typedef (t)));
> + name = type_to_string (t);
> +
> + b->exp_string = xstrprintf ("* (%s *) %s", name,
> + core_addr_to_string (addr));
> + xfree (name);
> +
> + /* The above expression is in C. */
> + b->language = language_c;
> + }
> + else
> + b->exp_string = savestring (exp_start, exp_end - exp_start);
> b->val = val;
> b->val_valid = 1;
> if (cond_start)
> @@ -8215,7 +8232,8 @@ watch_command_1 (char *arg, int accessflag, int from_tty)
> scope_breakpoint->related_breakpoint = b;
> }
>
> - value_free_to_mark (mark);
> + if (!just_location)
> + value_free_to_mark (mark);
>
> /* Finally update the new watchpoint. This creates the locations
> that should be inserted. */
> @@ -8305,37 +8323,59 @@ can_use_hardware_watchpoint (struct value *v)
> void
> watch_command_wrapper (char *arg, int from_tty)
> {
> - watch_command (arg, from_tty);
> + watch_command_1 (arg, hw_write, from_tty, 0);
> +}
> +
> +/* A helper function that looks for the "-location" argument and then
> + calls watch_command_1. */
> +
> +static void
> +watch_maybe_just_location (char *arg, int accessflag, int from_tty)
> +{
> + int just_location = 0;
> + if (strncmp (arg, "-location", sizeof ("-location") - 1) == 0)
> + {
> + arg += sizeof ("-location") - 1;
> + /* Handle "watch -location" as if there were an expression, and
> + let watch_command_1 issue an error. */
> + if (*arg == '\0' || isspace (*arg))
> + {
> + ep_skip_leading_whitespace (&arg);
> + just_location = 1;
> + }
> + }
> +
> + watch_command_1 (arg, accessflag, from_tty, just_location);
> }
>
> static void
> watch_command (char *arg, int from_tty)
> {
> - watch_command_1 (arg, hw_write, from_tty);
> + watch_maybe_just_location (arg, hw_write, from_tty);
> }
>
> void
> rwatch_command_wrapper (char *arg, int from_tty)
> {
> - rwatch_command (arg, from_tty);
> + watch_command_1 (arg, hw_read, from_tty, 0);
> }
>
> static void
> rwatch_command (char *arg, int from_tty)
> {
> - watch_command_1 (arg, hw_read, from_tty);
> + watch_maybe_just_location (arg, hw_read, from_tty);
> }
>
> void
> awatch_command_wrapper (char *arg, int from_tty)
> {
> - awatch_command (arg, from_tty);
> + watch_command_1 (arg, hw_access, from_tty, 0);
> }
>
> static void
> awatch_command (char *arg, int from_tty)
> {
> - watch_command_1 (arg, hw_access, from_tty);
> + watch_maybe_just_location (arg, hw_access, from_tty);
> }
> \f
>
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 7abb9ed..5d2815f 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -3699,7 +3699,7 @@ watchpoints, which do not slow down the running of your program.
>
> @table @code
> @kindex watch
> -@item watch @var{expr} @r{[}thread @var{threadnum}@r{]}
> +@item watch @r{[}-location@r{]} @var{expr} @r{[}thread @var{threadnum}@r{]}
> Set a watchpoint for an expression. @value{GDBN} will break when the
> expression @var{expr} is written into by the program and its value
> changes. The simplest (and the most popular) use of this command is
> @@ -3716,13 +3716,20 @@ change the value of @var{expr}, @value{GDBN} will not break. Note
> that watchpoints restricted to a single thread in this way only work
> with Hardware Watchpoints.
>
> +Ordinarily a watchpoint respects the scope of variables in @var{expr}
> +(see below). The @code{-location} argument tells @value{GDBN} to
> +instead watch the memory referred to by @var{expr}. In this case,
> +@value{GDBN} will evaluate @var{expr}, take the address of the result,
> +and watch that memory. If the expression's result does not have an
> +address, then @value{GDBN} will print an error.
> +
> @kindex rwatch
> -@item rwatch @var{expr} @r{[}thread @var{threadnum}@r{]}
> +@item rwatch @r{[}-location@r{]} @var{expr} @r{[}thread @var{threadnum}@r{]}
> Set a watchpoint that will break when the value of @var{expr} is read
> by the program.
>
> @kindex awatch
> -@item awatch @var{expr} @r{[}thread @var{threadnum}@r{]}
> +@item awatch @r{[}-location@r{]} @var{expr} @r{[}thread @var{threadnum}@r{]}
> Set a watchpoint that will break when @var{expr} is either read from
> or written into by the program.
>
> diff --git a/gdb/testsuite/gdb.base/watchpoint.c b/gdb/testsuite/gdb.base/watchpoint.c
> index 8c212c1..9ef9253 100644
> --- a/gdb/testsuite/gdb.base/watchpoint.c
> +++ b/gdb/testsuite/gdb.base/watchpoint.c
> @@ -126,6 +126,17 @@ func4 ()
> global_ptr++;
> }
>
> +void
> +func5 ()
> +{
> + int val = 0, val2 = 23;
> + int *x = &val;
> +
> + /* func5 breakpoint here */
> + x = &val2;
> + val = 27;
> +}
> +
> int main ()
> {
> #ifdef usestubs
> @@ -203,5 +214,7 @@ int main ()
>
> func4 ();
>
> + func5 ();
> +
> return 0;
> }
> diff --git a/gdb/testsuite/gdb.base/watchpoint.exp b/gdb/testsuite/gdb.base/watchpoint.exp
> index 6029b5b..edc7ea0 100644
> --- a/gdb/testsuite/gdb.base/watchpoint.exp
> +++ b/gdb/testsuite/gdb.base/watchpoint.exp
> @@ -615,6 +615,8 @@ proc test_watchpoint_and_breakpoint {} {
> kfail "gdb/38" "next after watch x"
> }
> }
> +
> + gdb_test_no_output "delete \$bpnum" "delete watch x"
> }
> }
>
> @@ -628,6 +630,19 @@ proc test_constant_watchpoint {} {
> gdb_test_no_output "delete \$bpnum" "delete watchpoint `7 + count'"
> }
>
> +proc test_watch_location {} {
> + gdb_breakpoint [gdb_get_line_number "func5 breakpoint here"]
> + gdb_continue_to_breakpoint "func5 breakpoint here"
> +
> + gdb_test "watch -location *x" "atchpoint .*: .*" "watch -location .x"
> +
> + gdb_test "continue" \
> + "Continuing.*\[Ww\]atchpoint .*: .*New value = 27.*" \
> + "continue with watch -location"
> +
> + gdb_test_no_output "delete \$bpnum" "delete watch -location"
> +}
> +
> proc test_inaccessible_watchpoint {} {
> global gdb_prompt
>
> @@ -678,6 +693,8 @@ proc test_watchpoint_in_big_blob {} {
>
> gdb_test "watch buf" ".*atchpoint \[0-9\]+: buf"
> gdb_test "cont" "Continuing.*atchpoint \[0-9\]+: buf\r\n\r\nOld value = .*testte\".*" "watchpoint on buf hit"
> +
> + gdb_test_no_output "delete \$bpnum" "delete watch buf"
> }
>
> # Start with a fresh gdb.
> @@ -853,6 +870,8 @@ if [initialize] then {
> }
>
> test_constant_watchpoint
> +
> + test_watch_location
> }
>
> # Restore old timeout
next prev parent reply other threads:[~2010-08-11 22:11 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-08-11 22:04 Tom Tromey
2010-08-11 22:11 ` Michael Snyder [this message]
2010-08-11 22:15 ` Tom Tromey
2010-08-12 2:45 ` Hui Zhu
2010-08-12 7:55 ` André Pönitz
2010-08-12 3:07 ` Eli Zaretskii
2010-08-12 8:17 ` Phil Muldoon
2010-08-13 16:39 ` Jan Kratochvil
2010-08-13 18:27 ` Tom Tromey
2010-08-16 19:54 ` Jan Kratochvil
2010-08-13 18:25 ` Tom Tromey
2010-08-13 19:19 ` Eli Zaretskii
2010-08-13 21:21 ` Jan Kratochvil
2010-08-13 21:24 ` Tom Tromey
2010-08-16 18:13 ` Tom Tromey
2010-08-16 18:43 ` Jan Kratochvil
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=4C632000.2060606@vmware.com \
--to=msnyder@vmware.com \
--cc=gdb-patches@sourceware.org \
--cc=tromey@redhat.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