btrace: Resume recording after disconnect.

This patch allows gdbserver to continue recording after disconnect.  On
reconnect, the recorded data is accessible to gdb as if no disconnect happened.

A possible application for this feature is remotely examine bugs that occur
at irregular intervals, where maintaining a gdb connection is inconvenient.

This also fixes the issue mentioned here:
https://sourceware.org/ml/gdb-patches/2015-11/msg00424.html

Signed-off-by: Tim Wiederhake <tim.wiederhake@intel.com>

gdb/ChangeLog:
	* NEWS: Resume btrace on reconnect.
	* record-btrace.c: Added record-btrace.h include.
	(record_btrace_open): Split into this and ...
	(record_btrace_push_target): ... this.
	(record_btrace_disconnect): New function.
	(init_record_btrace_ops): Use record_btrace_disconnect.
	* record-btrace.h: New file.
	* remote.c: Added record-btrace.h include.
	(remote_start_remote): Check recording status.
	(remote_btrace_maybe_reopen): New function.

gdb/doc/ChangeLog:
	* gdb.texinfo: Resume btrace on reconnect.

gdb/testsuite/ChangeLog:

	* gdb.btrace/reconnect.c: New file.
	* gdb.btrace/reconnect.exp: New file.

Change-Id: I95e8b0ab8a89e58591aba0e63818cee82fd211bc
This commit is contained in:
Tim Wiederhake 2016-07-25 10:57:06 +02:00
parent 95804507f2
commit c0272db585
10 changed files with 259 additions and 14 deletions

View File

@ -1,3 +1,16 @@
2016-07-25 Tim Wiederhake <tim.wiederhake@intel.com>
* NEWS: Resume btrace on reconnect.
* record-btrace.c: Added record-btrace.h include.
(record_btrace_open): Split into this and ...
(record_btrace_push_target): ... this.
(record_btrace_disconnect): New function.
(init_record_btrace_ops): Use record_btrace_disconnect.
* record-btrace.h: New file.
* remote.c: Added record-btrace.h include.
(remote_start_remote): Check recording status.
(remote_btrace_maybe_reopen): New function.
2016-07-23 Gabriel Krisman Bertazi <gabriel@krisman.be>
* xml-syscall.c (get_syscalls_by_group): New.

View File

@ -3,6 +3,9 @@
*** Changes since GDB 7.11
* GDBserver now supports recording btrace without maintaining an active
GDB connection.
* GDB now supports a negative repeat count in the 'x' command to examine
memory backward from the given address. For example:

View File

@ -1,3 +1,7 @@
2016-07-25 Tim Wiederhake <tim.wiederhake@intel.com>
* gdb.texinfo: Resume btrace on reconnect.
2016-07-23 Gabriel Krisman Bertazi <gabriel@krisman.be>
* gdb.texinfo (Set Catchpoints): Add 'group' argument to catch

View File

@ -6657,7 +6657,9 @@ Hardware-supported instruction recording. This method does not record
data. Further, the data is collected in a ring buffer so old data will
be overwritten when the buffer is full. It allows limited reverse
execution. Variables and registers are not available during reverse
execution.
execution. In remote debugging, recording continues on disconnect.
Recorded data can be inspected after reconnecting. The recording may
be stopped using @code{record stop}.
The recording format can be specified as parameter. Without a parameter
the command chooses the recording format. The following recording

View File

@ -21,6 +21,7 @@
#include "defs.h"
#include "record.h"
#include "record-btrace.h"
#include "gdbthread.h"
#include "target.h"
#include "gdbcmd.h"
@ -199,6 +200,26 @@ record_btrace_handle_async_inferior_event (gdb_client_data data)
inferior_event_handler (INF_REG_EVENT, NULL);
}
/* See record-btrace.h. */
void
record_btrace_push_target (void)
{
const char *format;
record_btrace_auto_enable ();
push_target (&record_btrace_ops);
record_btrace_async_inferior_event_handler
= create_async_event_handler (record_btrace_handle_async_inferior_event,
NULL);
record_btrace_generating_corefile = 0;
format = btrace_format_short_string (record_btrace_conf.format);
observer_notify_record_changed (current_inferior (), 1, "btrace", format);
}
/* The to_open method of target record-btrace. */
static void
@ -206,7 +227,6 @@ record_btrace_open (const char *args, int from_tty)
{
struct cleanup *disable_chain;
struct thread_info *tp;
const char *format;
DEBUG ("open");
@ -226,17 +246,7 @@ record_btrace_open (const char *args, int from_tty)
make_cleanup (record_btrace_disable_callback, tp);
}
record_btrace_auto_enable ();
push_target (&record_btrace_ops);
record_btrace_async_inferior_event_handler
= create_async_event_handler (record_btrace_handle_async_inferior_event,
NULL);
record_btrace_generating_corefile = 0;
format = btrace_format_short_string (record_btrace_conf.format);
observer_notify_record_changed (current_inferior (), 1, "btrace", format);
record_btrace_push_target ();
discard_cleanups (disable_chain);
}
@ -257,6 +267,21 @@ record_btrace_stop_recording (struct target_ops *self)
btrace_disable (tp);
}
/* The to_disconnect method of target record-btrace. */
static void
record_btrace_disconnect (struct target_ops *self, const char *args,
int from_tty)
{
struct target_ops *beneath = self->beneath;
/* Do not stop recording, just clean up GDB side. */
unpush_target (self);
/* Forward disconnect. */
beneath->to_disconnect (beneath, args, from_tty);
}
/* The to_close method of target record-btrace. */
static void
@ -2824,7 +2849,7 @@ init_record_btrace_ops (void)
ops->to_close = record_btrace_close;
ops->to_async = record_btrace_async;
ops->to_detach = record_detach;
ops->to_disconnect = record_disconnect;
ops->to_disconnect = record_btrace_disconnect;
ops->to_mourn_inferior = record_mourn_inferior;
ops->to_kill = record_kill;
ops->to_stop_recording = record_btrace_stop_recording;

28
gdb/record-btrace.h Normal file
View File

@ -0,0 +1,28 @@
/* Branch trace support for GDB, the GNU debugger.
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Intel Corp. <tim.wiederhake@intel.com>
This file is part of GDB.
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/>. */
#ifndef RECORD_BTRACE_H
#define RECORD_BTRACE_H
/* Push the record_btrace target. */
extern void record_btrace_push_target (void);
#endif /* RECORD_BTRACE_H */

View File

@ -70,6 +70,7 @@
#include "ax-gdb.h"
#include "agent.h"
#include "btrace.h"
#include "record-btrace.h"
/* Temp hacks for tracepoint encoding migration. */
static char *target_buf;
@ -231,6 +232,8 @@ static int remote_can_run_breakpoint_commands (struct target_ops *self);
static void remote_btrace_reset (void);
static void remote_btrace_maybe_reopen (void);
static int stop_reply_queue_length (void);
static void readahead_cache_invalidate (void);
@ -4298,6 +4301,10 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p)
merge_uploaded_tracepoints (&uploaded_tps);
}
/* Possibly the target has been engaged in a btrace record started
previously; find out where things are at. */
remote_btrace_maybe_reopen ();
/* The thread and inferior lists are now synchronized with the
target, our symbols have been relocated, and we're merged the
target's tracepoints with ours. We're done with basic start
@ -12774,6 +12781,60 @@ btrace_read_config (struct btrace_config *conf)
}
}
/* Maybe reopen target btrace. */
static void
remote_btrace_maybe_reopen (void)
{
struct remote_state *rs = get_remote_state ();
struct cleanup *cleanup;
struct thread_info *tp;
int btrace_target_pushed = 0;
int warned = 0;
cleanup = make_cleanup_restore_current_thread ();
ALL_NON_EXITED_THREADS (tp)
{
set_general_thread (tp->ptid);
memset (&rs->btrace_config, 0x00, sizeof (struct btrace_config));
btrace_read_config (&rs->btrace_config);
if (rs->btrace_config.format == BTRACE_FORMAT_NONE)
continue;
#if !defined (HAVE_LIBIPT)
if (rs->btrace_config.format == BTRACE_FORMAT_PT)
{
if (!warned)
{
warned = 1;
warning (_("GDB does not support Intel Processor Trace. "
"\"record\" will not work in this session."));
}
continue;
}
#endif /* !defined (HAVE_LIBIPT) */
/* Push target, once, but before anything else happens. This way our
changes to the threads will be cleaned up by unpushing the target
in case btrace_read_config () throws. */
if (!btrace_target_pushed)
{
btrace_target_pushed = 1;
record_btrace_push_target ();
printf_filtered (_("Target is recording using %s.\n"),
btrace_format_string (rs->btrace_config.format));
}
tp->btrace.target = XCNEW (struct btrace_target_info);
tp->btrace.target->ptid = tp->ptid;
tp->btrace.target->conf = rs->btrace_config;
}
do_cleanups (cleanup);
}
/* Enable branch tracing. */
static struct btrace_target_info *

View File

@ -1,3 +1,8 @@
2016-07-25 Tim Wiederhake <tim.wiederhake@intel.com>
* gdb.btrace/reconnect.c: New file.
* gdb.btrace/reconnect.exp: New file.
2016-07-23 Gabriel Krisman Bertazi <gabriel@krisman.be>
* gdb.base/catch-syscall.exp (do_syscall_tests): Add call

View File

@ -0,0 +1,25 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2016 Free Software Foundation, Inc.
Contributed by Intel Corp. <tim.wiederhake@intel.com>
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/>. */
int
main (void)
{
return 0;
}

View File

@ -0,0 +1,79 @@
# This testcase is part of GDB, the GNU debugger.
#
# Copyright 2016 Free Software Foundation, Inc.
#
# Contributed by Intel Corp. <tim.wiederhake@intel.com>
#
# 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/>.
load_lib gdbserver-support.exp
if { [skip_btrace_tests] } { return -1 }
if { [skip_gdbserver_tests] } { return -1 }
standard_testfile
if [prepare_for_testing $testfile.exp $testfile $srcfile] {
return -1
}
# Make sure we're disconnected and no recording is active, in case
# we're testing with an extended-remote board, therefore already
# connected.
with_test_prefix "preparation" {
gdb_test "record stop" ".*"
gdb_test "disconnect" ".*"
}
# Start fresh gdbserver.
set gdbserver_reconnect_p 1
set res [gdbserver_start "" $binfile]
set gdbserver_protocol [lindex $res 0]
set gdbserver_gdbport [lindex $res 1]
gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport
# Create a record, check, reconnect
with_test_prefix "first" {
gdb_test_no_output "record btrace" "record btrace enable"
gdb_test "stepi 19" "0x.* in .* from target.*"
gdb_test "info record" [multi_line \
"Active record target: .*" \
"Recorded 19 instructions in .+ functions \\(. gaps\\) for thread 1 \\(Thread .*\\)."
]
gdb_test "disconnect" "Ending remote debugging."
gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport
}
# Test if we can access the recorded data from first connect.
# Note: BTS loses the first function call entry with its associated
# instructions for technical reasons. This is why we test for
# "a number between 10 and 19", so we catch at least the case where
# there are 0 instructions in the record.
with_test_prefix "second" {
gdb_test "info record" [multi_line \
"Active record target: .*" \
"Recorded 1. instructions in .+ functions \\(. gaps\\) for thread 1 \\(Thread .*\\)."
]
gdb_test "record stop" "Process record is stopped and all execution logs are deleted."
gdb_test "disconnect" "Ending remote debugging."
gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport
}
# Test that recording is now off.
with_test_prefix "third" {
gdb_test "info record" "No record target is currently active."
}