From cbb55fa7a110e499dae0170060d762eb3f243768 Mon Sep 17 00:00:00 2001 From: Markus Metzger Date: Wed, 26 Aug 2015 11:33:07 +0200 Subject: btrace: non-stop Support non-stop mode in record btrace. gdb/ * record-btrace.c (record_btrace_open): Remove non_stop check. * NEWS: Announce that record btrace supports non-stop mode. testsuite/ * gdb.btrace/non-stop.c: New. * gdb.btrace/non-stop.exp: New. --- gdb/ChangeLog | 5 + gdb/NEWS | 2 + gdb/record-btrace.c | 3 - gdb/testsuite/ChangeLog | 5 + gdb/testsuite/gdb.btrace/non-stop.c | 45 +++++++ gdb/testsuite/gdb.btrace/non-stop.exp | 245 ++++++++++++++++++++++++++++++++++ 6 files changed, 302 insertions(+), 3 deletions(-) create mode 100644 gdb/testsuite/gdb.btrace/non-stop.c create mode 100644 gdb/testsuite/gdb.btrace/non-stop.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 82aade94937..214e6b05b32 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2015-09-18 Markus Metzger + + * record-btrace.c (record_btrace_open): Remove non_stop check. + * NEWS: Announce that record btrace supports non-stop mode. + 2015-09-18 Markus Metzger * infrun.c (handle_inferior_event_1): Switch to the eventing thread diff --git a/gdb/NEWS b/gdb/NEWS index f563b8c08b4..0d17ef4ff1d 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,6 +3,8 @@ *** Changes since GDB 7.10 +* Record btrace now supports non-stop mode. + * Support for tracepoints on aarch64-linux was added in GDBserver. * The 'record instruction-history' command now indicates speculative execution diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index 764b349cf4b..8eefae2829a 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -216,9 +216,6 @@ record_btrace_open (const char *args, int from_tty) if (!target_has_execution) error (_("The program is not being run.")); - if (non_stop) - error (_("Record btrace can't debug inferior in non-stop mode.")); - gdb_assert (record_btrace_thread_observer == NULL); disable_chain = make_cleanup (null_cleanup, NULL); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 8d0ffd4b1da..23a957b93c9 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-09-18 Markus Metzger + + * gdb.btrace/non-stop.c: New. + * gdb.btrace/non-stop.exp: New. + 2015-09-17 Pierre Langlois Yao Qi diff --git a/gdb/testsuite/gdb.btrace/non-stop.c b/gdb/testsuite/gdb.btrace/non-stop.c new file mode 100644 index 00000000000..2fc8dfbfe11 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/non-stop.c @@ -0,0 +1,45 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2015 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 . */ + +#include + +static int global; + +static void * +test (void *arg) +{ + unsigned int i; + + i = 0; /* bp.1 */ + for (; i < 10; ++i) global += i; /* loop */ + + return arg; /* bp.2 */ +} + +int +main (void) +{ + pthread_t th; + + pthread_create (&th, NULL, test, NULL); + + test (NULL); + + pthread_join (th, NULL); + + return 0; /* bp.3 */ +} diff --git a/gdb/testsuite/gdb.btrace/non-stop.exp b/gdb/testsuite/gdb.btrace/non-stop.exp new file mode 100644 index 00000000000..bc4ffb13100 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/non-stop.exp @@ -0,0 +1,245 @@ +# This testcase is part of GDB, the GNU debugger. +# +# Copyright 2015 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 . + +# check for btrace support +if { [skip_btrace_tests] } { return -1 } + + +# start inferior +standard_testfile +if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" "$binfile" executable {debug}] != "" } { + return -1 +} +clean_restart $testfile + +gdb_test_no_output "set non-stop on" + +if ![runto_main] { + return -1 +} + +# set up breakpoints +set bp_1 [gdb_get_line_number "bp.1" $srcfile] +set bp_2 [gdb_get_line_number "bp.2" $srcfile] +set bp_3 [gdb_get_line_number "bp.3" $srcfile] + +gdb_breakpoint $bp_1 +gdb_breakpoint $bp_2 + +# get the line number containing most of the trace +set loop [gdb_get_line_number "loop" $srcfile] + +# a stop on the above line as reported by GDB +set loop_line "$loop\[^\\\r\\\n\]*/\\\* loop \\\*/" + +# make sure $line matches the full expected output per thread. +# and let's hope that GDB never mixes the output from different threads. +proc gdb_cont_to { threads cmd line nthreads } { + global gdb_prompt + set full_cmd "thread apply $threads $cmd" + + # consume the prompt. since we started the command in the background, + # the prompt precedes any further output except some errors. + gdb_test_multiple "$full_cmd &" "$full_cmd: prompt" { + -re "$gdb_prompt " { + pass "$full_cmd: prompt" + } + } + + # now check for the expected line - one per thread. + for {set i 0} {$i < $nthreads} {incr i} { + set test "$full_cmd: thread $i" + + gdb_test_multiple "" $test { + -re "$line\[^\\\r\\\n\]*\r\n" { + pass $test + } + } + } +} + +proc gdb_cont_to_bp_line { line threads nthreads } { + gdb_cont_to $threads "continue" \ + [multi_line \ + "Breakpoint\[^\\\r\\\n\]*$line" \ + "\[^\\\r\\\n\]*" \ + ] \ + $nthreads +} + +proc gdb_cont_to_no_history { threads cmd nthreads } { + gdb_cont_to $threads $cmd \ + [multi_line \ + "No more reverse-execution history\." \ + "\[^\\\r\\\n\]*" \ + "\[^\\\r\\\n\]*" \ + ] \ + $nthreads +} + +# trace the code between the two breakpoints +gdb_cont_to_bp_line "$srcfile:$bp_1" all 2 +gdb_test_no_output "record btrace" +gdb_cont_to_bp_line "$srcfile:$bp_2" all 2 + +# we don't need those breakpoints any longer. +# they will only disturb our stepping. +delete_breakpoints + +# show the threads - this is useful for debugging fails +gdb_test "thread apply all info rec" ".*" +gdb_test "info threads" ".*" + +with_test_prefix "navigate" { + gdb_test "thread apply 1 record goto 2" "$loop_line" + gdb_test "thread apply 2 record goto 4" "$loop_line" + gdb_test "thread apply 1 info record" \ + ".*Replay in progress\. At instruction 2\." + gdb_test "thread apply 2 info record" \ + ".*Replay in progress\. At instruction 4\." + + gdb_test "thread apply all record goto 5" "$loop_line" + gdb_test "thread apply 1 info record" \ + ".*Replay in progress\. At instruction 5\." + gdb_test "thread apply 2 info record" \ + ".*Replay in progress\. At instruction 5\." +} + +with_test_prefix "step" { + with_test_prefix "thread 1" { + gdb_test "thread apply 1 stepi 2" "$loop_line" + gdb_test "thread apply 1 info record" \ + ".*Replay in progress\. At instruction 7\." + gdb_test "thread apply 2 info record" \ + ".*Replay in progress\. At instruction 5\." + } + + with_test_prefix "thread 2" { + gdb_test "thread apply 2 stepi 3" "$loop_line" + gdb_test "thread apply 1 info record" \ + ".*Replay in progress\. At instruction 7\." + gdb_test "thread apply 2 info record" \ + ".*Replay in progress\. At instruction 8\." + } + + with_test_prefix "all" { + gdb_cont_to all "stepi 4" "$loop_line" 2 + gdb_test "thread apply 1 info record" \ + ".*Replay in progress\. At instruction 11\." + gdb_test "thread apply 2 info record" \ + ".*Replay in progress\. At instruction 12\." + } +} + +with_test_prefix "reverse-step" { + with_test_prefix "thread 1" { + gdb_test "thread apply 1 reverse-stepi 2" "$loop_line" + gdb_test "thread apply 1 info record" \ + ".*Replay in progress\. At instruction 9\." + gdb_test "thread apply 2 info record" \ + ".*Replay in progress\. At instruction 12\." + } + + with_test_prefix "thread 2" { + gdb_test "thread apply 2 reverse-stepi 3" "$loop_line" + gdb_test "thread apply 1 info record" \ + ".*Replay in progress\. At instruction 9\." + gdb_test "thread apply 2 info record" \ + ".*Replay in progress\. At instruction 9\." + } + + with_test_prefix "all" { + gdb_cont_to all "reverse-stepi 4" "$loop_line" 2 + gdb_test "thread apply 1 info record" \ + ".*Replay in progress\. At instruction 5\." + gdb_test "thread apply 2 info record" \ + ".*Replay in progress\. At instruction 5\." + } +} + +with_test_prefix "continue" { + with_test_prefix "thread 1" { + gdb_cont_to_no_history 1 "continue" 1 + gdb_test "thread apply 1 info record" \ + ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*" + gdb_test "thread apply 2 info record" \ + ".*Replay in progress\. At instruction 5\." + + gdb_cont_to_no_history 1 "reverse-continue" 1 + gdb_test "thread apply 1 info record" \ + ".*Replay in progress\. At instruction 1\." + gdb_test "thread apply 2 info record" \ + ".*Replay in progress\. At instruction 5\." + } + + with_test_prefix "thread 2" { + gdb_cont_to_no_history 2 "continue" 1 + gdb_test "thread apply 1 info record" \ + ".*Replay in progress\. At instruction 1\." + gdb_test "thread apply 2 info record" \ + ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*" + + gdb_cont_to_no_history 2 "reverse-continue" 1 + gdb_test "thread apply 1 info record" \ + ".*Replay in progress\. At instruction 1\." + gdb_test "thread apply 2 info record" \ + ".*Replay in progress\. At instruction 1\." + } +} + +# a thread may only resume if no thread is still replaying +with_test_prefix "no progress" { + with_test_prefix "thread 1" { + gdb_test "thread apply 1 record goto end" ".*" + gdb_test "thread apply 2 record goto begin" ".*" + + gdb_cont_to_no_history 1 "continue" 1 + gdb_cont_to_no_history 1 "step" 1 + gdb_test "thread apply 1 info record" \ + ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*" + gdb_test "thread apply 2 info record" \ + ".*Replay in progress\. At instruction 1\." + } + + with_test_prefix "thread 2" { + gdb_test "thread apply 1 record goto begin" ".*" + gdb_test "thread apply 2 record goto end" ".*" + + gdb_cont_to_no_history 2 "continue" 1 + gdb_cont_to_no_history 2 "step" 1 + gdb_test "thread apply 1 info record" \ + ".*Replay in progress\. At instruction 1\." + gdb_test "thread apply 2 info record" \ + ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*" + } + + with_test_prefix "all" { + gdb_test "thread apply all record goto begin" ".*" + + gdb_cont_to_no_history all "continue" 2 + gdb_test "thread apply 1 info record" \ + ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*" + gdb_test "thread apply 2 info record" \ + ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*" + } +} + +# now that both threads stopped replaying we may resume recording +with_test_prefix "cont to end" { + gdb_breakpoint $bp_3 + gdb_cont_to_bp_line "$srcfile:$bp_3" all 1 +} -- cgit v1.2.1