1# Copyright 1999-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# Test Machine interface (MI) operations 17# 18# Test MI breakpoint commands. 19# 20# The goal is not to test gdb functionality, which is done by other 21# tests, but to verify the correct output response to MI operations. 22 23load_lib mi-support.exp 24set MIFLAGS "-i=mi" 25 26standard_testfile basics.c 27 28if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { 29 untested "failed to compile" 30 return -1 31} 32 33# Locate line numbers in basics.c. 34set line_callee4_head [gdb_get_line_number "callee4 ("] 35set line_callee4_body [expr $line_callee4_head + 2] 36set line_callee3_head [gdb_get_line_number "callee3 ("] 37set line_callee3_body [expr $line_callee3_head + 2] 38set line_callee2_head [gdb_get_line_number "callee2 ("] 39set line_callee2_body [expr $line_callee2_head + 2] 40set line_callee1_head [gdb_get_line_number "callee1 ("] 41set line_callee1_body [expr $line_callee1_head + 2] 42set line_main_head [gdb_get_line_number "main ("] 43set line_main_body [expr $line_main_head + 2] 44set line_callme_head [gdb_get_line_number "callme ("] 45set line_callme_body [expr $line_callme_head + 2] 46 47set fullname "fullname=\"${fullname_syntax}${srcfile}\"" 48 49proc_with_prefix test_tbreak_creation_and_listing {} { 50 global srcfile 51 global line_callee4_head 52 global line_callee4_body 53 global line_callee3_head 54 global line_callee3_body 55 global line_callee2_body 56 global line_main_body 57 58 # Insert some breakpoints and list them 59 # Also, disable some so they do not interfere with other tests 60 # Tests: 61 # -break-insert -t main 62 # -break-insert -t basics.c:callee2 63 # -break-insert -t basics.c:$line_callee3_head 64 # -break-insert -t srcfile:$line_callee4_head 65 # -break-list 66 67 set bps {} 68 lappend bps [mi_create_breakpoint "-t main" "break-insert -t operation" \ 69 -number 1 -disp del -func main -file ".*basics.c" \ 70 -line $line_main_body] 71 72 lappend bps [mi_create_breakpoint "-t basics.c:callee2" \ 73 "insert temp breakpoint at basics.c:callee2" \ 74 -number 2 -disp del -func callee2 -file ".*basics.c" \ 75 -line $line_callee2_body] 76 77 lappend bps [mi_create_breakpoint "-t basics.c:$line_callee3_head" \ 78 "insert temp breakpoint at basics.c:\$line_callee3_head" \ 79 -number 3 -disp del -func callee3 -file ".*basics.c" \ 80 -line $line_callee3_body] 81 82 # Getting the quoting right is tricky. 83 # That is "\"<file>\":$line_callee4_head" 84 lappend bps [mi_create_breakpoint \ 85 "-t \"\\\"${srcfile}\\\":$line_callee4_head\"" \ 86 "insert temp breakpoint at \"<fullfilename>\":\$line_callee4_head" \ 87 -number 4 -disp del -func callee4 -file ".*basics.c" \ 88 -line $line_callee4_body] 89 90 mi_gdb_test "666-break-list" \ 91 "666\\\^done,[mi_make_breakpoint_table $bps]" \ 92 "list of breakpoints" 93 94 mi_gdb_test "777-break-delete" \ 95 "777\\^done" \ 96 "delete temp breakpoints" 97} 98 99proc_with_prefix test_abreak_creation {} { 100 mi_create_varobj tpnum \$tpnum "create local variable tpnum" 101 # Test that $tpnum is not set before creating a tracepoint. 102 mi_gdb_test "521-var-evaluate-expression tpnum" \ 103 "521\\^done,value=\"void\"" "eval tpnum before tracepoint" 104 105 mi_gdb_test "522-break-insert -a main" \ 106 "522\\^done,[mi_make_breakpoint -number 10 -type tracepoint]" \ 107 "break-insert -a operation" 108 109 mi_gdb_test "523-var-update tpnum" \ 110 "523\\^done,changelist=\\\[\{name=\"tpnum\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ 111 "update tpnum" 112 # Test that $tpnum is updated after creating a tracepoint. 113 mi_gdb_test "524-var-evaluate-expression tpnum" \ 114 "524\\^done,value=\"10\"" "eval tpnum after tracepoint" 115} 116 117proc_with_prefix test_ignore_count {} { 118 global line_callme_body 119 120 mi_gdb_test "-break-insert -i 1 callme" \ 121 "\\^done,[mi_make_breakpoint -ignore 1]" \ 122 "insert breakpoint with ignore count at callme" 123 124 mi_run_cmd 125 126 mi_expect_stop "breakpoint-hit" "callme" "\{name=\"i\",value=\"2\"\}" ".*basics.c" $line_callme_body \ 127 {"" "disp=\"keep\"" } "run to breakpoint with ignore count" 128} 129 130proc_with_prefix test_error {} { 131 mi_gdb_test "-break-insert function_that_does_not_exist" \ 132 ".*\\^error,msg=\"Function \\\\\"function_that_does_not_exist\\\\\" not defined.\"" \ 133 "breakpoint at nonexistent function" 134 135 # We used to have a bug whereby -break-insert that failed would not 136 # clear some event hooks. As result, whenever we evaluate expression 137 # containing function call, the internal breakpoint created to handle 138 # function call would be reported, messing up MI output. 139 mi_gdb_test "-var-create V * return_1()" \ 140 "\\^done,name=\"V\",numchild=\"0\",value=\"1\",type=\"int\",has_more=\"0\"" \ 141 "create varobj for function call" 142 143 mi_gdb_test "-var-update *" \ 144 "\\^done,changelist=\\\[\\\]" \ 145 "update varobj for function call" 146 147 # Try setting breakpoints with garbage after the location. 148 149 # "if" only works in the CLI. It's not supposed to be accepted by 150 # MI. The way to specify a condition is with -c. 151 mi_gdb_test "-break-insert \"callme if i < 4\"" \ 152 ".*\\^error,msg=\"Garbage 'if i < 4' at end of location\"" \ 153 "breakpoint with garbage after location" 154 155 mi_gdb_test "-break-insert -c i==4 \"callme if i < 4\"" \ 156 ".*\\^error,msg=\"Garbage 'if i < 4' at end of location\"" \ 157 "conditional breakpoint with garbage after location" 158 159 # Try using an invalid condition. 160 mi_gdb_test "-break-insert -c bad callme" \ 161 ".*\\^error,msg=\"No symbol \\\\\"bad\\\\\" in current context.\"" \ 162 "breakpoint with bad condition" 163 164 mi_gdb_test "-dprintf-insert -c bad callme \"Hello\"" \ 165 ".*\\^error,msg=\"No symbol \\\\\"bad\\\\\" in current context.\"" \ 166 "dprintf with bad condition" 167 168 mi_gdb_test "-break-condition 5 bad" \ 169 ".*\\^error,msg=\"No symbol \\\\\"bad\\\\\" in current context.\"" \ 170 "invalid condition" 171} 172 173proc_with_prefix test_disabled_creation {} { 174 global line_callee2_body 175 176 set bp [mi_make_breakpoint -number 6 -type breakpoint -disp keep \ 177 -enabled n -func callee2 -file ".*basics.c" \ 178 -line $line_callee2_body] 179 mi_gdb_test "-break-insert -d basics.c:callee2" \ 180 "\\^done,$bp" \ 181 "test disabled creation" 182 183 mi_gdb_test "-break-delete" \ 184 "\\^done" \ 185 "test disabled creation: cleanup" 186} 187 188proc_with_prefix test_breakpoint_commands {} { 189 global line_callee2_body 190 191 set bp_no_script \ 192 [mi_create_breakpoint "basics.c:callee2" \ 193 "breakpoint commands: insert breakpoint at basics.c:callee2" \ 194 -number 7 -disp keep -func callee2 -file ".*basics.c" \ 195 -line $line_callee2_body] 196 197 mi_gdb_test "-break-commands 7 \"print 10\" \"continue\"" \ 198 "\\^done" \ 199 "breakpoint commands: set commands" 200 201 # Rebuild the breakpoint regexp instead of using the one returned 202 # by mi_create_breakpoint. Only in -break-info is the actual script 203 # seen. 204 set bp_script [mi_make_breakpoint -number 7 -disp keep -func callee2 \ 205 -file ".*basics.c" -line $line_callee2_body \ 206 -script {\["print 10","continue"\]}] 207 mi_gdb_test "-break-info 7" \ 208 "\\^done,[mi_make_breakpoint_table [list $bp_script]]" \ 209 "breakpoint commands: check that commands are set" 210 211 mi_gdb_test "-break-commands 7" \ 212 "\\^done" \ 213 "breakpoint commands: clear commands" 214 215 mi_gdb_test "-break-info" \ 216 "\\^done,[mi_make_breakpoint_table [list $bp_no_script]]" \ 217 "breakpoint commands: check that commands are cleared" 218 219 mi_runto_main 220 221 mi_create_breakpoint "basics.c:callee2" \ 222 "breakpoint commands: insert breakpoint at basics.c:callee2, again" \ 223 -number 9 -disp keep -func callee2 -file ".*basics.c" \ 224 -line $line_callee2_body 225 226 mi_gdb_test "-break-commands 9 \"bt\" \"set \$i=0\" \"while \$i<10\" \"print \$i\" \"set \$i=\$i+1\" \"end\" \"continue\" " \ 227 "\\^done" \ 228 "breakpoint commands: set more commands" 229 230 mi_send_resuming_command "exec-continue" "breakpoint commands: continue" 231 232 233 # The breakpoint command's output is always sent to the main UI, 234 # even when testing with MI running on a secondary UI. 235 global gdb_main_spawn_id 236 237 set test "intermediate stop and continue, bp commands" 238 gdb_expect { 239 -i $gdb_main_spawn_id 240 -re ".*callee2.*callee1.*main.*\\\$1 = 0.*\\\$10 = 9" { 241 pass $test 242 } 243 timeout { 244 fail $test 245 } 246 } 247 248 set test "intermediate stop and continue, mi running" 249 gdb_expect { 250 -re "\\*running" { 251 pass $test 252 } 253 timeout { 254 fail $test 255 } 256 } 257 258 mi_expect_stop "exited-normally" "" "" "" "" "" "test hitting breakpoint with commands" 259} 260 261# Test explicit breakpoints. These tests only test the MI portion of the 262# code. In-depth testing of explicit breakpoints is accomplished in 263# gdb.linespec tests. 264 265proc_with_prefix test_explicit_breakpoints {} { 266 global srcfile 267 global line_callee3_head line_callee4_head 268 global line_callee3_body line_callee4_body 269 global line_callee2_body line_main_body 270 271 mi_delete_breakpoints 272 273 # First check mixed explicit/parsed linespecs. 274 mi_gdb_test "-break-insert --function main $srcfile:$line_callee3_head" \ 275 ".*Garbage following explicit location.*" 276 277 # Insert some breakpoints and list them 278 # Also, disable some so they do not interfere with other tests 279 # Tests: 280 # -break-insert -t --function main 281 # -break-insert -t --source basics.c --function callee2 282 # -break-insert -t --source basics.c --line $line_callee3_head 283 # -break-insert -t --source srcfile --line $line_callee4_head 284 # -break-list 285 286 set bps {} 287 lappend bps [mi_create_breakpoint "-t --function main" \ 288 "insert temp explicit breakpoint in main" \ 289 -func main -file ".*$srcfile" -line $line_main_body] 290 291 lappend bps \ 292 [mi_create_breakpoint "-t --source $srcfile --function callee2" \ 293 "insert temp explicit breakpoint at $srcfile:callee2" \ 294 -func callee2 -file ".*$srcfile" -line $line_callee2_body] 295 296 lappend bps \ 297 [mi_create_breakpoint "-t --source $srcfile --line $line_callee3_head" \ 298 "insert temp explicit breakpoint at $srcfile:$line_callee3_head" \ 299 -func callee3 -file ".*$srcfile" -line $line_callee3_body] 300 301 lappend bps \ 302 [mi_create_breakpoint \ 303 "-t --source \"$srcfile\" --line $line_callee4_head" \ 304 "insert temp explicit breakpoint at \"$srcfile\":$line_callee4_head" \ 305 -func callee4 -file ".*$srcfile" -line $line_callee4_body] 306 307 mi_gdb_test "-break-list" "\\^done,[mi_make_breakpoint_table $bps]" \ 308 "list of explicit breakpoints" 309 310 mi_gdb_test "-break-delete" \ 311 "\\^done" \ 312 "delete temp breakpoints" 313 314 mi_create_breakpoint "-c \"intarg == 3\" --function callee2" \ 315 "insert explicit conditional breakpoint in callee2" \ 316 -func callee2 ".*$srcfile" -line $line_callee2_body \ 317 -cond "intarg == 3" 318 319 # mi_create_breakpoint cannot deal with displaying canonical 320 # linespecs. 321 mi_gdb_test \ 322 "-break-insert -c \"foo == 3\" --source $srcfile --function main --label label" \ 323 ".*No label .*label.* defined in function .*main.*" 324 325 mi_gdb_test \ 326 "-break-insert --source foobar.c --line 3" \ 327 ".*No source file named foobar.c.*" 328 329 mi_gdb_test \ 330 "-break-insert --source $srcfile --function foobar" \ 331 ".*Function .*foobar.* not defined in .*$srcfile.*" 332 333 mi_gdb_test \ 334 "-break-insert --source $srcfile --function main --label foobar" \ 335 ".*No label .*foobar.* defined in function .*main.*" 336 337 mi_gdb_test \ 338 "-break-insert --source $srcfile" \ 339 ".*-break-insert: --source option requires --function, --label, or --line.*" 340} 341 342# Test forcing an invalid condition. 343 344proc_with_prefix test_forced_conditions {} { 345 set warning ".*warning: failed to validate condition .* disabling.*" 346 347 set loc [mi_make_breakpoint_loc -enabled "N"] 348 set args [list -cond "bad" -locations "\\\[$loc\\\]"] 349 set bp [eval mi_make_breakpoint_multi $args] 350 351 mi_gdb_test "-break-insert -c bad --force-condition callme" \ 352 "${warning}\\^done,$bp" \ 353 "breakpoint with forced condition" 354 355 mi_gdb_test "-dprintf-insert -c bad --force-condition callme \"Hello\"" \ 356 "${warning}\\^done,$bp" \ 357 "dprintf with forced condition" 358 359 # Define a plain breakpoint first, and a condition later. 360 mi_create_breakpoint "callme" "define a bp" "" 361 mi_gdb_test "-break-condition --force 16 bad == 42" \ 362 "${warning}\\^done" \ 363 "invalid condition is forced" 364 set args [list -cond "bad == 42" -locations "\\\[$loc\\\]"] 365 set bp [eval mi_make_breakpoint_multi $args] 366 mi_gdb_test "-break-info 16" \ 367 "\\^done,[mi_make_breakpoint_table [list $bp]]" \ 368 "invalid condition is defined" 369 370 # No cond argument should clear the condition. 371 mi_gdb_test "-break-condition 16" \ 372 "~\"Breakpoint 16's condition is now valid at location 1, enabling.*\\^done" \ 373 "clear the condition" 374 set bp [mi_make_breakpoint -number 16] 375 mi_gdb_test "-break-info 16" \ 376 "\\^done,[mi_make_breakpoint_table [list $bp]]" \ 377 "condition is cleared" 378 379 # Zero-argument is an error. 380 mi_gdb_test "-break-condition" \ 381 "\\^error,msg=\"-break-condition: Missing the <number> argument\"" \ 382 "no arguments to -break-condition" 383 384 # Passing --force with no condition should not crash or raise an error. 385 mi_gdb_test "-break-condition --force 16" \ 386 "\\^done" \ 387 "clear the condition with --force" 388 mi_gdb_test "-break-condition --force" \ 389 "\\^error,msg=\"-break-condition: Missing the <number> argument\"" \ 390 "no arguments with --force" 391} 392 393proc test_break {mi_mode} { 394 global srcdir subdir binfile 395 396 mi_gdb_exit 397 398 if {$mi_mode == "separate"} { 399 set start_ops "separate-mi-tty" 400 } else { 401 set start_ops "" 402 } 403 if [mi_gdb_start $start_ops] { 404 return 405 } 406 407 mi_delete_breakpoints 408 mi_gdb_reinitialize_dir $srcdir/$subdir 409 mi_gdb_load ${binfile} 410 411 test_tbreak_creation_and_listing 412 413 test_ignore_count 414 415 test_error 416 417 test_disabled_creation 418 419 test_breakpoint_commands 420 421 test_abreak_creation 422 423 test_explicit_breakpoints 424 425 test_forced_conditions 426} 427 428if [gdb_debug_enabled] { 429 # gdb debug doesn't work for separate-mi-tty. 430 set modes {"main"} 431} else { 432 set modes {"main" "separate"} 433} 434 435foreach_with_prefix mi-mode $modes { 436 test_break ${mi-mode} 437} 438