1# Copyright 1998-2023 Free Software Foundation, Inc. 2# 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 3 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16# This file was written by Michael Snyder (msnyder@cygnus.com) 17 18load_lib "trace-support.exp" 19 20 21gdb_exit 22gdb_start 23 24standard_testfile actions.c 25if ![gdb_trace_common_supports_arch] { 26 unsupported "no trace-common.h support for arch" 27 return -1 28} 29if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \ 30 executable {debug nowarnings nopie}] != "" } { 31 untested "failed to compile" 32 return -1 33} 34gdb_load $binfile 35runto_main 36gdb_reinitialize_dir $srcdir/$subdir 37 38if {![gdb_target_supports_trace]} { 39 unsupported "current target does not support trace" 40 return 1 41 42} 43 44set cr "\[\r\n\]+" 45 46# If testing on a remote host, download the source file. 47# remote_download host $srcdir/$subdir/$srcfile 48 49# 50# test general reporting of trace experiment results 51# 52 53set testline1 0 54set testline2 0 55set testline3 0 56set testline4 0 57set testline5 0 58set testline6 0 59 60set arg1 1 61set arg2 2 62set arg3 3 63set arg4 4 64set arg5 5 65set arg6 6 66 67set gdb_recursion_test_baseline [gdb_find_recursion_test_baseline $srcfile] 68if { $gdb_recursion_test_baseline == -1 } { 69 fail "could not find gdb_recursion_test function" 70 return 71} 72 73set return_me 0 74 75gdb_test_multiple "list $gdb_recursion_test_baseline, +12" "" { 76 -re "\[\r\n\](\[0-9\]+)\[^\r\n\]+gdbtestline 1 " { 77 set testline1 $expect_out(1,string) 78 exp_continue 79 } 80 -re "\[\r\n\](\[0-9\]+)\[^\r\n\]+gdbtestline 2 " { 81 set testline2 $expect_out(1,string) 82 exp_continue 83 } 84 -re "\[\r\n\](\[0-9\]+)\[^\r\n\]+gdbtestline 3 " { 85 set testline3 $expect_out(1,string) 86 exp_continue 87 } 88 -re "\[\r\n\](\[0-9\]+)\[^\r\n\]+gdbtestline 4 " { 89 set testline4 $expect_out(1,string) 90 exp_continue 91 } 92 -re "\[\r\n\](\[0-9\]+)\[^\r\n\]+gdbtestline 5 " { 93 set testline5 $expect_out(1,string) 94 exp_continue 95 } 96 -re "\[\r\n\](\[0-9\]+)\[^\r\n\]+gdbtestline 6 " { 97 set testline6 $expect_out(1,string) 98 exp_continue 99 } 100 -re ".*$gdb_prompt $" { 101 if { ($testline1 == 0) || ($testline2 == 0) || ($testline3 == 0) || ($testline4 == 0) || ($testline5 == 0) || ($testline6 == 0) } { 102 untested "unexpected testline values" 103 set return_me 1 104all tests in this module will fail." 105 } 106 } 107 default { 108 untested "couldn't match pattern" 109 set return_me 1 110all tests in this module will fail." 111 } 112} 113 114if {$return_me == 1} { 115 return -1 116} 117 118# 119# Setup trace experiment. This will involve: 120# 1) a tracepoint where nothing is collected 121# 2) a tracepoint where only regs are collected 122# 3) a tracepoint where only args are collected 123# 4) a tracepoint where only locals are collected 124# 5) a tracepoint where some amount of stack memory is collected. 125# 6) a tracepoint where some expressions are collected. 126# 127 128gdb_delete_tracepoints 129set tdp1 [gdb_gettpnum $testline1] 130set tdp2 [gdb_gettpnum $testline2] 131set tdp3 [gdb_gettpnum $testline3] 132set tdp4 [gdb_gettpnum $testline4] 133set tdp5 [gdb_gettpnum $testline5] 134set tdp6 [gdb_gettpnum $testline6] 135 136if { $tdp1 <= 0 || $tdp2 <= 0 || $tdp3 <= 0 || \ 137 $tdp4 <= 0 || $tdp5 <= 0 || $tdp6 <= 0 } then { 138 fail "setting tracepoints failed" 139 return 140} 141 142gdb_trace_setactions "9.x: setup TP to collect regs" \ 143 "$tdp2" \ 144 "collect \$regs" "^$" 145 146 147gdb_trace_setactions "9.x: setup TP to collect args" \ 148 "$tdp3" \ 149 "collect \$args" "^$" 150 151gdb_trace_setactions "9.x: setup TP to collect locals" \ 152 "$tdp4" \ 153 "collect \$locs" "^$" 154 155gdb_trace_setactions "9.x: setup TP to collect stack memory" \ 156 "$tdp5" \ 157 "collect \$$fpreg, \*\(void \*\*\) \$$spreg @ 64" "^$" 158 159gdb_trace_setactions "9.x: setup TP to collect expressions" \ 160 "$tdp6" \ 161 "collect gdb_char_test, gdb_short_test, gdb_long_test" "^$" 162 163gdb_test "tstart" ".*" "" 164 165gdb_breakpoint "end" qualified 166gdb_test "continue" \ 167 "Continuing.*Breakpoint $decimal, end.*" \ 168 "run trace experiment" 169 170gdb_test "tstop" ".*" "" 171 172gdb_tfind_test "9.1: init: make sure not debugging any trace frame" \ 173 "none" "-1" 174 175# 9.3 help tdump 176 177gdb_test "help tdump" "Print everything collected at the current.*" \ 178 "9.3: help tdump" 179 180# Check the collected trace data from different sources, such as live 181# inferior and tfile. 182 183proc use_collected_data { data_source } { 184 with_test_prefix "${data_source}" { 185 global tdp1 tdp2 tdp3 tdp4 tdp5 tdp6 186 global testline1 testline2 testline3 testline4 testline5 testline6 187 global pcreg fpreg spreg 188 global srcfile srcdir subdir binfile 189 global arg1 arg3 190 global decimal hex gdb_prompt 191 # 192 # 9.1 test the tdump command 193 # 194 195 set timeout 60 196 197 gdb_tfind_test "9.1: find frame for TP $tdp1" "tracepoint $tdp1" \ 198 "\$tracepoint" "$tdp1" 199 200 # Nothing was collected at tdp1, so this tdump should be empty. 201 gdb_test "tdump" \ 202 "Data collected at tracepoint $tdp1, trace frame $decimal:" \ 203 "9.1: tdump, nothing collected" 204 205 gdb_tfind_test "9.1: find frame for TP $tdp2" "tracepoint $tdp2" \ 206 "\$tracepoint" "$tdp2" 207 208 # regs were collected at tdp2. 209 # How to match for the output of "info registers" on an unknown architecture? 210 # For now, assume that most architectures have a register called "pc". 211 212 gdb_test "tdump" \ 213 "\[\r\n\]$pcreg .*" \ 214 "9.1: tdump, regs collected" 215 216 gdb_tfind_test "9.1: find frame for TP $tdp3" "tracepoint $tdp3" \ 217 "\$tracepoint" "$tdp3" 218 219 # args were collected at tdp3 220 gdb_test "tdump" \ 221 "depth = 3.*q1 = 2.*q2 = 2.*q3 = 3.*q4 = 4.*q5 = 5.*q6 = 6" \ 222 "9.1: tdump, args collected" 223 224 gdb_tfind_test "9.1: find frame for TP $tdp4" "tracepoint $tdp4" \ 225 "\$tracepoint" "$tdp4" 226 227 # locals were collected at tdp4 228 gdb_test "tdump" \ 229 "q = 1" \ 230 "9.1: tdump, locals collected" 231 232 gdb_tfind_test "9.1: find frame for TP $tdp5" "tracepoint $tdp5" \ 233 "\$tracepoint" "$tdp5" 234 235 # stack was collected at tdp5, plus the frame pointer 236 gdb_test "tdump" \ 237 ".$fpreg = .*$spreg @ 64 = .*" \ 238 "9.1: tdump, memrange collected" 239 240 gdb_tfind_test "9.1: find frame for TP $tdp6" "tracepoint $tdp6" \ 241 "\$tracepoint" "$tdp6" 242 243 # globals were collected at tdp6 244 gdb_test "tdump" \ 245 "gdb_char_test = 1.*gdb_short_test = 2.*gdb_long_test = 3" \ 246 "9.1: tdump, global variables collected" 247 248 # 9.2 test tdump with arguments 249 # [no go, tdump doesn't have any arguments] 250 251 set linecount1 0 252 set linecount2 0 253 set linecount3 0 254 set linecount4 0 255 set linecount5 0 256 set linecount6 0 257 258 gdb_tfind_test "11.x, 12.1: find start frame" "start" "0" 259 260 # 261 # 11.x test built-in trace variables $trace_frame, $trace_line etc. 262 # 263 264 gdb_test "printf \"x %d x\\n\", \$trace_frame" "x 0 x" \ 265 "11.1: test \$trace_frame" 266 267 gdb_test "printf \"x %d x\\n\", \$tracepoint" "x $tdp1 x" \ 268 "11.2: test \$tracepoint" 269 270 gdb_test "printf \"x %d x\\n\", \$trace_line" "x $testline1 x" \ 271 "11.3: test \$trace_line" 272 273 gdb_test_multiple "print \$trace_file" "11.4: test \$trace_file" { 274 -re "\\$\[0-9\]+ = \"$srcfile\"\[\r\n\]+$gdb_prompt $" { 275 pass "11.4: test \$trace_file" 276 } 277 -re "\\$\[0-9\]+ = \"$srcdir/$subdir/$srcfile\"\[\r\n\]+$gdb_prompt $" { 278 pass "11.4: test \$trace_file" 279 } 280 } 281 282 #gdb_test "print \$trace_file" "\"$srcdir/$subdir/$srcfile\"" \ 283 # "11.4: test \$trace_file" 284 285 # 286 # 12.x test report generation using arbitrary GDB commands, loops etc. 287 # 288 289 gdb_test_multiple "while \$trace_frame != -1\n output \$trace_file\n printf \", line \%d \(tracepoint #\%d\)\\n\", \$trace_line, \$tracepoint\n tfind\n end" "12.1: trace report #1" { 290 -re "> end\r\n" { 291 exp_continue 292 } 293 -re "^Found trace frame \[0-9\]+, tracepoint \[0-9\]+\r\n" { 294 exp_continue 295 } 296 -re "^\[^\r\n\]* line $testline1 .tracepoint .$tdp1\\)\r\n" { 297 set linecount1 [expr $linecount1 + 1] 298 exp_continue 299 } 300 -re "^\[^\r\n\]* line $testline2 .tracepoint .$tdp2\\)\r\n" { 301 set linecount2 [expr $linecount2 + 1] 302 exp_continue 303 } 304 -re "^\[^\r\n\]* line $testline3 .tracepoint .$tdp3\\)\r\n" { 305 set linecount3 [expr $linecount3 + 1] 306 exp_continue 307 } 308 -re "^\[^\r\n\]* line $testline4 .tracepoint .$tdp4\\)\r\n" { 309 set linecount4 [expr $linecount4 + 1] 310 exp_continue 311 } 312 -re "^\[^\r\n\]* line $testline5 .tracepoint .$tdp5\\)\r\n" { 313 set linecount5 [expr $linecount5 + 1] 314 exp_continue 315 } 316 -re "^\[^\r\n\]* line $testline6 .tracepoint .$tdp6\\)\r\n" { 317 set linecount6 [expr $linecount6 + 1] 318 exp_continue 319 } 320 -re "^No trace frame found\r\n$gdb_prompt $" { 321 if { ($linecount1 < 4) || ($linecount2 < 4) || ($linecount3 < 4) || ($linecount4 < 4) || ($linecount5 < 4) || ($linecount6 < 4) } { 322 fail "12.1: trace report #1" 323 } else { 324 pass "12.1: trace report #1" 325 } 326 } 327 } 328 329 gdb_tfind_test "12.2: tfind end, selects no frame" "end" "-1" 330 gdb_tfind_test "12.2: find first TDP #2 frame" "tracepoint $tdp2" \ 331 "\$tracepoint" "$tdp2" 332 333 set linecount2 0 334 335 gdb_test_multiple "while \$trace_frame != -1\n printf \"tracepoint #\%d, FP 0x\%08x, SP 0x\%08x, PC 0x%08x\\n\", \$tracepoint, \$fp, \$sp, \$pc\n tfind tracepoint\n end" "12.2: trace report #2" { 336 -re "tracepoint #$tdp2, FP $hex, SP $hex, PC $hex" { 337 set linecount2 [expr $linecount2 + 1] 338 exp_continue 339 } 340 -re ".*$gdb_prompt $" { 341 if { ($linecount2 < 4) } { 342 fail "12.2: trace report #2" 343 } else { 344 pass "12.2: trace report #2" 345 } 346 } 347 } 348 349 gdb_tfind_test "12.3: tfind end, selects no frame" "end" "-1" 350 gdb_tfind_test "12.3: find first TDP #3 frame" "tracepoint $tdp3" \ 351 "\$tracepoint" "$tdp3" 352 353 set linecount3 0 354 355 gdb_test_multiple "while \$trace_frame != -1\n printf \"TDP #\%d, frame \%d: depth = \%d, q1 = \%d\\n\", \$tracepoint, \$trace_frame, depth, q1\n tfind tracepoint\n end" "12.3: trace report #3" { 356 -re "TDP #$tdp3, frame $decimal: depth = $decimal, q1 = $decimal" { 357 set linecount3 [expr $linecount3 + 1] 358 exp_continue 359 } 360 -re ".*$gdb_prompt $" { 361 if { ($linecount3 < 4) } { 362 fail "12.3: trace report #3" 363 } else { 364 pass "12.3: trace report #3" 365 } 366 } 367 } 368 369 gdb_tfind_test "12.4: tfind end, selects no frame" "end" "-1" 370 gdb_tfind_test "12.4: find first TDP #6 frame" "tracepoint $tdp6" \ 371 "\$tracepoint" "$tdp6" 372 373 set linecount6 0 374 375 gdb_test_multiple "while \$trace_frame != -1\n printf \"TDP #\%d, frame %d: char_test = \%d, long_test = \%d\\n\", \$tracepoint, \$trace_frame, gdb_char_test, gdb_long_test\n tfind tracepoint\n end" "12.4: trace report #4" { 376 -re "TDP #$tdp6, frame $decimal: char_test = $arg1, long_test = $arg3" { 377 set linecount6 [expr $linecount6 + 1] 378 exp_continue 379 } 380 -re ".*$gdb_prompt $" { 381 if { ($linecount6 < 4) } { 382 fail "12.4: trace report #4" 383 } else { 384 pass "12.4: trace report #4" 385 } 386 } 387 } 388 389 # There is always a thread of an inferior, either a live one or 390 # a faked one. 391 gdb_test "info threads" "\\* ${decimal} (process|Thread) \[0-9\.\]+\[ \t\].*" 392 gdb_test "info inferiors" "\\* 1 process ${decimal} \[ \t\]+\[^\r\n\]*\[ \t\]+${binfile}.*" 393 } 394} 395 396use_collected_data "live" 397 398# Finished! 399gdb_tfind_test "finished: make sure not debugging any trace frame" \ 400 "none" "-1" 401 402# Save trace frames to tfile. 403set tracefile [standard_output_file ${testfile}] 404gdb_test "tsave ${tracefile}.tf" \ 405 "Trace data saved to file '${tracefile}.tf'.*" \ 406 "save tfile trace file" 407 408# Save trace frames to ctf. 409gdb_test "tsave -ctf ${tracefile}.ctf" \ 410 "Trace data saved to directory '${tracefile}.ctf'.*" \ 411 "save ctf trace file" 412 413# Change target to tfile. 414set test "change to tfile target" 415gdb_test_multiple "target tfile ${tracefile}.tf" "$test" { 416 -re "A program is being debugged already. Kill it. .y or n. " { 417 send_gdb "y\n" 418 exp_continue 419 } 420 -re "$gdb_prompt $" { 421 pass "$test" 422 } 423} 424# Test the collected trace frames from tfile. 425use_collected_data "tfile" 426 427# Try to read ctf data if GDB supports. 428gdb_test_multiple "target ctf ${tracefile}.ctf" "" { 429 -re "Undefined target command: \"ctf ${tracefile}.ctf\"\. Try \"help target\"\.\r\n$gdb_prompt $" { 430 } 431 -re ".*\r\n$gdb_prompt $" { 432 use_collected_data "ctf" 433 } 434} 435