From: Hui Zhu Date: Wed, 26 Jun 2013 02:32:53 +0000 (+0000) Subject: 2013-06-26 Yao Qi X-Git-Tag: gdb_7_6_1-2013-08-30-release~73 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=80a0a9cda9979c0703447c79e4826777410feb82;p=thirdparty%2Fbinutils-gdb.git 2013-06-26 Yao Qi Hui Zhu Pedro Alves 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-26 Yao Qi Hui Zhu Pedro Alves 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. --- diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 8998167cb38..2345f1f13fc 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -5295,6 +5295,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); } } @@ -8952,25 +8954,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); @@ -12928,6 +12921,14 @@ base_breakpoint_explains_signal (struct breakpoint *b) 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, @@ -12947,7 +12948,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. */ @@ -13544,6 +13546,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'). */ @@ -16048,6 +16088,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 7a2c629dfe1..b85ffbb727c 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -614,6 +614,10 @@ struct breakpoint_ops 'catch signal' interact properly with 'handle'; see bpstat_explains_signal. */ enum bpstat_signal_value (*explains_signal) (struct breakpoint *); + + /* 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/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 . */ + +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 . + +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 . */ + +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 . + +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 430168bab0e..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" @@ -121,7 +118,7 @@ if $target_can_dprintf { gdb_test "continue" "Breakpoint \[0-9\]+, foo .*" "2nd dprintf, agent" gdb_test_sequence "info breakpoints" "dprintf info 2" { - "\[\r\n\]Num Type Disp Enb Address What" + "\[\r\n\]Num Type Disp Enb Address +What" "\[\r\n\]2 breakpoint" "\[\r\n\]\tbreakpoint already hit 2 times" "\[\r\n\]3 dprintf" @@ -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 fd32698d5bf..24ff55b3281 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