1# Copyright 2012-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# Tests for explicit locations 17 18load_lib completion-support.exp 19 20standard_testfile explicit.c explicit2.c 3explicit.c 21set exefile $testfile 22 23if {[prepare_for_testing "failed to prepare" $exefile \ 24 [list $srcfile $srcfile2 $srcfile3] {debug nowarnings}]} { 25 return -1 26} 27 28# Wrap the entire test in a namespace to avoid contaminating other tests. 29namespace eval $testfile { 30 31 # Test the given (explicit) LINESPEC which should cause gdb to break 32 # at LOCATION. 33 proc test_breakpoint {linespec location} { 34 35 set testname "set breakpoint at \"$linespec\"" 36 # Delete all breakpoints, set a new breakpoint at LINESPEC, 37 # and attempt to run to it. 38 delete_breakpoints 39 if {[gdb_breakpoint $linespec]} { 40 pass $testname 41 send_log "\nexpecting locpattern \"$location\"\n" 42 gdb_continue_to_breakpoint $linespec $location 43 } else { 44 fail $testname 45 } 46 } 47 48 # Add the given LINESPEC to the array named in THEARRAY. GDB is expected 49 # to stop at LOCATION. 50 proc add {thearray linespec location} { 51 upvar $thearray ar 52 53 lappend ar(linespecs) $linespec 54 lappend ar(locations) $location 55 } 56 57 # A list of all explicit linespec arguments. 58 variable all_arguments 59 set all_arguments {"source" "function" "label" "line"} 60 61 # Some locations used in this test 62 variable lineno 63 variable location 64 set lineno(normal) [gdb_get_line_number "myfunction location" $srcfile] 65 set lineno(top) [gdb_get_line_number "top location" $srcfile] 66 foreach v [array names lineno] { 67 set location($v) ".*[string_to_regexp "$srcfile:$lineno($v)"].*" 68 } 69 70 # A list of explicit locations and the corresponding location. 71 variable linespecs 72 set linespecs(linespecs) {} 73 set linespecs(location) {} 74 75 add linespecs "-source $srcfile -function myfunction" $location(normal) 76 add linespecs "-source $srcfile -function myfunction -label top" \ 77 $location(top) 78 79 # This isn't implemented yet; -line is silently ignored. 80 add linespecs "-source $srcfile -function myfunction -label top -line 3" \ 81 $location(top) 82 add linespecs "-source $srcfile -line $lineno(top)" $location(top) 83 add linespecs "-function myfunction" $location(normal) 84 add linespecs "-function myfunction -label top" $location(top) 85 86 # These are also not yet supported; -line is silently ignored. 87 add linespecs "-function myfunction -line 3" $location(normal) 88 add linespecs "-function myfunction -label top -line 3" $location(top) 89 add linespecs "-line 3" $location(normal) 90 91 # Fire up gdb. 92 if {![runto_main]} { 93 return -1 94 } 95 96 # Turn off queries 97 gdb_test_no_output "set confirm off" 98 99 # Simple error tests (many more are tested in ls-err.exp) 100 foreach arg $all_arguments { 101 # Test missing argument 102 gdb_test "break -$arg" \ 103 [string_to_regexp "missing argument for \"-$arg\""] 104 105 # Test abbreviations 106 set short [string range $arg 0 3] 107 if { $arg != $short } { 108 gdb_test "break -$short" \ 109 [string_to_regexp "missing argument for \"-$short\""] 110 } 111 } 112 113 # Test invalid arguments 114 foreach arg {"-foo" "-foo bar" "-function myfunction -foo" \ 115 "-function -myfunction -foo bar"} { 116 gdb_test "break $arg" \ 117 [string_to_regexp "invalid explicit location argument, \"-foo\""] 118 } 119 120 # Test explicit locations, with and without conditions. 121 # For these tests, it is easiest to turn of pending breakpoint. 122 gdb_test_no_output "set breakpoint pending off" \ 123 "turn off pending breakpoints" 124 125 foreach linespec $linespecs(linespecs) loc_pattern $linespecs(locations) { 126 127 # Test the linespec 128 test_breakpoint $linespec $loc_pattern 129 130 # Test with a valid condition 131 delete_breakpoints 132 set tst "set breakpoint at \"$linespec\" with valid condition" 133 if {[gdb_breakpoint "$linespec if arg == 0"]} { 134 pass $tst 135 136 gdb_test "info break" ".*stop only if arg == 0.*" \ 137 "info break of conditional breakpoint at \"$linespec\"" 138 } else { 139 fail $tst 140 } 141 142 # Test with invalid condition 143 gdb_test "break $linespec if foofoofoo == 1" \ 144 ".*No symbol \"foofoofoo\" in current context.*" \ 145 "set breakpoint at \"$linespec\" with invalid condition" 146 147 # Test with thread 148 delete_breakpoints 149 gdb_test "break $linespec thread 123" "Unknown thread 123." 150 } 151 152 # Tests below are about tab-completion, which doesn't work if readline 153 # library isn't used. Check it first. 154 if { [readline_is_used] } { 155 156 # Test the explicit location completer 157 foreach abbrev {"fun" "so" "lab" "li"} full {"function" "source" "label" "line"} { 158 set tst "complete 'break -$abbrev'" 159 send_gdb "break -${abbrev}\t" 160 gdb_test_multiple "" $tst { 161 -re "break -$full " { 162 send_gdb "\n" 163 gdb_test_multiple "" $tst { 164 -re "missing argument for \"-$full\".*$gdb_prompt " { 165 pass $tst 166 } 167 } 168 } 169 } 170 set tst "complete -$full with no value" 171 send_gdb "break -$full \t" 172 gdb_test_multiple "" $tst { 173 -re ".*break -$full " { 174 send_gdb "\n" 175 gdb_test_multiple "" $tst { 176 -re ".*Source filename requires function, label, or line offset\..*$gdb_prompt " { 177 if {[string equal $full "source"]} { 178 pass $tst 179 } else { 180 fail $tst 181 } 182 } 183 -re "missing argument for \"-$full\".*$gdb_prompt " { 184 pass $tst 185 } 186 } 187 } 188 } 189 } 190 191 set tst "complete unique function name" 192 send_gdb "break -function my_unique_func\t" 193 gdb_test_multiple "" $tst { 194 -re "break -function my_unique_function_name" { 195 send_gdb "\n" 196 gdb_test "" ".*Breakpoint \[0-9\]+.*" $tst 197 gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint" 198 } 199 } 200 201 set tst "complete non-unique function name" 202 send_gdb "break -function myfunc\t" 203 gdb_test_multiple "" $tst { 204 -re "break -function myfunc\\\x07tion" { 205 send_gdb "\t\t" 206 gdb_test_multiple "" $tst { 207 -re "\\\x07\r\nmyfunction\[ \t\]+myfunction2\[ \t\]+myfunction3\[ \t\]+myfunction4\[ \t\]+\r\n$gdb_prompt " { 208 gdb_test "2" ".*Breakpoint \[0-9\]+.*" $tst 209 gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint" 210 } 211 } 212 } 213 } 214 215 set tst "complete non-existant function name" 216 send_gdb "break -function foo\t" 217 gdb_test_multiple "" $tst { 218 -re "break -function foo\\\x07" { 219 send_gdb "\t\t" 220 gdb_test_multiple "" $tst { 221 -re "\\\x07\\\x07" { 222 send_gdb "\n" 223 gdb_test "" {Function "foo" not defined.} $tst 224 } 225 } 226 } 227 } 228 229 with_test_prefix "complete unique file name" { 230 foreach qc $completion::maybe_quoted_list { 231 set cmd "break -source ${qc}3explicit.c${qc}" 232 test_gdb_complete_unique \ 233 "break -source ${qc}3ex" \ 234 $cmd 235 gdb_test $cmd \ 236 {Source filename requires function, label, or line offset.} 237 } 238 } 239 240 set tst "complete non-unique file name" 241 send_gdb "break -source exp\t" 242 # We're matching two cases here: 243 # - without GLIBC debuginfo 244 # (gdb) break -source exp^Glicit^G^M 245 # explicit.c explicit2.c ^M 246 # (gdb) break -source explicit^M 247 # Source filename requires function, label, or line offset.^M 248 # (gdb) PASS: gdb.linespec/explicit.exp: complete non-unique file name 249 # - with GLIBC debuginfo: 250 # (gdb) break -source exp^Gl^G^M 251 # explicit.c explicit2.c explicit_bzero.c explicit_bzero_chk.c \ 252 # explodename.c ^M 253 # (gdb) break -source expl^M 254 # Source filename requires function, label, or line offset.^M 255 # (gdb) PASS: gdb.linespec/explicit.exp: complete non-unique file name 256 gdb_test_multiple "" $tst { 257 -re "break -source exp\\\x07l" { 258 # At this point, either output is done (first case), or a 259 # further "icit" is emitted (second case). We have no reliable 260 # way to decide one way or another, so just send the tabs, even 261 # though that may be a little early in the second case. 262 send_gdb "\t\t" 263 gdb_test_multiple "" $tst { 264 -re "\\\x07\r\nexplicit.c\[ \t\]+explicit2.c\[ \t\]+\(expl.*\)?\r\n$gdb_prompt" { 265 send_gdb "\n" 266 gdb_test "" \ 267 {Source filename requires function, label, or line offset.} \ 268 $tst 269 } 270 } 271 } 272 } 273 274 set tst "complete non-existant file name" 275 send_gdb "break -source foo\t" 276 gdb_test_multiple "" $tst { 277 -re "break -source foo" { 278 send_gdb "\t\t" 279 gdb_test_multiple "" $tst { 280 -re "\\\x07\\\x07" { 281 send_gdb "\n" 282 gdb_test "" \ 283 {Source filename requires function, label, or line offset.} \ 284 $tst 285 } 286 } 287 } 288 } 289 290 set tst "complete filename and unique function name" 291 send_gdb "break -source explicit.c -function ma\t" 292 gdb_test_multiple "" $tst { 293 -re "break -source explicit.c -function main " { 294 send_gdb "\n" 295 gdb_test "" ".*Breakpoint .*" $tst 296 gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint" 297 } 298 } 299 300 set tst "complete filename and non-unique function name" 301 send_gdb "break -so 3explicit.c -func myfunc\t" 302 gdb_test_multiple "" $tst { 303 -re "break -so 3explicit.c -func myfunc\\\x07tion" { 304 send_gdb "\t\t" 305 gdb_test_multiple "" $tst { 306 -re "\\\x07\r\nmyfunction3\[ \t\]+myfunction4\[ \t\]+\r\n$gdb_prompt " { 307 gdb_test "3" ".*Breakpoint \[0-9\]+.*" $tst 308 gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint" 309 } 310 } 311 } 312 } 313 314 set tst "complete filename and non-existant function name" 315 send_gdb "break -sou 3explicit.c -fun foo\t" 316 gdb_test_multiple "" $tst { 317 -re "break -sou 3explicit.c -fun foo\\\x07" { 318 send_gdb "\t\t" 319 gdb_test_multiple "" $tst { 320 -re "\\\x07\\\x07" { 321 send_gdb "\n" 322 gdb_test "" \ 323 {Function "foo" not defined in "3explicit.c".} $tst 324 } 325 } 326 } 327 } 328 329 set tst "complete filename and function reversed" 330 send_gdb "break -func myfunction4 -source 3ex\t" 331 gdb_test_multiple "" $tst { 332 -re "break -func myfunction4 -source 3explicit.c " { 333 send_gdb "\n" 334 gdb_test "" "Breakpoint \[0-9\]+.*" $tst 335 gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint" 336 } 337 } 338 339 with_test_prefix "complete unique label name" { 340 foreach qc $completion::maybe_quoted_list { 341 test_gdb_complete_unique \ 342 "break -function myfunction -label ${qc}to" \ 343 "break -function myfunction -label ${qc}top${qc}" 344 } 345 } 346 347 with_test_prefix "complete unique label name with source file" { 348 test_gdb_complete_unique \ 349 "break -source explicit.c -function myfunction -label to" \ 350 "break -source explicit.c -function myfunction -label top" 351 } 352 353 with_test_prefix "complete unique label name reversed" { 354 test_gdb_complete_multiple "b -label top -function " "myfunction" "" { 355 "myfunction" 356 "myfunction2" 357 "myfunction3" 358 "myfunction4" 359 } 360 } 361 362 with_test_prefix "complete non-unique label name" { 363 test_gdb_complete_multiple "b -function myfunction -label " "" "" { 364 "done" 365 "top" 366 } 367 } 368 369 # The program is stopped at myfunction, so gdb is able to 370 # infer the label's function. 371 with_test_prefix "complete label name with no function" { 372 test_gdb_complete_unique \ 373 "break -label to" \ 374 "break -label top" 375 check_bp_locations_match_list \ 376 "break -label top" { 377 "-function myfunction -label top" 378 } 379 } 380 381 # See above. 382 with_test_prefix "complete label name with source file but no function" { 383 test_gdb_complete_unique \ 384 "break -source explicit.c -label to" \ 385 "break -source explicit.c -label top" 386 check_bp_locations_match_list \ 387 "break -source explicit.c -label top" { 388 "-source explicit.c -function myfunction -label top" 389 } 390 } 391 392 with_test_prefix "complete label name with wrong source file" { 393 test_gdb_complete_none \ 394 "break -source explicit2.c -function myfunction -label to" 395 check_setting_bp_fails \ 396 "break -source explicit2.c -function myfunction -label top" 397 } 398 399 # Get rid of symbols from shared libraries, otherwise 400 # "b -source thr<tab>" could find some system library's 401 # source. 402 gdb_test_no_output "nosharedlibrary" 403 404 # Test that after a seemingly finished option argument, 405 # completion matches both the explicit location options and 406 # the linespec keywords. 407 set completions_list { 408 "-force-condition" 409 "-function" 410 "-label" 411 "-line" 412 "-qualified" 413 "-source" 414 "if" 415 "task" 416 "thread" 417 } 418 foreach what { "-function" "-label" "-line" "-source" } { 419 # Also test with "-qualified" appearing before the 420 # explicit location. 421 foreach prefix {"" "-qualified "} { 422 423 # ... and with "-qualified" appearing after the 424 # explicit location. 425 foreach suffix {"" " -qualified"} { 426 with_test_prefix "complete after $prefix$what$suffix" { 427 if {$what != "-line"} { 428 set w "$prefix$what argument$suffix " 429 test_gdb_complete_multiple \ 430 "b $w" "" "" $completions_list 431 test_gdb_complete_unique \ 432 "b $w thr" \ 433 "b $w thread" 434 test_gdb_complete_unique \ 435 "b $w -fun" \ 436 "b $w -function" 437 } else { 438 # After -line, we expect a number / offset. 439 foreach line {"10" "+10" "-10"} { 440 set w "$prefix-line $line$suffix" 441 test_gdb_complete_multiple \ 442 "b $w " "" "" $completions_list 443 test_gdb_complete_unique \ 444 "b $w thr" \ 445 "b $w thread" 446 test_gdb_complete_unique \ 447 "b $w -fun" \ 448 "b $w -function" 449 } 450 451 # With an invalid -line argument, we don't get any 452 # completions. 453 test_gdb_complete_none "b $prefix-line argument$suffix " 454 } 455 456 } 457 458 } 459 460 # These tests don't make sense with "-qualified" after 461 # the location. 462 with_test_prefix "complete after $prefix$what" { 463 # Don't complete a linespec keyword ("thread") or 464 # another option name when expecting an option 465 # argument. 466 test_gdb_complete_none "b $prefix$what thr" 467 test_gdb_complete_none "b $prefix$what -fun" 468 } 469 } 470 } 471 472 # Test that after a seemingly finished option argument, 473 # completion for "-" matches both the explicit location 474 # options and the linespec keywords that start with "-". 475 with_test_prefix "complete '-' after options" { 476 test_gdb_complete_multiple "b -function myfunction " "-" "" { 477 "-force-condition" 478 "-function" 479 "-label" 480 "-line" 481 "-qualified" 482 "-source" 483 } 484 } 485 486 # Tests that ensure that after "if" we complete on expressions 487 # are in cpcompletion.exp. 488 489 # Disable the completion limit for the rest of the testcase. 490 gdb_test_no_output "set max-completions unlimited" 491 492 # Get rid of symbols from shared libraries, otherwise the 493 # completions match list for "break <tab>" is huge and makes 494 # the test below quite long while the gdb_test_multiple loop 495 # below consumes the matches. Not doing this added ~20 496 # seconds at the time of writing. (Actually, already done above.) 497 # gdb_test_no_output "nosharedlibrary" 498 499 # Test completion with no input argument. We should see all 500 # the options, plus all the functions. To keep it simple, as 501 # proxy, we check for presence of one explicit location 502 # option, one probe location, and one function. 503 set saw_opt_function 0 504 set saw_opt_probe_stap 0 505 set saw_function 0 506 507 set tst "complete with no arguments" 508 send_gdb "break \t" 509 gdb_test_multiple "" $tst { 510 "break \\\x07" { 511 send_gdb "\t" 512 gdb_test_multiple "" $tst { 513 "Display all" { 514 send_gdb "y" 515 exp_continue 516 } 517 -re "-function" { 518 set saw_opt_function 1 519 exp_continue 520 } 521 -re "-probe-stap" { 522 set saw_opt_probe_stap 1 523 exp_continue 524 } 525 -re "myfunction4" { 526 set saw_function 1 527 exp_continue 528 } 529 -re "\r\n$gdb_prompt " { 530 gdb_assert {$saw_opt_function && $saw_opt_probe_stap && $saw_function} $tst 531 } 532 -re " " { 533 exp_continue 534 } 535 } 536 } 537 } 538 clear_input_line $tst 539 540 # NOTE: We don't bother testing more elaborate combinations of options, 541 # such as "-func main -sour 3ex\t" (main is defined in explicit.c). 542 # The completer cannot handle these yet. 543 544 # The following completion tests require having no symbols 545 # loaded. 546 gdb_exit 547 gdb_start 548 549 # The match list you get when you complete with no options 550 # specified at all. 551 set completion_list { 552 "-function" 553 "-label" 554 "-line" 555 "-probe" 556 "-probe-dtrace" 557 "-probe-stap" 558 "-qualified" 559 "-source" 560 } 561 with_test_prefix "complete with no arguments and no symbols" { 562 test_gdb_complete_multiple "b " "" "-" $completion_list 563 test_gdb_complete_multiple "b " "-" "" $completion_list 564 } 565 } 566 # End of completion tests. 567 568 # Test pending explicit breakpoints 569 gdb_exit 570 gdb_start 571 572 set tst "pending invalid conditional explicit breakpoint" 573 if {![gdb_breakpoint "-func myfunction if foofoofoo == 1" \ 574 allow-pending]} { 575 fail "set $tst" 576 } else { 577 gdb_test "info break" ".*PENDING.*myfunction if foofoofoo == 1.*" $tst 578 } 579 580 gdb_exit 581 gdb_start 582 583 set tst "pending valid conditional explicit breakpoint" 584 if {![gdb_breakpoint "-func myfunction if arg == 0" \ 585 allow-pending]} { 586 fail "set $tst" 587 } else { 588 gdb_test "info break" ".*PENDING.*myfunction if arg == 0" $tst 589 590 gdb_load [standard_output_file $exefile] 591 gdb_test "info break" \ 592 ".*in myfunction at .*$srcfile:.*stop only if arg == 0.*" \ 593 "$tst resolved" 594 } 595 596 # Test interaction of condition command and explicit linespec conditons. 597 gdb_exit 598 gdb_start 599 gdb_load [standard_output_file $exefile] 600 601 set tst "condition_command overrides explicit linespec condition" 602 if {![runto_main]} { 603 fail $tst 604 } else { 605 if {![gdb_breakpoint "-func myfunction if arg == 1"]} { 606 fail "set breakpoint with condition 'arg == 1'" 607 } else { 608 gdb_test_no_output "cond 2 arg == 0" \ 609 "set new breakpoint condition for explicit linespec" 610 611 gdb_continue_to_breakpoint $tst $location(normal) 612 } 613 } 614 615 gdb_test "cond 2" [string_to_regexp "Breakpoint 2 now unconditional."] \ 616 "clear condition for explicit breakpoint" 617 set tst "info break of cleared condition of explicit breakpoint" 618 gdb_test_multiple "info break" $tst { 619 -re ".*in myfunction at .*$srcfile:.*stop only if arg == 0.*" { 620 fail $tst 621 } 622 -re ".*in myfunction at .*$srcfile:.*$gdb_prompt $" { 623 pass $tst 624 } 625 } 626 627 # Test explicit "ranges." Make sure that using explicit 628 # locations doesn't alter the expected outcome. 629 gdb_test "list -q main" ".*" "list main 1" 630 set list_result [capture_command_output "list -,+" ""] 631 gdb_test "list -q main" ".*" "list main 2" 632 gdb_test "list -line -,-line +" [string_to_regexp $list_result] 633 634 # Ditto for the reverse (except that no output is expected). 635 gdb_test "list -q myfunction" ".*" "list myfunction 1" 636 gdb_test_no_output "list +,-" 637 gdb_test "list -q myfunction" ".*" "list myfunction 2" 638 gdb_test_no_output "list -line +, -line -" 639} 640 641namespace delete $testfile 642