aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog62
-rw-r--r--gdb/Makefile.in2
-rw-r--r--gdb/NEWS9
-rw-r--r--gdb/btrace.c71
-rw-r--r--gdb/btrace.h11
-rw-r--r--gdb/common/btrace-common.h11
-rw-r--r--gdb/doc/ChangeLog7
-rw-r--r--gdb/doc/gdb.texinfo71
-rw-r--r--gdb/features/btrace-conf.dtd10
-rw-r--r--gdb/gdbserver/ChangeLog17
-rw-r--r--gdb/gdbserver/linux-low.c35
-rw-r--r--gdb/gdbserver/server.c78
-rw-r--r--gdb/gdbserver/target.h19
-rw-r--r--gdb/nat/linux-btrace.c140
-rw-r--r--gdb/nat/linux-btrace.h35
-rw-r--r--gdb/record-btrace.c69
-rw-r--r--gdb/remote.c85
-rw-r--r--gdb/target-debug.h4
-rw-r--r--gdb/target-delegates.c45
-rw-r--r--gdb/target.c12
-rw-r--r--gdb/target.h24
-rw-r--r--gdb/testsuite/ChangeLog12
-rw-r--r--gdb/testsuite/gdb.btrace/delta.exp4
-rw-r--r--gdb/testsuite/gdb.btrace/enable.exp4
-rw-r--r--gdb/testsuite/gdb.btrace/finish.exp1
-rw-r--r--gdb/testsuite/gdb.btrace/instruction_history.exp2
-rw-r--r--gdb/testsuite/gdb.btrace/next.exp2
-rw-r--r--gdb/testsuite/gdb.btrace/nexti.exp2
-rw-r--r--gdb/testsuite/gdb.btrace/nohist.exp1
-rw-r--r--gdb/testsuite/gdb.btrace/step.exp2
-rw-r--r--gdb/testsuite/gdb.btrace/stepi.exp2
-rw-r--r--gdb/x86-linux-nat.c16
32 files changed, 775 insertions, 90 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 5989460..57ad061 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,67 @@
2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
+ * Makefile.in (XMLFILES): Add btrace-conf.dtd.
+ * x86-linux-nat.c (x86_linux_enable_btrace): Update parameters.
+ (x86_linux_btrace_conf): New.
+ (x86_linux_create_target): Initialize to_btrace_conf.
+ * nat/linux-btrace.c (linux_enable_btrace): Update parameters.
+ Check format. Split into this and ...
+ (linux_enable_bts): ... this.
+ (linux_btrace_conf): New.
+ (perf_event_skip_record): Renamed into ...
+ (perf_event_skip_bts_record): ... this. Updated users.
+ (linux_disable_btrace): Split into this and ...
+ (linux_disable_bts): ... this.
+ (linux_read_btrace): Check format.
+ * nat/linux-btrace.h (linux_enable_btrace): Update parameters.
+ (linux_btrace_conf): New.
+ (btrace_target_info)<ptid>: Moved.
+ (btrace_target_info)<conf>: New.
+ (btrace_target_info): Split into this and ...
+ (btrace_tinfo_bts): ... this. Updated users.
+ * btrace.c (btrace_enable): Update parameters.
+ (btrace_conf, parse_xml_btrace_conf_bts, parse_xml_btrace_conf)
+ (btrace_conf_children, btrace_conf_attributes)
+ (btrace_conf_elements): New.
+ * btrace.h (btrace_enable): Update parameters.
+ (btrace_conf, parse_xml_btrace_conf): New.
+ * common/btrace-common.h (btrace_config): New.
+ * feature/btrace-conf.dtd: New.
+ * record-btrace.c (record_btrace_conf): New.
+ (record_btrace_cmdlist): New.
+ (record_btrace_enable_warn, record_btrace_open): Pass
+ &record_btrace_conf.
+ (record_btrace_info): Print recording format.
+ (cmd_record_btrace_bts_start): New.
+ (cmd_record_btrace_start): Call cmd_record_btrace_bts_start.
+ (_initialize_record_btrace): Add "record btrace bts" subcommand.
+ Add "record bts" alias command.
+ * remote.c (remote_state)<btrace_config>: New.
+ (remote_btrace_reset, PACKET_qXfer_btrace_conf): New.
+ (remote_protocol_features): Add qXfer:btrace-conf:read.
+ (remote_open_1): Call remote_btrace_reset.
+ (remote_xfer_partial): Handle TARGET_OBJECT_BTRACE_CONF.
+ (btrace_target_info)<conf>: New.
+ (btrace_sync_conf, btrace_read_config): New.
+ (remote_enable_btrace): Update parameters. Call btrace_sync_conf and
+ btrace_read_conf.
+ (remote_btrace_conf): New.
+ (init_remote_ops): Initialize to_btrace_conf.
+ (_initialize_remote): Add qXfer:btrace-conf packet.
+ * target.c (target_enable_btrace): Update parameters.
+ (target_btrace_conf): New.
+ * target.h (target_enable_btrace): Update parameters.
+ (target_btrace_conf): New.
+ (target_object)<TARGET_OBJECT_BTRACE_CONF>: New.
+ (target_ops)<to_enable_btrace>: Update parameters and comment.
+ (target_ops)<to_btrace_conf>: New.
+ * target-delegates: Regenerate.
+ * target-debug.h (target_debug_print_const_struct_btrace_config_p)
+ (target_debug_print_const_struct_btrace_target_info_p): New.
+ * NEWS: Announce new command and new packet.
+
+2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
+
* nat/linux-btrace.h (perf_event_buffer): New.
(btrace_target_info) <buffer, size, data_head>: Replace with ...
<bts>: ... this.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index bfebf61..00fb2cd 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -601,7 +601,7 @@ XMLFILES = $(srcdir)/features/gdb-target.dtd $(srcdir)/features/xinclude.dtd \
$(srcdir)/features/library-list-aix.dtd \
$(srcdir)/features/library-list-svr4.dtd $(srcdir)/features/osdata.dtd \
$(srcdir)/features/threads.dtd $(srcdir)/features/traceframe-info.dtd \
- $(srcdir)/features/btrace.dtd
+ $(srcdir)/features/btrace.dtd $(srcdir)/features/btrace-conf.dtd
# This is ser-unix.o for any system which supports a v7/BSD/SYSV/POSIX
# interface to the serial port. Hopefully if get ported to OS/2, VMS,
diff --git a/gdb/NEWS b/gdb/NEWS
index f19577a..b3f8f60 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -24,6 +24,10 @@ maint print symbol-cache-statistics
maint flush-symbol-cache
Flush the contents of the symbol cache.
+record btrace bts
+record bts
+ Start branch trace recording using Branch Trace Store (BTS) format.
+
* New options
set max-completions
@@ -45,6 +49,11 @@ maint show symbol-cache-size
** GDB now supports auto-loading of Python/Guile scripts contained in the
special section named `.debug_gdb_scripts'.
+* New remote packets
+
+qXfer:btrace-conf:read
+ Return the branch trace configuration for the current thread.
+
*** Changes in GDB 7.9
* GDB now supports hardware watchpoints on x86 GNU Hurd.
diff --git a/gdb/btrace.c b/gdb/btrace.c
index 4e32bdc..8930c3c 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -726,17 +726,17 @@ btrace_add_pc (struct thread_info *tp)
/* See btrace.h. */
void
-btrace_enable (struct thread_info *tp)
+btrace_enable (struct thread_info *tp, const struct btrace_config *conf)
{
if (tp->btrace.target != NULL)
return;
- if (!target_supports_btrace (BTRACE_FORMAT_BTS))
+ if (!target_supports_btrace (conf->format))
error (_("Target does not support branch tracing."));
DEBUG ("enable thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
- tp->btrace.target = target_enable_btrace (tp->ptid);
+ tp->btrace.target = target_enable_btrace (tp->ptid, conf);
/* Add an entry for the current PC so we start tracing from where we
enabled it. */
@@ -746,6 +746,17 @@ btrace_enable (struct thread_info *tp)
/* See btrace.h. */
+const struct btrace_config *
+btrace_conf (const struct btrace_thread_info *btinfo)
+{
+ if (btinfo->target == NULL)
+ return NULL;
+
+ return target_btrace_conf (btinfo->target);
+}
+
+/* See btrace.h. */
+
void
btrace_disable (struct thread_info *tp)
{
@@ -1106,6 +1117,60 @@ parse_xml_btrace (struct btrace_data *btrace, const char *buffer)
#endif /* !defined (HAVE_LIBEXPAT) */
}
+#if defined (HAVE_LIBEXPAT)
+
+/* Parse a btrace-conf "bts" xml record. */
+
+static void
+parse_xml_btrace_conf_bts (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, VEC (gdb_xml_value_s) *attributes)
+{
+ struct btrace_config *conf;
+
+ conf = user_data;
+ conf->format = BTRACE_FORMAT_BTS;
+}
+
+static const struct gdb_xml_element btrace_conf_children[] = {
+ { "bts", NULL, NULL, GDB_XML_EF_OPTIONAL, parse_xml_btrace_conf_bts, NULL },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_attribute btrace_conf_attributes[] = {
+ { "version", GDB_XML_AF_NONE, NULL, NULL },
+ { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element btrace_conf_elements[] = {
+ { "btrace-conf", btrace_conf_attributes, btrace_conf_children,
+ GDB_XML_EF_NONE, NULL, NULL },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+#endif /* defined (HAVE_LIBEXPAT) */
+
+/* See btrace.h. */
+
+void
+parse_xml_btrace_conf (struct btrace_config *conf, const char *xml)
+{
+ int errcode;
+
+#if defined (HAVE_LIBEXPAT)
+
+ errcode = gdb_xml_parse_quick (_("btrace-conf"), "btrace-conf.dtd",
+ btrace_conf_elements, xml, conf);
+ if (errcode != 0)
+ error (_("Error parsing branch trace configuration."));
+
+#else /* !defined (HAVE_LIBEXPAT) */
+
+ error (_("XML parsing is not supported."));
+
+#endif /* !defined (HAVE_LIBEXPAT) */
+}
+
/* See btrace.h. */
const struct btrace_insn *
diff --git a/gdb/btrace.h b/gdb/btrace.h
index 730cb5f..fde0619 100644
--- a/gdb/btrace.h
+++ b/gdb/btrace.h
@@ -215,7 +215,13 @@ struct btrace_thread_info
};
/* Enable branch tracing for a thread. */
-extern void btrace_enable (struct thread_info *tp);
+extern void btrace_enable (struct thread_info *tp,
+ const struct btrace_config *conf);
+
+/* Get the branch trace configuration for a thread.
+ Return NULL if branch tracing is not enabled for that thread. */
+extern const struct btrace_config *
+ btrace_conf (const struct btrace_thread_info *);
/* Disable branch tracing for a thread.
This will also delete the current branch trace data. */
@@ -238,6 +244,9 @@ extern void btrace_free_objfile (struct objfile *);
/* Parse a branch trace xml document XML into DATA. */
extern void parse_xml_btrace (struct btrace_data *data, const char *xml);
+/* Parse a branch trace configuration xml document XML into CONF. */
+extern void parse_xml_btrace_conf (struct btrace_config *conf, const char *xml);
+
/* Dereference a branch trace instruction iterator. Return a pointer to the
instruction the iterator points to. */
extern const struct btrace_insn *
diff --git a/gdb/common/btrace-common.h b/gdb/common/btrace-common.h
index f230dbc..1df5821 100644
--- a/gdb/common/btrace-common.h
+++ b/gdb/common/btrace-common.h
@@ -61,6 +61,17 @@ enum btrace_format
BTRACE_FORMAT_BTS
};
+/* A branch tracing configuration.
+
+ This describes the requested configuration as well as the actually
+ obtained configuration. */
+
+struct btrace_config
+{
+ /* The branch tracing format. */
+ enum btrace_format format;
+};
+
/* Branch trace in BTS format. */
struct btrace_data_bts
{
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 9c12d9a..b4a9cba 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,10 @@
+2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
+
+ * gdb.texinfo (Process Record and Replay): Describe the "record
+ btrace bts" command.
+ (General Query Packets): Describe qXfer:btrace-conf:read packet.
+ (Branch Trace Configuration Format): New.
+
2015-01-31 Gary Benson <gbenson@redhat.com>
Doug Evans <dje@google.com>
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index aee17d3..411f067 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -6372,9 +6372,13 @@ For architecture environments that support process record and replay,
@kindex record
@kindex record full
@kindex record btrace
+@kindex record btrace bts
+@kindex record bts
@kindex rec
@kindex rec full
@kindex rec btrace
+@kindex rec btrace bts
+@kindex rec bts
@item record @var{method}
This command starts the process record and replay target. The
recording method can be specified as parameter. Without a parameter
@@ -6387,13 +6391,25 @@ Full record/replay recording using @value{GDBN}'s software record and
replay implementation. This method allows replaying and reverse
execution.
-@item btrace
+@item btrace @var{format}
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 replay and
reverse execution.
-This recording method may not be available on all processors.
+The recording format can be specified as parameter. Without a parameter
+the command chooses the recording format. The following recording
+formats are available:
+
+@table @code
+@item bts
+@cindex branch trace store
+Use the @dfn{Branch Trace Store} (@acronym{BTS}) recording format. In
+this format, the processor stores a from/to record for each executed
+branch in the btrace ring buffer.
+@end table
+
+Not all recording formats may be available on all processors.
@end table
The process record and replay target can only debug a process that is
@@ -6571,9 +6587,9 @@ Maximum number of instructions that may be contained in the execution log.
@end itemize
@item btrace
-For the @code{btrace} recording method, it shows the number of
-instructions that have been recorded and the number of blocks of
-sequential control-flow that is formed by the recorded instructions.
+For the @code{btrace} recording method, it shows the recording format,
+the number of instructions that have been recorded and the number of blocks
+of sequential control-flow that is formed by the recorded instructions.
@end table
@kindex record delete
@@ -33066,7 +33082,8 @@ MS-Windows shared libraries (@pxref{Shared Libraries})
@item
Traceframe info (@pxref{Traceframe Info Format})
@item
-Branch trace (@pxref{Branch Trace Format})
+Branch trace (@pxref{Branch Trace Format},
+@pxref{Branch Trace Configuration Format})
@end itemize
@item zlib
@@ -34051,6 +34068,7 @@ Show the current setting of the target wait timeout.
* Thread List Format::
* Traceframe Info Format::
* Branch Trace Format::
+* Branch Trace Configuration Format::
@end menu
@node Overview
@@ -35723,6 +35741,11 @@ These are the currently defined stub features and their properties:
@tab @samp{-}
@tab Yes
+@item @samp{qXfer:btrace-conf:read}
+@tab No
+@tab @samp{-}
+@tab Yes
+
@item @samp{qXfer:features:read}
@tab No
@tab @samp{-}
@@ -35907,6 +35930,10 @@ The remote stub understands the @samp{qXfer:auxv:read} packet
The remote stub understands the @samp{qXfer:btrace:read}
packet (@pxref{qXfer btrace read}).
+@item qXfer:btrace-conf:read
+The remote stub understands the @samp{qXfer:btrace-conf:read}
+packet (@pxref{qXfer btrace-conf read}).
+
@item qXfer:features:read
The remote stub understands the @samp{qXfer:features:read} packet
(@pxref{qXfer target description read}).
@@ -36201,6 +36228,15 @@ If the trace buffer overflowed, returns an error indicating the overflow.
This packet is not probed by default; the remote stub must request it
by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
+@item qXfer:btrace-conf:read::@var{offset},@var{length}
+@anchor{qXfer btrace-conf read}
+
+Return a description of the current branch trace configuration.
+@xref{Branch Trace Configuration Format}.
+
+This packet is not probed by default; the remote stub must request it
+by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
+
@item qXfer:features:read:@var{annex}:@var{offset},@var{length}
@anchor{qXfer target description read}
Access the @dfn{target description}. @xref{Target Descriptions}. The
@@ -39005,6 +39041,29 @@ The formal DTD for the branch trace format is given below:
end CDATA #REQUIRED>
@end smallexample
+@node Branch Trace Configuration Format
+@section Branch Trace Configuration Format
+@cindex branch trace configuration format
+
+For each inferior thread, @value{GDBN} can obtain the branch trace
+configuration using the @samp{qXfer:btrace-conf:read}
+(@pxref{qXfer btrace-conf read}) packet.
+
+The configuration describes the branch trace format and configuration
+settings for that format.
+
+@value{GDBN} must be linked with the Expat library to support XML
+branch trace configuration discovery. @xref{Expat}.
+
+The formal DTD for the branch trace configuration format is given below:
+
+@smallexample
+<!ELEMENT btrace-conf (bts?)>
+<!ATTLIST btrace-conf version CDATA #FIXED "1.0">
+
+<!ELEMENT bts EMPTY>
+@end smallexample
+
@include agentexpr.texi
@node Target Descriptions
diff --git a/gdb/features/btrace-conf.dtd b/gdb/features/btrace-conf.dtd
new file mode 100644
index 0000000..ff54822
--- /dev/null
+++ b/gdb/features/btrace-conf.dtd
@@ -0,0 +1,10 @@
+<!-- Copyright (C) 2013-2015 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!ELEMENT btrace-conf (bts?)>
+<!ATTLIST btrace-conf version CDATA #FIXED "1.0">
+
+<!ELEMENT bts EMPTY>
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 636ad2e..d489ebf 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,22 @@
2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
+ * linux-low.c (linux_low_enable_btrace): Update parameters.
+ (linux_low_btrace_conf): New.
+ (linux_target_ops)<to_btrace_conf>: Initialize.
+ * server.c (current_btrace_conf): New.
+ (handle_btrace_enable): Rename to ...
+ (handle_btrace_enable_bts): ... this. Pass &current_btrace_conf
+ to target_enable_btrace. Update comment. Update users.
+ (handle_qxfer_btrace_conf): New.
+ (qxfer_packets): Add btrace-conf entry.
+ (handle_query): Report qXfer:btrace-conf:read as supported packet.
+ * target.h (target_ops)<enable_btrace>: Update parameters and comment.
+ (target_ops)<read_btrace_conf>: New.
+ (target_enable_btrace): Update parameters.
+ (target_read_btrace_conf): New.
+
+2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
+
* server.c (handle_btrace_general_set): Remove call to
target_supports_btrace.
(supported_btrace_packets): New.
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 8bc73a4..b311d4b 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -5938,11 +5938,11 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
/* See to_enable_btrace target method. */
static struct btrace_target_info *
-linux_low_enable_btrace (ptid_t ptid)
+linux_low_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
{
struct btrace_target_info *tinfo;
- tinfo = linux_enable_btrace (ptid);
+ tinfo = linux_enable_btrace (ptid, conf);
if (tinfo != NULL)
{
@@ -6020,6 +6020,35 @@ linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer,
btrace_data_fini (&btrace);
return 0;
}
+
+/* See to_btrace_conf target method. */
+
+static int
+linux_low_btrace_conf (const struct btrace_target_info *tinfo,
+ struct buffer *buffer)
+{
+ const struct btrace_config *conf;
+
+ buffer_grow_str (buffer, "<!DOCTYPE btrace-conf SYSTEM \"btrace-conf.dtd\">\n");
+ buffer_grow_str (buffer, "<btrace-conf version=\"1.0\">\n");
+
+ conf = linux_btrace_conf (tinfo);
+ if (conf != NULL)
+ {
+ switch (conf->format)
+ {
+ case BTRACE_FORMAT_NONE:
+ break;
+
+ case BTRACE_FORMAT_BTS:
+ buffer_xml_printf (buffer, "<bts/>\n");
+ break;
+ }
+ }
+
+ buffer_grow_str0 (buffer, "</btrace-conf>\n");
+ return 0;
+}
#endif /* HAVE_LINUX_BTRACE */
static struct target_ops linux_target_ops = {
@@ -6093,11 +6122,13 @@ static struct target_ops linux_target_ops = {
linux_low_enable_btrace,
linux_low_disable_btrace,
linux_low_read_btrace,
+ linux_low_btrace_conf,
#else
NULL,
NULL,
NULL,
NULL,
+ NULL,
#endif
linux_supports_range_stepping,
};
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 1756a1f..17ee5e1 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -122,6 +122,10 @@ struct vstop_notif
struct target_waitstatus status;
};
+/* The current btrace configuration. This is gdbserver's mirror of GDB's
+ btrace configuration. */
+static struct btrace_config current_btrace_conf;
+
DEFINE_QUEUE_P (notif_event_p);
/* Put a stop reply to the stop reply queue. */
@@ -381,15 +385,17 @@ write_qxfer_response (char *buf, const void *data, int len, int is_more)
PBUFSIZ - 2) + 1;
}
-/* Handle btrace enabling. */
+/* Handle btrace enabling in BTS format. */
static const char *
-handle_btrace_enable (struct thread_info *thread)
+handle_btrace_enable_bts (struct thread_info *thread)
{
if (thread->btrace != NULL)
return "E.Btrace already enabled.";
- thread->btrace = target_enable_btrace (thread->entry.id);
+ current_btrace_conf.format = BTRACE_FORMAT_BTS;
+ thread->btrace = target_enable_btrace (thread->entry.id,
+ &current_btrace_conf);
if (thread->btrace == NULL)
return "E.Could not enable btrace.";
@@ -443,7 +449,7 @@ handle_btrace_general_set (char *own_buf)
err = NULL;
if (strcmp (op, "bts") == 0)
- err = handle_btrace_enable (thread);
+ err = handle_btrace_enable_bts (thread);
else if (strcmp (op, "off") == 0)
err = handle_btrace_disable (thread);
else
@@ -1510,10 +1516,73 @@ handle_qxfer_btrace (const char *annex,
return len;
}
+/* Handle qXfer:btrace-conf:read. */
+
+static int
+handle_qxfer_btrace_conf (const char *annex,
+ gdb_byte *readbuf, const gdb_byte *writebuf,
+ ULONGEST offset, LONGEST len)
+{
+ static struct buffer cache;
+ struct thread_info *thread;
+ int result;
+
+ if (the_target->read_btrace_conf == NULL || writebuf != NULL)
+ return -2;
+
+ if (annex[0] != '\0' || !target_running ())
+ return -1;
+
+ if (ptid_equal (general_thread, null_ptid)
+ || ptid_equal (general_thread, minus_one_ptid))
+ {
+ strcpy (own_buf, "E.Must select a single thread.");
+ return -3;
+ }
+
+ thread = find_thread_ptid (general_thread);
+ if (thread == NULL)
+ {
+ strcpy (own_buf, "E.No such thread.");
+ return -3;
+ }
+
+ if (thread->btrace == NULL)
+ {
+ strcpy (own_buf, "E.Btrace not enabled.");
+ return -3;
+ }
+
+ if (offset == 0)
+ {
+ buffer_free (&cache);
+
+ result = target_read_btrace_conf (thread->btrace, &cache);
+ if (result != 0)
+ {
+ memcpy (own_buf, cache.buffer, cache.used_size);
+ return -3;
+ }
+ }
+ else if (offset > cache.used_size)
+ {
+ buffer_free (&cache);
+ return -3;
+ }
+
+ if (len > cache.used_size - offset)
+ len = cache.used_size - offset;
+
+ memcpy (readbuf, cache.buffer + offset, len);
+
+ return len;
+}
+
static const struct qxfer qxfer_packets[] =
{
{ "auxv", handle_qxfer_auxv },
{ "btrace", handle_qxfer_btrace },
+ { "btrace-conf", handle_qxfer_btrace_conf },
{ "fdpic", handle_qxfer_fdpic},
{ "features", handle_qxfer_features },
{ "libraries", handle_qxfer_libraries },
@@ -1698,6 +1767,7 @@ supported_btrace_packets (char *buf)
strcat (buf, ";Qbtrace:off+");
strcat (buf, ";qXfer:btrace:read+");
+ strcat (buf, ";qXfer:btrace-conf:read+");
}
/* Handle all of the extended 'q' packets. */
diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h
index ed57886..05feb36 100644
--- a/gdb/gdbserver/target.h
+++ b/gdb/gdbserver/target.h
@@ -357,9 +357,10 @@ struct target_ops
/* Check whether the target supports branch tracing. */
int (*supports_btrace) (struct target_ops *, enum btrace_format);
- /* Enable branch tracing for @ptid and allocate a branch trace target
- information struct for reading and for disabling branch trace. */
- struct btrace_target_info *(*enable_btrace) (ptid_t ptid);
+ /* Enable branch tracing for PTID based on CONF and allocate a branch trace
+ target information struct for reading and for disabling branch trace. */
+ struct btrace_target_info *(*enable_btrace)
+ (ptid_t ptid, const struct btrace_config *conf);
/* Disable branch tracing.
Returns zero on success, non-zero otherwise. */
@@ -371,6 +372,11 @@ struct target_ops
otherwise. */
int (*read_btrace) (struct btrace_target_info *, struct buffer *, int type);
+ /* Read the branch trace configuration into BUFFER.
+ Return 0 on success; print an error message into BUFFER and return -1
+ otherwise. */
+ int (*read_btrace_conf) (const struct btrace_target_info *, struct buffer *);
+
/* Return true if target supports range stepping. */
int (*supports_range_stepping) (void);
};
@@ -493,8 +499,8 @@ int kill_inferior (int);
(the_target->supports_btrace \
? (*the_target->supports_btrace) (the_target, format) : 0)
-#define target_enable_btrace(ptid) \
- (*the_target->enable_btrace) (ptid)
+#define target_enable_btrace(ptid, conf) \
+ (*the_target->enable_btrace) (ptid, conf)
#define target_disable_btrace(tinfo) \
(*the_target->disable_btrace) (tinfo)
@@ -502,6 +508,9 @@ int kill_inferior (int);
#define target_read_btrace(tinfo, buffer, type) \
(*the_target->read_btrace) (tinfo, buffer, type)
+#define target_read_btrace_conf(tinfo, buffer) \
+ (*the_target->read_btrace_conf) (tinfo, buffer)
+
#define target_supports_range_stepping() \
(the_target->supports_range_stepping ? \
(*the_target->supports_range_stepping) () : 0)
diff --git a/gdb/nat/linux-btrace.c b/gdb/nat/linux-btrace.c
index 5b22661..e827e92 100644
--- a/gdb/nat/linux-btrace.c
+++ b/gdb/nat/linux-btrace.c
@@ -90,8 +90,8 @@ perf_event_is_kernel_addr (const struct btrace_target_info *tinfo,
/* Check whether a perf event record should be skipped. */
static inline int
-perf_event_skip_record (const struct btrace_target_info *tinfo,
- const struct perf_event_bts *bts)
+perf_event_skip_bts_record (const struct btrace_target_info *tinfo,
+ const struct perf_event_bts *bts)
{
/* The hardware may report branches from kernel into user space. Branches
from user into kernel space will be suppressed. We filter the former to
@@ -194,7 +194,7 @@ perf_event_read_bts (struct btrace_target_info* tinfo, const uint8_t *begin,
break;
}
- if (perf_event_skip_record (tinfo, &psample->bts))
+ if (perf_event_skip_bts_record (tinfo, &psample->bts))
continue;
/* We found a valid sample, so we can complete the current block. */
@@ -395,39 +395,42 @@ linux_supports_btrace (struct target_ops *ops, enum btrace_format format)
internal_error (__FILE__, __LINE__, _("Unknown branch trace format"));
}
-/* See linux-btrace.h. */
+/* Enable branch tracing in BTS format. */
-struct btrace_target_info *
-linux_enable_btrace (ptid_t ptid)
+static struct btrace_target_info *
+linux_enable_bts (ptid_t ptid, const struct btrace_config *conf)
{
struct perf_event_mmap_page *header;
struct btrace_target_info *tinfo;
+ struct btrace_tinfo_bts *bts;
int pid, pg;
tinfo = xzalloc (sizeof (*tinfo));
tinfo->ptid = ptid;
+ tinfo->ptr_bits = 0;
- tinfo->attr.size = sizeof (tinfo->attr);
- tinfo->attr.type = PERF_TYPE_HARDWARE;
- tinfo->attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
- tinfo->attr.sample_period = 1;
+ tinfo->conf.format = BTRACE_FORMAT_BTS;
+ bts = &tinfo->variant.bts;
- /* We sample from and to address. */
- tinfo->attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_ADDR;
+ bts->attr.size = sizeof (bts->attr);
+ bts->attr.type = PERF_TYPE_HARDWARE;
+ bts->attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
+ bts->attr.sample_period = 1;
- tinfo->attr.exclude_kernel = 1;
- tinfo->attr.exclude_hv = 1;
- tinfo->attr.exclude_idle = 1;
+ /* We sample from and to address. */
+ bts->attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_ADDR;
- tinfo->ptr_bits = 0;
+ bts->attr.exclude_kernel = 1;
+ bts->attr.exclude_hv = 1;
+ bts->attr.exclude_idle = 1;
pid = ptid_get_lwp (ptid);
if (pid == 0)
pid = ptid_get_pid (ptid);
errno = 0;
- tinfo->file = syscall (SYS_perf_event_open, &tinfo->attr, pid, -1, -1, 0);
- if (tinfo->file < 0)
+ bts->file = syscall (SYS_perf_event_open, &bts->attr, pid, -1, -1, 0);
+ if (bts->file < 0)
goto err;
/* We try to allocate as much buffer as we can get.
@@ -437,7 +440,7 @@ linux_enable_btrace (ptid_t ptid)
{
/* The number of pages we request needs to be a power of two. */
header = mmap (NULL, ((1 << pg) + 1) * PAGE_SIZE, PROT_READ, MAP_SHARED,
- tinfo->file, 0);
+ bts->file, 0);
if (header != MAP_FAILED)
break;
}
@@ -445,17 +448,17 @@ linux_enable_btrace (ptid_t ptid)
if (header == MAP_FAILED)
goto err_file;
- tinfo->header = header;
- tinfo->bts.mem = ((const uint8_t *) header) + PAGE_SIZE;
- tinfo->bts.size = (1 << pg) * PAGE_SIZE;
- tinfo->bts.data_head = &header->data_head;
- tinfo->bts.last_head = 0;
+ bts->header = header;
+ bts->bts.mem = ((const uint8_t *) header) + PAGE_SIZE;
+ bts->bts.size = (1 << pg) * PAGE_SIZE;
+ bts->bts.data_head = &header->data_head;
+ bts->bts.last_head = 0;
return tinfo;
err_file:
/* We were not able to allocate any buffer. */
- close (tinfo->file);
+ close (bts->file);
err:
xfree (tinfo);
@@ -464,16 +467,60 @@ linux_enable_btrace (ptid_t ptid)
/* See linux-btrace.h. */
-enum btrace_error
-linux_disable_btrace (struct btrace_target_info *tinfo)
+struct btrace_target_info *
+linux_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
+{
+ struct btrace_target_info *tinfo;
+
+ tinfo = NULL;
+ switch (conf->format)
+ {
+ case BTRACE_FORMAT_NONE:
+ break;
+
+ case BTRACE_FORMAT_BTS:
+ tinfo = linux_enable_bts (ptid, conf);
+ break;
+ }
+
+ return tinfo;
+}
+
+/* Disable BTS tracing. */
+
+static enum btrace_error
+linux_disable_bts (struct btrace_tinfo_bts *tinfo)
{
munmap((void *) tinfo->header, tinfo->bts.size + PAGE_SIZE);
close (tinfo->file);
- xfree (tinfo);
return BTRACE_ERR_NONE;
}
+/* See linux-btrace.h. */
+
+enum btrace_error
+linux_disable_btrace (struct btrace_target_info *tinfo)
+{
+ enum btrace_error errcode;
+
+ errcode = BTRACE_ERR_NOT_SUPPORTED;
+ switch (tinfo->conf.format)
+ {
+ case BTRACE_FORMAT_NONE:
+ break;
+
+ case BTRACE_FORMAT_BTS:
+ errcode = linux_disable_bts (&tinfo->variant.bts);
+ break;
+ }
+
+ if (errcode == BTRACE_ERR_NONE)
+ xfree (tinfo);
+
+ return errcode;
+}
+
/* Read branch trace data in BTS format for the thread given by TINFO into
BTRACE using the TYPE reading method. */
@@ -487,7 +534,7 @@ linux_read_bts (struct btrace_data_bts *btrace,
unsigned long long data_head, data_tail, buffer_size, size;
unsigned int retries = 5;
- pevent = &tinfo->bts;
+ pevent = &tinfo->variant.bts.bts;
/* For delta reads, we return at least the partial last block containing
the current PC. */
@@ -570,11 +617,28 @@ linux_read_btrace (struct btrace_data *btrace,
struct btrace_target_info *tinfo,
enum btrace_read_type type)
{
- /* We read btrace in BTS format. */
- btrace->format = BTRACE_FORMAT_BTS;
- btrace->variant.bts.blocks = NULL;
+ switch (tinfo->conf.format)
+ {
+ case BTRACE_FORMAT_NONE:
+ return BTRACE_ERR_NOT_SUPPORTED;
+
+ case BTRACE_FORMAT_BTS:
+ /* We read btrace in BTS format. */
+ btrace->format = BTRACE_FORMAT_BTS;
+ btrace->variant.bts.blocks = NULL;
+
+ return linux_read_bts (&btrace->variant.bts, tinfo, type);
+ }
+
+ internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
+}
+
+/* See linux-btrace.h. */
- return linux_read_bts (&btrace->variant.bts, tinfo, type);
+const struct btrace_config *
+linux_btrace_conf (const struct btrace_target_info *tinfo)
+{
+ return &tinfo->conf;
}
#else /* !HAVE_LINUX_PERF_EVENT_H */
@@ -590,7 +654,7 @@ linux_supports_btrace (struct target_ops *ops, enum btrace_format format)
/* See linux-btrace.h. */
struct btrace_target_info *
-linux_enable_btrace (ptid_t ptid)
+linux_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
{
return NULL;
}
@@ -613,4 +677,12 @@ linux_read_btrace (struct btrace_data *btrace,
return BTRACE_ERR_NOT_SUPPORTED;
}
+/* See linux-btrace.h. */
+
+const struct btrace_config *
+linux_btrace_conf (const struct btrace_target_info *tinfo)
+{
+ return NULL;
+}
+
#endif /* !HAVE_LINUX_PERF_EVENT_H */
diff --git a/gdb/nat/linux-btrace.h b/gdb/nat/linux-btrace.h
index 602a571..12cdcde 100644
--- a/gdb/nat/linux-btrace.h
+++ b/gdb/nat/linux-btrace.h
@@ -48,18 +48,13 @@ struct perf_event_buffer
/* The data_head value from the last read. */
unsigned long long last_head;
};
-#endif /* HAVE_LINUX_PERF_EVENT_H */
-/* Branch trace target information per thread. */
-struct btrace_target_info
+/* Branch trace target information for BTS tracing. */
+struct btrace_tinfo_bts
{
-#if HAVE_LINUX_PERF_EVENT_H
/* The Linux perf_event configuration for collecting the branch trace. */
struct perf_event_attr attr;
- /* The ptid of this thread. */
- ptid_t ptid;
-
/* The perf event file. */
int file;
@@ -68,6 +63,25 @@ struct btrace_target_info
/* The BTS perf event buffer. */
struct perf_event_buffer bts;
+};
+#endif /* HAVE_LINUX_PERF_EVENT_H */
+
+/* Branch trace target information per thread. */
+struct btrace_target_info
+{
+ /* The ptid of this thread. */
+ ptid_t ptid;
+
+ /* The obtained branch trace configuration. */
+ struct btrace_config conf;
+
+#if HAVE_LINUX_PERF_EVENT_H
+ /* The branch tracing format specific information. */
+ union
+ {
+ /* CONF.FORMAT == BTRACE_FORMAT_BTS. */
+ struct btrace_tinfo_bts bts;
+ } variant;
#endif /* HAVE_LINUX_PERF_EVENT_H */
/* The size of a pointer in bits for this thread.
@@ -80,7 +94,8 @@ struct btrace_target_info
extern int linux_supports_btrace (struct target_ops *, enum btrace_format);
/* See to_enable_btrace in target.h. */
-extern struct btrace_target_info *linux_enable_btrace (ptid_t ptid);
+extern struct btrace_target_info *
+ linux_enable_btrace (ptid_t ptid, const struct btrace_config *conf);
/* See to_disable_btrace in target.h. */
extern enum btrace_error linux_disable_btrace (struct btrace_target_info *ti);
@@ -90,4 +105,8 @@ extern enum btrace_error linux_read_btrace (struct btrace_data *btrace,
struct btrace_target_info *btinfo,
enum btrace_read_type type);
+/* See to_btrace_conf in target.h. */
+extern const struct btrace_config *
+ linux_btrace_conf (const struct btrace_target_info *);
+
#endif /* LINUX_BTRACE_H */
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 99c6684..5c6ee43 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -70,6 +70,12 @@ static struct async_event_handler *record_btrace_async_inferior_event_handler;
/* A flag indicating that we are currently generating a core file. */
static int record_btrace_generating_corefile;
+/* The current branch trace configuration. */
+static struct btrace_config record_btrace_conf;
+
+/* Command list for "record btrace". */
+static struct cmd_list_element *record_btrace_cmdlist;
+
/* Print a record-btrace debug message. Use do ... while (0) to avoid
ambiguities when used in if statements. */
@@ -132,7 +138,7 @@ record_btrace_enable_warn (struct thread_info *tp)
volatile struct gdb_exception error;
TRY_CATCH (error, RETURN_MASK_ERROR)
- btrace_enable (tp);
+ btrace_enable (tp, &record_btrace_conf);
if (error.message != NULL)
warning ("%s", error.message);
@@ -208,7 +214,7 @@ record_btrace_open (const char *args, int from_tty)
ALL_NON_EXITED_THREADS (tp)
if (args == NULL || *args == 0 || number_is_in_list (args, tp->num))
{
- btrace_enable (tp);
+ btrace_enable (tp, &record_btrace_conf);
make_cleanup (record_btrace_disable_callback, tp);
}
@@ -285,6 +291,7 @@ static void
record_btrace_info (struct target_ops *self)
{
struct btrace_thread_info *btinfo;
+ const struct btrace_config *conf;
struct thread_info *tp;
unsigned int insns, calls;
@@ -294,13 +301,18 @@ record_btrace_info (struct target_ops *self)
if (tp == NULL)
error (_("No thread."));
+ btinfo = &tp->btrace;
+
+ conf = btrace_conf (btinfo);
+ if (conf != NULL)
+ printf_unfiltered (_("Recording format: %s.\n"),
+ btrace_format_string (conf->format));
+
btrace_fetch (tp);
insns = 0;
calls = 0;
- btinfo = &tp->btrace;
-
if (!btrace_is_empty (tp))
{
struct btrace_call_iterator call;
@@ -1991,15 +2003,48 @@ init_record_btrace_ops (void)
ops->to_magic = OPS_MAGIC;
}
+/* Start recording in BTS format. */
+
+static void
+cmd_record_btrace_bts_start (char *args, int from_tty)
+{
+ volatile struct gdb_exception exception;
+
+ if (args != NULL && *args != 0)
+ error (_("Invalid argument."));
+
+ record_btrace_conf.format = BTRACE_FORMAT_BTS;
+
+ TRY_CATCH (exception, RETURN_MASK_ALL)
+ execute_command ("target record-btrace", from_tty);
+
+ if (exception.error != 0)
+ {
+ record_btrace_conf.format = BTRACE_FORMAT_NONE;
+ throw_exception (exception);
+ }
+}
+
/* Alias for "target record". */
static void
cmd_record_btrace_start (char *args, int from_tty)
{
+ volatile struct gdb_exception exception;
+
if (args != NULL && *args != 0)
error (_("Invalid argument."));
- execute_command ("target record-btrace", from_tty);
+ record_btrace_conf.format = BTRACE_FORMAT_BTS;
+
+ TRY_CATCH (exception, RETURN_MASK_ALL)
+ execute_command ("target record-btrace", from_tty);
+
+ if (exception.error == 0)
+ return;
+
+ record_btrace_conf.format = BTRACE_FORMAT_NONE;
+ throw_exception (exception);
}
/* The "set record btrace" command. */
@@ -2035,11 +2080,19 @@ void _initialize_record_btrace (void);
void
_initialize_record_btrace (void)
{
- add_cmd ("btrace", class_obscure, cmd_record_btrace_start,
- _("Start branch trace recording."),
- &record_cmdlist);
+ add_prefix_cmd ("btrace", class_obscure, cmd_record_btrace_start,
+ _("Start branch trace recording."), &record_btrace_cmdlist,
+ "record btrace ", 0, &record_cmdlist);
add_alias_cmd ("b", "btrace", class_obscure, 1, &record_cmdlist);
+ add_cmd ("bts", class_obscure, cmd_record_btrace_bts_start,
+ _("\
+Start branch trace recording in Branch Trace Store (BTS) format.\n\n\
+The processor stores a from/to record for each branch into a cyclic buffer.\n\
+This format may not be available on all processors."),
+ &record_btrace_cmdlist);
+ add_alias_cmd ("bts", "btrace bts", class_obscure, 1, &record_cmdlist);
+
add_prefix_cmd ("btrace", class_support, cmd_set_record_btrace,
_("Set record options"), &set_record_btrace_cmdlist,
"set record btrace ", 0, &set_record_cmdlist);
diff --git a/gdb/remote.c b/gdb/remote.c
index 61420ec..0226f3f 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -221,6 +221,8 @@ static int remote_supports_cond_breakpoints (struct target_ops *self);
static int remote_can_run_breakpoint_commands (struct target_ops *self);
+static void remote_btrace_reset (void);
+
/* For "remote". */
static struct cmd_list_element *remote_cmdlist;
@@ -371,6 +373,9 @@ struct remote_state
/* The state of remote notification. */
struct remote_notif_state *notif_state;
+
+ /* The branch trace configuration. */
+ struct btrace_config btrace_config;
};
/* Private data that we'll store in (struct thread_info)->private. */
@@ -1327,6 +1332,9 @@ enum {
/* Support for qXfer:libraries-svr4:read with a non-empty annex. */
PACKET_augmented_libraries_svr4_read_feature,
+ /* Support for the qXfer:btrace-conf:read packet. */
+ PACKET_qXfer_btrace_conf,
+
PACKET_MAX
};
@@ -4010,7 +4018,9 @@ static const struct protocol_feature remote_protocol_features[] = {
{ "Qbtrace:off", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace_off },
{ "Qbtrace:bts", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace_bts },
{ "qXfer:btrace:read", PACKET_DISABLE, remote_supported_packet,
- PACKET_qXfer_btrace }
+ PACKET_qXfer_btrace },
+ { "qXfer:btrace-conf:read", PACKET_DISABLE, remote_supported_packet,
+ PACKET_qXfer_btrace_conf }
};
static char *remote_support_xml;
@@ -4358,6 +4368,8 @@ remote_open_1 (const char *name, int from_tty,
}
}
+ remote_btrace_reset ();
+
if (target_async_permitted)
wait_forever_enabled_p = 1;
}
@@ -8945,6 +8957,11 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object,
xfered_len,
&remote_protocol_packets[PACKET_qXfer_btrace]);
+ case TARGET_OBJECT_BTRACE_CONF:
+ return remote_read_qxfer (ops, "btrace-conf", annex, readbuf, offset,
+ len, xfered_len,
+ &remote_protocol_packets[PACKET_qXfer_btrace_conf]);
+
default:
return TARGET_XFER_E_IO;
}
@@ -11319,8 +11336,21 @@ struct btrace_target_info
{
/* The ptid of the traced thread. */
ptid_t ptid;
+
+ /* The obtained branch trace configuration. */
+ struct btrace_config conf;
};
+/* Reset our idea of our target's btrace configuration. */
+
+static void
+remote_btrace_reset (void)
+{
+ struct remote_state *rs = get_remote_state ();
+
+ memset (&rs->btrace_config, 0, sizeof (rs->btrace_config));
+}
+
/* Check whether the target supports branch tracing. */
static int
@@ -11343,20 +11373,52 @@ remote_supports_btrace (struct target_ops *self, enum btrace_format format)
internal_error (__FILE__, __LINE__, _("Unknown branch trace format"));
}
+/* Synchronize the configuration with the target. */
+
+static void
+btrace_sync_conf (const struct btrace_config *conf)
+{
+ /* Nothing to do for now. */
+}
+
+/* Read the current thread's btrace configuration from the target and
+ store it into CONF. */
+
+static void
+btrace_read_config (struct btrace_config *conf)
+{
+ char *xml;
+
+ xml = target_read_stralloc (&current_target,
+ TARGET_OBJECT_BTRACE_CONF, "");
+ if (xml != NULL)
+ {
+ struct cleanup *cleanup;
+
+ cleanup = make_cleanup (xfree, xml);
+ parse_xml_btrace_conf (conf, xml);
+ do_cleanups (cleanup);
+ }
+}
+
/* Enable branch tracing. */
static struct btrace_target_info *
-remote_enable_btrace (struct target_ops *self, ptid_t ptid)
+remote_enable_btrace (struct target_ops *self, ptid_t ptid,
+ const struct btrace_config *conf)
{
struct btrace_target_info *tinfo = NULL;
struct packet_config *packet = &remote_protocol_packets[PACKET_Qbtrace_bts];
struct remote_state *rs = get_remote_state ();
char *buf = rs->buf;
char *endbuf = rs->buf + get_remote_packet_size ();
+ volatile struct gdb_exception err;
if (packet_config_support (packet) != PACKET_ENABLE)
error (_("Target does not support branch tracing."));
+ btrace_sync_conf (conf);
+
set_general_thread (ptid);
buf += xsnprintf (buf, endbuf - buf, "%s", packet->name);
@@ -11376,6 +11438,14 @@ remote_enable_btrace (struct target_ops *self, ptid_t ptid)
tinfo = xzalloc (sizeof (*tinfo));
tinfo->ptid = ptid;
+ /* If we fail to read the configuration, we lose some information, but the
+ tracing itself is not impacted. */
+ TRY_CATCH (err, RETURN_MASK_ERROR)
+ btrace_read_config (&tinfo->conf);
+
+ if (err.message != NULL)
+ warning ("%s", err.message);
+
return tinfo;
}
@@ -11472,6 +11542,13 @@ remote_read_btrace (struct target_ops *self,
return BTRACE_ERR_NONE;
}
+static const struct btrace_config *
+remote_btrace_conf (struct target_ops *self,
+ const struct btrace_target_info *tinfo)
+{
+ return &tinfo->conf;
+}
+
static int
remote_augmented_libraries_svr4_read (struct target_ops *self)
{
@@ -11608,6 +11685,7 @@ Specify the serial device it is connected to\n\
remote_ops.to_disable_btrace = remote_disable_btrace;
remote_ops.to_teardown_btrace = remote_teardown_btrace;
remote_ops.to_read_btrace = remote_read_btrace;
+ remote_ops.to_btrace_conf = remote_btrace_conf;
remote_ops.to_augmented_libraries_svr4_read =
remote_augmented_libraries_svr4_read;
}
@@ -12206,6 +12284,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_btrace],
"qXfer:btrace", "read-btrace", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_btrace_conf],
+ "qXfer:btrace-conf", "read-btrace-conf", 0);
+
/* Assert that we've registered commands for all packet configs. */
{
int i;
diff --git a/gdb/target-debug.h b/gdb/target-debug.h
index 61cc3a5..63ce12c 100644
--- a/gdb/target-debug.h
+++ b/gdb/target-debug.h
@@ -148,6 +148,10 @@
target_debug_do_print (host_address_to_string (X))
#define target_debug_print_enum_btrace_format(X) \
target_debug_do_print (plongest (X))
+#define target_debug_print_const_struct_btrace_config_p(X) \
+ target_debug_do_print (host_address_to_string (X))
+#define target_debug_print_const_struct_btrace_target_info_p(X) \
+ target_debug_do_print (host_address_to_string (X))
static void
target_debug_print_struct_target_waitstatus_p (struct target_waitstatus *status)
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index 9cdb31e..e026179 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -3114,28 +3114,30 @@ debug_supports_btrace (struct target_ops *self, enum btrace_format arg1)
}
static struct btrace_target_info *
-delegate_enable_btrace (struct target_ops *self, ptid_t arg1)
+delegate_enable_btrace (struct target_ops *self, ptid_t arg1, const struct btrace_config *arg2)
{
self = self->beneath;
- return self->to_enable_btrace (self, arg1);
+ return self->to_enable_btrace (self, arg1, arg2);
}
static struct btrace_target_info *
-tdefault_enable_btrace (struct target_ops *self, ptid_t arg1)
+tdefault_enable_btrace (struct target_ops *self, ptid_t arg1, const struct btrace_config *arg2)
{
tcomplain ();
}
static struct btrace_target_info *
-debug_enable_btrace (struct target_ops *self, ptid_t arg1)
+debug_enable_btrace (struct target_ops *self, ptid_t arg1, const struct btrace_config *arg2)
{
struct btrace_target_info * result;
fprintf_unfiltered (gdb_stdlog, "-> %s->to_enable_btrace (...)\n", debug_target.to_shortname);
- result = debug_target.to_enable_btrace (&debug_target, arg1);
+ result = debug_target.to_enable_btrace (&debug_target, arg1, arg2);
fprintf_unfiltered (gdb_stdlog, "<- %s->to_enable_btrace (", debug_target.to_shortname);
target_debug_print_struct_target_ops_p (&debug_target);
fputs_unfiltered (", ", gdb_stdlog);
target_debug_print_ptid_t (arg1);
+ fputs_unfiltered (", ", gdb_stdlog);
+ target_debug_print_const_struct_btrace_config_p (arg2);
fputs_unfiltered (") = ", gdb_stdlog);
target_debug_print_struct_btrace_target_info_p (result);
fputs_unfiltered ("\n", gdb_stdlog);
@@ -3225,6 +3227,35 @@ debug_read_btrace (struct target_ops *self, struct btrace_data *arg1, struct btr
return result;
}
+static const struct btrace_config *
+delegate_btrace_conf (struct target_ops *self, const struct btrace_target_info *arg1)
+{
+ self = self->beneath;
+ return self->to_btrace_conf (self, arg1);
+}
+
+static const struct btrace_config *
+tdefault_btrace_conf (struct target_ops *self, const struct btrace_target_info *arg1)
+{
+ return NULL;
+}
+
+static const struct btrace_config *
+debug_btrace_conf (struct target_ops *self, const struct btrace_target_info *arg1)
+{
+ const struct btrace_config * result;
+ fprintf_unfiltered (gdb_stdlog, "-> %s->to_btrace_conf (...)\n", debug_target.to_shortname);
+ result = debug_target.to_btrace_conf (&debug_target, arg1);
+ fprintf_unfiltered (gdb_stdlog, "<- %s->to_btrace_conf (", debug_target.to_shortname);
+ target_debug_print_struct_target_ops_p (&debug_target);
+ fputs_unfiltered (", ", gdb_stdlog);
+ target_debug_print_const_struct_btrace_target_info_p (arg1);
+ fputs_unfiltered (") = ", gdb_stdlog);
+ target_debug_print_const_struct_btrace_config_p (result);
+ fputs_unfiltered ("\n", gdb_stdlog);
+ return result;
+}
+
static void
delegate_stop_recording (struct target_ops *self)
{
@@ -3972,6 +4003,8 @@ install_delegators (struct target_ops *ops)
ops->to_teardown_btrace = delegate_teardown_btrace;
if (ops->to_read_btrace == NULL)
ops->to_read_btrace = delegate_read_btrace;
+ if (ops->to_btrace_conf == NULL)
+ ops->to_btrace_conf = delegate_btrace_conf;
if (ops->to_stop_recording == NULL)
ops->to_stop_recording = delegate_stop_recording;
if (ops->to_info_record == NULL)
@@ -4135,6 +4168,7 @@ install_dummy_methods (struct target_ops *ops)
ops->to_disable_btrace = tdefault_disable_btrace;
ops->to_teardown_btrace = tdefault_teardown_btrace;
ops->to_read_btrace = tdefault_read_btrace;
+ ops->to_btrace_conf = tdefault_btrace_conf;
ops->to_stop_recording = tdefault_stop_recording;
ops->to_info_record = tdefault_info_record;
ops->to_save_record = tdefault_save_record;
@@ -4278,6 +4312,7 @@ init_debug_target (struct target_ops *ops)
ops->to_disable_btrace = debug_disable_btrace;
ops->to_teardown_btrace = debug_teardown_btrace;
ops->to_read_btrace = debug_read_btrace;
+ ops->to_btrace_conf = debug_btrace_conf;
ops->to_stop_recording = debug_stop_recording;
ops->to_info_record = debug_info_record;
ops->to_save_record = debug_save_record;
diff --git a/gdb/target.c b/gdb/target.c
index d2f0050..569c999 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -3398,9 +3398,9 @@ target_supports_btrace (enum btrace_format format)
/* See target.h. */
struct btrace_target_info *
-target_enable_btrace (ptid_t ptid)
+target_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
{
- return current_target.to_enable_btrace (&current_target, ptid);
+ return current_target.to_enable_btrace (&current_target, ptid, conf);
}
/* See target.h. */
@@ -3431,6 +3431,14 @@ target_read_btrace (struct btrace_data *btrace,
/* See target.h. */
+const struct btrace_config *
+target_btrace_conf (const struct btrace_target_info *btinfo)
+{
+ return current_target.to_btrace_conf (&current_target, btinfo);
+}
+
+/* See target.h. */
+
void
target_stop_recording (void)
{
diff --git a/gdb/target.h b/gdb/target.h
index 803ef28..fb60123 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -200,7 +200,9 @@ enum target_object
/* OpenVMS Unwind Information Block. */
TARGET_OBJECT_OPENVMS_UIB,
/* Branch trace data, in XML format. */
- TARGET_OBJECT_BTRACE
+ TARGET_OBJECT_BTRACE,
+ /* Branch trace configuration, in XML format. */
+ TARGET_OBJECT_BTRACE_CONF
/* Possible future objects: TARGET_OBJECT_FILE, ... */
};
@@ -1002,10 +1004,12 @@ struct target_ops
int (*to_supports_btrace) (struct target_ops *, enum btrace_format)
TARGET_DEFAULT_RETURN (0);
- /* Enable branch tracing for PTID and allocate a branch trace target
- information struct for reading and for disabling branch trace. */
+ /* Enable branch tracing for PTID using CONF configuration.
+ Return a branch trace target information struct for reading and for
+ disabling branch trace. */
struct btrace_target_info *(*to_enable_btrace) (struct target_ops *,
- ptid_t ptid)
+ ptid_t ptid,
+ const struct btrace_config *conf)
TARGET_DEFAULT_NORETURN (tcomplain ());
/* Disable branch tracing and deallocate TINFO. */
@@ -1029,6 +1033,11 @@ struct target_ops
enum btrace_read_type type)
TARGET_DEFAULT_NORETURN (tcomplain ());
+ /* Get the branch trace configuration. */
+ const struct btrace_config *(*to_btrace_conf) (struct target_ops *self,
+ const struct btrace_target_info *)
+ TARGET_DEFAULT_RETURN (NULL);
+
/* Stop trace recording. */
void (*to_stop_recording) (struct target_ops *)
TARGET_DEFAULT_IGNORE ();
@@ -2218,7 +2227,8 @@ extern void update_target_permissions (void);
extern int target_supports_btrace (enum btrace_format);
/* See to_enable_btrace in struct target_ops. */
-extern struct btrace_target_info *target_enable_btrace (ptid_t ptid);
+extern struct btrace_target_info *
+ target_enable_btrace (ptid_t ptid, const struct btrace_config *);
/* See to_disable_btrace in struct target_ops. */
extern void target_disable_btrace (struct btrace_target_info *btinfo);
@@ -2231,6 +2241,10 @@ extern enum btrace_error target_read_btrace (struct btrace_data *,
struct btrace_target_info *,
enum btrace_read_type);
+/* See to_btrace_conf in struct target_ops. */
+extern const struct btrace_config *
+ target_btrace_conf (const struct btrace_target_info *);
+
/* See to_stop_recording in struct target_ops. */
extern void target_stop_recording (void);
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index c458bd7..a211483 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,15 @@
+2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
+
+ * gdb.btrace/delta.exp: Update "info record" output.
+ * gdb.btrace/enable.exp: Update "info record" output.
+ * gdb.btrace/finish.exp: Update "info record" output.
+ * gdb.btrace/instruction_history.exp: Update "info record" output.
+ * gdb.btrace/next.exp: Update "info record" output.
+ * gdb.btrace/nexti.exp: Update "info record" output.
+ * gdb.btrace/step.exp: Update "info record" output.
+ * gdb.btrace/stepi.exp: Update "info record" output.
+ * gdb.btrace/nohist.exp: Update "info record" output.
+
2015-02-06 Simon Marchi <simon.marchi@ericsson.com>
PR gdb/15678
diff --git a/gdb/testsuite/gdb.btrace/delta.exp b/gdb/testsuite/gdb.btrace/delta.exp
index 480fd1f..59959bc 100644
--- a/gdb/testsuite/gdb.btrace/delta.exp
+++ b/gdb/testsuite/gdb.btrace/delta.exp
@@ -39,6 +39,7 @@ gdb_test_no_output "record btrace"
with_test_prefix "no trace" {
gdb_test "info record" [join [list \
"Active record target: record-btrace" \
+ "Recording format: .*" \
"Recorded 0 instructions in 0 functions for .*" \
] "\r\n"]
gdb_test "record instruction-history" "No trace\."
@@ -51,6 +52,7 @@ gdb_test "stepi"
proc check_trace {} {
gdb_test "info record" [join [list \
"Active record target: record-btrace" \
+ "Recording format: .*" \
"Recorded 1 instructions in 1 functions for .*" \
] "\r\n"]
gdb_test "record instruction-history /f 1" \
@@ -71,6 +73,7 @@ with_test_prefix "twice" {
gdb_test "reverse-stepi"
gdb_test "info record" [join [list \
"Active record target: record-btrace" \
+ "Recording format: .*" \
"Recorded 1 instructions in 1 functions for .*" \
"Replay in progress\. At instruction 1\." \
] "\r\n"] "reverse-stepi"
@@ -79,5 +82,6 @@ gdb_test "info record" [join [list \
gdb_test "stepi"
gdb_test "info record" [join [list \
"Active record target: record-btrace" \
+ "Recording format: .*" \
"Recorded 1 instructions in 1 functions for .*" \
] "\r\n"] "and back"
diff --git a/gdb/testsuite/gdb.btrace/enable.exp b/gdb/testsuite/gdb.btrace/enable.exp
index 79799b6..1122884 100644
--- a/gdb/testsuite/gdb.btrace/enable.exp
+++ b/gdb/testsuite/gdb.btrace/enable.exp
@@ -56,7 +56,9 @@ gdb_test "record btrace" "The process is already being recorded\\. Use \"record
gdb_test "record full" "The process is already being recorded\\. Use \"record stop\" to stop recording first\\." "record full cannot be enabled"
# no trace recorded yet
-gdb_test "info record" "Active record target: record-btrace\r\nRecorded 0 instructions in 0 functions for thread 1.*\\." "info record without trace"
+gdb_test "info record" "Active record target: record-btrace\r
+.*\r
+Recorded 0 instructions in 0 functions for thread 1.*\\." "info record without trace"
# stop btrace record
gdb_test "record stop" "Process record is stopped and all execution logs are deleted\\." "record stop"
diff --git a/gdb/testsuite/gdb.btrace/finish.exp b/gdb/testsuite/gdb.btrace/finish.exp
index 918232f..3857c10 100644
--- a/gdb/testsuite/gdb.btrace/finish.exp
+++ b/gdb/testsuite/gdb.btrace/finish.exp
@@ -37,6 +37,7 @@ gdb_test "next"
proc check_replay_at { insn } {
gdb_test "info record" [join [list \
"Active record target: record-btrace" \
+ "Recording format: .*" \
"Recorded 40 instructions in 16 functions for .*" \
"Replay in progress\. At instruction $insn\." \
] "\r\n"]
diff --git a/gdb/testsuite/gdb.btrace/instruction_history.exp b/gdb/testsuite/gdb.btrace/instruction_history.exp
index 6c0b9d9..63d902b 100644
--- a/gdb/testsuite/gdb.btrace/instruction_history.exp
+++ b/gdb/testsuite/gdb.btrace/instruction_history.exp
@@ -50,7 +50,7 @@ gdb_continue_to_breakpoint "cont to $bp_location" ".*$srcfile2:$bp_location.*"
set traced {}
set testname "determine number of recorded instructions"
gdb_test_multiple "info record" $testname {
- -re "Active record target: record-btrace\r\nRecorded \(\[0-9\]*\) instructions in \(\[0-9\]*\) functions for thread 1 .*\\.\r\n$gdb_prompt $" {
+ -re "Active record target: record-btrace\r\n.*\r\nRecorded \(\[0-9\]*\) instructions in \(\[0-9\]*\) functions for thread 1 .*\\.\r\n$gdb_prompt $" {
set traced $expect_out(1,string)
pass $testname
}
diff --git a/gdb/testsuite/gdb.btrace/next.exp b/gdb/testsuite/gdb.btrace/next.exp
index d48c092..88bd8af 100644
--- a/gdb/testsuite/gdb.btrace/next.exp
+++ b/gdb/testsuite/gdb.btrace/next.exp
@@ -37,6 +37,7 @@ gdb_test "next"
proc check_replay_at { insn } {
gdb_test "info record" [join [list \
"Active record target: record-btrace" \
+ "Recording format: .*" \
"Recorded 40 instructions in 16 functions for .*" \
"Replay in progress\. At instruction $insn\." \
] "\r\n"]
@@ -55,6 +56,7 @@ with_test_prefix "reverse-next - 2" { check_replay_at 1 }
gdb_test "next" ".*main\.3.*"
gdb_test "info record" [join [list \
"Active record target: record-btrace" \
+ "Recording format: .*" \
"Recorded 40 instructions in 16 functions for \[^\\\r\\\n\]*" \
] "\r\n"] "next back"
diff --git a/gdb/testsuite/gdb.btrace/nexti.exp b/gdb/testsuite/gdb.btrace/nexti.exp
index e68be1d..76ca0a6 100644
--- a/gdb/testsuite/gdb.btrace/nexti.exp
+++ b/gdb/testsuite/gdb.btrace/nexti.exp
@@ -37,6 +37,7 @@ gdb_test "next"
proc check_replay_at { insn } {
gdb_test "info record" [join [list \
"Active record target: record-btrace" \
+ "Recording format: .*" \
"Recorded 40 instructions in 16 functions for .*" \
"Replay in progress\. At instruction $insn\." \
] "\r\n"]
@@ -55,6 +56,7 @@ with_test_prefix "reverse-nexti - 1" { check_replay_at 1 }
gdb_test "nexti" ".*main\.3.*" "next, 1.5"
gdb_test "info record" [join [list \
"Active record target: record-btrace" \
+ "Recording format: .*" \
"Recorded 40 instructions in 16 functions for \[^\\\r\\\n\]*" \
] "\r\n"] "nexti back"
diff --git a/gdb/testsuite/gdb.btrace/nohist.exp b/gdb/testsuite/gdb.btrace/nohist.exp
index 0377053..f53870b 100644
--- a/gdb/testsuite/gdb.btrace/nohist.exp
+++ b/gdb/testsuite/gdb.btrace/nohist.exp
@@ -33,6 +33,7 @@ if ![runto_main] {
proc check_not_replaying {} {
gdb_test "info record" [join [list \
"Active record target: record-btrace" \
+ "Recording format: .*" \
"Recorded 0 instructions in 0 functions for \[^\\\r\\\n\]*" \
] "\r\n"]
}
diff --git a/gdb/testsuite/gdb.btrace/step.exp b/gdb/testsuite/gdb.btrace/step.exp
index 0f2fe5b..e3febe1 100644
--- a/gdb/testsuite/gdb.btrace/step.exp
+++ b/gdb/testsuite/gdb.btrace/step.exp
@@ -37,6 +37,7 @@ gdb_test "next"
proc check_replay_at { insn } {
gdb_test "info record" [join [list \
"Active record target: record-btrace" \
+ "Recording format: .*" \
"Recorded 40 instructions in 16 functions for .*" \
"Replay in progress\. At instruction $insn\." \
] "\r\n"]
@@ -85,5 +86,6 @@ with_test_prefix "step to 39" { check_replay_at 39 }
gdb_test "step" ".*main\.3.*"
gdb_test "info record" [join [list \
"Active record target: record-btrace" \
+ "Recording format: .*" \
"Recorded 40 instructions in 16 functions for \[^\\\r\\\n\]*" \
] "\r\n"] "step to live"
diff --git a/gdb/testsuite/gdb.btrace/stepi.exp b/gdb/testsuite/gdb.btrace/stepi.exp
index 585be21..0276f72 100644
--- a/gdb/testsuite/gdb.btrace/stepi.exp
+++ b/gdb/testsuite/gdb.btrace/stepi.exp
@@ -35,6 +35,7 @@ if ![runto_main] {
proc check_replay_at { insn } {
gdb_test "info record" [join [list \
"Active record target: record-btrace" \
+ "Recording format: .*" \
"Recorded 40 instructions in 16 functions for .*" \
"Replay in progress\. At instruction $insn\." \
] "\r\n"]
@@ -59,6 +60,7 @@ with_test_prefix "stepi to 40" { check_replay_at 40 }
gdb_test "stepi" ".*main\.3.*"
gdb_test "info record" [join [list \
"Active record target: record-btrace" \
+ "Recording format: .*" \
"Recorded 40 instructions in 16 functions for \[^\\\r\\\n\]*" \
] "\r\n"] "stepi to live"
diff --git a/gdb/x86-linux-nat.c b/gdb/x86-linux-nat.c
index 78b547b..9d82be2 100644
--- a/gdb/x86-linux-nat.c
+++ b/gdb/x86-linux-nat.c
@@ -427,13 +427,14 @@ x86_linux_read_description (struct target_ops *ops)
/* Enable branch tracing. */
static struct btrace_target_info *
-x86_linux_enable_btrace (struct target_ops *self, ptid_t ptid)
+x86_linux_enable_btrace (struct target_ops *self, ptid_t ptid,
+ const struct btrace_config *conf)
{
struct btrace_target_info *tinfo;
struct gdbarch *gdbarch;
errno = 0;
- tinfo = linux_enable_btrace (ptid);
+ tinfo = linux_enable_btrace (ptid, conf);
if (tinfo == NULL)
error (_("Could not enable branch tracing for %s: %s."),
@@ -476,6 +477,16 @@ x86_linux_read_btrace (struct target_ops *self,
{
return linux_read_btrace (data, btinfo, type);
}
+
+/* See to_btrace_conf in target.h. */
+
+static const struct btrace_config *
+x86_linux_btrace_conf (struct target_ops *self,
+ const struct btrace_target_info *btinfo)
+{
+ return linux_btrace_conf (btinfo);
+}
+
/* Helper for ps_get_thread_area. Sets BASE_ADDR to a pointer to
@@ -550,6 +561,7 @@ x86_linux_create_target (void)
t->to_disable_btrace = x86_linux_disable_btrace;
t->to_teardown_btrace = x86_linux_teardown_btrace;
t->to_read_btrace = x86_linux_read_btrace;
+ t->to_btrace_conf = x86_linux_btrace_conf;
return t;
}