+2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
+
+ * btrace.c (parse_xml_btrace_conf_bts): Add size.
+ (btrace_conf_bts_attributes): New.
+ (btrace_conf_children): Add attributes.
+ * common/btrace-common.h (btrace_config_bts): New.
+ (btrace_config)<bts>: New.
+ (btrace_config): Update comment.
+ * nat/linux-btrace.c (linux_enable_btrace, linux_enable_bts):
+ Use config.
+ * features/btrace-conf.dtd: Increment version. Add size
+ attribute to bts element.
+ * record-btrace.c (set_record_btrace_bts_cmdlist,
+ show_record_btrace_bts_cmdlist): New.
+ (record_btrace_adjust_size, record_btrace_print_bts_conf,
+ record_btrace_print_conf, cmd_set_record_btrace_bts,
+ cmd_show_record_btrace_bts): New.
+ (record_btrace_info): Call record_btrace_print_conf.
+ (_initialize_record_btrace): Add commands.
+ * remote.c: Add PACKET_Qbtrace_conf_bts_size enum.
+ (remote_protocol_features): Add Qbtrace-conf:bts:size packet.
+ (btrace_sync_conf): Synchronize bts size.
+ (_initialize_remote): Add Qbtrace-conf:bts:size packet.
+ * NEWS: Announce new commands and new packets.
+
2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
* Makefile.in (XMLFILES): Add btrace-conf.dtd.
maint show symbol-cache-size
Control the size of the symbol cache.
+set|show record btrace bts buffer-size
+ Set and show the size of the ring buffer used for branch tracing in
+ BTS format.
+ The obtained size may differ from the requested size. Use "info
+ record" to see the obtained buffer size.
+
* The command 'thread apply all' can now support new option '-ascending'
to call its specified command for all threads in ascending order.
qXfer:btrace-conf:read
Return the branch trace configuration for the current thread.
+Qbtrace-conf:bts:size
+ Set the requested ring buffer size for branch tracing in BTS format.
+
+* The info record command now shows the recording format and the
+ branch tracing configuration for the current thread when using
+ the btrace record target.
+ For the BTS format, it shows the ring buffer size.
+
*** Changes in GDB 7.9
* GDB now supports hardware watchpoints on x86 GNU Hurd.
void *user_data, VEC (gdb_xml_value_s) *attributes)
{
struct btrace_config *conf;
+ struct gdb_xml_value *size;
conf = user_data;
conf->format = BTRACE_FORMAT_BTS;
+ conf->bts.size = 0;
+
+ size = xml_find_attribute (attributes, "size");
+ if (size != NULL)
+ conf->bts.size = (unsigned int) * (ULONGEST *) size->value;
}
+static const struct gdb_xml_attribute btrace_conf_bts_attributes[] = {
+ { "size", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
+ { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
static const struct gdb_xml_element btrace_conf_children[] = {
- { "bts", NULL, NULL, GDB_XML_EF_OPTIONAL, parse_xml_btrace_conf_bts, NULL },
+ { "bts", btrace_conf_bts_attributes, NULL, GDB_XML_EF_OPTIONAL,
+ parse_xml_btrace_conf_bts, NULL },
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};
BTRACE_FORMAT_BTS
};
+/* A BTS configuration. */
+
+struct btrace_config_bts
+{
+ /* The size of the branch trace buffer in bytes. */
+ unsigned int size;
+};
+
/* A branch tracing configuration.
This describes the requested configuration as well as the actually
- obtained configuration. */
+ obtained configuration.
+ We describe the configuration for all different formats so we can
+ easily switch between formats. */
struct btrace_config
{
/* The branch tracing format. */
enum btrace_format format;
+
+ /* The BTS format configuration. */
+ struct btrace_config_bts bts;
};
/* Branch trace in BTS format. */
+2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
+
+ * gdb.texinfo (Branch Trace Configuration Format): Add size.
+ (Process Record and Replay): Describe new set|show commands.
+ (General Query Packets): Describe Qbtrace-conf:bts:size packet.
+
2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
* gdb.texinfo (Process Record and Replay): Describe the "record
@item show record btrace replay-memory-access
Show the current setting of @code{replay-memory-access}.
+@kindex set record btrace bts
+@item set record btrace bts buffer-size @var{size}
+@itemx set record btrace bts buffer-size unlimited
+Set the requested ring buffer size for branch tracing in @acronym{BTS}
+format. Default is 64KB.
+
+If @var{size} is a positive number, then @value{GDBN} will try to
+allocate a buffer of at least @var{size} bytes for each new thread
+that uses the btrace recording method and the @acronym{BTS} format.
+The actually obtained buffer size may differ from the requested
+@var{size}. Use the @code{info record} command to see the actual
+buffer size for each thread that uses the btrace recording method and
+the @acronym{BTS} format.
+
+If @var{limit} is @code{unlimited} or zero, @value{GDBN} will try to
+allocate a buffer of 4MB.
+
+Bigger buffers mean longer traces. On the other hand, @value{GDBN} will
+also need longer to process the branch trace data before it can be used.
+
+@item show record btrace bts buffer-size @var{size}
+Show the current setting of the requested ring buffer size for branch
+tracing in @acronym{BTS} format.
+
@kindex info record
@item info record
Show various statistics about the recording depending on the recording
@end itemize
@item btrace
-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.
+For the @code{btrace} recording method, it shows:
+
+@itemize @bullet
+@item
+Recording format.
+@item
+Number of instructions that have been recorded.
+@item
+Number of blocks of sequential control-flow formed by the recorded
+instructions.
+@item
+Whether in record mode or replay mode.
+@end itemize
+
+For the @code{bts} recording format, it also shows:
+@itemize @bullet
+@item
+Size of the perf ring buffer.
+@end itemize
@end table
@kindex record delete
@tab @samp{-}
@tab Yes
+@item @samp{Qbtrace-conf:bts:size}
+@tab Yes
+@tab @samp{-}
+@tab Yes
+
@item @samp{QNonStop}
@tab No
@tab @samp{-}
@item Qbtrace:bts
The remote stub understands the @samp{Qbtrace:bts} packet.
+@item Qbtrace-conf:bts:size
+The remote stub understands the @samp{Qbtrace-conf:bts:size} packet.
+
@end table
@item qSymbol::
A badly formed request or an error was encountered.
@end table
+@item Qbtrace-conf:bts:size=@var{value}
+Set the requested ring buffer size for new threads that use the
+btrace recording method in bts format.
+
+Reply:
+@table @samp
+@item OK
+The ring buffer size has been set.
+@item E.errtext
+A badly formed request or an error was encountered.
+@end table
+
@end table
@node Architecture-Specific Protocol Details
(@pxref{qXfer btrace-conf read}) packet.
The configuration describes the branch trace format and configuration
-settings for that format.
+settings for that format. The following information is described:
+
+@table @code
+@item bts
+This thread uses the @dfn{Branch Trace Store} (@acronym{BTS}) format.
+@table @code
+@item size
+The size of the @acronym{BTS} ring buffer in bytes.
+@end table
+@end table
@value{GDBN} must be linked with the Expat library to support XML
branch trace configuration discovery. @xref{Expat}.
<!ATTLIST btrace-conf version CDATA #FIXED "1.0">
<!ELEMENT bts EMPTY>
+<!ATTLIST bts size CDATA #IMPLIED>
@end smallexample
@include agentexpr.texi
<!ATTLIST btrace-conf version CDATA #FIXED "1.0">
<!ELEMENT bts EMPTY>
+<!ATTLIST bts size CDATA #IMPLIED>
+2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
+
+ * linux-low.c (linux_low_btrace_conf): Print size.
+ * server.c (handle_btrace_conf_general_set): New.
+ (hanle_general_set): Call handle_btrace_conf_general_set.
+ (handle_query): Report Qbtrace-conf:bts:size as supported.
+
2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
* linux-low.c (linux_low_enable_btrace): Update parameters.
break;
case BTRACE_FORMAT_BTS:
- buffer_xml_printf (buffer, "<bts/>\n");
+ buffer_xml_printf (buffer, "<bts");
+ buffer_xml_printf (buffer, " size=\"0x%x\"", conf->bts.size);
+ buffer_xml_printf (buffer, " />\n");
break;
}
}
return 1;
}
+/* Handle the "Qbtrace-conf" packet. */
+
+static int
+handle_btrace_conf_general_set (char *own_buf)
+{
+ struct thread_info *thread;
+ char *op;
+
+ if (strncmp ("Qbtrace-conf:", own_buf, strlen ("Qbtrace-conf:")) != 0)
+ return 0;
+
+ op = own_buf + strlen ("Qbtrace-conf:");
+
+ if (ptid_equal (general_thread, null_ptid)
+ || ptid_equal (general_thread, minus_one_ptid))
+ {
+ strcpy (own_buf, "E.Must select a single thread.");
+ return -1;
+ }
+
+ thread = find_thread_ptid (general_thread);
+ if (thread == NULL)
+ {
+ strcpy (own_buf, "E.No such thread.");
+ return -1;
+ }
+
+ if (strncmp (op, "bts:size=", strlen ("bts:size=")) == 0)
+ {
+ unsigned long size;
+ char *endp = NULL;
+
+ errno = 0;
+ size = strtoul (op + strlen ("bts:size="), &endp, 16);
+ if (endp == NULL || *endp != 0 || errno != 0 || size > UINT_MAX)
+ {
+ strcpy (own_buf, "E.Bad size value.");
+ return -1;
+ }
+
+ current_btrace_conf.bts.size = (unsigned int) size;
+ }
+ else
+ {
+ strcpy (own_buf, "E.Bad Qbtrace configuration option.");
+ return -1;
+ }
+
+ write_ok (own_buf);
+ return 1;
+}
+
/* Handle all of the extended 'Q' packets. */
static void
if (handle_btrace_general_set (own_buf))
return;
+ if (handle_btrace_conf_general_set (own_buf))
+ return;
+
/* Otherwise we didn't know what packet it was. Say we didn't
understand it. */
own_buf[0] = 0;
supported_btrace_packets (char *buf)
{
if (target_supports_btrace (BTRACE_FORMAT_BTS))
- strcat (buf, ";Qbtrace:bts+");
+ {
+ strcat (buf, ";Qbtrace:bts+");
+ strcat (buf, ";Qbtrace-conf:bts:size+");
+ }
else
return;
/* Enable branch tracing in BTS format. */
static struct btrace_target_info *
-linux_enable_bts (ptid_t ptid, const struct btrace_config *conf)
+linux_enable_bts (ptid_t ptid, const struct btrace_config_bts *conf)
{
struct perf_event_mmap_page *header;
struct btrace_target_info *tinfo;
struct btrace_tinfo_bts *bts;
+ unsigned long long size, pages;
int pid, pg;
tinfo = xzalloc (sizeof (*tinfo));
if (bts->file < 0)
goto err;
- /* We try to allocate as much buffer as we can get.
- We could allow the user to specify the size of the buffer, but then
- we'd leave this search for the maximum buffer size to him. */
- for (pg = 4; pg >= 0; --pg)
+ /* Convert the requested size in bytes to pages (rounding up). */
+ pages = (((unsigned long long) conf->size) + PAGE_SIZE - 1) / PAGE_SIZE;
+ /* We need at least one page. */
+ if (pages == 0)
+ pages = 1;
+
+ /* The buffer size can be requested in powers of two pages. Adjust PAGES
+ to the next power of two. */
+ for (pg = 0; pages != (1u << pg); ++pg)
+ if ((pages & (1u << pg)) != 0)
+ pages += (1u << pg);
+
+ /* We try to allocate the requested size.
+ If that fails, try to get as much as we can. */
+ for (; pages > 0; pages >>= 1)
{
+ size_t length;
+
+ size = pages * PAGE_SIZE;
+ length = size + PAGE_SIZE;
+
+ /* Check for overflows. */
+ if ((unsigned long long) length < size)
+ continue;
+
/* 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,
- bts->file, 0);
+ header = mmap (NULL, length, PROT_READ, MAP_SHARED, bts->file, 0);
if (header != MAP_FAILED)
break;
}
bts->header = header;
bts->bts.mem = ((const uint8_t *) header) + PAGE_SIZE;
- bts->bts.size = (1 << pg) * PAGE_SIZE;
+ bts->bts.size = size;
bts->bts.data_head = &header->data_head;
bts->bts.last_head = 0;
+ tinfo->conf.bts.size = size;
return tinfo;
err_file:
break;
case BTRACE_FORMAT_BTS:
- tinfo = linux_enable_bts (ptid, conf);
+ tinfo = linux_enable_bts (ptid, &conf->bts);
break;
}
/* Command list for "record btrace". */
static struct cmd_list_element *record_btrace_cmdlist;
+/* Command lists for "set/show record btrace". */
+static struct cmd_list_element *set_record_btrace_cmdlist;
+static struct cmd_list_element *show_record_btrace_cmdlist;
+
+/* Command lists for "set/show record btrace bts". */
+static struct cmd_list_element *set_record_btrace_bts_cmdlist;
+static struct cmd_list_element *show_record_btrace_bts_cmdlist;
+
/* Print a record-btrace debug message. Use do ... while (0) to avoid
ambiguities when used in if statements. */
ops->beneath->to_async (ops->beneath, callback, context);
}
+/* Adjusts the size and returns a human readable size suffix. */
+
+static const char *
+record_btrace_adjust_size (unsigned int *size)
+{
+ unsigned int sz;
+
+ sz = *size;
+
+ if ((sz & ((1u << 30) - 1)) == 0)
+ {
+ *size = sz >> 30;
+ return "GB";
+ }
+ else if ((sz & ((1u << 20) - 1)) == 0)
+ {
+ *size = sz >> 20;
+ return "MB";
+ }
+ else if ((sz & ((1u << 10) - 1)) == 0)
+ {
+ *size = sz >> 10;
+ return "kB";
+ }
+ else
+ return "";
+}
+
+/* Print a BTS configuration. */
+
+static void
+record_btrace_print_bts_conf (const struct btrace_config_bts *conf)
+{
+ const char *suffix;
+ unsigned int size;
+
+ size = conf->size;
+ if (size > 0)
+ {
+ suffix = record_btrace_adjust_size (&size);
+ printf_unfiltered (_("Buffer size: %u%s.\n"), size, suffix);
+ }
+}
+
+/* Print a branch tracing configuration. */
+
+static void
+record_btrace_print_conf (const struct btrace_config *conf)
+{
+ printf_unfiltered (_("Recording format: %s.\n"),
+ btrace_format_string (conf->format));
+
+ switch (conf->format)
+ {
+ case BTRACE_FORMAT_NONE:
+ return;
+
+ case BTRACE_FORMAT_BTS:
+ record_btrace_print_bts_conf (&conf->bts);
+ return;
+ }
+
+ internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
+}
+
/* The to_info_record method of target record-btrace. */
static void
conf = btrace_conf (btinfo);
if (conf != NULL)
- printf_unfiltered (_("Recording format: %s.\n"),
- btrace_format_string (conf->format));
+ record_btrace_print_conf (conf);
btrace_fetch (tp);
replay_memory_access);
}
+/* The "set record btrace bts" command. */
+
+static void
+cmd_set_record_btrace_bts (char *args, int from_tty)
+{
+ printf_unfiltered (_("\"set record btrace bts\" must be followed "
+ "by an apporpriate subcommand.\n"));
+ help_list (set_record_btrace_bts_cmdlist, "set record btrace bts ",
+ all_commands, gdb_stdout);
+}
+
+/* The "show record btrace bts" command. */
+
+static void
+cmd_show_record_btrace_bts (char *args, int from_tty)
+{
+ cmd_show_list (show_record_btrace_bts_cmdlist, from_tty, "");
+}
+
void _initialize_record_btrace (void);
/* Initialize btrace commands. */
&set_record_btrace_cmdlist,
&show_record_btrace_cmdlist);
+ add_prefix_cmd ("bts", class_support, cmd_set_record_btrace_bts,
+ _("Set record btrace bts options"),
+ &set_record_btrace_bts_cmdlist,
+ "set record btrace bts ", 0, &set_record_btrace_cmdlist);
+
+ add_prefix_cmd ("bts", class_support, cmd_show_record_btrace_bts,
+ _("Show record btrace bts options"),
+ &show_record_btrace_bts_cmdlist,
+ "show record btrace bts ", 0, &show_record_btrace_cmdlist);
+
+ add_setshow_uinteger_cmd ("buffer-size", no_class,
+ &record_btrace_conf.bts.size,
+ _("Set the record/replay bts buffer size."),
+ _("Show the record/replay bts buffer size."), _("\
+When starting recording request a trace buffer of this size. \
+The actual buffer size may differ from the requested size. \
+Use \"info record\" to see the actual buffer size.\n\n\
+Bigger buffers allow longer recording but also take more time to process \
+the recorded execution trace.\n\n\
+The trace buffer size may not be changed while recording."), NULL, NULL,
+ &set_record_btrace_bts_cmdlist,
+ &show_record_btrace_bts_cmdlist);
+
init_record_btrace_ops ();
add_target (&record_btrace_ops);
bfcache = htab_create_alloc (50, bfcache_hash, bfcache_eq, NULL,
xcalloc, xfree);
+
+ record_btrace_conf.bts.size = 64 * 1024;
}
/* Support for the qXfer:btrace-conf:read packet. */
PACKET_qXfer_btrace_conf,
+ /* Support for the Qbtrace-conf:bts:size packet. */
+ PACKET_Qbtrace_conf_bts_size,
+
PACKET_MAX
};
{ "qXfer:btrace:read", PACKET_DISABLE, remote_supported_packet,
PACKET_qXfer_btrace },
{ "qXfer:btrace-conf:read", PACKET_DISABLE, remote_supported_packet,
- PACKET_qXfer_btrace_conf }
+ PACKET_qXfer_btrace_conf },
+ { "Qbtrace-conf:bts:size", PACKET_DISABLE, remote_supported_packet,
+ PACKET_Qbtrace_conf_bts_size }
};
static char *remote_support_xml;
static void
btrace_sync_conf (const struct btrace_config *conf)
{
- /* Nothing to do for now. */
+ struct packet_config *packet;
+ struct remote_state *rs;
+ char *buf, *pos, *endbuf;
+
+ rs = get_remote_state ();
+ buf = rs->buf;
+ endbuf = buf + get_remote_packet_size ();
+
+ packet = &remote_protocol_packets[PACKET_Qbtrace_conf_bts_size];
+ if (packet_config_support (packet) == PACKET_ENABLE
+ && conf->bts.size != rs->btrace_config.bts.size)
+ {
+ pos = buf;
+ pos += xsnprintf (pos, endbuf - pos, "%s=0x%x", packet->name,
+ conf->bts.size);
+
+ putpkt (buf);
+ getpkt (&buf, &rs->buf_size, 0);
+
+ if (packet_ok (buf, packet) == PACKET_ERROR)
+ {
+ if (buf[0] == 'E' && buf[1] == '.')
+ error (_("Failed to configure the BTS buffer size: %s"), buf + 2);
+ else
+ error (_("Failed to configure the BTS buffer size."));
+ }
+
+ rs->btrace_config.bts.size = conf->bts.size;
+ }
}
/* Read the current thread's btrace configuration from the target and
add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_btrace_conf],
"qXfer:btrace-conf", "read-btrace-conf", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_Qbtrace_conf_bts_size],
+ "Qbtrace-conf:bts:size", "btrace-conf-bts-size", 0);
+
/* Assert that we've registered commands for all packet configs. */
{
int i;
+2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
+
+ * gdb.btrace/buffer-size: New.
+
2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
* gdb.btrace/delta.exp: Update "info record" output.
--- /dev/null
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2013-2015 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <markus.t.metzger@intel.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+# start inferior
+standard_testfile record_goto.c
+if [prepare_for_testing $testfile.exp $testfile $srcfile] {
+ return -1
+}
+
+if ![runto_main] {
+ return -1
+}
+
+gdb_test_no_output "set record btrace bts buffer-size 1"
+gdb_test "show record btrace bts buffer-size" "The record/replay bts buffer size is 1\.\r" "bts buffer size before recording"
+
+gdb_test_no_output "record btrace bts"
+gdb_test "show record btrace bts buffer-size" "The record/replay bts buffer size is 1\.\r" "bts buffer size while recording"
+gdb_test "info record" [join [list \
+ "Active record target: record-btrace" \
+ "Recording format: Branch Trace Store\." \
+ "Buffer size: 4kB\." \
+ "Recorded 0 instructions in 0 functions for \[^\\\r\\\n\]*" \
+ ] "\r\n"] "info record with small bts buffer"
+gdb_test "record stop" ".*" "stop recording with small bts buffer"
+
+gdb_test_no_output "set record btrace bts buffer-size 0"
+gdb_test "show record btrace bts buffer-size" "The record/replay bts buffer size is unlimited\.\r" "unlimited bts buffer size before recording"
+
+gdb_test_no_output "record btrace bts"
+gdb_test "show record btrace bts buffer-size" "The record/replay bts buffer size is unlimited\.\r" "unlimited bts buffer size while recording"
+gdb_test "info record" [join [list \
+ "Active record target: record-btrace" \
+ "Recording format: Branch Trace Store\." \
+ "Buffer size: .*\." \
+ "Recorded 0 instructions in 0 functions for \[^\\\r\\\n\]*" \
+ ] "\r\n"] "info record with unlimited bts buffer"
+gdb_test "record stop" ".*" "stop recording with unlimited bts buffer"