1# Copyright (C) 1998-2020 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 17# 18# Support procedures for trace testing 19# 20 21 22# 23# Program counter / stack pointer / frame pointer for supported targets. 24# Used in many tests, kept here to avoid duplication. 25# 26 27if [is_amd64_regs_target] { 28 set fpreg "rbp" 29 set spreg "rsp" 30 set pcreg "rip" 31} elseif [is_x86_like_target] { 32 set fpreg "ebp" 33 set spreg "esp" 34 set pcreg "eip" 35} elseif [is_aarch64_target] { 36 set fpreg "x29" 37 set spreg "sp" 38 set pcreg "pc" 39} elseif [istarget "powerpc*-*-*"] { 40 set fpreg "r31" 41 set spreg "r1" 42 set pcreg "pc" 43} elseif { [istarget "s390*-*-*"] } { 44 set fpreg "r11" 45 set spreg "r15" 46 set pcreg "pc" 47} else { 48 set fpreg "fp" 49 set spreg "sp" 50 set pcreg "pc" 51} 52 53# 54# Procedure: gdb_trace_common_supports_arch 55# Returns true if gdb.trace/trace-common.h knows about this target. 56# Allows skipping tests that depend on being able to include this file. 57# Please keep this in sync with the supported targets in the header. 58# 59 60proc gdb_trace_common_supports_arch { } { 61 if { [istarget "x86_64*-*-*"] 62 || [istarget "i386*-*-*"] 63 || [istarget "aarch64*-*-*"] 64 || [istarget "powerpc*-*-*"] 65 || [istarget "s390*-*-*"] } { 66 return 1 67 } else { 68 return 0 69 } 70} 71 72# 73# Procedure: gdb_target_supports_trace 74# Returns true if GDB is connected to a target that supports tracing. 75# Allows tests to abort early if not running on a trace-aware target. 76# 77 78proc gdb_target_supports_trace { } { 79 global gdb_prompt 80 81 send_gdb "tstatus\n" 82 gdb_expect { 83 -re "\[Tt\]race can only be run on.*$gdb_prompt $" { 84 return 0 85 } 86 -re "\[Tt\]race can not be run on.*$gdb_prompt $" { 87 return 0 88 } 89 -re "\[Tt\]arget does not support.*$gdb_prompt $" { 90 return 0 91 } 92 -re ".*\[Ee\]rror.*$gdb_prompt $" { 93 return 0 94 } 95 -re ".*\[Ww\]arning.*$gdb_prompt $" { 96 return 0 97 } 98 -re ".*$gdb_prompt $" { 99 return 1 100 } 101 timeout { 102 return 0 103 } 104 } 105} 106 107 108# 109# Procedure: gdb_delete_tracepoints 110# Many of the tests depend on setting tracepoints at various places and 111# running until that tracepoint is reached. At times, we want to start 112# with a clean slate with respect to tracepoints, so this utility proc 113# lets us do this without duplicating this code everywhere. 114# 115 116proc gdb_delete_tracepoints {} { 117 global gdb_prompt 118 119 send_gdb "delete tracepoints\n" 120 gdb_expect 30 { 121 -re "Delete all tracepoints.*y or n.*$" { 122 send_gdb "y\n" 123 exp_continue 124 } 125 -re ".*$gdb_prompt $" { # This happens if there were no tracepoints } 126 timeout { 127 perror "Delete all tracepoints in delete_tracepoints (timeout)" 128 return 129 } 130 } 131 send_gdb "info tracepoints\n" 132 gdb_expect 30 { 133 -re "No tracepoints.*$gdb_prompt $" {} 134 -re "$gdb_prompt $" { perror "tracepoints not deleted" ; return } 135 timeout { perror "info tracepoints (timeout)" ; return } 136 } 137} 138 139# Define actions for a tracepoint. 140# Arguments: 141# actions_command -- the command used to create the actions. 142# either "actions" or "commands". 143# testname -- identifying string for pass/fail output 144# tracepoint -- to which tracepoint(s) do these actions apply? (optional) 145# args -- list of actions to be defined. 146# Returns: 147# zero -- success 148# non-zero -- failure 149 150proc gdb_trace_setactions_command { actions_command testname tracepoint args } { 151 global gdb_prompt 152 153 set state 0 154 set passfail "pass" 155 send_gdb "$actions_command $tracepoint\n" 156 set expected_result "" 157 gdb_expect 5 { 158 -re "No tracepoint number .*$gdb_prompt $" { 159 fail $testname 160 return 1 161 } 162 -re "Enter actions for tracepoint $tracepoint.*>" { 163 if { [llength $args] > 0 } { 164 set lastcommand "[lindex $args $state]" 165 send_gdb "[lindex $args $state]\n" 166 incr state 167 set expected_result [lindex $args $state] 168 incr state 169 } else { 170 send_gdb "end\n" 171 } 172 exp_continue 173 } 174 -re "\(.*\)\[\r\n\]+\[ \t]*>$" { 175 if { $expected_result != "" } { 176 regsub "^\[^\r\n\]+\[\r\n\]+" "$expect_out(1,string)" "" out 177 if ![regexp $expected_result $out] { 178 set passfail "fail" 179 } 180 set expected_result "" 181 } 182 if { $state < [llength $args] } { 183 send_gdb "[lindex $args $state]\n" 184 incr state 185 set expected_result [lindex $args $state] 186 incr state 187 } else { 188 send_gdb "end\n" 189 set expected_result "" 190 } 191 exp_continue 192 } 193 -re "\(.*\)$gdb_prompt $" { 194 if { $expected_result != "" } { 195 if ![regexp $expected_result $expect_out(1,string)] { 196 set passfail "fail" 197 } 198 set expected_result "" 199 } 200 if { [llength $args] < $state } { 201 set passfail "fail" 202 } 203 } 204 default { 205 set passfail "fail" 206 } 207 } 208 if { $testname != "" } { 209 $passfail $testname 210 } 211 if { $passfail == "pass" } then { 212 return 0 213 } else { 214 return 1 215 } 216} 217 218# Define actions for a tracepoint, using the "actions" command. See 219# gdb_trace_setactions_command. 220# 221proc gdb_trace_setactions { testname tracepoint args } { 222 eval gdb_trace_setactions_command "actions" {$testname} {$tracepoint} $args 223} 224 225# Define actions for a tracepoint, using the "commands" command. See 226# gdb_trace_setactions_command. 227# 228proc gdb_trace_setcommands { testname tracepoint args } { 229 eval gdb_trace_setactions_command "commands" {$testname} {$tracepoint} $args 230} 231 232# 233# Procedure: gdb_tfind_test 234# Find a specified trace frame. 235# Arguments: 236# testname -- identifying string for pass/fail output 237# tfind_arg -- frame (line, PC, etc.) identifier 238# exp_res -- Expected result of frame test 239# args -- Test expression 240# Returns: 241# zero -- success 242# non-zero -- failure 243# 244 245proc gdb_tfind_test { testname tfind_arg exp_res args } { 246 global gdb_prompt 247 248 if { "$args" != "" } { 249 set expr "$exp_res" 250 set exp_res "$args" 251 } else { 252 set expr "(int) \$trace_frame" 253 } 254 set passfail "fail" 255 256 gdb_test "tfind $tfind_arg" "" "" 257 send_gdb "printf \"x \%d x\\n\", $expr\n" 258 gdb_expect 10 { 259 -re "x (-*\[0-9\]+) x" { 260 if { $expect_out(1,string) == $exp_res } { 261 set passfail "pass" 262 } 263 exp_continue 264 } 265 -re "$gdb_prompt $" { } 266 } 267 $passfail "$testname" 268 if { $passfail == "pass" } then { 269 return 0 270 } else { 271 return 1 272 } 273} 274 275# 276# Procedure: gdb_readexpr 277# Arguments: 278# gdb_expr -- the expression whose value is desired 279# Returns: 280# the value of gdb_expr, as evaluated by gdb. 281# [FIXME: returns -1 on error, which is sometimes a legit value] 282# 283 284proc gdb_readexpr { gdb_expr } { 285 global gdb_prompt 286 287 set result -1 288 send_gdb "print $gdb_expr\n" 289 gdb_expect 5 { 290 -re "\[$\].*= (\[0-9\]+).*$gdb_prompt $" { 291 set result $expect_out(1,string) 292 } 293 -re "$gdb_prompt $" { } 294 default { } 295 } 296 return $result 297} 298 299# 300# Procedure: gdb_gettpnum 301# Arguments: 302# tracepoint (optional): if supplied, set a tracepoint here. 303# Returns: 304# the tracepoint ID of the most recently set tracepoint. 305# 306 307proc gdb_gettpnum { tracepoint } { 308 global gdb_prompt 309 310 if { $tracepoint != "" } { 311 gdb_test "trace $tracepoint" "" "" 312 } 313 return [gdb_readexpr "\$tpnum"] 314} 315 316 317# 318# Procedure: gdb_find_function_baseline 319# Arguments: 320# func_name -- name of source function 321# Returns: 322# Sourcefile line of function definition (open curly brace), 323# or -1 on failure. Caller must check return value. 324# Note: 325# Works only for open curly brace at beginning of source line! 326# 327 328proc gdb_find_function_baseline { func_name } { 329 global gdb_prompt 330 331 set baseline -1 332 333 send_gdb "list $func_name\n" 334# gdb_expect { 335# -re "\[\r\n\]\[\{\].*$gdb_prompt $" { 336# set baseline 1 337# } 338# } 339} 340 341# 342# Procedure: gdb_find_function_baseline 343# Arguments: 344# filename: name of source file of desired function. 345# Returns: 346# Sourcefile line of function definition (open curly brace), 347# or -1 on failure. Caller must check return value. 348# Note: 349# Works only for open curly brace at beginning of source line! 350# 351 352proc gdb_find_recursion_test_baseline { filename } { 353 global gdb_prompt 354 355 set baseline -1 356 357 gdb_test "list $filename:1" "" "" 358 send_gdb "search gdb_recursion_test line 0\n" 359 gdb_expect { 360 -re "(\[0-9\]+)\[\t \]+\{.*line 0.*$gdb_prompt $" { 361 set baseline $expect_out(1,string) 362 } 363 -re "$gdb_prompt $" { } 364 default { } 365 } 366 return $baseline 367} 368 369# Return the location of the IPA library. 370 371proc get_in_proc_agent {} { 372 global objdir 373 374 if [target_info exists in_proc_agent] { 375 return [target_info in_proc_agent] 376 } else { 377 return $objdir/../../gdbserver/libinproctrace.so 378 } 379} 380 381# Execute BINFILE on target to generate tracefile. Return 1 if 382# tracefile is generated successfully, return 0 otherwise. 383 384proc generate_tracefile { binfile } { 385 set status [remote_exec target "$binfile"] 386 387 if { [lindex $status 0] != 0 } { 388 # Failed to execute $binfile, for example on bare metal targets. 389 # Alternatively, load the binary and run it. If target doesn't 390 # have fileio capabilities, tracefile can't be generated. Skip 391 # the test. 392 if [target_info exists gdb,nofileio] { 393 return 0 394 } 395 396 clean_restart $binfile 397 398 if ![runto_main] then { 399 return 0 400 } 401 gdb_continue_to_end "" continue 1 402 gdb_exit 403 } 404 405 return 1 406} 407