From 9d6e6e84f73ef7c5410c097a23d5952a99684f5b Mon Sep 17 00:00:00 2001 From: Hui Zhu <teawater@gmail.com> Date: Tue, 25 Jun 2013 11:37:48 +0000 Subject: [PATCH] 2013-06-25 Yao Qi <yao@codesourcery.com> Hui Zhu <hui@codesourcery.com> Pedro Alves <palves@redhat.com> PR breakpoints/15075 PR breakpoints/15434 * breakpoint.c (bpstat_stop_status): Call b->ops->after_condition_true. (update_dprintf_command_list): Don't append "continue" command to the command list of dprintf breakpoint. (base_breakpoint_after_condition_true): New function. (base_breakpoint_ops): Add base_breakpoint_after_condition_true. (dprintf_after_condition_true): New function. (initialize_breakpoint_ops): Set dprintf_after_condition_true. * breakpoint.h (breakpoint_ops): Add after_condition_true. 2013-06-25 Yao Qi <yao@codesourcery.com> Hui Zhu <hui@codesourcery.com> Pedro Alves <palves@redhat.com> PR breakpoints/15075 PR breakpoints/15434 * gdb.base/dprintf-next.c: New file. * gdb.base/dprintf-next.exp: New file. * gdb.base/dprintf-non-stop.c: New file. * gdb.base/dprintf-non-stop.exp: New file. * gdb.base/dprintf.exp: Don't check "continue" in the output of "info breakpoints". * gdb.mi/mi-breakpoint-changed.exp (test_insert_delete_modify): Don't check "continue" in script field. --- gdb/ChangeLog | 16 +++++ gdb/breakpoint.c | 69 +++++++++++++++---- gdb/breakpoint.h | 4 ++ gdb/testsuite/ChangeLog | 15 ++++ gdb/testsuite/gdb.base/dprintf-next.c | 26 +++++++ gdb/testsuite/gdb.base/dprintf-next.exp | 36 ++++++++++ gdb/testsuite/gdb.base/dprintf-non-stop.c | 30 ++++++++ gdb/testsuite/gdb.base/dprintf-non-stop.exp | 67 ++++++++++++++++++ gdb/testsuite/gdb.base/dprintf.exp | 4 -- .../gdb.mi/mi-breakpoint-changed.exp | 2 +- 10 files changed, 250 insertions(+), 19 deletions(-) create mode 100644 gdb/testsuite/gdb.base/dprintf-next.c create mode 100644 gdb/testsuite/gdb.base/dprintf-next.exp create mode 100644 gdb/testsuite/gdb.base/dprintf-non-stop.c create mode 100644 gdb/testsuite/gdb.base/dprintf-non-stop.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 465bdce529c..e5905c58882 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,19 @@ +2013-06-25 Yao Qi <yao@codesourcery.com> + Hui Zhu <hui@codesourcery.com> + Pedro Alves <palves@redhat.com> + + PR breakpoints/15075 + PR breakpoints/15434 + * breakpoint.c (bpstat_stop_status): Call + b->ops->after_condition_true. + (update_dprintf_command_list): Don't append "continue" command + to the command list of dprintf breakpoint. + (base_breakpoint_after_condition_true): New function. + (base_breakpoint_ops): Add base_breakpoint_after_condition_true. + (dprintf_after_condition_true): New function. + (initialize_breakpoint_ops): Set dprintf_after_condition_true. + * breakpoint.h (breakpoint_ops): Add after_condition_true. + 2013-06-24 Kevin Buettner <kevinb@redhat.com> * Makefile.in (ALL_TARGET_OBS): Add msp430-tdep.o. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 0ff5a4e6ec0..ccd05d9795f 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -5308,6 +5308,8 @@ bpstat_stop_status (struct address_space *aspace, if (command_line_is_silent (bs->commands ? bs->commands->commands : NULL)) bs->print = 0; + + b->ops->after_condition_true (bs); } } @@ -8943,25 +8945,16 @@ update_dprintf_command_list (struct breakpoint *b) _("Invalid dprintf style.")); gdb_assert (printf_line != NULL); - /* Manufacture a printf/continue sequence. */ + /* Manufacture a printf sequence. */ { - struct command_line *printf_cmd_line, *cont_cmd_line = NULL; - - if (strcmp (dprintf_style, dprintf_style_agent) != 0) - { - cont_cmd_line = xmalloc (sizeof (struct command_line)); - cont_cmd_line->control_type = simple_control; - cont_cmd_line->body_count = 0; - cont_cmd_line->body_list = NULL; - cont_cmd_line->next = NULL; - cont_cmd_line->line = xstrdup ("continue"); - } + struct command_line *printf_cmd_line + = xmalloc (sizeof (struct command_line)); printf_cmd_line = xmalloc (sizeof (struct command_line)); printf_cmd_line->control_type = simple_control; printf_cmd_line->body_count = 0; printf_cmd_line->body_list = NULL; - printf_cmd_line->next = cont_cmd_line; + printf_cmd_line->next = NULL; printf_cmd_line->line = printf_line; breakpoint_set_commands (b, printf_cmd_line); @@ -12761,6 +12754,14 @@ base_breakpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig) return BPSTAT_SIGNAL_HIDE; } +/* The default "after_condition_true" method. */ + +static void +base_breakpoint_after_condition_true (struct bpstats *bs) +{ + /* Nothing to do. */ +} + struct breakpoint_ops base_breakpoint_ops = { base_breakpoint_dtor, @@ -12780,7 +12781,8 @@ struct breakpoint_ops base_breakpoint_ops = base_breakpoint_create_sals_from_address, base_breakpoint_create_breakpoints_sal, base_breakpoint_decode_linespec, - base_breakpoint_explains_signal + base_breakpoint_explains_signal, + base_breakpoint_after_condition_true, }; /* Default breakpoint_ops methods. */ @@ -13374,6 +13376,44 @@ dprintf_print_recreate (struct breakpoint *tp, struct ui_file *fp) print_recreate_thread (tp, fp); } +/* Implement the "after_condition_true" breakpoint_ops method for + dprintf. + + dprintf's are implemented with regular commands in their command + list, but we run the commands here instead of before presenting the + stop to the user, as dprintf's don't actually cause a stop. This + also makes it so that the commands of multiple dprintfs at the same + address are all handled. */ + +static void +dprintf_after_condition_true (struct bpstats *bs) +{ + struct cleanup *old_chain; + struct bpstats tmp_bs = { NULL }; + struct bpstats *tmp_bs_p = &tmp_bs; + + /* dprintf's never cause a stop. This wasn't set in the + check_status hook instead because that would make the dprintf's + condition not be evaluated. */ + bs->stop = 0; + + /* Run the command list here. Take ownership of it instead of + copying. We never want these commands to run later in + bpstat_do_actions, if a breakpoint that causes a stop happens to + be set at same address as this dprintf, or even if running the + commands here throws. */ + tmp_bs.commands = bs->commands; + bs->commands = NULL; + old_chain = make_cleanup_decref_counted_command_line (&tmp_bs.commands); + + bpstat_do_actions_1 (&tmp_bs_p); + + /* 'tmp_bs.commands' will usually be NULL by now, but + bpstat_do_actions_1 may return early without processing the whole + list. */ + do_cleanups (old_chain); +} + /* The breakpoint_ops structure to be used on static tracepoints with markers (`-m'). */ @@ -15870,6 +15910,7 @@ initialize_breakpoint_ops (void) ops->print_it = bkpt_print_it; ops->print_mention = bkpt_print_mention; ops->print_recreate = dprintf_print_recreate; + ops->after_condition_true = dprintf_after_condition_true; } /* Chain containing all defined "enable breakpoint" subcommands. */ diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 43ab906757f..19961fea78d 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -615,6 +615,10 @@ struct breakpoint_ops bpstat_explains_signal. */ enum bpstat_signal_value (*explains_signal) (struct breakpoint *, enum gdb_signal); + + /* Called after evaluating the breakpoint's condition, + and only if it evaluated true. */ + void (*after_condition_true) (struct bpstats *bs); }; /* Helper for breakpoint_ops->print_recreate implementations. Prints diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 9abc780b3c6..04fadb2fe23 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,18 @@ +2013-06-25 Yao Qi <yao@codesourcery.com> + Hui Zhu <hui@codesourcery.com> + Pedro Alves <palves@redhat.com> + + PR breakpoints/15075 + PR breakpoints/15434 + * gdb.base/dprintf-next.c: New file. + * gdb.base/dprintf-next.exp: New file. + * gdb.base/dprintf-non-stop.c: New file. + * gdb.base/dprintf-non-stop.exp: New file. + * gdb.base/dprintf.exp: Don't check "continue" in the output + of "info breakpoints". + * gdb.mi/mi-breakpoint-changed.exp (test_insert_delete_modify): + Don't check "continue" in script field. + 2013-06-21 Tom Tromey <tromey@redhat.com> * gdb.trace/actions.exp (check_tracepoint): Don't use a full file diff --git a/gdb/testsuite/gdb.base/dprintf-next.c b/gdb/testsuite/gdb.base/dprintf-next.c new file mode 100644 index 00000000000..053f48c2420 --- /dev/null +++ b/gdb/testsuite/gdb.base/dprintf-next.c @@ -0,0 +1,26 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright (C) 2013 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +int +main (void) +{ + int x = 5; + + ++x; /* Next without dprintf. */ + ++x; /* Set dprintf here. */ + return x - 7; +} diff --git a/gdb/testsuite/gdb.base/dprintf-next.exp b/gdb/testsuite/gdb.base/dprintf-next.exp new file mode 100644 index 00000000000..42c0b9d0269 --- /dev/null +++ b/gdb/testsuite/gdb.base/dprintf-next.exp @@ -0,0 +1,36 @@ +# Copyright 2013 Free Software Foundation, Inc. +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +standard_testfile + +set executable $testfile +set expfile $testfile.exp + +set dp_location [gdb_get_line_number "Set dprintf here"] + +if [prepare_for_testing "failed to prepare for dprintf with next" \ + ${testfile} ${srcfile} {debug}] { + return -1 +} + +if ![runto_main] { + fail "Can't run to main" + return -1 +} + +gdb_test "dprintf $dp_location, \"%d\\n\", x" \ + "Dprintf .*" + +gdb_test "next" "\\+\\+x\;.*\/\* Next without dprintf.*" "next 1" +gdb_test "next" "\\+\\+x\;.*\/\* Set dprintf here.*" "next 2" diff --git a/gdb/testsuite/gdb.base/dprintf-non-stop.c b/gdb/testsuite/gdb.base/dprintf-non-stop.c new file mode 100644 index 00000000000..2d25d9eb959 --- /dev/null +++ b/gdb/testsuite/gdb.base/dprintf-non-stop.c @@ -0,0 +1,30 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright (C) 2013 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +void +foo () +{ +} + +int +main () +{ + sleep (1); + foo (); + sleep (3); + return 0; +} diff --git a/gdb/testsuite/gdb.base/dprintf-non-stop.exp b/gdb/testsuite/gdb.base/dprintf-non-stop.exp new file mode 100644 index 00000000000..707f913c50e --- /dev/null +++ b/gdb/testsuite/gdb.base/dprintf-non-stop.exp @@ -0,0 +1,67 @@ +# Copyright (C) 2013 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if [is_remote target] then { + # Testing with remote/non-stop is racy at the moment. + unsupported "Testing dprintf with remote/non-stop is not supported." + return 0 +} + +standard_testfile + +if [prepare_for_testing "failed to prepare for dprintf with non-stop" \ + ${testfile} ${srcfile} {debug}] { + return -1 +} + +gdb_test_no_output "set target-async on" +gdb_test_no_output "set non-stop on" + +if ![runto main] { + fail "Can't run to main" + return -1 +} + +gdb_test "dprintf foo,\"At foo entry\\n\"" "Dprintf .*" + +gdb_test "continue &" "Continuing\\." + +# Wait for the dprintf to trigger. +set test "dprintf triggered" +gdb_expect { + -re "At foo entry" { + pass "$test" + } + timeout { + fail "$test (timeout)" + } +} + +# Now test that we're still able to issue commands. GDB used to +# implement re-resuming from dprintfs with a synchronous "continue" in +# the dprintf's command list, which stole the prompt from the user. +set test "interrupt" +gdb_test_multiple $test $test { + -re "interrupt\r\n$gdb_prompt " { + pass $test + } +} + +set test "inferior stopped" +gdb_test_multiple "" $test { + -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" { + pass $test + } +} diff --git a/gdb/testsuite/gdb.base/dprintf.exp b/gdb/testsuite/gdb.base/dprintf.exp index 71f35545d70..d37d4ecda8e 100644 --- a/gdb/testsuite/gdb.base/dprintf.exp +++ b/gdb/testsuite/gdb.base/dprintf.exp @@ -50,10 +50,8 @@ gdb_test_sequence "info breakpoints" "dprintf info 1" { "\[\r\n\]2 breakpoint" "\[\r\n\]3 dprintf" "\[\r\n\] printf \"At foo entry\\\\n\"" - "\[\r\n\] continue" "\[\r\n\]4 dprintf" "\[\r\n\] printf \"arg=%d, g=%d\\\\n\", arg, g" - "\[\r\n\] continue" } gdb_test "break $bp_location1" \ @@ -111,7 +109,6 @@ gdb_test_multiple "set dprintf-style agent" $msg { } if $target_can_dprintf { - gdb_run_cmd gdb_test "" "Breakpoint" @@ -135,4 +132,3 @@ if $target_can_dprintf { gdb_test "set dprintf-style foobar" "Undefined item: \"foobar\"." \ "Set dprintf style to an unrecognized type" - diff --git a/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp b/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp index 04a56366c43..a4d35818493 100644 --- a/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp +++ b/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp @@ -96,7 +96,7 @@ proc test_insert_delete_modify { } { $test set test "dprintf marker, \"arg\" \"" mi_gdb_test $test \ - {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\",\"continue\"\}.*\}\r\n\^done} \ + {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\"\}.*\}\r\n\^done} \ $test # 2. when modifying condition