summaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.server/server-kill.exp
blob: 4125e5bf92daab969703806205ce6683dc398ca2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# This testcase is part of GDB, the GNU debugger.
#
# Copyright 2013-2021 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 <http://www.gnu.org/licenses/>.

# Check that GDB handles GDBserver disconnecting abruptly, in several
# scenarios.

load_lib gdbserver-support.exp

standard_testfile

if {[skip_gdbserver_tests]} {
    return 0
}

if { [build_executable "failed to prepare" ${testfile}] } {
    return -1
}

# Global control variable used by the proc prepare.  Should be set to
# either 'inferior' or 'server'.
#
# In the proc prepare we start gdbserver and extract a pid, which will
# later be killed by calling the proc kill_server.
#
# When KILL_PID_OF is set to 'inferior' then the pid we kill is that
# of the inferior running under gdbserver, when this process dies
# gdbserver itself will exit.
#
# When KILL_PID_OF is set to 'server' then the pid we kill is that of
# the gdbserver itself, this is a much more aggressive strategy and
# exposes different bugs within GDB.
set kill_pid_of "inferior"

# Spawn GDBserver, run to main, extract GDBserver's PID and save it in
# the SERVER_PID global.

proc prepare {} {
    global binfile gdb_prompt srcfile decimal
    global server_pid
    global GDBFLAGS

    save_vars { GDBFLAGS } {
	# If GDB and GDBserver are both running locally, set the sysroot to avoid
	# reading files via the remote protocol.
	if { ![is_remote host] && ![is_remote target] } {
	    set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
	}

	clean_restart $binfile
    }

    # Make sure we're disconnected, in case we're testing with an
    # extended-remote board, therefore already connected.
    gdb_test "disconnect" ".*"

    gdbserver_run ""

    # Continue past server_pid assignment.  We do this for both scenarios,
    # to avoid doing a backtrace from _start, which may not trigger remote
    # communication.
    gdb_breakpoint ${srcfile}:[gdb_get_line_number "i = 0;"]
    gdb_continue_to_breakpoint "after server_pid assignment"

    if { $::kill_pid_of == "inferior" } {
	# Get the pid of GDBServer.
	set test "p server_pid"
	set server_pid 0
	gdb_test_multiple $test $test {
	    -re " = ($decimal)\r\n$gdb_prompt $" {
		set server_pid $expect_out(1,string)
		pass $test
	    }
	}
    } else {
	set server_pid [exp_pid -i $::server_spawn_id]
    }

    if {$server_pid == 0} {
	return 0
    }

    return 1
}

# Kill GDBserver using the PID saved by prepare.

proc kill_server {} {
    global server_pid

    remote_exec target "kill -9 $server_pid"
}

# Test issuing "tstatus" right after the connection is dropped.

proc_with_prefix test_tstatus {} {
    if ![prepare] {
	return
    }

    kill_server

    # Enable trace status packet which is disabled after the
    # connection if the remote target doesn't support tracepoint at
    # all.  Otherwise, no RSP packet is sent out.
    gdb_test_no_output "set remote trace-status-packet on"

    # Force GDB to talk with GDBserver, so that we can get the
    # "connection closed" error.
    gdb_test "tstatus" {Remote connection closed|Remote communication error\.  Target disconnected\.: Connection reset by peer\.}
}

# Test unwinding with no debug/unwind info, right after the connection
# is dropped.

proc_with_prefix test_unwind_nosyms {} {
    if ![prepare] {
	return
    }

    # Remove symbols, so that we try to unwind with one of the
    # heuristic unwinders, and read memory from within its sniffer.
    gdb_unload

    kill_server

    gdb_test "bt" "(Target disconnected|Remote connection closed|Remote communication error).*"
}

# Test unwinding with debug/unwind info, right after the connection is
# dropped.

proc_with_prefix test_unwind_syms {} {
    if ![prepare] {
	return
    }

    kill_server

    gdb_test "bt" "(Target disconnected|Remote connection closed|Remote communication error).*"
}

# Test performing a stepi right after the connection is dropped.

proc_with_prefix test_stepi {} {
    if ![prepare] {
	return
    }

    kill_server

    gdb_test "stepi" "(Target disconnected|Remote connection closed|Remote communication error).*"
}

# Run each test twice, see the description of KILL_PID_OF earlier in
# this file for more details.

foreach_with_prefix kill_pid_of { "inferior" "server" } {
    test_tstatus
    test_unwind_nosyms
    test_unwind_syms
    test_stepi
}