From 06a64a0b786b2a3b81e8caced730c43939a78684 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Mon, 16 Aug 2010 19:19:22 +0000 Subject: [PATCH] gdb * value.c (release_value): Clear 'next' pointer. * 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. (check_for_argument): New function. (_initialize_breakpoint): Update help text. gdb/testsuite * gdb.base/help.exp: Update. * 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. gdb/doc * gdb.texinfo (Set Watchpoints): Document -location option. --- gdb/ChangeLog | 14 ++++ gdb/breakpoint.c | 105 ++++++++++++++++++++------ gdb/doc/ChangeLog | 4 + gdb/doc/gdb.texinfo | 15 +++- gdb/testsuite/ChangeLog | 10 +++ gdb/testsuite/gdb.base/help.exp | 2 +- gdb/testsuite/gdb.base/watchpoint.c | 13 ++++ gdb/testsuite/gdb.base/watchpoint.exp | 19 +++++ gdb/value.c | 2 + 9 files changed, 159 insertions(+), 25 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8e283faeeb4..78296e8b4a2 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,17 @@ +2010-08-16 Tom Tromey + + * value.c (release_value): Clear 'next' pointer. + * 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. + (check_for_argument): New function. + (_initialize_breakpoint): Update help text. + 2010-08-14 Ulrich Weigand * arm-tdep.c (arm_push_dummy_call): Handle pointers to diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index c542fb178b0..212c2033bb0 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); @@ -7995,7 +7987,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; @@ -8100,7 +8092,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; @@ -8202,7 +8202,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) @@ -8229,7 +8246,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. */ @@ -8319,37 +8337,73 @@ 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 an argument at the start of a + string. The argument must also either be at the end of the string, + or be followed by whitespace. Returns 1 if it finds the argument, + 0 otherwise. If the argument is found, it updates *STR. */ + +static int +check_for_argument (char **str, char *arg, int arg_len) +{ + if (strncmp (*str, arg, arg_len) == 0 + && ((*str)[arg_len] == '\0' || isspace ((*str)[arg_len]))) + { + *str += arg_len; + return 1; + } + return 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 (arg + && (check_for_argument (&arg, "-location", sizeof ("-location") - 1) + || check_for_argument (&arg, "-l", sizeof ("-l") - 1))) + { + 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); } @@ -11847,20 +11901,29 @@ With an argument, catch only exceptions with the given name."), c = add_com ("watch", class_breakpoint, watch_command, _("\ Set a watchpoint for an expression.\n\ +Usage: watch [-l|-location] EXPRESSION\n\ A watchpoint stops execution of your program whenever the value of\n\ -an expression changes.")); +an expression changes.\n\ +If -l or -location is given, this evaluates EXPRESSION and watches\n\ +the memory to which it refers.")); set_cmd_completer (c, expression_completer); c = add_com ("rwatch", class_breakpoint, rwatch_command, _("\ Set a read watchpoint for an expression.\n\ +Usage: rwatch [-l|-location] EXPRESSION\n\ A watchpoint stops execution of your program whenever the value of\n\ -an expression is read.")); +an expression is read.\n\ +If -l or -location is given, this evaluates EXPRESSION and watches\n\ +the memory to which it refers.")); set_cmd_completer (c, expression_completer); c = add_com ("awatch", class_breakpoint, awatch_command, _("\ Set a watchpoint for an expression.\n\ +Usage: awatch [-l|-location] EXPRESSION\n\ A watchpoint stops execution of your program whenever the value of\n\ -an expression is either read or written.")); +an expression is either read or written.\n\ +If -l or -location is given, this evaluates EXPRESSION and watches\n\ +the memory to which it refers.")); set_cmd_completer (c, expression_completer); add_info ("watchpoints", watchpoints_info, _("\ diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index b8f060baf91..36099c25a01 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2010-08-16 Tom Tromey + + * gdb.texinfo (Set Watchpoints): Document -location option. + 2010-08-13 Doug Evans * gdb.texinfo (.debug_gdb_scripts section): Fix typo. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index cd3ac0f0e98..fa50761ffab 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -3711,7 +3711,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{[}-l@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 @@ -3728,13 +3728,22 @@ 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 the memory at that address. The type of the result is used +to determine the size of the watched 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{[}-l@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{[}-l@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/ChangeLog b/gdb/testsuite/ChangeLog index 14e6d327a5b..b9424ca8d17 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2010-08-16 Tom Tromey + + * gdb.base/help.exp: Update. + * 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. + 2010-08-16 Doug Evans * gdb.python/python.exp: Fix syntax in "post event insertion" test. diff --git a/gdb/testsuite/gdb.base/help.exp b/gdb/testsuite/gdb.base/help.exp index d270be1ed8e..6e70b9d7778 100644 --- a/gdb/testsuite/gdb.base/help.exp +++ b/gdb/testsuite/gdb.base/help.exp @@ -669,7 +669,7 @@ test_class_help "user-defined" { "Use the \"define\" command to define a command\.\[\r\n\]+" } # test help watch -gdb_test "help watch" "Set a watchpoint for an expression\.\[\r\n\]+A watchpoint stops execution of your program whenever the value of\[\r\n\]+an expression changes\." "help watch" +gdb_test "help watch" "Set a watchpoint for an expression\.\[\r\n\]+Usage: watch .-l.-location. EXPRESSION\[\r\n\]+A watchpoint stops execution of your program whenever the value of\[\r\n\]+an expression changes\.\[\r\n\]+If -l or -location is given, this evaluates EXPRESSION and watches\[\r\n\]+the memory to which it refers\." "help watch" # test help whatis gdb_test "help whatis" "Print data type of expression EXP\." "help whatis" # test help where diff --git a/gdb/testsuite/gdb.base/watchpoint.c b/gdb/testsuite/gdb.base/watchpoint.c index 8c212c17f30..9ef92539288 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 6029b5ba3b2..edc7ea012df 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 diff --git a/gdb/value.c b/gdb/value.c index b65ba32eb39..d1c37e37c2d 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -747,6 +747,7 @@ release_value (struct value *val) if (all_values == val) { all_values = val->next; + val->next = NULL; return; } @@ -755,6 +756,7 @@ release_value (struct value *val) if (v->next == val) { v->next = val->next; + val->next = NULL; break; } } -- 2.30.2