static struct frame_info *sentinel_frame;
+/* Number of calls to reinit_frame_cache. */
+static unsigned int frame_cache_generation = 0;
+
+/* See frame.h. */
+
+unsigned int
+get_frame_cache_generation ()
+{
+ return frame_cache_generation;
+}
+
/* The values behind the global "set backtrace ..." settings. */
set_backtrace_options user_set_backtrace_options;
{
struct frame_info *fi;
+ ++frame_cache_generation;
+
/* Tear down all frame caches. */
for (fi = sentinel_frame; fi != NULL; fi = fi->prev)
{
if (prev_frame->level == 0)
return prev_frame;
+ unsigned int entry_generation = get_frame_cache_generation ();
+
try
{
compute_frame_id (prev_frame);
}
catch (const gdb_exception &ex)
{
- prev_frame->next = NULL;
- this_frame->prev = NULL;
+ if (get_frame_cache_generation () == entry_generation)
+ {
+ prev_frame->next = NULL;
+ this_frame->prev = NULL;
+ }
throw;
}
# 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
return 0
}
-if { [prepare_for_testing "failed to prepare" ${testfile}] } {
+if { [build_executable "failed to prepare" ${testfile}] } {
return -1
}
-# Make sure we're disconnected, in case we're testing with an
-# extended-remote board, therefore already connected.
-gdb_test "disconnect" ".*"
+# 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
+
+ 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 ""
+ gdbserver_run ""
-# Continue past server_pid assignment.
-gdb_breakpoint ${srcfile}:[gdb_get_line_number "i = 0;"]
-gdb_continue_to_breakpoint "after server_pid assignment"
+ # Continue past server_pid assignment.
+ gdb_breakpoint ${srcfile}:[gdb_get_line_number "i = 0;"]
+ gdb_continue_to_breakpoint "after server_pid assignment"
-# Get the pid of GDBServer.
-set test "p server_pid"
-gdb_test_multiple $test $test {
- -re " = ($decimal)\r\n$gdb_prompt $" {
- set server_pid $expect_out(1,string)
- pass $test
+ # 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
+ }
}
+
+ if {$server_pid == 0} {
+ return 0
+ }
+
+ return 1
}
-if ![info exists server_pid] {
- 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).*"
}
-remote_exec target "kill -9 $server_pid"
+# Test unwinding with debug/unwind info, right after the connection is
+# dropped.
-# 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"
+proc_with_prefix test_unwind_syms {} {
+ if ![prepare] {
+ return
+ }
+
+ kill_server
+
+ gdb_test "bt" "(Target disconnected|Remote connection closed|Remote communication error).*"
+}
-# 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_tstatus
+test_unwind_nosyms
+test_unwind_syms