# Copyright 2015-2020 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Test that GDB doesn't get badly wedged if the inferior is killed # from outside GDB (with SIGKILL) while the program is stopped. standard_testfile # Get the value of variable VAR in the inferior. MSG is used as the # test message. proc get_value {var msg} { global expect_out global gdb_prompt global decimal set value -1 gdb_test_multiple "print $var" "$msg" { -re ".*= ($decimal).*\r\n$gdb_prompt $" { set value $expect_out(1,string) pass "$msg" } } return ${value} } # Runs the program until a breakpoint, deletes all breakpoints, and # then kills the inferior from _outside_ GDB, with SIGKILL. Runs CMDS # afterwards, to make sure GDB copes with the inferior disappearing, # and then quits GDB. proc test {cmds_after_kill} { global binfile global gdb_prompt global decimal clean_restart ${binfile} if ![runto done] { return } # So that "continue" doesn't try a step over, etc. delete_breakpoints set testpid [get_value "pid" "get pid of inferior"] if { $testpid == -1 } { return -1 } remote_exec target "kill -9 ${testpid}" # Give it some time to die. sleep 2 uplevel 1 $cmds_after_kill # Make sure we can quit. set msg "quit GDB" gdb_test_multiple "quit" $msg { -re "Quit anyway\\? \\(y or n\\) $" { send_gdb "y\n" exp_continue } eof { pass $msg } } } if {[prepare_for_testing "failed to prepare" $testfile $srcfile] == -1} { return -1 } # The actual output GDB prints in response to commands after the # inferior is gone isn't very well defined, and will depend on target. # What we're trying to make sure is that GDB doesn't internal error or # get wedged. # Try simply continuing. with_test_prefix "continue" { test { # Try stepping the program. Stepping may need to read/write # registers, unlike continue. gdb_test "continue" ".*" # Try listing threads afterwards. It's probably what the user # will do after an error. gdb_test "info threads" ".*" } } # Try stepping the program. Stepping may go through diferent code # paths in the target backends. with_test_prefix "stepi" { test { gdb_test "si" ".*" gdb_test "info threads" ".*" } } # Try fetching registers explicitly, which should cover the error many # other commands would trigger. with_test_prefix "registers" { test { gdb_test "flushregs" ".*" gdb_test "info threads" ".*" } } # Try only listing threads explicitly, first thing, which is another # operation GDB may or not decide to do itself and is likely to be # what a user would try after error too. with_test_prefix "info threads" { test { gdb_test "info threads" ".*" } }