From f4abbc168227003a4836dd1a5dd558f40be96372 Mon Sep 17 00:00:00 2001 From: Markus Metzger Date: Thu, 28 Nov 2013 15:44:13 +0100 Subject: [PATCH] record btrace: add configuration struct Add a struct to describe the branch trace configuration and use it for enabling branch tracing. The user will be able to set configuration fields for each tracing format to be used for new threads. The actual configuration that is active for a given thread will be shown in the "info record" command. At the moment, the configuration struct only contains a format field that is set to the only available format. The format is the only configuration option that can not be set via set commands. It is given as argument to the "record btrace" command when starting recording. 2015-02-09 Markus Metzger * 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): Moved. (btrace_target_info): 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): 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): 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): New. (target_ops): Update parameters and comment. (target_ops): 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. doc/ * 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. gdbserver/ * linux-low.c (linux_low_enable_btrace): Update parameters. (linux_low_btrace_conf): New. (linux_target_ops): Initialize. * server.c (current_btrace_conf): New. (handle_btrace_enable): Rename to ... (handle_btrace_enable_bts): ... this. Pass ¤t_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): Update parameters and comment. (target_ops): New. (target_enable_btrace): Update parameters. (target_read_btrace_conf): New. testsuite/ * 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. --- gdb/ChangeLog | 62 ++++++++ gdb/Makefile.in | 2 +- gdb/NEWS | 9 ++ gdb/btrace.c | 71 ++++++++- gdb/btrace.h | 11 +- gdb/common/btrace-common.h | 11 ++ gdb/doc/ChangeLog | 7 + gdb/doc/gdb.texinfo | 71 ++++++++- gdb/features/btrace-conf.dtd | 10 ++ gdb/gdbserver/ChangeLog | 17 +++ gdb/gdbserver/linux-low.c | 35 ++++- gdb/gdbserver/server.c | 78 +++++++++- gdb/gdbserver/target.h | 19 ++- gdb/nat/linux-btrace.c | 140 +++++++++++++----- gdb/nat/linux-btrace.h | 35 ++++- gdb/record-btrace.c | 69 ++++++++- gdb/remote.c | 85 ++++++++++- gdb/target-debug.h | 4 + gdb/target-delegates.c | 45 +++++- gdb/target.c | 12 +- gdb/target.h | 24 ++- gdb/testsuite/ChangeLog | 12 ++ gdb/testsuite/gdb.btrace/delta.exp | 4 + gdb/testsuite/gdb.btrace/enable.exp | 4 +- gdb/testsuite/gdb.btrace/finish.exp | 1 + .../gdb.btrace/instruction_history.exp | 2 +- gdb/testsuite/gdb.btrace/next.exp | 2 + gdb/testsuite/gdb.btrace/nexti.exp | 2 + gdb/testsuite/gdb.btrace/nohist.exp | 1 + gdb/testsuite/gdb.btrace/step.exp | 2 + gdb/testsuite/gdb.btrace/stepi.exp | 2 + gdb/x86-linux-nat.c | 16 +- 32 files changed, 775 insertions(+), 90 deletions(-) create mode 100644 gdb/features/btrace-conf.dtd diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5989460e7bd..57ad0612879 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,65 @@ +2015-02-09 Markus Metzger + + * 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): Moved. + (btrace_target_info): 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): 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): 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): New. + (target_ops): Update parameters and comment. + (target_ops): 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 * nat/linux-btrace.h (perf_event_buffer): New. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index bfebf613a2e..00fb2cd7980 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 f19577a3a6d..b3f8f60d1c2 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 4e32bdcb426..8930c3cf6a9 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 730cb5f80fa..fde06199729 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 f230dbc9222..1df5821403a 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 9c12d9af8e9..b4a9cbac7d4 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,10 @@ +2015-02-09 Markus Metzger + + * 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 Doug Evans diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index aee17d3b752..411f0679f38 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 + + + + +@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 00000000000..ff54822d8b1 --- /dev/null +++ b/gdb/features/btrace-conf.dtd @@ -0,0 +1,10 @@ + + + + + + diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 636ad2e6bb2..d489ebfa214 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,20 @@ +2015-02-09 Markus Metzger + + * linux-low.c (linux_low_enable_btrace): Update parameters. + (linux_low_btrace_conf): New. + (linux_target_ops): Initialize. + * server.c (current_btrace_conf): New. + (handle_btrace_enable): Rename to ... + (handle_btrace_enable_bts): ... this. Pass ¤t_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): Update parameters and comment. + (target_ops): New. + (target_enable_btrace): Update parameters. + (target_read_btrace_conf): New. + 2015-02-09 Markus Metzger * server.c (handle_btrace_general_set): Remove call to diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 8bc73a473a5..b311d4b8386 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, "\n"); + buffer_grow_str (buffer, "\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, "\n"); + break; + } + } + + buffer_grow_str0 (buffer, "\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 1756a1f0686..17ee5e1e902 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, + ¤t_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 ed57886498b..05feb36e5fe 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 5b2266104b8..e827e9225dc 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; + + 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; /* We sample from and to address. */ - tinfo->attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_ADDR; + bts->attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_ADDR; - tinfo->attr.exclude_kernel = 1; - tinfo->attr.exclude_hv = 1; - tinfo->attr.exclude_idle = 1; - - 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; - return linux_read_bts (&btrace->variant.bts, tinfo, type); + 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. */ + +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 602a57134e1..12cdcde596e 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 99c668417b8..5c6ee434a55 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 61420ec96e5..0226f3f4a82 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 (¤t_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 61cc3a5bf11..63ce12cfaf3 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 9cdb31e0885..e0261797d19 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 d2f0050ee10..569c9990096 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 (¤t_target, ptid); + return current_target.to_enable_btrace (¤t_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 (¤t_target, btinfo); +} + +/* See target.h. */ + void target_stop_recording (void) { diff --git a/gdb/target.h b/gdb/target.h index 803ef2874aa..fb6012335bd 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 c458bd7efb0..a211483b450 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2015-02-09 Markus Metzger + + * 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 PR gdb/15678 diff --git a/gdb/testsuite/gdb.btrace/delta.exp b/gdb/testsuite/gdb.btrace/delta.exp index 480fd1f4784..59959bcd4ad 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 79799b642de..1122884ced0 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 918232f6eb0..3857c100b70 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 6c0b9d9f4b6..63d902b6d17 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 d48c0926129..88bd8afa589 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 e68be1d3008..76ca0a61c15 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 03770532d84..f53870bc94b 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 0f2fe5bd3a0..e3febe1cc5f 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 585be212ac6..0276f722b36 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 78b547b7b15..9d82be2017e 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; }