Home | History | Annotate | Line # | Download | only in gdb.server
      1 # This testcase is part of GDB, the GNU debugger.
      2 #
      3 # Copyright 2019-2024 Free Software Foundation, Inc.
      4 #
      5 # This program is free software; you can redistribute it and/or modify
      6 # it under the terms of the GNU General Public License as published by
      7 # the Free Software Foundation; either version 3 of the License, or
      8 # (at your option) any later version.
      9 #
     10 # This program is distributed in the hope that it will be useful,
     11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 # GNU General Public License for more details.
     14 #
     15 # You should have received a copy of the GNU General Public License
     16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18 # Test what happens if we have multiple UIs in use, and an error
     19 # occurs while running a GDB command.  Specifically, do both UIs
     20 # return to an interactive state, or does one (or both) of them get
     21 # stuck in a non-interactive state.
     22 
     23 load_lib gdbserver-support.exp
     24 
     25 standard_testfile
     26 
     27 require allow_gdbserver_tests
     28 # The test-case uses "spawn -pty", which creates a pty on build, which gdb
     29 # cannot use on remote host.
     30 require {!is_remote host}
     31 
     32 save_vars { GDBFLAGS } {
     33     # If GDB and GDBserver are both running locally, set the sysroot to avoid
     34     # reading files via the remote protocol.
     35     if { ![is_remote host] && ![is_remote target] } {
     36 	set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
     37     }
     38 
     39     if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile}]} {
     40 	return -1
     41     }
     42 }
     43 
     44 # Make sure we're disconnected, in case we're testing with an
     45 # extended-remote board, therefore already connected.
     46 gdb_test "disconnect" ".*"
     47 
     48 # Start gdbserver.
     49 set res [gdbserver_spawn "${binfile}"]
     50 set gdbserver_protocol [lindex $res 0]
     51 set gdbserver_gdbport [lindex $res 1]
     52 set gdbserver_pid [exp_pid -i $server_spawn_id]
     53 
     54 # Save the main UI's spawn ID.
     55 set gdb_main_spawn_id $gdb_spawn_id
     56 
     57 # Create the new PTY for the secondary console UI, issue the 'new-ui'
     58 # command, and wait for a prompt on the second UI.
     59 spawn -pty
     60 set extra_spawn_id $spawn_id
     61 set extra_tty_name $spawn_out(slave,name)
     62 gdb_test_multiple "new-ui console $extra_tty_name" "new-ui" {
     63     -re "New UI allocated\r\n$gdb_prompt $" {
     64 	pass $gdb_test_name
     65     }
     66 }
     67 with_spawn_id $extra_spawn_id {
     68     gdb_test_multiple "" "initial prompt on extra console" {
     69 	-re "$gdb_prompt $" {
     70 	    pass $gdb_test_name
     71 	}
     72     }
     73 }
     74 
     75 # Connect to the remote and continue its execution from the other UI.
     76 with_spawn_id $extra_spawn_id {
     77     gdb_test "target $gdbserver_protocol $gdbserver_gdbport" ".*" \
     78 	"connect to gdbserver"
     79 
     80     # Issue a continue and consume the response.  Don't expect a prompt.
     81     gdb_test_multiple "continue" "continue - extra UI" {
     82 	-re  "\r\nContinuing\.\r\n" {
     83 	    pass $gdb_test_name
     84 	}
     85     }
     86 }
     87 
     88 # We're going to kill the gdbserver, but before we do, lets make sure
     89 # that the inferior has started executing.
     90 with_spawn_id $server_spawn_id {
     91     gdb_test_multiple "" "ensure inferior is running" {
     92 	-re "@@XX@@ Inferior Starting @@XX@@" {
     93 	    pass $gdb_test_name
     94 	}
     95 	timeout {
     96 	    fail $gdb_test_name
     97 	}
     98     }
     99 }
    100 
    101 # Interact with the main UI.
    102 with_spawn_id $gdb_main_spawn_id {
    103     gdb_test "echo hello\\n" "hello" "interact with GDB's main UI"
    104 }
    105 
    106 # Get the gdbserver PID.
    107 set gdbserver_pid 0
    108 with_spawn_id $gdb_main_spawn_id {
    109     gdb_test -no-prompt-anchor "interrupt"
    110 
    111     gdb_test_multiple "" "interrupt arrived" {
    112 	-re "Program received signal SIGINT, Interrupt\\.\r\n" {
    113 	    pass $gdb_test_name
    114 	}
    115     }
    116 
    117     gdb_test_multiple "p server_pid" "" {
    118 	-re -wrap " = ($decimal)" {
    119 	    set gdbserver_pid $expect_out(1,string)
    120 	    pass $gdb_test_name
    121 	}
    122     }
    123 
    124     gdb_test_multiple continue "" {
    125 	-re "Continuing\\.\r\n" {
    126 	    pass $gdb_test_name
    127 	}
    128     }
    129 }
    130 
    131 if { $gdbserver_pid == 0 } {
    132     return
    133 }
    134 
    135 # Now kill the gdbserver.
    136 remote_exec target "kill -9 $gdbserver_pid"
    137 
    138 # We expect to land back at a GDB prompt in both UIs, however there is
    139 # currently an issue that in the original UI GDB doesn't reprint its
    140 # prompt.  That said, getting a prompt isn't the point of this test.
    141 # The point is that we should be able to interact with GDB from either
    142 # interpreter now.
    143 
    144 with_spawn_id $gdb_main_spawn_id {
    145     gdb_test_multiple "" "remote connection closed - main UI" {
    146 	-re -wrap "Remote connection closed" {
    147 	    pass $gdb_test_name
    148 	}
    149     }
    150 }
    151 
    152 with_spawn_id $gdb_main_spawn_id {
    153     gdb_test "echo" "" \
    154 	"main UI, prompt after gdbserver dies"
    155 }
    156 
    157 with_spawn_id $extra_spawn_id {
    158     gdb_test "echo" "" \
    159 	"extra UI, prompt after gdbserver dies"
    160 }
    161