1# This testcase is part of GDB, the GNU debugger. 2# 3# Copyright 2015-2020 Free Software Foundation, Inc. 4# 5# This program is free software; you can redistribute it and/or modify 6# it under the terms of the GNU General Public License as published by 7# the Free Software Foundation; either version 3 of the License, or 8# (at your option) any later version. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18if { [skip_btrace_tests] } { 19 unsupported "target does not support record-btrace" 20 return -1 21} 22 23standard_testfile 24if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" "$binfile" executable {debug}] != "" } { 25 untested "failed to prepare" 26 return -1 27} 28 29save_vars { GDBFLAGS } { 30 append GDBFLAGS " -ex \"set non-stop on\"" 31 clean_restart $testfile 32} 33 34if ![runto_main] { 35 untested "failed to run to main" 36 return -1 37} 38 39# set up breakpoints 40set bp_1 [gdb_get_line_number "bp.1" $srcfile] 41set bp_2 [gdb_get_line_number "bp.2" $srcfile] 42set bp_3 [gdb_get_line_number "bp.3" $srcfile] 43 44gdb_breakpoint $bp_1 45gdb_breakpoint $bp_2 46 47# get the line number containing most of the trace 48set loop [gdb_get_line_number "loop" $srcfile] 49 50# a stop on the above line as reported by GDB 51set loop_line "$loop\[^\\\r\\\n\]*/\\\* loop \\\*/" 52 53# make sure $line matches the full expected output per thread. 54# and let's hope that GDB never mixes the output from different threads. 55proc gdb_cont_to { threads cmd line nthreads } { 56 global gdb_prompt 57 set full_cmd "thread apply $threads $cmd" 58 59 # consume the prompt. since we started the command in the background, 60 # the prompt precedes any further output except some errors. 61 gdb_test_multiple "$full_cmd &" "$full_cmd: prompt" { 62 -re "$gdb_prompt " { 63 pass "$full_cmd: prompt" 64 } 65 } 66 67 # now check for the expected line - one per thread. 68 for {set i 0} {$i < $nthreads} {incr i} { 69 set test "$full_cmd: thread $i" 70 71 gdb_test_multiple "" $test { 72 -re "$line\[^\\\r\\\n\]*\r\n" { 73 pass $test 74 } 75 } 76 } 77} 78 79proc gdb_cont_to_bp_line { line threads nthreads } { 80 gdb_cont_to $threads "continue" \ 81 [multi_line \ 82 "Breakpoint\[^\\\r\\\n\]*$line" \ 83 "\[^\\\r\\\n\]*" \ 84 ] \ 85 $nthreads 86} 87 88proc gdb_cont_to_no_history { threads cmd nthreads } { 89 gdb_cont_to $threads $cmd \ 90 [multi_line \ 91 "No more reverse-execution history\." \ 92 "\[^\\\r\\\n\]*" \ 93 "\[^\\\r\\\n\]*" \ 94 ] \ 95 $nthreads 96} 97 98# trace the code between the two breakpoints 99gdb_cont_to_bp_line "$srcfile:$bp_1" all 2 100gdb_test_no_output "record btrace" 101gdb_cont_to_bp_line "$srcfile:$bp_2" all 2 102 103# we don't need those breakpoints any longer. 104# they will only disturb our stepping. 105delete_breakpoints 106 107# show the threads - this is useful for debugging fails 108gdb_test "thread apply all info rec" ".*" 109gdb_test "info threads" ".*" 110 111with_test_prefix "navigate" { 112 gdb_test "thread apply 1 record goto 2" "$loop_line" 113 gdb_test "thread apply 2 record goto 4" "$loop_line" 114 gdb_test "thread apply 1 info record" \ 115 ".*Replay in progress\. At instruction 2\." 116 gdb_test "thread apply 2 info record" \ 117 ".*Replay in progress\. At instruction 4\." 118 119 gdb_test "thread apply all record goto 5" "$loop_line" 120 gdb_test "thread apply 1 info record" \ 121 ".*Replay in progress\. At instruction 5\." 122 gdb_test "thread apply 2 info record" \ 123 ".*Replay in progress\. At instruction 5\." 124} 125 126with_test_prefix "step" { 127 with_test_prefix "thread 1" { 128 gdb_test "thread apply 1 stepi 2" "$loop_line" 129 gdb_test "thread apply 1 info record" \ 130 ".*Replay in progress\. At instruction 7\." 131 gdb_test "thread apply 2 info record" \ 132 ".*Replay in progress\. At instruction 5\." 133 } 134 135 with_test_prefix "thread 2" { 136 gdb_test "thread apply 2 stepi 3" "$loop_line" 137 gdb_test "thread apply 1 info record" \ 138 ".*Replay in progress\. At instruction 7\." 139 gdb_test "thread apply 2 info record" \ 140 ".*Replay in progress\. At instruction 8\." 141 } 142 143 with_test_prefix "all" { 144 gdb_cont_to all "stepi 4" "$loop_line" 2 145 gdb_test "thread apply 1 info record" \ 146 ".*Replay in progress\. At instruction 11\." 147 gdb_test "thread apply 2 info record" \ 148 ".*Replay in progress\. At instruction 12\." 149 } 150} 151 152with_test_prefix "reverse-step" { 153 with_test_prefix "thread 1" { 154 gdb_test "thread apply 1 reverse-stepi 2" "$loop_line" 155 gdb_test "thread apply 1 info record" \ 156 ".*Replay in progress\. At instruction 9\." 157 gdb_test "thread apply 2 info record" \ 158 ".*Replay in progress\. At instruction 12\." 159 } 160 161 with_test_prefix "thread 2" { 162 gdb_test "thread apply 2 reverse-stepi 3" "$loop_line" 163 gdb_test "thread apply 1 info record" \ 164 ".*Replay in progress\. At instruction 9\." 165 gdb_test "thread apply 2 info record" \ 166 ".*Replay in progress\. At instruction 9\." 167 } 168 169 with_test_prefix "all" { 170 gdb_cont_to all "reverse-stepi 4" "$loop_line" 2 171 gdb_test "thread apply 1 info record" \ 172 ".*Replay in progress\. At instruction 5\." 173 gdb_test "thread apply 2 info record" \ 174 ".*Replay in progress\. At instruction 5\." 175 } 176} 177 178with_test_prefix "continue" { 179 with_test_prefix "thread 1" { 180 gdb_cont_to_no_history 1 "continue" 1 181 gdb_test "thread apply 1 info record" \ 182 ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*" 183 gdb_test "thread apply 2 info record" \ 184 ".*Replay in progress\. At instruction 5\." 185 186 gdb_cont_to_no_history 1 "reverse-continue" 1 187 gdb_test "thread apply 1 info record" \ 188 ".*Replay in progress\. At instruction 1\." 189 gdb_test "thread apply 2 info record" \ 190 ".*Replay in progress\. At instruction 5\." 191 } 192 193 with_test_prefix "thread 2" { 194 gdb_cont_to_no_history 2 "continue" 1 195 gdb_test "thread apply 1 info record" \ 196 ".*Replay in progress\. At instruction 1\." 197 gdb_test "thread apply 2 info record" \ 198 ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*" 199 200 gdb_cont_to_no_history 2 "reverse-continue" 1 201 gdb_test "thread apply 1 info record" \ 202 ".*Replay in progress\. At instruction 1\." 203 gdb_test "thread apply 2 info record" \ 204 ".*Replay in progress\. At instruction 1\." 205 } 206} 207 208# a thread may only resume if no thread is still replaying 209with_test_prefix "no progress" { 210 with_test_prefix "thread 1" { 211 gdb_test "thread apply 1 record goto end" ".*" 212 gdb_test "thread apply 2 record goto begin" ".*" 213 214 gdb_cont_to_no_history 1 "continue" 1 215 gdb_cont_to_no_history 1 "step" 1 216 gdb_test "thread apply 1 info record" \ 217 ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*" 218 gdb_test "thread apply 2 info record" \ 219 ".*Replay in progress\. At instruction 1\." 220 } 221 222 with_test_prefix "thread 2" { 223 gdb_test "thread apply 1 record goto begin" ".*" 224 gdb_test "thread apply 2 record goto end" ".*" 225 226 gdb_cont_to_no_history 2 "continue" 1 227 gdb_cont_to_no_history 2 "step" 1 228 gdb_test "thread apply 1 info record" \ 229 ".*Replay in progress\. At instruction 1\." 230 gdb_test "thread apply 2 info record" \ 231 ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*" 232 } 233 234 with_test_prefix "all" { 235 gdb_test "thread apply all record goto begin" ".*" 236 237 gdb_cont_to_no_history all "continue" 2 238 gdb_test "thread apply 1 info record" \ 239 ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*" 240 gdb_test "thread apply 2 info record" \ 241 ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*" 242 } 243} 244 245# now that both threads stopped replaying we may resume recording 246with_test_prefix "cont to end" { 247 gdb_breakpoint $bp_3 248 gdb_cont_to_bp_line "$srcfile:$bp_3" all 1 249} 250