diff options
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, @@ -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 ¤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)<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, + ¤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 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 (¤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 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 (¤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 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; } |