[PATCH v2 05/13] record-btrace: add bts buffer size configuration option

Markus Metzger
2014-11-20T10:47:45Z

Allow the size of the branch trace ring buffer to be defined by the
user. The specified buffer size will be used when BTS tracing is
enabled for new threads.

The obtained buffer size may differ from the requested size. The
actual buffer size for the current thread is shown in the "info record"
command.

Bigger buffers mean longer traces, but also longer processing time.

CC: Eli Zaretskii <eliz@gnu.org>

2014-11-20 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): 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.

doc/
* 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.

testsuite/
* gdb.btrace/buffer-size: New.

gdbserver/
* 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.
---
gdb/NEWS | 16 +++++
gdb/btrace.c | 14 +++-
gdb/common/btrace-common.h | 15 +++-
gdb/doc/gdb.texinfo | 77 ++++++++++++++++++--
gdb/features/btrace-conf.dtd | 1 +
gdb/gdbserver/linux-low.c | 4 +-
gdb/gdbserver/server.c | 60 +++++++++++++++-
gdb/nat/linux-btrace.c | 34 ++++++---
gdb/record-btrace.c | 120 ++++++++++++++++++++++++++++++-
gdb/remote.c | 40 ++++++++++-
gdb/testsuite/gdb.btrace/buffer-size.exp | 57 +++++++++++++++
11 files changed, 418 insertions(+), 20 deletions(-)
create mode 100644 gdb/testsuite/gdb.btrace/buffer-size.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index 689eaa1..b19faf5 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -31,6 +31,14 @@ record btrace bts
record bts
Start branch trace recording using Intel(R) Branch Trace Store format.

+* New options
+
+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.
+
* On resume, GDB now always passes the signal the program had stopped
for to the thread the signal was sent to, even if the user changed
threads before resuming. Previously GDB would often (but not
@@ -69,6 +77,14 @@ VAX running Ultrix vax-*-ultrix*
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.8

* New command line options
diff --git a/gdb/btrace.c b/gdb/btrace.c
index 6b50be7..3e9020a 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -1127,13 +1127,25 @@ parse_xml_btrace_conf_bts (struct gdb_xml_parser *parser,
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 }
};

diff --git a/gdb/common/btrace-common.h b/gdb/common/btrace-common.h
index 1e0e595..8147e6d 100644
--- a/gdb/common/btrace-common.h
+++ b/gdb/common/btrace-common.h
@@ -62,15 +62,28 @@ enum btrace_format
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. */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 121ae5b..0dcac9b 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -6525,6 +6525,29 @@ position.
@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 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 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 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 BTS format.
+
@kindex info record
@item info record
Show various statistics about the recording depending on the recording
@@ -6551,9 +6574,25 @@ 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 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
@@ -35451,6 +35490,11 @@ These are the currently defined stub features and their properties:
@tab @samp{-}
@tab Yes

+@item @samp{Qbtrace-conf:bts:size}
+@tab Yes
+@tab @samp{-}
+@tab Yes
+
@item @samp{QNonStop}
@tab No
@tab @samp{-}
@@ -35708,6 +35752,9 @@ The remote stub understands the @samp{Qbtrace:off} packet.
@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::
@@ -36147,6 +36194,18 @@ Branch tracing has been disabled.
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
@@ -38675,7 +38734,16 @@ 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.
+settings for that format. The following information is described:
+
+@table @code
+@item bts
+This thread uses the Branch Trace Store (BTS) format.
+@table @code
+@item size
+The size of the 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}.
@@ -38687,6 +38755,7 @@ The formal DTD for the branch trace configuration format is given below:
<!ATTLIST btrace-conf version CDATA #FIXED "1.0">

<!ELEMENT bts EMPTY>
+<!ATTLIST bts size CDATA #IMPLIED>
@end smallexample

@include agentexpr.texi
diff --git a/gdb/features/btrace-conf.dtd b/gdb/features/btrace-conf.dtd
index e9cb2ef..907816c 100644
--- a/gdb/features/btrace-conf.dtd
+++ b/gdb/features/btrace-conf.dtd
@@ -8,3 +8,4 @@
<!ATTLIST btrace-conf version CDATA #FIXED "1.0">

<!ELEMENT bts EMPTY>
+<!ATTLIST bts size CDATA #IMPLIED>
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 8a706a8..08192c5 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -6038,7 +6038,9 @@ linux_low_btrace_conf (const struct btrace_target_info *tinfo,
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;
}
}
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index b8359e6..ebacd96 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -463,6 +463,58 @@ handle_btrace_general_set (char *own_buf)
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
@@ -622,6 +674,9 @@ handle_general_set (char *own_buf)
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;
@@ -1761,7 +1816,10 @@ static void
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;

diff --git a/gdb/nat/linux-btrace.c b/gdb/nat/linux-btrace.c
index c369483..66f37ea 100644
--- a/gdb/nat/linux-btrace.c
+++ b/gdb/nat/linux-btrace.c
@@ -398,11 +398,12 @@ linux_supports_btrace (struct target_ops *ops, enum btrace_format format)
/* 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 int pages, size;
int pid, pg;

tinfo = xzalloc (sizeof (*tinfo));
@@ -428,18 +429,34 @@ linux_enable_bts (ptid_t ptid, const struct btrace_config *conf)
if (pid == 0)
pid = ptid_get_pid (ptid);

+ /* Cast to ULONGEST to avoid overflows before we divide by PAGE_SIZE. */
+ size = (unsigned int) (((ULONGEST) conf->size + PAGE_SIZE - 1) / PAGE_SIZE);
+ if (size == 0)
+ {
+ errno = EINVAL;
+ goto err;
+ }
+
errno = 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.
- 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)
+ /* The buffer size can be requested in powers of two pages.
+ We track the number of pages we request in PAGES and its base-2 log
+ in PG. */
+
+ /* Adjust size to the next power of two. */
+ for (pg = 0, pages = 1; pages != size; ++pg, pages = (1u << pg))
+ if ((pages & size) != 0)
+ size += pages;
+
+ /* We try to allocate the requested size.
+ If that fails, try to get as much as we can. */
+ for (; size > 0; size >>= 1)
{
/* 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,
+ header = mmap (NULL, (size + 1) * PAGE_SIZE, PROT_READ, MAP_SHARED,
bts->file, 0);
if (header != MAP_FAILED)
break;
@@ -450,10 +467,11 @@ linux_enable_bts (ptid_t ptid, const struct btrace_config *conf)

bts->header = header;
bts->bts.mem = ((const uint8_t *) header) + PAGE_SIZE;
- bts->bts.size = (1 << pg) * PAGE_SIZE;
+ bts->bts.size = size * PAGE_SIZE;
bts->bts.data_head = &header->data_head;
bts->bts.last_head = 0;

+ tinfo->conf.bts.size = bts->bts.size;
return tinfo;

err_file:
@@ -479,7 +497,7 @@ linux_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
break;

case BTRACE_FORMAT_BTS:
- tinfo = linux_enable_bts (ptid, conf);
+ tinfo = linux_enable_bts (ptid, &conf->bts);
break;
}

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index d9ad9d4..d9c1456 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -76,6 +76,14 @@ static struct btrace_config record_btrace_conf;
/* 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. */

@@ -269,6 +277,71 @@ record_btrace_close (struct target_ops *self)
btrace_teardown (tp);
}

+/* 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
@@ -289,8 +362,7 @@ record_btrace_info (struct target_ops *self)

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);

@@ -2056,6 +2128,25 @@ cmd_show_replay_memory_access (struct ui_file *file, int from_tty,
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. */
@@ -2099,9 +2190,34 @@ replay."),
&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;
}
diff --git a/gdb/remote.c b/gdb/remote.c
index 16cb60f..e97a9f5 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1335,6 +1335,9 @@ enum {
/* 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
};

@@ -4020,7 +4023,9 @@ static const struct protocol_feature remote_protocol_features[] = {
{ "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;
@@ -11378,7 +11383,35 @@ remote_supports_btrace (struct target_ops *self, enum btrace_format format)
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
@@ -12279,6 +12312,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_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;
diff --git a/gdb/testsuite/gdb.btrace/buffer-size.exp b/gdb/testsuite/gdb.btrace/buffer-size.exp
new file mode 100644
index 0000000..9d36361
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/buffer-size.exp
@@ -0,0 +1,57 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2013-2014 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 x86-record_goto.S
+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: Intel\\\(R\\\) 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: Intel\\\(R\\\) 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"
--
1.8.3.1