1# This testcase is part of GDB, the GNU debugger.
2#
3# Copyright 2013-2023 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# Check that GDB handles GDBserver disconnecting abruptly, in several
19# scenarios.
20
21load_lib gdbserver-support.exp
22
23standard_testfile
24
25if {[skip_gdbserver_tests]} {
26    return 0
27}
28
29if { [build_executable "failed to prepare" ${testfile}] } {
30    return -1
31}
32
33# Global control variable used by the proc prepare.  Should be set to
34# either 'inferior' or 'server'.
35#
36# In the proc prepare we start gdbserver and extract a pid, which will
37# later be killed by calling the proc kill_server.
38#
39# When KILL_PID_OF is set to 'inferior' then the pid we kill is that
40# of the inferior running under gdbserver, when this process dies
41# gdbserver itself will exit.
42#
43# When KILL_PID_OF is set to 'server' then the pid we kill is that of
44# the gdbserver itself, this is a much more aggressive strategy and
45# exposes different bugs within GDB.
46set kill_pid_of "inferior"
47
48# Spawn GDBserver, run to main, extract GDBserver's PID and save it in
49# the SERVER_PID global.
50
51proc prepare {} {
52    global binfile gdb_prompt srcfile decimal
53    global server_pid
54    global GDBFLAGS
55
56    save_vars { GDBFLAGS } {
57	# If GDB and GDBserver are both running locally, set the sysroot to avoid
58	# reading files via the remote protocol.
59	if { ![is_remote host] && ![is_remote target] } {
60	    set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
61	}
62
63	clean_restart $binfile
64    }
65
66    # Make sure we're disconnected, in case we're testing with an
67    # extended-remote board, therefore already connected.
68    gdb_test "disconnect" ".*"
69
70    gdbserver_run ""
71
72    # Continue past server_pid assignment.  We do this for both scenarios,
73    # to avoid doing a backtrace from _start, which may not trigger remote
74    # communication.
75    gdb_breakpoint ${srcfile}:[gdb_get_line_number "i = 0;"]
76    gdb_continue_to_breakpoint "after server_pid assignment"
77
78    if { $::kill_pid_of == "inferior" } {
79	# Get the pid of GDBServer.
80	set test "p server_pid"
81	set server_pid 0
82	gdb_test_multiple $test $test {
83	    -re " = ($decimal)\r\n$gdb_prompt $" {
84		set server_pid $expect_out(1,string)
85		pass $test
86	    }
87	}
88    } else {
89	set server_pid [exp_pid -i $::server_spawn_id]
90    }
91
92    if {$server_pid == 0} {
93	return 0
94    }
95
96    return 1
97}
98
99# Kill GDBserver using the PID saved by prepare.
100
101proc kill_server {} {
102    global server_pid
103
104    remote_exec target "kill -9 $server_pid"
105}
106
107# Test issuing "tstatus" right after the connection is dropped.
108
109proc_with_prefix test_tstatus {} {
110    if ![prepare] {
111	return
112    }
113
114    kill_server
115
116    # Enable trace status packet which is disabled after the
117    # connection if the remote target doesn't support tracepoint at
118    # all.  Otherwise, no RSP packet is sent out.
119    gdb_test_no_output "set remote trace-status-packet on"
120
121    # Force GDB to talk with GDBserver, so that we can get the
122    # "connection closed" error.
123    gdb_test "tstatus" {Remote connection closed|Remote communication error\.  Target disconnected\.: Connection reset by peer\.}
124}
125
126# Test unwinding with no debug/unwind info, right after the connection
127# is dropped.
128
129proc_with_prefix test_unwind_nosyms {} {
130    if ![prepare] {
131	return
132    }
133
134    # Remove symbols, so that we try to unwind with one of the
135    # heuristic unwinders, and read memory from within its sniffer.
136    gdb_unload
137
138    kill_server
139
140    gdb_test "bt" "(Target disconnected|Remote connection closed|Remote communication error).*"
141}
142
143# Test unwinding with debug/unwind info, right after the connection is
144# dropped.
145
146proc_with_prefix test_unwind_syms {} {
147    if ![prepare] {
148	return
149    }
150
151    kill_server
152
153    gdb_test "bt" "(Target disconnected|Remote connection closed|Remote communication error).*"
154}
155
156# Test performing a stepi right after the connection is dropped.
157
158proc_with_prefix test_stepi {} {
159    if ![prepare] {
160	return
161    }
162
163    kill_server
164
165    gdb_test "stepi" "(Target disconnected|Remote connection closed|Remote communication error).*"
166}
167
168# Run each test twice, see the description of KILL_PID_OF earlier in
169# this file for more details.
170
171foreach_with_prefix kill_pid_of { "inferior" "server" } {
172    test_tstatus
173    test_unwind_nosyms
174    test_unwind_syms
175    test_stepi
176}
177