* [patch v5 06/12] remote, btrace: add branch trace remote ops
2012-12-07 10:37 [patch v5 00/12] branch tracing support for Atom markus.t.metzger
@ 2012-12-07 10:37 ` markus.t.metzger
2012-12-07 10:37 ` [patch v5 09/12] gdbserver, linux, btrace: add btrace support for linux-low markus.t.metzger
` (10 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: markus.t.metzger @ 2012-12-07 10:37 UTC (permalink / raw)
To: gdb-patches
Cc: markus.t.metzger, jan.kratochvil, palves, tromey, kettenis,
Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Add the gdb remote target operations for branch tracing. We define the following
packets:
qbtrace:<ptid> query if new trace data is available for a thread
returns "yes" or "no" or "Enn"
Qbtrace:<ptid>:on enable branch tracing for one thread
returns "OK" or "Enn"
Qbtrace:<ptid>:off disable branch tracing for one thread
returns "OK" or "Enn"
qXfer:btrace:read read the full branch trace data for the current thread
2012-12-07 Markus Metzger <markus.t.metzger@intel.com>
* target.h (enum target_object): Add TARGET_OBJECT_BTRACE.
* remote.c: Include btrace.h.
(struct btrace_target_info): New struct.
(remote_supports_btrace): New function.
(send_Qbtrace): New function.
(remote_enable_btrace): New function.
(remote_disable_btrace): New function.
(remote_btrace_has_changed): New function.
(remote_read_btrace): New function.
(init_remote_ops): Add btrace ops.
(enum <unnamed>): Add btrace packets.
(struct protocol_feature remote_protocol_features[]): Add btrace packets.
(_initialize_remote): Add packet configuration for branch tracing.
---
gdb/remote.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
gdb/target.h | 4 +-
2 files changed, 174 insertions(+), 1 deletions(-)
mode change 100644 => 100755 gdb/remote.c
diff --git a/gdb/remote.c b/gdb/remote.c
old mode 100644
new mode 100755
index 929d4f5..a502c2c
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -67,6 +67,7 @@
#include "ax.h"
#include "ax-gdb.h"
#include "agent.h"
+#include "btrace.h"
/* Temp hacks for tracepoint encoding migration. */
static char *target_buf;
@@ -1292,6 +1293,9 @@ enum {
PACKET_qXfer_fdpic,
PACKET_QDisableRandomization,
PACKET_QAgent,
+ PACKET_qbtrace,
+ PACKET_Qbtrace,
+ PACKET_qXfer_btrace,
PACKET_MAX
};
@@ -3946,6 +3950,10 @@ static struct protocol_feature remote_protocol_features[] = {
{ "QAgent", PACKET_DISABLE, remote_supported_packet, PACKET_QAgent},
{ "tracenz", PACKET_DISABLE,
remote_string_tracing_feature, -1 },
+ { "qbtrace", PACKET_DISABLE, remote_supported_packet, PACKET_qbtrace },
+ { "Qbtrace", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace },
+ { "qXfer:btrace:read", PACKET_DISABLE, remote_supported_packet,
+ PACKET_qXfer_btrace }
};
static char *remote_support_xml;
@@ -8682,6 +8690,10 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object,
return remote_read_qxfer (ops, "uib", annex, readbuf, offset, len,
&remote_protocol_packets[PACKET_qXfer_uib]);
+ case TARGET_OBJECT_BTRACE:
+ return remote_read_qxfer (ops, "btrace", annex, readbuf, offset, len,
+ &remote_protocol_packets[PACKET_qXfer_btrace]);
+
default:
return -1;
}
@@ -11001,6 +11013,151 @@ remote_can_use_agent (void)
return (remote_protocol_packets[PACKET_QAgent].support != PACKET_DISABLE);
}
+struct btrace_target_info
+{
+ /* The ptid of the traced thread. */
+ ptid_t ptid;
+};
+
+/* Check whether the target supports branch tracing. */
+
+static int
+remote_supports_btrace (void)
+{
+ if (remote_protocol_packets[PACKET_qbtrace].support != PACKET_ENABLE)
+ return 0;
+ if (remote_protocol_packets[PACKET_Qbtrace].support != PACKET_ENABLE)
+ return 0;
+ if (remote_protocol_packets[PACKET_qXfer_btrace].support != PACKET_ENABLE)
+ return 0;
+
+ return 1;
+}
+
+/* Send the Qbtrace packet and check the response. */
+
+static void
+send_Qbtrace (ptid_t ptid, int enable)
+{
+ struct packet_config *packet = &remote_protocol_packets[PACKET_Qbtrace];
+ struct remote_state *rs = get_remote_state ();
+ char *buf = rs->buf;
+ char *endbuf = rs->buf + get_remote_packet_size ();
+
+ if (packet->support != PACKET_ENABLE)
+ error (_("Target does not support branch tracing."));
+
+ set_general_thread (ptid);
+
+ buf += xsnprintf (buf, endbuf - buf, "%s:", packet->name);
+ buf += xsnprintf (buf, endbuf - buf, enable ? "on" : "off");
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ if (packet_ok (rs->buf, packet) == PACKET_ERROR)
+ error (_("Could not %s branch tracing for %s: %s"),
+ enable ? "enable" : "disable", target_pid_to_str (ptid), rs->buf);
+}
+
+/* Enable branch tracing. */
+
+static struct btrace_target_info *
+remote_enable_btrace (ptid_t ptid)
+{
+ struct btrace_target_info *tinfo = NULL;
+
+ /* This will throw an error if enabling failed. */
+ send_Qbtrace (ptid, 1);
+
+ tinfo = xzalloc (sizeof (*tinfo));
+ tinfo->ptid = ptid;
+
+ return tinfo;
+}
+
+/* Disable branch tracing. */
+
+static void
+remote_disable_btrace (struct btrace_target_info *tinfo)
+{
+ /* This will throw an error if disabling failed. */
+ send_Qbtrace (tinfo->ptid, 0);
+
+ xfree (tinfo);
+}
+
+/* Check whether branch trace data has changed. */
+
+static int
+remote_btrace_has_changed (struct btrace_target_info *tinfo)
+{
+ struct packet_config *packet = &remote_protocol_packets[PACKET_qbtrace];
+ struct remote_state *rs = get_remote_state ();
+ char *buf = rs->buf;
+ char *endbuf = rs->buf + get_remote_packet_size ();
+
+ if (packet->support != PACKET_ENABLE)
+ error (_("Target does not support branch tracing."));
+
+ buf += xsnprintf (buf, endbuf - buf, "%s:", packet->name);
+ buf = write_ptid (buf, endbuf, tinfo->ptid);
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ switch (packet_ok (rs->buf, packet))
+ {
+ case PACKET_OK:
+ break;
+
+ case PACKET_UNKNOWN:
+ return 0;
+
+ case PACKET_ERROR:
+ error (_("Failed to check for branch trace data for %s: %s."),
+ target_pid_to_str (tinfo->ptid), rs->buf);
+ }
+
+ if (strcmp (rs->buf, "yes") == 0)
+ return 1;
+
+ if (strcmp (rs->buf, "no") == 0)
+ return 0;
+
+ error (_("Bad remote reply: %s."), rs->buf);
+
+ return 0;
+}
+
+/* Read the branch trace. */
+
+static VEC (btrace_block_s) *
+remote_read_btrace (struct btrace_target_info *tinfo)
+{
+ struct packet_config *packet = &remote_protocol_packets[PACKET_qXfer_btrace];
+ struct remote_state *rs = get_remote_state ();
+ VEC (btrace_block_s) *btrace = NULL;
+ char *xml;
+
+ if (packet->support != PACKET_ENABLE)
+ error (_("Target does not support branch tracing."));
+
+#if !defined(HAVE_LIBEXPAT)
+ error (_("Cannot process branch tracing result. XML parsing not supported."));
+#endif
+
+ xml = target_read_stralloc (¤t_target,
+ TARGET_OBJECT_BTRACE, NULL);
+ if (xml)
+ {
+ struct cleanup *cleanup = make_cleanup (xfree, xml);
+
+ btrace = parse_xml_btrace (xml);
+ do_cleanups (cleanup);
+ }
+
+ return btrace;
+}
+
static void
init_remote_ops (void)
{
@@ -11117,6 +11274,11 @@ Specify the serial device it is connected to\n\
remote_ops.to_traceframe_info = remote_traceframe_info;
remote_ops.to_use_agent = remote_use_agent;
remote_ops.to_can_use_agent = remote_can_use_agent;
+ remote_ops.to_supports_btrace = remote_supports_btrace;
+ remote_ops.to_enable_btrace = remote_enable_btrace;
+ remote_ops.to_disable_btrace = remote_disable_btrace;
+ remote_ops.to_btrace_has_changed = remote_btrace_has_changed;
+ remote_ops.to_read_btrace = remote_read_btrace;
}
/* Set up the extended remote vector by making a copy of the standard
@@ -11643,6 +11805,15 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
add_packet_config_cmd (&remote_protocol_packets[PACKET_QAgent],
"QAgent", "agent", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qbtrace],
+ "qbtrace", "query-btrace", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_Qbtrace],
+ "Qbtrace", "enable-btrace", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_btrace],
+ "qXfer:btrace", "read-btrace", 0);
+
/* Keep the old ``set remote Z-packet ...'' working. Each individual
Z sub-packet has its own set and show commands, but users may
have sets to this variable in their .gdbinit files (or in their
diff --git a/gdb/target.h b/gdb/target.h
index 4889ce4..ffdd512 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -287,7 +287,9 @@ enum target_object
/* Darwin dynamic linker info data. */
TARGET_OBJECT_DARWIN_DYLD_INFO,
/* OpenVMS Unwind Information Block. */
- TARGET_OBJECT_OPENVMS_UIB
+ TARGET_OBJECT_OPENVMS_UIB,
+ /* Branch trace data, in XML format. */
+ TARGET_OBJECT_BTRACE
/* Possible future objects: TARGET_OBJECT_FILE, ... */
};
--
1.7.1
^ permalink raw reply [flat|nested] 20+ messages in thread* [patch v5 09/12] gdbserver, linux, btrace: add btrace support for linux-low
2012-12-07 10:37 [patch v5 00/12] branch tracing support for Atom markus.t.metzger
2012-12-07 10:37 ` [patch v5 06/12] remote, btrace: add branch trace remote ops markus.t.metzger
@ 2012-12-07 10:37 ` markus.t.metzger
2012-12-07 10:38 ` [patch v5 02/12] cli, btrace: add btrace cli markus.t.metzger
` (9 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: markus.t.metzger @ 2012-12-07 10:37 UTC (permalink / raw)
To: gdb-patches
Cc: markus.t.metzger, jan.kratochvil, palves, tromey, kettenis,
Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Implement btrace target ops in target linux-low using the common linux-btrace
functions.
2012-12-07 Markus Metzger <markus.t.metzger@intel.com>
gdbserver/
* linux-low: Include linux-btrace.h.
(linux_low_enable_btrace): New function.
(linux_low_read_btrace): New function.
(linux_target_ops): Add btrace ops.
* configure.srv (i[34567]86-*-linux*): Add linux-btrace.o.
Add srv_linux_btrace=yes.
(x86_64-*-linux*): Add linux-btrace.o.
Add srv_linux_btrace=yes.
* configure.ac: Define HAVE_LINUX_BTRACE.
* config.in: Regenerated.
* configure: Regenerated.
---
gdb/gdbserver/config.in | 3 ++
gdb/gdbserver/configure | 6 ++++
gdb/gdbserver/configure.ac | 5 ++++
gdb/gdbserver/configure.srv | 6 +++-
gdb/gdbserver/linux-low.c | 57 +++++++++++++++++++++++++++++++++++++++++++
5 files changed, 75 insertions(+), 2 deletions(-)
diff --git a/gdb/gdbserver/config.in b/gdb/gdbserver/config.in
index b791b89..76fa209 100644
--- a/gdb/gdbserver/config.in
+++ b/gdb/gdbserver/config.in
@@ -73,6 +73,9 @@
/* Define to 1 if you have the `dl' library (-ldl). */
#undef HAVE_LIBDL
+/* Define if the target supports branch tracing. */
+#undef HAVE_LINUX_BTRACE
+
/* Define to 1 if you have the <linux/elf.h> header file. */
#undef HAVE_LINUX_ELF_H
diff --git a/gdb/gdbserver/configure b/gdb/gdbserver/configure
index ab22b5e..b5e23b4 100755
--- a/gdb/gdbserver/configure
+++ b/gdb/gdbserver/configure
@@ -4981,6 +4981,12 @@ $as_echo "#define HAVE_PTRACE_GETFPXREGS 1" >>confdefs.h
fi
fi
+if test "${srv_linux_btrace}" = "yes"; then
+
+$as_echo "#define HAVE_LINUX_BTRACE 1" >>confdefs.h
+
+fi
+
if test "$ac_cv_header_sys_procfs_h" = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for lwpid_t in sys/procfs.h" >&5
$as_echo_n "checking for lwpid_t in sys/procfs.h... " >&6; }
diff --git a/gdb/gdbserver/configure.ac b/gdb/gdbserver/configure.ac
index 35da28b..1865074 100644
--- a/gdb/gdbserver/configure.ac
+++ b/gdb/gdbserver/configure.ac
@@ -279,6 +279,11 @@ if test "${srv_linux_regsets}" = "yes"; then
fi
fi
+if test "${srv_linux_btrace}" = "yes"; then
+ AC_DEFINE(HAVE_LINUX_BTRACE, 1,
+ [Define if the target supports branch tracing.])
+fi
+
if test "$ac_cv_header_sys_procfs_h" = yes; then
BFD_HAVE_SYS_PROCFS_TYPE(lwpid_t)
BFD_HAVE_SYS_PROCFS_TYPE(psaddr_t)
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index d1e04a9..3492c16 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -97,10 +97,11 @@ case "${target}" in
srv_xmlfiles="${srv_xmlfiles} $srv_amd64_linux_xmlfiles"
fi
srv_tgtobj="linux-low.o linux-osdata.o linux-x86-low.o i386-low.o i387-fp.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="${srv_tgtobj} linux-ptrace.o linux-btrace.o"
srv_linux_usrregs=yes
srv_linux_regsets=yes
srv_linux_thread_db=yes
+ srv_linux_btrace=yes
ipa_obj="${ipa_i386_linux_regobj} linux-i386-ipa.o"
;;
i[34567]86-*-lynxos*) srv_regobj="i386.o"
@@ -293,11 +294,12 @@ case "${target}" in
;;
x86_64-*-linux*) srv_regobj="$srv_amd64_linux_regobj $srv_i386_linux_regobj"
srv_tgtobj="linux-low.o linux-osdata.o linux-x86-low.o i386-low.o i387-fp.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="${srv_tgtobj} linux-ptrace.o linux-btrace.o"
srv_xmlfiles="$srv_i386_linux_xmlfiles $srv_amd64_linux_xmlfiles"
srv_linux_usrregs=yes # This is for i386 progs.
srv_linux_regsets=yes
srv_linux_thread_db=yes
+ srv_linux_btrace=yes
ipa_obj="${ipa_amd64_linux_regobj} linux-amd64-ipa.o"
;;
x86_64-*-mingw*) srv_regobj="$srv_amd64_regobj"
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index c697f6b..5f5a5a3 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -84,6 +84,10 @@
#endif
#endif
+#ifdef HAVE_LINUX_BTRACE
+#include "linux-btrace.h"
+#endif
+
#ifndef HAVE_ELF32_AUXV_T
/* Copied from glibc's elf.h. */
typedef struct
@@ -5794,6 +5798,46 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
return len;
}
+#ifdef HAVE_LINUX_BTRACE
+
+/* Enable branch tracing. */
+
+static struct btrace_target_info *
+linux_low_enable_btrace (ptid_t ptid)
+{
+ struct btrace_target_info *tinfo;
+
+ tinfo = linux_enable_btrace (ptid);
+ if (tinfo)
+ tinfo->ptr_bits = register_size (0) * 8;
+
+ return tinfo;
+}
+
+/* Read branch trace data as btrace xml document. */
+
+static void
+linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer)
+{
+ VEC (btrace_block_s) *btrace;
+ struct btrace_block *block;
+ int i;
+
+ btrace = linux_read_btrace (tinfo);
+
+ buffer_grow_str (buffer, "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n");
+ buffer_grow_str (buffer, "<btrace version=\"1.0\">\n");
+
+ for (i = 0; VEC_iterate (btrace_block_s, btrace, i, block); i++)
+ buffer_xml_printf (buffer, "<block begin=\"0x%s\" end=\"0x%s\"/>\n",
+ paddress (block->begin), paddress (block->end));
+
+ buffer_grow_str (buffer, "</btrace>\n");
+
+ VEC_free (btrace_block_s, btrace);
+}
+#endif /* HAVE_LINUX_BTRACE */
+
static struct target_ops linux_target_ops = {
linux_create_inferior,
linux_attach,
@@ -5858,6 +5902,19 @@ static struct target_ops linux_target_ops = {
linux_get_min_fast_tracepoint_insn_len,
linux_qxfer_libraries_svr4,
linux_supports_agent,
+#ifdef HAVE_LINUX_BTRACE
+ linux_supports_btrace,
+ linux_low_enable_btrace,
+ linux_disable_btrace,
+ linux_btrace_has_changed,
+ linux_low_read_btrace,
+#else
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+#endif
};
static void
--
1.7.1
^ permalink raw reply [flat|nested] 20+ messages in thread* [patch v5 02/12] cli, btrace: add btrace cli
2012-12-07 10:37 [patch v5 00/12] branch tracing support for Atom markus.t.metzger
2012-12-07 10:37 ` [patch v5 06/12] remote, btrace: add branch trace remote ops markus.t.metzger
2012-12-07 10:37 ` [patch v5 09/12] gdbserver, linux, btrace: add btrace support for linux-low markus.t.metzger
@ 2012-12-07 10:38 ` markus.t.metzger
2012-12-07 15:16 ` Eli Zaretskii
2012-12-07 10:38 ` [patch v5 01/12] thread, btrace: add generic branch trace support markus.t.metzger
` (8 subsequent siblings)
11 siblings, 1 reply; 20+ messages in thread
From: markus.t.metzger @ 2012-12-07 10:38 UTC (permalink / raw)
To: gdb-patches
Cc: markus.t.metzger, jan.kratochvil, palves, tromey, kettenis,
Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Add branch trace commands:
- "btrace enable/disable" perform the obvious operation
"" on the current thread.
"all" on each existing thread.
"auto" on each newly created thread.
Actually, "btrace enable auto" turns on automatic enabling for new threads,
and "btrace disable auto" turns it off, again.
- "btrace list" prints the blocks that have been traced.
The output may be configured using modifiers. It prints:
- the block number
/a the begin and end code address of that block
/f the function containing the block
/l the source lines contained in the block
With the /t modifier, it prints the total number of blocks and exits.
It accepts an optional range argument specifying the range of blocks to be
listed. If no argument is given, all blocks are listed.
The block number can be used to print the trace for one particular block or
for a range of blocks.
- "btrace" prints the branch trace disassembly for the current thread.
Branch trace is printed block-by-block. Typically, one block at a time is
printed.
By default, the disassembly for the next block is printed, thus iterating
over the full branch trace.
The command supports the /m and /r modifiers accepted by the disassemble
command.
In addition, the command supports the following arguments:
- "<n>" set the iterator to the <n>-th block
- "+[<n>]" advance the iterator by <n> (default: 1)
- "-[<n>]" advance the iterator by -<n> (default: 1)
- "<l>-<h>" set the iterator to the <h>'th block and
print the blocks in the range in reverse (i.e. original
control flow) order.
Mixed source and disassembly does not work very well for inlined functions,
a problem that it shares with the disassemble command.
2012-12-07 Markus Metzger <markus.t.metzger@intel.com>
* command.h (enum command_class): Add class_btrace.
* btrace.c (warn_enable_btrace): New function.
(warn_disable_btrace): New function.
(cmd_btrace_enable): New function.
(cmd_btrace_enable_all): New function.
(cmd_btrace_enable_auto): New function.
(cmd_btrace_disable): New function.
(cmd_btrace_disable_all): New function.
(cmd_btrace_disable_auto): New function.
(do_btrace_list_address): New function.
(do_btrace_list_function): New function.
(do_btrace_list_line): New function.
(do_btrace_list_item): New function.
(do_btrace_list): New function.
(cmd_btrace_list): New function.
(do_btrace): New function.
(do_btrace_range): New function.
(do_prev_btrace): New function.
(do_next_btrace): New function.
(cmd_btrace): New function.
(_initialize_btrace): New function.
---
gdb/btrace.c | 600 +++++++++++++++++++++++++++++++++++++++
gdb/command.h | 2 +-
gdb/testsuite/gdb.base/page.exp | 3 +-
3 files changed, 603 insertions(+), 2 deletions(-)
diff --git a/gdb/btrace.c b/gdb/btrace.c
index 418f360..68b109a 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -25,6 +25,28 @@
#include "exceptions.h"
#include "inferior.h"
#include "target.h"
+#include "observer.h"
+#include "command.h"
+#include "cli/cli-cmds.h"
+#include "cli/cli-utils.h"
+#include "arch-utils.h"
+#include "disasm.h"
+#include "gdbarch.h"
+
+#include <ctype.h>
+#include <string.h>
+
+/* A new thread observer enabling branch tracing for the new thread. */
+static struct observer *btrace_thread_observer;
+
+/* Branch tracing command list. */
+static struct cmd_list_element *btcmdlist;
+
+/* Branch tracing enable command list. */
+static struct cmd_list_element *btencmdlist;
+
+/* Branch tracing disable command list. */
+static struct cmd_list_element *btdiscmdlist;
/* See btrace.h. */
@@ -166,3 +188,581 @@ next_btrace (struct thread_info *tp)
return VEC_index (btrace_block_s, btp->btrace, btp->iterator);
}
+
+/* Enable branch tracing. Turn errors into warnings. */
+
+static void
+warn_enable_btrace (struct thread_info *tp)
+{
+ volatile struct gdb_exception error;
+
+ TRY_CATCH (error, RETURN_MASK_ERROR)
+ enable_btrace (tp);
+
+ if (error.message)
+ warning (_("%s"), error.message);
+}
+
+/* Disable branch tracing. Turn errors into warnings. */
+
+static void
+warn_disable_btrace (struct thread_info *tp)
+{
+ volatile struct gdb_exception error;
+
+ TRY_CATCH (error, RETURN_MASK_ERROR)
+ disable_btrace (tp);
+
+ if (error.message)
+ warning (_("%s"), error.message);
+}
+
+/* The "btrace enable" command. */
+
+static void
+cmd_btrace_enable (char *args, int from_tty)
+{
+ struct thread_info *tp;
+
+ if (args && *args)
+ {
+ ALL_THREADS (tp)
+ if (number_is_in_list (args, tp->num))
+ warn_enable_btrace (tp);
+ }
+ else
+ {
+ tp = find_thread_ptid (inferior_ptid);
+ if (!tp)
+ error (_("Couldn't enable branch tracing: no inferior thread."));
+
+ enable_btrace (tp);
+ }
+}
+
+/* The "btrace enable all" command. */
+
+static void
+cmd_btrace_enable_all (char *args, int from_tty)
+{
+ struct thread_info *tp;
+
+ if (args && *args)
+ error (_("Invalid argument."));
+
+ ALL_THREADS (tp)
+ warn_enable_btrace (tp);
+}
+
+/* The "btrace enable auto" command. */
+
+static void
+cmd_btrace_enable_auto (char *args, int from_tty)
+{
+ if (args && *args)
+ error (_("Invalid argument."));
+
+ if (btrace_thread_observer)
+ return;
+
+ btrace_thread_observer
+ = observer_attach_new_thread (warn_enable_btrace);
+}
+
+/* The "btrace disable" command. */
+
+static void
+cmd_btrace_disable (char *args, int from_tty)
+{
+ struct thread_info *tp;
+
+ if (args && *args)
+ {
+ ALL_THREADS (tp)
+ if (number_is_in_list (args, tp->num))
+ warn_enable_btrace (tp);
+ }
+ else
+ {
+ tp = find_thread_ptid (inferior_ptid);
+ if (!tp)
+ error (_("Couldn't disable branch tracing: no inferior thread."));
+
+ disable_btrace (tp);
+ }
+}
+
+/* The "btrace disable all" command. */
+
+static void
+cmd_btrace_disable_all (char *args, int from_tty)
+{
+ struct thread_info *tp;
+
+ if (args && *args)
+ error (_("Invalid argument."));
+
+ ALL_THREADS (tp)
+ warn_disable_btrace (tp);
+}
+
+/* The "btrace disable auto" command. */
+
+static void
+cmd_btrace_disable_auto (char *args, int from_tty)
+{
+ if (args && *args)
+ error (_("Invalid argument."));
+
+ if (!btrace_thread_observer)
+ return;
+
+ observer_detach_new_thread (btrace_thread_observer);
+ btrace_thread_observer = NULL;
+}
+
+/* Flags controlling the output of a btrace list command. */
+enum btrace_list_flags
+{
+ /* Print code addresses. */
+ BTR_LIST_ADDRESS = (1 << 0),
+
+ /* Print function names. */
+ BTR_LIST_FUNCTION = (1 << 1),
+
+ /* Print line information. */
+ BTR_LIST_LINE = (1 << 2),
+
+ /* Print the total number of btrace blocks. */
+ BTR_LIST_TOTAL = (1 << 3)
+};
+
+/* Print the addresses for a btrace block. */
+
+static void
+do_btrace_list_address (struct btrace_block *trace)
+{
+ struct gdbarch *gdbarch = target_gdbarch ();
+
+ ui_out_field_core_addr (current_uiout, "begin", gdbarch, trace->begin);
+ ui_out_text (current_uiout, " - ");
+ ui_out_field_core_addr (current_uiout, "end", gdbarch, trace->end);
+}
+
+/* Print the function containing a btrace block. */
+
+static void
+do_btrace_list_function (struct btrace_block *trace)
+{
+ struct minimal_symbol *msymbol;
+ struct symbol *symbol;
+ const char* func;
+
+ func = "??";
+ symbol = find_pc_function (trace->begin);
+ if (symbol)
+ func = SYMBOL_PRINT_NAME (symbol);
+ else
+ {
+ msymbol = lookup_minimal_symbol_by_pc (trace->begin);
+ if (msymbol)
+ func = SYMBOL_PRINT_NAME (msymbol);
+ }
+
+ ui_out_text (current_uiout, " in ");
+ ui_out_field_string (current_uiout, "function", func);
+}
+
+/* Print the line information for a btrace block. */
+
+static void
+do_btrace_list_line (struct btrace_block *trace)
+{
+ struct symbol *symbol = find_pc_function (trace->begin);
+ struct symtab *symtab = NULL;
+ struct linetable *linetable = NULL;
+ const char *filename = NULL;
+
+ if (symbol)
+ symtab = symbol->symtab;
+ if (!symtab)
+ symtab = find_pc_symtab (trace->begin);
+ if (symtab)
+ {
+ linetable = symtab->linetable;
+ filename = symtab->filename;
+ }
+
+ if (filename)
+ {
+ ui_out_text (current_uiout, " at ");
+ ui_out_field_string (current_uiout, "file", filename);
+
+ if (linetable)
+ {
+ struct linetable_entry *line = linetable->item;
+ int nitems = linetable->nitems, i = 0;
+ int begin = INT_MAX, end = 0;
+
+ /* Skip all preceding entries. */
+ for (; i < (nitems - 1) && line[i + 1].pc <= trace->begin; ++i);
+
+ for (; i < nitems && line[i].pc <= trace->end; ++i)
+ {
+ begin = min (begin, line[i].line);
+ end = max (end, line[i].line);
+ }
+
+ if (begin <= end)
+ {
+ ui_out_text (current_uiout, ":");
+ ui_out_field_int (current_uiout, "lbegin", begin);
+
+ if (begin < end)
+ {
+ ui_out_text (current_uiout, "-");
+ ui_out_field_int (current_uiout, "lend", end);
+ }
+ }
+ }
+ }
+}
+
+/* Print a btrace block. */
+
+static void
+do_btrace_list_item (struct btrace_block *trace, enum btrace_list_flags flags)
+{
+ if (flags & BTR_LIST_ADDRESS)
+ do_btrace_list_address (trace);
+
+ if (flags & BTR_LIST_FUNCTION)
+ do_btrace_list_function (trace);
+
+ if (flags & BTR_LIST_LINE)
+ do_btrace_list_line (trace);
+}
+
+/* Print the btrace list for a range of blocks. */
+
+static void
+do_btrace_list (VEC (btrace_block_s) *btrace, char *range,
+ enum btrace_list_flags flags)
+{
+ struct cleanup *ui_out_chain;
+ unsigned int block;
+ struct btrace_block *trace;
+
+ ui_out_chain
+ = make_cleanup_ui_out_tuple_begin_end (current_uiout, "btrace blocks");
+ block = 0;
+
+ while (VEC_iterate (btrace_block_s, btrace, block, trace))
+ {
+ ++block;
+
+ if (number_is_in_list (range, block))
+ {
+ ui_out_field_fmt_int (current_uiout, 5, ui_left, "block", block);
+ do_btrace_list_item (trace, flags);
+ ui_out_text (current_uiout, "\n");
+ }
+ }
+
+ do_cleanups (ui_out_chain);
+}
+
+/* The "btrace list" command. */
+
+static void
+cmd_btrace_list (char *args, int from_tty)
+{
+ struct thread_info *tp = find_thread_ptid (inferior_ptid);
+ enum btrace_list_flags flags = BTR_LIST_FUNCTION | BTR_LIST_LINE;
+ VEC (btrace_block_s) *btrace;
+
+ if (!tp)
+ error (_("No thread."));
+
+ btrace = get_btrace (tp);
+
+ /* Parse modifier. */
+ if (args && *args)
+ {
+ if (*args == '/')
+ flags = 0;
+
+ while (*args == '/')
+ {
+ ++args;
+
+ if (*args == '\0')
+ error (_("Missing modifier."));
+
+ for (; *args; ++args)
+ {
+ if (isspace (*args))
+ break;
+
+ if (*args == '/')
+ continue;
+
+ switch (*args)
+ {
+ case 'a':
+ flags |= BTR_LIST_ADDRESS;
+ break;
+ case 'f':
+ flags |= BTR_LIST_FUNCTION;
+ break;
+ case 'l':
+ flags |= BTR_LIST_LINE;
+ break;
+ case 't':
+ flags |= BTR_LIST_TOTAL;
+ break;
+ default:
+ error (_("Invalid modifier: %c."), *args);
+ }
+ }
+
+ args = skip_spaces (args);
+ }
+ }
+
+ if (flags & BTR_LIST_TOTAL)
+ {
+ struct cleanup *ui_out_chain;
+ unsigned int total;
+
+ total = VEC_length (btrace_block_s, btrace);
+ ui_out_chain
+ = make_cleanup_ui_out_tuple_begin_end (current_uiout, "btrace blocks");
+
+ ui_out_text (current_uiout, "total: ");
+ ui_out_field_int (current_uiout, "total", total);
+ ui_out_text (current_uiout, "\n");
+
+ do_cleanups (ui_out_chain);
+ }
+ else if (btrace)
+ do_btrace_list (btrace, args, flags);
+ else
+ error (_("No trace."));
+}
+
+/* Print the disassembly of a btrace block. */
+
+static void
+do_btrace (struct btrace_block *trace, int flags)
+{
+ struct gdbarch *gdbarch = target_gdbarch ();
+
+ if (!trace)
+ error (_("No trace."));
+
+ if (trace->end < trace->begin)
+ warning (_("Bad trace: %s - %s"), paddress (gdbarch, trace->begin),
+ paddress (gdbarch, trace->end));
+
+ gdb_disassembly (gdbarch, current_uiout, 0, flags, -1,
+ trace->begin, trace->end + 1);
+}
+
+/* Print the branch trace disassembly for a range of btrace blocks. */
+
+static void
+do_btrace_range (struct thread_info *tp, int flags, char *args)
+{
+ struct get_number_or_range_state state;
+ unsigned int i;
+ VEC (btrace_block_s) *btrace;
+ struct cleanup *cleanup;
+
+ btrace = NULL;
+ cleanup = make_cleanup (VEC_cleanup (btrace_block_s), &btrace);
+
+ /* We store the relevant blocks into a separate vector, so we can display
+ them in reverse order. */
+ init_number_or_range (&state, args);
+ while (!state.finished)
+ {
+ struct btrace_block *trace;
+ int index;
+
+ index = get_number_or_range (&state);
+ if (!index)
+ error (_("Args must be numbers or '$' variables."));
+
+ trace = read_btrace (tp, index - 1);
+ if (!trace)
+ continue;
+
+ VEC_safe_push (btrace_block_s, btrace, trace);
+ }
+
+ i = VEC_length (btrace_block_s, btrace);
+ while (i--)
+ do_btrace (VEC_index (btrace_block_s, btrace, i), flags);
+
+ do_cleanups (cleanup);
+}
+
+/* Print the branch trace disassembly for a preceding block. */
+
+static void
+do_prev_btrace (struct thread_info *tp, int flags, char *args)
+{
+ struct btrace_block *trace = NULL;
+ size_t skip = 1;
+
+ if (args[0])
+ skip = get_number (&args);
+
+ while (skip--)
+ trace = prev_btrace (tp);
+
+ if (args[0])
+ error (_("Junk after argument: %s"), args);
+
+ do_btrace (trace, flags);
+}
+
+/* Print the branch trace disassembly for a succeding block. */
+
+static void
+do_next_btrace (struct thread_info *tp, int flags, char *args)
+{
+ struct btrace_block *trace = NULL;
+ size_t skip = 1;
+
+ if (args[0])
+ skip = get_number (&args);
+
+ while (skip--)
+ trace = next_btrace (tp);
+
+ if (args[0])
+ error (_("Junk after argument: %s"), args);
+
+ do_btrace (trace, flags);
+}
+
+/* The "btrace" command. */
+
+static void
+cmd_btrace (char *args, int from_tty)
+{
+ struct thread_info *tp = find_thread_ptid (inferior_ptid);
+ struct btrace_block *trace = NULL;
+ int flags = 0;
+
+ if (!tp)
+ error (_("No thread."));
+
+ /* Parse modifier. We accept the same modifiers as the disas command. */
+ if (args && *args)
+ {
+ while (*args == '/')
+ {
+ ++args;
+
+ if (*args == '\0')
+ error (_("Missing modifier."));
+
+ for (; *args; ++args)
+ {
+ if (isspace (*args))
+ break;
+
+ if (*args == '/')
+ continue;
+
+ switch (*args)
+ {
+ case 'm':
+ flags |= DISASSEMBLY_SOURCE;
+ flags |= DISASSEMBLY_FILENAME;
+ break;
+ case 'r':
+ flags |= DISASSEMBLY_RAW_INSN;
+ break;
+ default:
+ error (_("Invalid modifier: %c."), *args);
+ }
+ }
+
+ args = skip_spaces (args);
+ }
+ }
+
+ if (!args || !*args)
+ do_btrace (prev_btrace (tp), flags);
+ else if (args[0] == '+')
+ do_prev_btrace (tp, flags, args+1);
+ else if (args[0] == '-')
+ do_next_btrace (tp, flags, args+1);
+ else
+ do_btrace_range (tp, flags, args);
+}
+
+void _initialize_btrace (void);
+
+/* Initialize btrace commands. */
+
+void
+_initialize_btrace (void)
+{
+ struct cmd_list_element *c;
+
+ add_cmd ("branchtrace", class_btrace, NULL, _("Recording a branch trace."),
+ &cmdlist);
+
+ add_prefix_cmd ("btrace", class_btrace, cmd_btrace, _("\
+Disassemble the selected branch trace block.\n\n\
+With a /m modifier, source lines are included (if available).\n\
+With a /r modifier, raw instructions in hex are included.\n\n\
+Without arguments, selects the chronologically preceding block.\n\
+With \"+[<n>]\" argument, selects the n-th chronologically preceding block.\n\
+With \"-[<n>]\" argument, selects the n-th chronologically succeeding block.\n\
+With one positive integer argument, selects the respective block.\n\
+With a range argument \"<l>-<h>\", selects the h-th block and disassembles \
+blocks in the range in reverse (i.e. original control flow) order.\n"),
+ &btcmdlist, "btrace ", 1, &cmdlist);
+
+ add_prefix_cmd ("enable", class_btrace, cmd_btrace_enable, _("\
+Enable branch trace recording for the current thread.\n"),
+ &btencmdlist, "btrace enable ", 1, &btcmdlist);
+
+ add_cmd ("all", class_btrace, cmd_btrace_enable_all, _("\
+Enable branch trace recording for all existing threads.\n"),
+ &btencmdlist);
+
+ add_cmd ("auto", class_btrace, cmd_btrace_enable_auto, _("\
+Enable branch trace recording for each new thread.\n"),
+ &btencmdlist);
+
+ add_prefix_cmd ("disable", class_btrace, cmd_btrace_disable, _("\
+Disable branch trace recording for the current thread.\n"),
+ &btdiscmdlist, "btrace disable ", 1, &btcmdlist);
+
+ add_cmd ("all", class_btrace, cmd_btrace_disable_all, _("\
+Disable branch trace recording for all existing threads.\n"),
+ &btdiscmdlist);
+
+ add_cmd ("auto", class_btrace, cmd_btrace_disable_auto, _("\
+Stop enabling branch trace recording for each new thread.\n"),
+ &btdiscmdlist);
+
+ add_cmd ("list", class_btrace, cmd_btrace_list, _("\
+List branch trace blocks.\n\n\
+Prints a list of all blocks for which branch trace is available.\n\
+With a /a modifier, addresses are included.\n\
+With a /f modifier, the function name is included (if available).\n\
+With a /l modifier, source lines are include (if available).\n\
+With a /t modifier, prints the total number of trace blocks and stops.\n\
+Without any modifier, behaves as if /fl were specified.\n\n\
+Without arguments, the full list of blocks is listed.\n\
+With a range (<start>[-<end>]) argument, lists all blocks in that range.\n"),
+ &btcmdlist);
+}
diff --git a/gdb/command.h b/gdb/command.h
index 8eb86ba..b576b70 100644
--- a/gdb/command.h
+++ b/gdb/command.h
@@ -39,7 +39,7 @@ enum command_class
no_class = -1, class_run = 0, class_vars, class_stack, class_files,
class_support, class_info, class_breakpoint, class_trace,
class_alias, class_bookmark, class_obscure, class_maintenance,
- class_pseudo, class_tui, class_user, class_xdb,
+ class_pseudo, class_tui, class_user, class_xdb, class_btrace,
no_set_class /* Used for "show" commands that have no corresponding
"set" command. */
};
diff --git a/gdb/testsuite/gdb.base/page.exp b/gdb/testsuite/gdb.base/page.exp
index 0629807..d9b3899 100644
--- a/gdb/testsuite/gdb.base/page.exp
+++ b/gdb/testsuite/gdb.base/page.exp
@@ -25,6 +25,7 @@ gdb_test_sequence "help" "unpaged help" {
"List of classes of commands:"
""
"aliases -- Aliases of other commands"
+ "branchtrace -- Recording a branch trace"
"breakpoints -- Making program stop at certain points"
"data -- Examining data"
"files -- Specifying and examining files"
@@ -52,12 +53,12 @@ gdb_expect_list "paged help" \
"List of classes of commands:"
""
"aliases -- Aliases of other commands"
+ "branchtrace -- Recording a branch trace"
"breakpoints -- Making program stop at certain points"
"data -- Examining data"
"files -- Specifying and examining files"
"internals -- Maintenance commands"
"obscure -- Obscure features"
- "running -- Running the program"
}
gdb_test "q"
--
1.7.1
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [patch v5 02/12] cli, btrace: add btrace cli
2012-12-07 10:38 ` [patch v5 02/12] cli, btrace: add btrace cli markus.t.metzger
@ 2012-12-07 15:16 ` Eli Zaretskii
2012-12-13 9:14 ` Metzger, Markus T
0 siblings, 1 reply; 20+ messages in thread
From: Eli Zaretskii @ 2012-12-07 15:16 UTC (permalink / raw)
To: markus.t.metzger; +Cc: gdb-patches, jan.kratochvil, palves, tromey, kettenis
> From: markus.t.metzger@intel.com
> Cc: markus.t.metzger@gmail.com, jan.kratochvil@redhat.com, palves@redhat.com, tromey@redhat.com, kettenis@gnu.org, Markus Metzger <markus.t.metzger@intel.com>
> Date: Fri, 7 Dec 2012 11:37:14 +0100
>
> From: Markus Metzger <markus.t.metzger@intel.com>
>
> Add branch trace commands:
Thanks. This will be documented at some point, yes?
> + add_cmd ("list", class_btrace, cmd_btrace_list, _("\
> +List branch trace blocks.\n\n\
> +Prints a list of all blocks for which branch trace is available.\n\
"Print", not "prints", to be compatible with "List".
> +With a /a modifier, addresses are included.\n\
> +With a /f modifier, the function name is included (if available).\n\
It is better to use active tense, not passive tense:
With a /a modifier, include addresses.
With a /f modifier, include function names (if available).
> +With a /l modifier, source lines are include (if available).\n\
^^^^^^^
A typo.
> +With a /t modifier, prints the total number of trace blocks and stops.\n\
^^^^^^
"print"
> +Without any modifier, behaves as if /fl were specified.\n\n\
By default, include function names and source lines.
And I have a question: how to turn off all the optional print-outs?
Is there a /no-f modifier or something?
> +Without arguments, the full list of blocks is listed.\n\
> +With a range (<start>[-<end>]) argument, lists all blocks in that range.\n"),
Again, use active tense, and "list" instead of "lists".
Thanks.
^ permalink raw reply [flat|nested] 20+ messages in thread* RE: [patch v5 02/12] cli, btrace: add btrace cli
2012-12-07 15:16 ` Eli Zaretskii
@ 2012-12-13 9:14 ` Metzger, Markus T
0 siblings, 0 replies; 20+ messages in thread
From: Metzger, Markus T @ 2012-12-13 9:14 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches, jan.kratochvil, palves, tromey, kettenis
> -----Original Message-----
> From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-owner@sourceware.org] On Behalf Of Eli Zaretskii
> Sent: Friday, December 07, 2012 4:16 PM
Thanks for your review.
[...]
> > Add branch trace commands:
>
> Thanks. This will be documented at some point, yes?
Yes. I will start it shortly.
> > + add_cmd ("list", class_btrace, cmd_btrace_list, _("\
> > +List branch trace blocks.\n\n\
> > +Prints a list of all blocks for which branch trace is available.\n\
>
> "Print", not "prints", to be compatible with "List".
Fixed.
> > +With a /a modifier, addresses are included.\n\
> > +With a /f modifier, the function name is included (if available).\n\
>
> It is better to use active tense, not passive tense:
>
> With a /a modifier, include addresses.
> With a /f modifier, include function names (if available).
I changed this for all command texts.
> > +With a /l modifier, source lines are include (if available).\n\
> ^^^^^^^
> A typo.
Changed to active tense.
> > +With a /t modifier, prints the total number of trace blocks and stops.\n\
> ^^^^^^
> "print"
Fixed. Everywhere.
> > +Without any modifier, behaves as if /fl were specified.\n\n\
>
> By default, include function names and source lines.
Fixed.
> And I have a question: how to turn off all the optional print-outs?
> Is there a /no-f modifier or something?
No, there isn't. Everything is optional, except for the block number. If you wanted to turn off everything, you would get a list of integers, which would be fairly useless. You can get the total number of blocks using /t.
> > +Without arguments, the full list of blocks is listed.\n\
> > +With a range (<start>[-<end>]) argument, lists all blocks in that range.\n"),
>
> Again, use active tense, and "list" instead of "lists".
Fixed.
Regards,
Markus.
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052
^ permalink raw reply [flat|nested] 20+ messages in thread
* [patch v5 01/12] thread, btrace: add generic branch trace support
2012-12-07 10:37 [patch v5 00/12] branch tracing support for Atom markus.t.metzger
` (2 preceding siblings ...)
2012-12-07 10:38 ` [patch v5 02/12] cli, btrace: add btrace cli markus.t.metzger
@ 2012-12-07 10:38 ` markus.t.metzger
2012-12-07 10:38 ` [patch v5 03/12] linux, btrace: perf_event based branch tracing markus.t.metzger
` (7 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: markus.t.metzger @ 2012-12-07 10:38 UTC (permalink / raw)
To: gdb-patches
Cc: markus.t.metzger, jan.kratochvil, palves, tromey, kettenis,
Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Add branch trace information to struct thread_info to hold the branch trace
information for that thread.
Add functions to enable/disable, and get a thread's branch trace, as well as
for iterating over it.
Iteration uses a per-thread iterator stored in the thread_info's branch trace
information.
Iterators are reset implicitly when a thread's branch trace changes.
2012-12-07 Markus Metzger <markus.t.metzger@intel.com>
* target.h: Include btrace.h.
(struct target_ops): Add btrace ops.
* target.c (update_current_target): Initialize btrace ops.
(target_supports_btrace): New function.
(target_enable_btrace): New function.
(target_disable_btrace): New function.
(target_read_btrace): New function.
(target_btrace_has_changed): New function.
* btrace.h: New file.
* btrace.c: New file.
* Makefile.in: Add btrace.c.
* gdbthread.h: Include btrace.h.
(struct thread_info): Add btrace field.
* thread.c: Include btrace.h.
(free_thread): Call disable_btrace.
* infcmd.c: Include btrace.h.
(detach_command): Call disconnect_btrace.
* common/btrace-common.h: New file.
---
gdb/Makefile.in | 4 +-
gdb/btrace.c | 168 ++++++++++++++++++++++++++++++++++++++++++++
gdb/btrace.h | 83 ++++++++++++++++++++++
gdb/common/btrace-common.h | 62 ++++++++++++++++
gdb/gdbthread.h | 4 +
gdb/infcmd.c | 2 +
gdb/target.c | 69 ++++++++++++++++++
gdb/target.h | 35 +++++++++
gdb/thread.c | 4 +
9 files changed, 429 insertions(+), 2 deletions(-)
create mode 100644 gdb/btrace.c
create mode 100644 gdb/btrace.h
create mode 100644 gdb/common/btrace-common.h
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 9f6f3a9..ac34f9f 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -751,7 +751,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
regset.c sol-thread.c windows-termcap.c \
common/gdb_vecs.c common/common-utils.c common/xml-utils.c \
common/ptid.c common/buffer.c gdb-dlfcn.c common/agent.c \
- common/format.c
+ common/format.c btrace.c
LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
@@ -917,7 +917,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
inferior.o osdata.o gdb_usleep.o record.o gcore.o \
gdb_vecs.o jit.o progspace.o skip.o probe.o \
common-utils.o buffer.o ptid.o gdb-dlfcn.o common-agent.o \
- format.o registry.o
+ format.o registry.o btrace.o
TSOBS = inflow.o
diff --git a/gdb/btrace.c b/gdb/btrace.c
new file mode 100644
index 0000000..418f360
--- /dev/null
+++ b/gdb/btrace.c
@@ -0,0 +1,168 @@
+/* Branch trace support for GDB, the GNU debugger.
+
+ Copyright (C) 2012 Free Software Foundation, Inc.
+
+ Contributed by Intel Corp. <markus.t.metzger@intel.com>
+
+ This file is part of GDB.
+
+ 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/>. */
+
+#include "btrace.h"
+#include "gdbthread.h"
+#include "regcache.h"
+#include "exceptions.h"
+#include "inferior.h"
+#include "target.h"
+
+/* See btrace.h. */
+
+void
+enable_btrace (struct thread_info *tp)
+{
+ if (tp->btrace.target)
+ return;
+
+ if (!target_supports_btrace ())
+ error (_("Target does not support branch tracing."));
+
+ tp->btrace.target = target_enable_btrace (tp->ptid);
+}
+
+/* See btrace.h. */
+
+void
+disable_btrace (struct thread_info *tp)
+{
+ struct btrace_thread_info *btp = &tp->btrace;
+ int errcode = 0;
+
+ if (!btp->target)
+ return;
+
+ if (!target_supports_btrace ())
+ return;
+
+ target_disable_btrace (btp->target);
+ btp->target = NULL;
+
+ VEC_free (btrace_block_s, btp->btrace);
+}
+
+/* See btrace.h. */
+
+void
+disconnect_btrace (void)
+{
+ struct thread_info *tp;
+
+ ALL_THREADS (tp)
+ disable_btrace (tp);
+}
+
+/* Update the thread's branch trace data in case of new trace. */
+
+static void
+update_btrace (struct thread_info *tp)
+{
+ struct btrace_thread_info *btp = &tp->btrace;
+
+ if (btp->target && target_btrace_has_changed (btp->target))
+ {
+ btp->btrace = target_read_btrace (btp->target);
+ btp->iterator = -1;
+
+ /* The first block ends at the current pc. */
+ if (!VEC_empty (btrace_block_s, btp->btrace))
+ {
+ struct regcache *regcache;
+ struct btrace_block *head;
+
+ regcache = get_thread_regcache (tp->ptid);
+ head = VEC_index (btrace_block_s, btp->btrace, 0);
+ if (head && !head->end)
+ head->end = regcache_read_pc (regcache);
+ }
+ }
+}
+
+/* See btrace.h. */
+
+VEC (btrace_block_s) *
+get_btrace (struct thread_info *tp)
+{
+ update_btrace (tp);
+
+ return tp->btrace.btrace;
+}
+
+/* See btrace.h. */
+
+struct btrace_block *
+read_btrace (struct thread_info *tp, int index)
+{
+ struct btrace_thread_info *btp = &tp->btrace;
+
+ if (index < 0)
+ error (_("Invalid index: %d."), index);
+
+ update_btrace (tp);
+ btp->iterator = index;
+
+ if (btp->iterator >= VEC_length (btrace_block_s, btp->btrace))
+ {
+ btp->iterator = VEC_length (btrace_block_s, btp->btrace);
+ return NULL;
+ }
+
+ return VEC_index (btrace_block_s, btp->btrace, btp->iterator);
+}
+
+/* See btrace.h. */
+
+struct btrace_block *
+prev_btrace (struct thread_info *tp)
+{
+ struct btrace_thread_info *btp = &tp->btrace;
+
+ update_btrace (tp);
+ btp->iterator += 1;
+
+ if (btp->iterator >= VEC_length (btrace_block_s, btp->btrace))
+ {
+ btp->iterator = VEC_length (btrace_block_s, btp->btrace);
+ return NULL;
+ }
+
+ return VEC_index (btrace_block_s, btp->btrace, btp->iterator);
+}
+
+/* See btrace.h. */
+
+struct btrace_block *
+next_btrace (struct thread_info *tp)
+{
+ struct btrace_thread_info *btp = &tp->btrace;
+
+ update_btrace (tp);
+ btp->iterator -= 1;
+
+ if (btp->iterator <= -1)
+ {
+ btp->iterator = -1;
+ return NULL;
+ }
+
+ return VEC_index (btrace_block_s, btp->btrace, btp->iterator);
+}
diff --git a/gdb/btrace.h b/gdb/btrace.h
new file mode 100644
index 0000000..df9df23
--- /dev/null
+++ b/gdb/btrace.h
@@ -0,0 +1,83 @@
+/* Branch trace support for GDB, the GNU debugger.
+
+ Copyright (C) 2012 Free Software Foundation, Inc.
+
+ Contributed by Intel Corp. <markus.t.metzger@intel.com>.
+
+ This file is part of GDB.
+
+ 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/>. */
+
+#ifndef BTRACE_H
+#define BTRACE_H
+
+/* Branch tracing (btrace) is a per-thread control-flow execution trace of the
+ inferior. For presentation purposes, the branch trace is represented as a
+ list of sequential control-flow blocks, one such list per thread. */
+
+#include "btrace-common.h"
+
+struct thread_info;
+
+/* Branch trace information per thread.
+
+ This represents the branch trace configuration as well as the entry point
+ into the branch trace data. For the latter, it also contains the index into
+ an array of branch trace blocks used for iterating though the branch trace
+ blocks of a thread. */
+struct btrace_thread_info
+{
+ /* The target branch trace information for this thread.
+
+ This contains the branch trace configuration as well as any
+ target-specific information necessary for implementing branch tracing on
+ the underlying architecture. */
+ struct btrace_target_info *target;
+
+ /* The current branch trace for this thread. */
+ VEC (btrace_block_s) *btrace;
+
+ /* The current iterator position in the above trace vector.
+ In additon to valid vector indices, the iterator can be:
+
+ -1 one before the head
+ VEC_length() one after the tail */
+ int iterator;
+};
+
+/* Enable branch tracing for a thread. */
+extern void enable_btrace (struct thread_info *tp);
+
+/* Disable branch tracing for a thread.
+ This will also delete the current branch trace data. */
+extern void disable_btrace (struct thread_info *);
+
+/* Disconnect branch tracing on detach. */
+extern void disconnect_btrace (void);
+
+/* Return the current branch trace vector for a thread, or NULL if there is no
+ branch trace data available. */
+extern VEC (btrace_block_s) *get_btrace (struct thread_info *);
+
+/* Functions to iterate over a thread's branch trace.
+ There is one global iterator per thread. The iterator is reset implicitly
+ when branch trace for this thread changes.
+ On success, read_btrace sets the iterator to the returned trace entry.
+ Returns the selected block or NULL if there is no trace or the iterator is
+ out of bounds. */
+extern struct btrace_block *read_btrace (struct thread_info *, int);
+extern struct btrace_block *prev_btrace (struct thread_info *);
+extern struct btrace_block *next_btrace (struct thread_info *);
+
+#endif /* BTRACE_H */
diff --git a/gdb/common/btrace-common.h b/gdb/common/btrace-common.h
new file mode 100644
index 0000000..90372ba
--- /dev/null
+++ b/gdb/common/btrace-common.h
@@ -0,0 +1,62 @@
+/* Branch trace support for GDB, the GNU debugger.
+
+ Copyright (C) 2012 Free Software Foundation, Inc.
+
+ Contributed by Intel Corp. <markus.t.metzger@intel.com>.
+
+ This file is part of GDB.
+
+ 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/>. */
+
+#ifndef BTRACE_COMMON_H
+#define BTRACE_COMMON_H
+
+/* Branch tracing (btrace) is a per-thread control-flow execution trace of the
+ inferior. For presentation purposes, the branch trace is represented as a
+ list of sequential control-flow blocks, one such list per thread. */
+
+#ifdef GDBSERVER
+# include "server.h"
+#else
+# include "defs.h"
+#endif
+
+#include "vec.h"
+
+/* A branch trace block.
+
+ This represents a block of sequential control-flow. Adjacent blocks will be
+ connected via calls, returns, or jumps. The latter can be direct or
+ indirect, conditional or unconditional. Branches can further be
+ asynchronous, e.g. interrupts. */
+struct btrace_block
+{
+ /* The address of the first instruction in the block. */
+ CORE_ADDR begin;
+
+ /* The address of the last instruction in the block. */
+ CORE_ADDR end;
+};
+
+/* Branch trace is represented as a vector of branch trace blocks starting with
+ the most recent block. */
+typedef struct btrace_block btrace_block_s;
+
+/* Define functions operating on a vector of branch trace blocks. */
+DEF_VEC_O (btrace_block_s);
+
+/* Target specific branch trace information. */
+struct btrace_target_info;
+
+#endif /* BTRACE_COMMON_H */
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index 0250555..69320f3 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -28,6 +28,7 @@ struct symtab;
#include "frame.h"
#include "ui-out.h"
#include "inferior.h"
+#include "btrace.h"
/* Frontend view of the thread state. Possible extensions: stepping,
finishing, until(ling),... */
@@ -227,6 +228,9 @@ struct thread_info
/* Function that is called to free PRIVATE. If this is NULL, then
xfree will be called on PRIVATE. */
void (*private_dtor) (struct private_thread_info *);
+
+ /* Branch trace information for this thread. */
+ struct btrace_thread_info btrace;
};
/* Create an empty thread list, or empty the existing one. */
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index db9b9b5..cc8bedb 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -56,6 +56,7 @@
#include "inf-loop.h"
#include "continuations.h"
#include "linespec.h"
+#include "btrace.h"
/* Functions exported for general use, in inferior.h: */
@@ -2745,6 +2746,7 @@ detach_command (char *args, int from_tty)
error (_("The program is not being run."));
disconnect_tracing (from_tty);
+ disconnect_btrace ();
target_detach (args, from_tty);
diff --git a/gdb/target.c b/gdb/target.c
index 5015e51..90f3a4b 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -4149,6 +4149,75 @@ target_ranged_break_num_registers (void)
return -1;
}
+/* See target.h. */
+int
+target_supports_btrace (void)
+{
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ if (t->to_supports_btrace != NULL)
+ return t->to_supports_btrace ();
+
+ return 0;
+}
+
+/* See target.h. */
+struct btrace_target_info *
+target_enable_btrace (ptid_t ptid)
+{
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ if (t->to_enable_btrace != NULL)
+ return t->to_enable_btrace (ptid);
+
+ tcomplain ();
+ return NULL;
+}
+
+/* See target.h. */
+void
+target_disable_btrace (struct btrace_target_info *btinfo)
+{
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ if (t->to_disable_btrace != NULL)
+ return t->to_disable_btrace (btinfo);
+
+ tcomplain ();
+}
+
+/* See target.h. */
+int
+target_btrace_has_changed (struct btrace_target_info *btinfo)
+{
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ if (t->to_btrace_has_changed != NULL)
+ return t->to_btrace_has_changed (btinfo);
+
+ tcomplain ();
+ return 0;
+}
+
+/* See target.h. */
+VEC (btrace_block_s) *
+target_read_btrace (struct btrace_target_info *btinfo)
+{
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ if (t->to_read_btrace != NULL)
+ return t->to_read_btrace (btinfo);
+
+ tcomplain ();
+ return NULL;
+}
+
+
static void
debug_to_prepare_to_store (struct regcache *regcache)
{
diff --git a/gdb/target.h b/gdb/target.h
index 7907ee1..4889ce4 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -62,6 +62,7 @@ struct expression;
#include "memattr.h"
#include "vec.h"
#include "gdb_signals.h"
+#include "btrace.h"
enum strata
{
@@ -857,6 +858,22 @@ struct target_ops
/* Is the target able to use agent in current state? */
int (*to_can_use_agent) (void);
+ /* Check whether the target supports branch tracing. */
+ int (*to_supports_btrace) (void);
+
+ /* Enable branch tracing for @ptid and allocate a branch trace target
+ information struct for reading and for disabling branch trace. */
+ struct btrace_target_info *(*to_enable_btrace) (ptid_t ptid);
+
+ /* Disable branch tracing and deallocate @tinfo. */
+ void (*to_disable_btrace) (struct btrace_target_info *tinfo);
+
+ /* Check whether branch trace changed on the target. */
+ int (*to_btrace_has_changed) (struct btrace_target_info *);
+
+ /* Read branch trace data. */
+ VEC (btrace_block_s) *(*to_read_btrace) (struct btrace_target_info *);
+
int to_magic;
/* Need sub-structure for target machine related rather than comm related?
*/
@@ -1894,4 +1911,22 @@ extern void update_target_permissions (void);
/* Blank target vector entries are initialized to target_ignore. */
void target_ignore (void);
+/* Check whether the target supports branch tracing. */
+extern int target_supports_btrace (void);
+
+/* Enable branch tracing for @ptid.
+ Returns a branch tracing target info object. */
+extern struct btrace_target_info *target_enable_btrace (ptid_t ptid);
+
+/* Disable branch tracing. Deallocates @btinfo. */
+extern void target_disable_btrace (struct btrace_target_info *btinfo);
+
+/* Check whether there is no branch tracing data available. */
+extern int target_btrace_has_changed (struct btrace_target_info *btinfo);
+
+/* Read branch tracing data.
+ Returns a vector of branch trace blocks with the latest entry at index 0. */
+extern VEC (btrace_block_s) *target_read_btrace (struct btrace_target_info *);
+
+
#endif /* !defined (TARGET_H) */
diff --git a/gdb/thread.c b/gdb/thread.c
index 7e8eec5..e6b8c6a 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -34,6 +34,7 @@
#include "regcache.h"
#include "gdb.h"
#include "gdb_string.h"
+#include "btrace.h"
#include <ctype.h>
#include <sys/types.h>
@@ -132,6 +133,9 @@ free_thread (struct thread_info *tp)
xfree (tp->private);
}
+ if (tp->btrace.target)
+ disable_btrace (tp);
+
xfree (tp->name);
xfree (tp);
}
--
1.7.1
^ permalink raw reply [flat|nested] 20+ messages in thread* [patch v5 03/12] linux, btrace: perf_event based branch tracing
2012-12-07 10:37 [patch v5 00/12] branch tracing support for Atom markus.t.metzger
` (3 preceding siblings ...)
2012-12-07 10:38 ` [patch v5 01/12] thread, btrace: add generic branch trace support markus.t.metzger
@ 2012-12-07 10:38 ` markus.t.metzger
2012-12-07 10:38 ` [patch v5 05/12] xml, btrace: define btrace xml document style markus.t.metzger
` (6 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: markus.t.metzger @ 2012-12-07 10:38 UTC (permalink / raw)
To: gdb-patches
Cc: markus.t.metzger, jan.kratochvil, palves, tromey, kettenis,
Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Implement branch tracing on Linux based on perf_event such taht it can be shared
between gdb and gdbserver.
The actual btrace target ops will be implemented on top.
2012-12-07 Markus Metzger <markus.t.metzger@intel.com>
* common/linux_btrace.h: New file.
* common/linux_btrace.c: New file.
* Makefile.in (SFILES): Add btrace.c.
(HFILES_NO_SRCDIR): Add common/linux-btrace.h.
(COMMON_OBS): Add btrace.o.
(linux-btrace.o): New rule.
gdbserver/
* Makefile.in (SFILES): Add $(srcdir)/common/linux-btrace.c.
(linux_btrace_h): New variable.
(linux-btrace.o): New rule.
---
gdb/Makefile.in | 6 +-
gdb/common/linux-btrace.c | 425 +++++++++++++++++++++++++++++++++++++++++++++
gdb/common/linux-btrace.h | 76 ++++++++
gdb/gdbserver/Makefile.in | 7 +-
4 files changed, 512 insertions(+), 2 deletions(-)
create mode 100644 gdb/common/linux-btrace.c
create mode 100644 gdb/common/linux-btrace.h
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index ac34f9f..112f13e 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -825,7 +825,7 @@ gnulib/import/extra/snippet/arg-nonnull.h gnulib/import/extra/snippet/c++defs.h
gnulib/import/extra/snippet/warn-on-use.h \
gnulib/import/stddef.in.h gnulib/import/inttypes.in.h inline-frame.h skip.h \
common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \
-common/format.h common/host-defs.h utils.h \
+common/format.h common/host-defs.h common/linux-btrace.h utils.h \
common/linux-osdata.h gdb-dlfcn.h auto-load.h probe.h stap-probe.h gdb_bfd.h
# Header files that already have srcdir in them, or which are in objdir.
@@ -1942,6 +1942,10 @@ vec.o: ${srcdir}/common/vec.c
$(COMPILE) $(srcdir)/common/vec.c
$(POSTCOMPILE)
+linux-btrace.o: ${srcdir}/common/linux-btrace.c
+ $(COMPILE) $(srcdir)/common/linux-btrace.c
+ $(POSTCOMPILE)
+
#
# gdb/tui/ dependencies
#
diff --git a/gdb/common/linux-btrace.c b/gdb/common/linux-btrace.c
new file mode 100644
index 0000000..2441816
--- /dev/null
+++ b/gdb/common/linux-btrace.c
@@ -0,0 +1,425 @@
+/* Linux-dependent part of branch trace support for GDB, and GDBserver.
+
+ Copyright (C) 2012 Free Software Foundation, Inc.
+
+ Contributed by Intel Corp. <markus.t.metzger@intel.com>
+
+ This file is part of GDB.
+
+ 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/>. */
+
+#ifdef GDBSERVER
+#include "server.h"
+#else
+#include "defs.h"
+#endif
+
+#include "linux-btrace.h"
+#include "common-utils.h"
+#include "gdb_assert.h"
+
+#if HAVE_LINUX_PERF_EVENT_H
+
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/mman.h>
+#include <sys/user.h>
+
+#if defined(__GNUC__)
+# define memory_barrier() asm volatile ("" : : : "memory")
+#else
+# define memory_barrier() do {} while (0)
+#endif
+
+/* A branch trace record in perf_event. */
+struct perf_event_bts
+{
+ /* The linear address of the branch source. */
+ uint64_t from;
+
+ /* The linear address of the branch destination. */
+ uint64_t to;
+};
+
+/* A perf_event branch trace sample. */
+struct perf_event_sample
+{
+ /* The perf_event sample header. */
+ struct perf_event_header header;
+
+ /* The perf_event branch tracing payload. */
+ struct perf_event_bts bts;
+};
+
+/* Get the perf_event header. */
+
+static inline volatile struct perf_event_mmap_page *
+perf_event_header (struct btrace_target_info* tinfo)
+{
+ return tinfo->buffer;
+}
+
+/* Get the size of the perf_event mmap buffer. */
+
+static inline size_t
+perf_event_mmap_size (const struct btrace_target_info *tinfo)
+{
+ /* The branch trace buffer is preceded by a configuration page. */
+ return (tinfo->size + 1) * PAGE_SIZE;
+}
+
+/* Get the size of the perf_event buffer. */
+
+static inline size_t
+perf_event_buffer_size (struct btrace_target_info* tinfo)
+{
+ return tinfo->size * PAGE_SIZE;
+}
+
+/* Get the start address of the perf_event buffer. */
+
+static inline const uint8_t *
+perf_event_buffer_begin (struct btrace_target_info* tinfo)
+{
+ return ((const uint8_t *) tinfo->buffer) + PAGE_SIZE;
+}
+
+/* Get the end address of the perf_event buffer. */
+
+static inline const uint8_t *
+perf_event_buffer_end (struct btrace_target_info* tinfo)
+{
+ return perf_event_buffer_begin (tinfo) + perf_event_buffer_size (tinfo);
+}
+
+/* Check whether an address is in the kernel. */
+
+static inline int
+perf_event_is_kernel_addr (const struct btrace_target_info *tinfo,
+ uint64_t addr)
+{
+ uint64_t mask;
+
+ /* If we don't know the size of a pointer, we can't check. Let's assume it's
+ not a kernel address in this case. */
+ if (!tinfo->ptr_bits)
+ return 0;
+
+ /* A bit mask for the most significant bit in an address. */
+ mask = (uint64_t) 1 << (tinfo->ptr_bits - 1);
+
+ /* Check whether the most significant bit in the address is set. */
+ return (addr & mask) != 0;
+}
+
+/* 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)
+{
+ /* The hardware may report branches from kernel into user space. Branches
+ from user into kernel space will be suppressed. We filter the former to
+ provide a consistent branch trace excluding kernel. */
+ return perf_event_is_kernel_addr (tinfo, bts->from);
+}
+
+/* Perform a few consistency checks on a perf event sample record. This is
+ meant to catch cases when we get out of sync with the perf event stream. */
+
+static inline int
+perf_event_sample_ok (const struct perf_event_sample *sample)
+{
+ if (sample->header.type != PERF_RECORD_SAMPLE)
+ return 0;
+
+ if (sample->header.size != sizeof (*sample))
+ return 0;
+
+ return 1;
+}
+
+/* Branch trace is collected in a circular buffer [begin; end) as pairs of from
+ and to addresses (plus a header).
+
+ Start points into that buffer at the next sample position.
+ We read the collected samples backwards from start.
+
+ While reading the samples, we convert the information into a list of blocks.
+ For two adjacent samples s1 and s2, we form a block b such that b.begin =
+ s1.to and b.end = s2.from.
+
+ In case the buffer overflows during sampling, one sample may have its lower
+ part at the end and its upper part at the beginning of the buffer. */
+
+static VEC (btrace_block_s) *
+perf_event_read_bts (struct btrace_target_info* tinfo, const uint8_t *begin,
+ const uint8_t *end, const uint8_t *start)
+{
+ VEC (btrace_block_s) *btrace = NULL;
+ struct perf_event_sample sample;
+ size_t read = 0, size = (end - begin);
+ struct btrace_block block = { 0, 0 };
+
+ gdb_assert (begin <= start);
+ gdb_assert (start <= end);
+
+ /* The buffer may contain a partial record as its last entry (i.e. when the
+ buffer size is not a multiple of the sample size). */
+ read = sizeof (sample) - 1;
+
+ for (; read < size; read += sizeof (sample))
+ {
+ const struct perf_event_sample *psample;
+
+ /* Find the next perf_event sample in a backwards traversal. */
+ start -= sizeof (sample);
+
+ /* If we're still inside the buffer, we're done. */
+ if (begin <= start)
+ psample = (const struct perf_event_sample *) start;
+ else
+ {
+ int missing;
+
+ /* We're to the left of the ring buffer, we will wrap around and
+ reappear at the very right of the ring buffer. */
+
+ missing = (begin - start);
+ start = (end - missing);
+
+ /* If the entire sample is missing, we're done. */
+ if (missing == sizeof (sample))
+ psample = (const struct perf_event_sample *) start;
+ else
+ {
+ uint8_t *stack;
+
+ /* The sample wrapped around. The lower part is at the end and
+ the upper part is at the beginning of the buffer. */
+ stack = (uint8_t *) &sample;
+
+ /* Copy the two parts so we have a contiguous sample. */
+ memcpy (stack, start, missing);
+ memcpy (stack + missing, begin, sizeof (sample) - missing);
+
+ psample = &sample;
+ }
+ }
+
+ if (!perf_event_sample_ok (psample))
+ {
+ warning (_("Branch trace may be incomplete."));
+ break;
+ }
+
+ if (perf_event_skip_record (tinfo, &psample->bts))
+ continue;
+
+ /* We found a valid sample, so we can complete the current block. */
+ block.begin = psample->bts.to;
+
+ VEC_safe_push (btrace_block_s, btrace, &block);
+
+ /* Start the next block. */
+ block.end = psample->bts.from;
+ }
+
+ return btrace;
+}
+
+/* See linux-btrace.h. */
+
+int
+linux_supports_btrace (void)
+{
+ return 1;
+}
+
+/* See linux-btrace.h. */
+
+int
+linux_btrace_has_changed (struct btrace_target_info *tinfo)
+{
+ volatile struct perf_event_mmap_page *header = perf_event_header (tinfo);
+
+ return header->data_head != tinfo->data_head;
+}
+
+/* See linux-btrace.h. */
+
+struct btrace_target_info *
+linux_enable_btrace (ptid_t ptid)
+{
+ struct btrace_target_info *tinfo;
+ int pid;
+
+ tinfo = xzalloc (sizeof (*tinfo));
+ 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;
+
+ /* We sample from and to address. */
+ tinfo->attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_ADDR;
+
+ tinfo->attr.exclude_kernel = 1;
+ tinfo->attr.exclude_hv = 1;
+ tinfo->attr.exclude_idle = 1;
+
+ tinfo->ptr_bits = 0;
+
+ pid = ptid_get_lwp (ptid);
+ if (!pid)
+ pid = ptid_get_pid (ptid);
+
+ errno = 0;
+ tinfo->file = syscall (SYS_perf_event_open, &tinfo->attr, pid, -1, -1, 0);
+ if (tinfo->file < 0)
+ goto err;
+
+ /* We hard-code the trace buffer size.
+ At some later time, we should make this configurable. */
+ tinfo->size = 1;
+ tinfo->buffer = mmap (NULL, perf_event_mmap_size (tinfo),
+ PROT_READ, MAP_SHARED, tinfo->file, 0);
+ if (tinfo->buffer == MAP_FAILED)
+ goto err_file;
+
+ return tinfo;
+
+err_file:
+ close (tinfo->file);
+
+err:
+ xfree (tinfo);
+ return NULL;
+}
+
+/* See linux-btrace.h. */
+
+int
+linux_disable_btrace (struct btrace_target_info *tinfo)
+{
+ int errcode;
+
+ errno = 0;
+ errcode = munmap (tinfo->buffer, perf_event_mmap_size (tinfo));
+ if (errcode)
+ return errno;
+
+ close (tinfo->file);
+ xfree (tinfo);
+
+ return 0;
+}
+
+/* See linux-btrace.h. */
+
+VEC (btrace_block_s) *
+linux_read_btrace (struct btrace_target_info *tinfo)
+{
+ VEC (btrace_block_s) *btrace = NULL;
+ volatile struct perf_event_mmap_page *header;
+ const uint8_t *begin, *end, *start;
+ unsigned long data_head, retries = 5;
+ size_t buffer_size;
+
+ header = perf_event_header (tinfo);
+ buffer_size = perf_event_buffer_size (tinfo);
+
+ /* We may need to retry reading the trace. See below. */
+ while (retries--)
+ {
+ data_head = header->data_head;
+
+ /* Make sure the trace data is up-to-date. */
+ memory_barrier ();
+
+ /* If there's new trace, let's read it. */
+ if (data_head != tinfo->data_head)
+ {
+ /* Data_head keeps growing; the buffer itself is circular. */
+ begin = perf_event_buffer_begin (tinfo);
+ start = begin + data_head % buffer_size;
+
+ if (data_head <= buffer_size)
+ end = start;
+ else
+ end = perf_event_buffer_end (tinfo);
+
+ btrace = perf_event_read_bts (tinfo, begin, end, start);
+ }
+
+ /* The stopping thread notifies its ptracer before it is scheduled out.
+ On multi-core systems, the debugger might therefore run while the
+ kernel might be writing the last branch trace records.
+
+ Let's check whether the data head moved while we read the trace. */
+ if (data_head == header->data_head)
+ break;
+ }
+
+ tinfo->data_head = data_head;
+
+ return btrace;
+}
+
+#else /* !HAVE_LINUX_PERF_EVENT_H */
+
+/* See linux-btrace.h. */
+
+int
+linux_supports_btrace (void)
+{
+ return 0;
+}
+
+/* See linux-btrace.h. */
+
+int
+linux_btrace_has_changed (struct btrace_target_info *tinfo)
+{
+ return 0;
+}
+
+/* See linux-btrace.h. */
+
+struct btrace_target_info *
+linux_enable_btrace (ptid_t ptid)
+{
+ return NULL;
+}
+
+/* See linux-btrace.h. */
+
+int
+linux_disable_btrace (struct btrace_target_info *tinfo)
+{
+ return ENOSYS;
+}
+
+/* See linux-btrace.h. */
+
+VEC (btrace_block_s) *
+linux_read_btrace (struct btrace_target_info *tinfo)
+{
+ return NULL;
+}
+
+#endif /* !HAVE_LINUX_PERF_EVENT_H */
diff --git a/gdb/common/linux-btrace.h b/gdb/common/linux-btrace.h
new file mode 100644
index 0000000..b0f8459
--- /dev/null
+++ b/gdb/common/linux-btrace.h
@@ -0,0 +1,76 @@
+/* Linux-dependent part of branch trace support for GDB, and GDBserver.
+
+ Copyright (C) 2012 Free Software Foundation, Inc.
+
+ Contributed by Intel Corp. <markus.t.metzger@intel.com>
+
+ This file is part of GDB.
+
+ 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/>. */
+
+#ifndef LINUX_BTRACE_H
+#define LINUX_BTRACE_H
+
+#include "btrace-common.h"
+#include "config.h"
+#include "vec.h"
+#include "ptid.h"
+#include <stddef.h>
+#include <stdint.h>
+
+#if HAVE_LINUX_PERF_EVENT_H
+# include <linux/perf_event.h>
+#endif
+
+/* Branch trace target information per thread. */
+struct btrace_target_info
+{
+#if HAVE_LINUX_PERF_EVENT_H
+ /* The Linux perf_event configuration for collecting the branch trace. */
+ struct perf_event_attr attr;
+
+ /* The mmap configuration mapping the branch trace perf_event buffer.
+
+ file .. the file descriptor
+ buffer .. the mmapped memory buffer
+ size .. the buffer's size in pages without the configuration page
+ data_head .. the data head from the last read */
+ int file;
+ void *buffer;
+ size_t size;
+ unsigned long data_head;
+#endif /* HAVE_LINUX_PERF_EVENT_H */
+
+ /* The size of a pointer in bits for this thread.
+ The information is used to identify kernel addresses in order to skip
+ records from/to kernel space. */
+ int ptr_bits;
+};
+
+/* Check whether branch tracing is supported. */
+extern int linux_supports_btrace (void);
+
+/* Enable branch tracing for @ptid. */
+extern struct btrace_target_info *linux_enable_btrace (ptid_t ptid);
+
+/* Disable branch tracing and deallocate @tinfo. */
+extern int linux_disable_btrace (struct btrace_target_info *tinfo);
+
+/* Check whether there is new trace data available. */
+extern int linux_btrace_has_changed (struct btrace_target_info *);
+
+/* Read branch trace data. */
+extern VEC (btrace_block_s) *linux_read_btrace (struct btrace_target_info *);
+
+#endif /* LINUX_BTRACE_H */
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index fc4fd1d..cd4ae8f 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -143,7 +143,7 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
$(srcdir)/common/vec.c $(srcdir)/common/gdb_vecs.c \
$(srcdir)/common/common-utils.c $(srcdir)/common/xml-utils.c \
$(srcdir)/common/linux-osdata.c $(srcdir)/common/ptid.c \
- $(srcdir)/common/buffer.c
+ $(srcdir)/common/buffer.c $(srcdir)/common/linux-btrace.c
DEPFILES = @GDBSERVER_DEPFILES@
@@ -412,6 +412,8 @@ signals_h = $(srcdir)/../../include/gdb/signals.h $(signals_def)
ptid_h = $(srcdir)/../common/ptid.h
ax_h = $(srcdir)/ax.h
agent_h = $(srcdir)/../common/agent.h
+linux_btrace_h = $(srcdir)/../common/linux-btrace.h \
+ $(srcdir)/../common/btrace-common.h $(vec_h) $(ptid_h)
linux_osdata_h = $(srcdir)/../common/linux-osdata.h
vec_h = $(srcdir)/../common/vec.h
gdb_vecs_h = $(srcdir)/../common/gdb_vecs.h
@@ -532,6 +534,9 @@ format.o: ../common/format.c $(server_h)
agent.o: ../common/agent.c $(server_h) $(agent_h)
$(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $<
+linux-btrace.o: ../common/linux-btrace.c $(linux_btrace_h) $(server_h)
+ $(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $<
+
# We build vasprintf with -DHAVE_CONFIG_H because we want that unit to
# include our config.h file. Otherwise, some system headers do not get
# included, and the compiler emits a warning about implicitly defined
--
1.7.1
^ permalink raw reply [flat|nested] 20+ messages in thread* [patch v5 05/12] xml, btrace: define btrace xml document style
2012-12-07 10:37 [patch v5 00/12] branch tracing support for Atom markus.t.metzger
` (4 preceding siblings ...)
2012-12-07 10:38 ` [patch v5 03/12] linux, btrace: perf_event based branch tracing markus.t.metzger
@ 2012-12-07 10:38 ` markus.t.metzger
2012-12-07 10:38 ` [patch v5 10/12] test, btrace: add branch tracing tests markus.t.metzger
` (5 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: markus.t.metzger @ 2012-12-07 10:38 UTC (permalink / raw)
To: gdb-patches
Cc: markus.t.metzger, jan.kratochvil, palves, tromey, kettenis,
Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Define the xml document style for transferring branch trace data.
Add a function to parse a btrace xml document into a vector of branch trace
blocks.
2012-12-07 Markus Metzger <markus.t.metzger@intel.com>
* features/btrace.dtd: New file.
* Makefile.in (XMLFILES): Add btrace.dtd.
* btrace.h (parse_xml_btrace): New declaration.
* btrace.c (parse_xml_btrace): New function.
(parse_xml_btrace_block): New function.
(block_attributes): New struct.
(btrace_attributes): New struct.
(btrace_children): New struct.
(btrace_elements): New struct.
---
gdb/Makefile.in | 3 +-
gdb/btrace.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++
gdb/btrace.h | 3 +
gdb/features/btrace.dtd | 12 ++++++
4 files changed, 112 insertions(+), 1 deletions(-)
create mode 100644 gdb/features/btrace.dtd
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 112f13e..57f6548 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -494,7 +494,8 @@ RUNTESTFLAGS=
XMLFILES = $(srcdir)/features/gdb-target.dtd $(srcdir)/features/xinclude.dtd \
$(srcdir)/features/library-list.dtd \
$(srcdir)/features/library-list-svr4.dtd $(srcdir)/features/osdata.dtd \
- $(srcdir)/features/threads.dtd $(srcdir)/features/traceframe-info.dtd
+ $(srcdir)/features/threads.dtd $(srcdir)/features/traceframe-info.dtd \
+ $(srcdir)/features/btrace.dtd
# This is ser-unix.o for any system which supports a v7/BSD/SYSV/POSIX
# interface to the serial port. Hopefully if get ported to OS/2, VMS,
diff --git a/gdb/btrace.c b/gdb/btrace.c
index 68b109a..00b2d90 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -32,6 +32,7 @@
#include "arch-utils.h"
#include "disasm.h"
#include "gdbarch.h"
+#include "xml-support.h"
#include <ctype.h>
#include <string.h>
@@ -706,6 +707,100 @@ cmd_btrace (char *args, int from_tty)
do_btrace_range (tp, flags, args);
}
+#if defined(HAVE_LIBEXPAT)
+
+/* Check the btrace document version. */
+
+static void
+check_xml_btrace_version (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, VEC (gdb_xml_value_s) *attributes)
+{
+ const char *version = xml_find_attribute (attributes, "version")->value;
+
+ if (strcmp (version, "1.0") != 0)
+ gdb_xml_error (parser, _("Unsupported btrace version: \"%s\""), version);
+}
+
+/* Parse a btrace "block" xml record. */
+
+static void
+parse_xml_btrace_block (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, VEC (gdb_xml_value_s) *attributes)
+{
+ VEC (btrace_block_s) **btrace;
+ struct btrace_block *block;
+ ULONGEST *begin, *end;
+
+ btrace = user_data;
+ block = VEC_safe_push (btrace_block_s, *btrace, NULL);
+
+ begin = xml_find_attribute (attributes, "begin")->value;
+ end = xml_find_attribute (attributes, "end")->value;
+
+ block->begin = *begin;
+ block->end = *end;
+}
+
+static const struct gdb_xml_attribute block_attributes[] = {
+ { "begin", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+ { "end", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+ { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_attribute btrace_attributes[] = {
+ { "version", GDB_XML_AF_NONE, NULL, NULL },
+ { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element btrace_children[] = {
+ { "block", block_attributes, NULL,
+ GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, parse_xml_btrace_block, NULL },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element btrace_elements[] = {
+ { "btrace", btrace_attributes, btrace_children, GDB_XML_EF_NONE,
+ check_xml_btrace_version, NULL },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+#endif /* defined(HAVE_LIBEXPAT) */
+
+/* See btrace.h. */
+
+VEC (btrace_block_s) *
+parse_xml_btrace (const char *buffer)
+{
+ VEC (btrace_block_s) *btrace = NULL;
+ struct cleanup *cleanup;
+ int errcode;
+
+#if defined(HAVE_LIBEXPAT)
+
+ cleanup = make_cleanup (VEC_cleanup (btrace_block_s), &btrace);
+ errcode = gdb_xml_parse_quick (_("btrace"), "btrace.dtd", btrace_elements,
+ buffer, &btrace);
+ if (errcode)
+ {
+ do_cleanups (cleanup);
+ errno = errcode;
+ return NULL;
+ }
+
+ /* Keep parse results. */
+ discard_cleanups (cleanup);
+
+#else /* !defined(HAVE_LIBEXPAT) */
+
+ error (_("Cannot process branch tracing result. XML parsing not supported."));
+
+#endif /* !defined(HAVE_LIBEXPAT) */
+
+ return btrace;
+}
+
void _initialize_btrace (void);
/* Initialize btrace commands. */
diff --git a/gdb/btrace.h b/gdb/btrace.h
index df9df23..26fafc7 100644
--- a/gdb/btrace.h
+++ b/gdb/btrace.h
@@ -80,4 +80,7 @@ extern struct btrace_block *read_btrace (struct thread_info *, int);
extern struct btrace_block *prev_btrace (struct thread_info *);
extern struct btrace_block *next_btrace (struct thread_info *);
+/* Parse a branch trace xml document into a block vector. */
+extern VEC (btrace_block_s) *parse_xml_btrace (const char*);
+
#endif /* BTRACE_H */
diff --git a/gdb/features/btrace.dtd b/gdb/features/btrace.dtd
new file mode 100644
index 0000000..18c5b2a
--- /dev/null
+++ b/gdb/features/btrace.dtd
@@ -0,0 +1,12 @@
+<!-- Copyright (C) 2012 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 (block)* >
+<!ATTLIST btrace version CDATA #FIXED "1.0">
+
+<!ELEMENT block EMPTY>
+<!ATTLIST block begin CDATA #REQUIRED
+ end CDATA #REQUIRED>
--
1.7.1
^ permalink raw reply [flat|nested] 20+ messages in thread* [patch v5 10/12] test, btrace: add branch tracing tests
2012-12-07 10:37 [patch v5 00/12] branch tracing support for Atom markus.t.metzger
` (5 preceding siblings ...)
2012-12-07 10:38 ` [patch v5 05/12] xml, btrace: define btrace xml document style markus.t.metzger
@ 2012-12-07 10:38 ` markus.t.metzger
2012-12-07 10:38 ` [patch v5 08/12] gdbserver, btrace: add generic btrace support markus.t.metzger
` (4 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: markus.t.metzger @ 2012-12-07 10:38 UTC (permalink / raw)
To: gdb-patches
Cc: markus.t.metzger, jan.kratochvil, palves, tromey, kettenis,
Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Add tests covering btrace enable/disable/auto and btrace list.
2012-12-07 Markus Metzger <markus.t.metzger@intel.com>
testsuite/
* configure.ac: Add gdb.btrace makefile.
* configure: Regenerated.
* lib/btrace.exp: New file.
* gdb.btrace/Makefile.in: New file.
* gdb.btrace/enable.exp: New file.
* gdb.btrace/list.exp: New file.
* gdb.btrace/x86-list.S: New file.
---
gdb/testsuite/Makefile.in | 3 +-
gdb/testsuite/configure | 3 +-
gdb/testsuite/configure.ac | 2 +-
gdb/testsuite/gdb.btrace/Makefile.in | 13 ++
gdb/testsuite/gdb.btrace/dec.c | 23 ++++
gdb/testsuite/gdb.btrace/enable.exp | 89 ++++++++++++++
gdb/testsuite/gdb.btrace/inc.c | 23 ++++
gdb/testsuite/gdb.btrace/list.exp | 175 ++++++++++++++++++++++++++++
gdb/testsuite/gdb.btrace/list_function.c | 31 +++++
gdb/testsuite/gdb.btrace/list_function.exp | 50 ++++++++
gdb/testsuite/gdb.btrace/x86-list.S | 70 +++++++++++
gdb/testsuite/lib/btrace.exp | 78 ++++++++++++
12 files changed, 557 insertions(+), 3 deletions(-)
create mode 100755 gdb/testsuite/gdb.btrace/Makefile.in
create mode 100644 gdb/testsuite/gdb.btrace/dec.c
create mode 100644 gdb/testsuite/gdb.btrace/enable.exp
create mode 100644 gdb/testsuite/gdb.btrace/inc.c
create mode 100644 gdb/testsuite/gdb.btrace/list.exp
create mode 100644 gdb/testsuite/gdb.btrace/list_function.c
create mode 100644 gdb/testsuite/gdb.btrace/list_function.exp
create mode 100644 gdb/testsuite/gdb.btrace/x86-list.S
create mode 100644 gdb/testsuite/lib/btrace.exp
diff --git a/gdb/testsuite/Makefile.in b/gdb/testsuite/Makefile.in
index fab124e..62fcd1f 100644
--- a/gdb/testsuite/Makefile.in
+++ b/gdb/testsuite/Makefile.in
@@ -33,7 +33,8 @@ SHELL = @SHELL@
EXEEXT = @EXEEXT@
SUBDIRS = @subdirs@
RPATH_ENVVAR = @RPATH_ENVVAR@
-ALL_SUBDIRS = gdb.ada gdb.arch gdb.asm gdb.base gdb.cell gdb.cp gdb.disasm \
+ALL_SUBDIRS = gdb.ada gdb.arch gdb.asm gdb.base gdb.btrace gdb.cell \
+ gdb.cp gdb.disasm \
gdb.dwarf2 gdb.fortran gdb.gdb gdb.hp \
gdb.java gdb.linespec gdb.mi gdb.modula2 gdb.multi \
gdb.objc gdb.opencl gdb.opt gdb.pascal gdb.python gdb.server \
diff --git a/gdb/testsuite/configure b/gdb/testsuite/configure
index 0c8c344..a40c144 100755
--- a/gdb/testsuite/configure
+++ b/gdb/testsuite/configure
@@ -3448,7 +3448,7 @@ done
-ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.fortran/Makefile gdb.go/Makefile gdb.server/Makefile gdb.java/Makefile gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile gdb.hp/gdb.defects/Makefile gdb.linespec/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile"
+ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.btrace/Makefile gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.fortran/Makefile gdb.go/Makefile gdb.server/Makefile gdb.java/Makefile gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile gdb.hp/gdb.defects/Makefile gdb.linespec/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -4153,6 +4153,7 @@ do
"gdb.arch/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.arch/Makefile" ;;
"gdb.asm/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.asm/Makefile" ;;
"gdb.base/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.base/Makefile" ;;
+ "gdb.btrace/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.btrace/Makefile" ;;
"gdb.cell/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.cell/Makefile" ;;
"gdb.cp/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.cp/Makefile" ;;
"gdb.disasm/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.disasm/Makefile" ;;
diff --git a/gdb/testsuite/configure.ac b/gdb/testsuite/configure.ac
index d9ab9f7..1884b64 100644
--- a/gdb/testsuite/configure.ac
+++ b/gdb/testsuite/configure.ac
@@ -89,7 +89,7 @@ AC_EXEEXT
AC_OUTPUT([Makefile \
gdb.ada/Makefile \
- gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile \
+ gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.btrace/Makefile \
gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile \
gdb.fortran/Makefile gdb.go/Makefile gdb.server/Makefile gdb.java/Makefile \
gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile \
diff --git a/gdb/testsuite/gdb.btrace/Makefile.in b/gdb/testsuite/gdb.btrace/Makefile.in
new file mode 100755
index 0000000..16afe0a
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/Makefile.in
@@ -0,0 +1,13 @@
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+.PHONY: all clean mostlyclean distclean realclean
+
+all info install-info dvi install uninstall installcheck check:
+ @echo "Nothing to be done for $@..."
+
+clean mostlyclean:
+ -rm -f *.o *.x *.diff *~ *.bad core
+
+distclean maintainer-clean realclean: clean
+ -rm -f Makefile config.status config.log gdb.log gdb.sum
diff --git a/gdb/testsuite/gdb.btrace/dec.c b/gdb/testsuite/gdb.btrace/dec.c
new file mode 100644
index 0000000..5b9187e
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/dec.c
@@ -0,0 +1,23 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2012 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/>. */
+
+extern int dec (int x)
+{
+ return x - 1;
+}
diff --git a/gdb/testsuite/gdb.btrace/enable.exp b/gdb/testsuite/gdb.btrace/enable.exp
new file mode 100644
index 0000000..3ddaf2c
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/enable.exp
@@ -0,0 +1,89 @@
+# Copyright 2012 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/>.
+
+if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] } {
+ verbose "Tests ignored for all but x86 based targets."
+ return
+}
+
+load_lib btrace.exp
+
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+
+# automatic enabling can be turned on without an inferior
+gdb_test_no_output "btrace enable auto" "btrace enable 1.0"
+
+# enabling is idempotent
+gdb_test_no_output "btrace enable auto" "btrace enable 1.1"
+
+# we can disable it
+gdb_test_no_output "btrace disable auto" "btrace enable 1.2"
+
+# disabling is also idempotent
+gdb_test_no_output "btrace disable auto" "btrace enable 1.3"
+
+# we cannot enable/disable trace without a thread
+gdb_test "btrace enable" "Couldn't enable branch tracing: no inferior thread." "btrace enable 2.0"
+gdb_test "btrace disable" "Couldn't disable branch tracing: no inferior thread." "btrace enable 2.1"
+
+# we don't have trace, yet
+gdb_test "btrace" "No thread\." "btrace enable 2.2"
+gdb_test "btrace /m" "No thread\." "btrace enable 2.3"
+gdb_test "btrace list /fal" "No thread\." "btrace enable 2.4"
+gdb_test "btrace list /t" "No thread\." "btrace enable 2.5"
+
+set testfile "x86-list"
+
+# start a debuggee program
+if { [set binfile [btrace_assemble ${testfile}]] == "" } {
+ untested ${testfile}.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+# automatic enabling is off.
+if ![runto test_1] {
+ fail "runto test function, 1"
+ return -1
+}
+
+# since we support btrace, we should be able to enable it
+gdb_test_no_output "btrace enable" "btrace enable 3.0"
+
+# enabling is idempotent
+gdb_test_no_output "btrace enable" "btrace enable 3.1"
+
+# we should be able to disable it
+gdb_test_no_output "btrace disable" "btrace enable 3.2"
+
+# disabling is idempotent, as well
+gdb_test_no_output "btrace disable" "btrace enable 3.3"
+
+# we don't have trace, yet
+gdb_test "btrace" "No trace\." "btrace enable 3.0"
+gdb_test "btrace /m" "No trace\." "btrace enable 3.1"
+gdb_test "btrace list" "No trace\." "btrace enable 3.2"
+
+return 0
diff --git a/gdb/testsuite/gdb.btrace/inc.c b/gdb/testsuite/gdb.btrace/inc.c
new file mode 100644
index 0000000..a012268
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/inc.c
@@ -0,0 +1,23 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2012 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/>. */
+
+extern int inc (int x)
+{
+ return x + 1;
+}
diff --git a/gdb/testsuite/gdb.btrace/list.exp b/gdb/testsuite/gdb.btrace/list.exp
new file mode 100644
index 0000000..0e88f8b
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/list.exp
@@ -0,0 +1,175 @@
+# Copyright 2012 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/>.
+
+if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] } {
+ verbose "Tests ignored for all but x86 based targets."
+ return
+}
+
+load_lib btrace.exp
+
+set testfile "x86-list"
+
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+if { [set binfile [btrace_assemble ${testfile}]] == "" } {
+ untested ${testfile}.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+# Automatically enable branch tracing.
+gdb_test_no_output "btr enable auto"
+
+# Make sure we don't die when enabling trace for a newly created thread.
+if ![runto test_1] {
+ fail "runto test function, 1"
+ return -1
+}
+
+# we expect some trace at this point, but we don't really know how much or how
+# it would look like. Ignore it.
+
+# Reset branch trace so we get predictable output.
+btrace_reset_trace
+
+gdb_test "stepi" "0x0*400200 in test_1_sub.*" ""
+
+gdb_test "btr list /af" "
+1 *0x0*400200 - 0x0*400200 in test_1_sub" "btrace list 1.1"
+
+# We assume 5 bytes for call.
+gdb_test "stepi" "0x0*400215 in test_1.*" ""
+
+# We assume 5 bytes for call.
+gdb_test "btr list /af" "
+1 *0x0*400215 - 0x0*400215 in test_1\r
+2 *0x0*400200 - 0x0*400200 in test_1_sub" "btrace list 1.2"
+
+gdb_test "stepi" "0x0*400200 in test_1_sub.*" ""
+gdb_test "stepi" "0x0*40021a in test_1.*" ""
+
+# We assume 5 bytes for call.
+gdb_test "btr list /af" "
+1 *0x0*40021a - 0x0*40021a in test_1\r
+2 *0x0*400200 - 0x0*400200 in test_1_sub\r
+3 *0x0*400215 - 0x0*400215 in test_1\r
+4 *0x0*400200 - 0x0*400200 in test_1_sub" "btrace list 1.3"
+
+# List a single block.
+gdb_test "btr list /af 2" "
+2 *0x0*400200 - 0x0*400200 in test_1_sub" "btrace list 1.4"
+
+# List a range of blocks.
+gdb_test "btr list /af 2-4" "
+2 *0x0*400200 - 0x0*400200 in test_1_sub\r
+3 *0x0*400215 - 0x0*400215 in test_1\r
+4 *0x0*400200 - 0x0*400200 in test_1_sub" "btrace list 1.5"
+
+# We ignore too big upper bounds.
+gdb_test "btr list /af 3-9" "
+3 *0x0*400215 - 0x0*400215 in test_1\r
+4 *0x0*400200 - 0x0*400200 in test_1_sub" "btrace list 1.6"
+
+# If the entire range is out of bounds, the list is empty.
+gdb_test "btr list /a 9-18" "" "btrace list 1.7"
+
+# Check modifiers individually
+gdb_test "btr list /a 2" "
+2 *0x0*400200 - 0x0*400200" "btrace list 1.8"
+
+gdb_test "btr list /f 2" "
+2 *in test_1_sub" "btrace list 1.9"
+
+# Check order of modifiers
+gdb_test "btr list /fa 2" "
+2 *0x0*400200 - 0x0*400200 in test_1_sub" "btrace list 1.10"
+
+gdb_test "btr list /f /a 2" "
+2 *0x0*400200 - 0x0*400200 in test_1_sub" "btrace list 1.11"
+
+gdb_test "btr list /a /f 2" "
+2 *0x0*400200 - 0x0*400200 in test_1_sub" "btrace list 1.12"
+
+
+# Proceed to the next test.
+gdb_breakpoint "test_2"
+gdb_continue_to_breakpoint "proceed to test 2" ".*test_2.*"
+
+# Reset branch trace so we get predictable output.
+btrace_reset_trace
+
+# We assume 1 byte for nop.
+gdb_test "stepi" "0x0*400231 in test_2.*" ""
+
+# We have not seen a branch, yet, so there is no trace.
+gdb_test "btr list" "No trace\." "btrace list 2.1"
+
+gdb_test "stepi" "0x0*400220 in test_2_sub.*" ""
+
+gdb_test "btr list /af" "
+1 *0x0*400220 - 0x0*400220 in test_2_sub" "btrace list 2.2"
+
+# We assume 1 byte for nop.
+gdb_test "stepi" "0x0*400221 in test_2_sub.*" ""
+
+# We assume 1 byte for nop.
+gdb_test "btr list /af" "
+1 *0x0*400220 - 0x0*400221 in test_2_sub" "btrace list 2.3"
+
+# We assume 1 byte for nop.
+gdb_test "stepi" "0x0*400222 in test_2_sub.*" ""
+
+# We assume 1 byte for nop.
+gdb_test "btr list /af" "
+1 *0x0*400220 - 0x0*400222 in test_2_sub" "btrace list 2.4"
+
+
+# Proceed to the next test.
+gdb_breakpoint "test_3"
+gdb_continue_to_breakpoint "proceed to test 3" ".*test_3.*"
+
+# Reset branch trace so we get predictable output.
+btrace_reset_trace
+
+gdb_test "stepi" "0x0*400260 in test_3.*" ""
+
+gdb_test "btr list /af" "
+1 *0x0*400260 - 0x0*400260 in test_3" "btrace list 3.1"
+
+gdb_test "stepi" "0x0*400250 in test_3.*" ""
+
+gdb_test "btr list /af" "
+1 *0x0*400250 - 0x0*400250 in test_3\r
+2 *0x0*400260 - 0x0*400260 in test_3" "btrace list 3.2"
+
+# We assume 1 byte for nop.
+gdb_test "stepi" "0x0*400251 in test_3.*" ""
+
+# We assume 1 byte for nop.
+gdb_test "btr list /af" "
+1 *0x0*400250 - 0x0*400251 in test_3\r
+2 *0x0*400260 - 0x0*400260 in test_3" "btrace list 3.3"
+
+return 0
diff --git a/gdb/testsuite/gdb.btrace/list_function.c b/gdb/testsuite/gdb.btrace/list_function.c
new file mode 100644
index 0000000..b10ab34
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/list_function.c
@@ -0,0 +1,31 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2012 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/>. */
+
+extern int inc (int);
+extern int dec (int);
+
+extern int main (void)
+{
+ int x = 0;
+
+ x = inc (x);
+ x = dec (x);
+
+ return x; /* bp.1 */
+}
diff --git a/gdb/testsuite/gdb.btrace/list_function.exp b/gdb/testsuite/gdb.btrace/list_function.exp
new file mode 100644
index 0000000..180273f
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/list_function.exp
@@ -0,0 +1,50 @@
+# Copyright 2012 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/>.
+
+load_lib btrace.exp
+
+set testfile "list_function"
+set sources [list $testfile.c inc.c dec.c]
+
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+if [prepare_for_testing list_function.exp $testfile.x $sources {debug}] {
+ untested list_function.exp
+ return -1
+}
+
+if ![runto_main] then {
+ fail "runto test function, 1"
+ return -1
+}
+
+set bp_location [gdb_get_line_number "bp.1" $testfile.c]
+
+gdb_breakpoint $bp_location
+
+gdb_test_no_output "btr enable"
+
+gdb_continue_to_breakpoint "cont to $bp_location" ".*$testfile.c:$bp_location.*"
+
+gdb_test "btr list /f" "
+1 *in main\r
+2 *in dec\r
+3 *in main\r
+4 *in inc" "btrace list function 1.0"
+
+return 0
diff --git a/gdb/testsuite/gdb.btrace/x86-list.S b/gdb/testsuite/gdb.btrace/x86-list.S
new file mode 100644
index 0000000..7956db2
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/x86-list.S
@@ -0,0 +1,70 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2012 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/>.
+
+ .text
+ .globl _start
+ .globl main
+ .globl test_1
+ .globl test_2
+ .globl test_3
+ .align 0x100 # 0x400100
+_start:
+ call main
+ hlt
+
+ .align 0x10 # 0x400110
+main:
+ call test_1
+ call test_2
+ call test_3
+ ret
+
+ .align 0x100 # 0x400200
+test_1_sub:
+ ret
+
+ .align 0x10 # 0x400210
+test_1:
+ call test_1_sub
+ call test_1_sub
+ nop
+ ret
+
+ .align 0x10 # 0x400220
+test_2_sub:
+ nop
+ nop
+ ret
+
+ .align 0x10 # 0x400230
+test_2:
+ nop
+ call test_2_sub
+ ret
+
+ .align 0x10 # 0x400240
+test_3:
+ jmp .L3.1
+ .align 0x10 # 0x400250
+.L3.2:
+ nop
+ ret
+ .align 0x10 # 0x400260
+.L3.1:
+ jmp .L3.2
diff --git a/gdb/testsuite/lib/btrace.exp b/gdb/testsuite/lib/btrace.exp
new file mode 100644
index 0000000..eb516fa
--- /dev/null
+++ b/gdb/testsuite/lib/btrace.exp
@@ -0,0 +1,78 @@
+# Copyright 2012 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/>.
+
+proc btrace_assemble { testfile } {
+ global srcdir
+ global objdir
+ global subdir
+
+ set srcfile ${srcdir}/${subdir}/${testfile}.S
+ set objfile ${objdir}/${subdir}/${testfile}.o
+ set binfile ${objdir}/${subdir}/${testfile}.x
+
+ if {[target_assemble ${srcfile} ${objfile} ""] != ""} { return "" }
+
+ if {[target_link ${objfile} ${binfile} "-Ttext 0x400100"] != ""} { return "" }
+
+ return ${binfile}
+}
+
+proc skip_btrace_tests {} {
+ global gdb_prompt
+
+ set testfile "x86-list"
+ set skip 0
+
+ if { [set binfile [btrace_assemble ${testfile}]] == "" } {
+ return 1
+ }
+
+ gdb_exit
+ gdb_start
+ gdb_load $binfile
+
+ runto main
+
+ gdb_test_multiple "btrace enable" "check btrace support" {
+ -re "You can't do that when your target is.*\r\n$gdb_prompt $" {
+ xfail "check btrace support"
+ set skip 1
+ }
+ -re "Target does not support branch tracing.*\r\n$gdb_prompt $" {
+ xfail "check btrace support"
+ set skip 1
+ }
+ -re "Could not enable branch tracing.*\r\n$gdb_prompt $" {
+ xfail "check btrace support"
+ set skip 1
+ }
+ -re "$gdb_prompt $" {
+ pass "check btrace support"
+ }
+ }
+ gdb_exit
+ remote_file build delete $testfile
+
+ return $skip
+}
+
+proc btrace_reset_trace {} {
+ gdb_test_no_output "btr disable"
+ gdb_test_no_output "btr enable"
+
+ gdb_test "btr list" "No trace." "reset btrace"
+}
--
1.7.1
^ permalink raw reply [flat|nested] 20+ messages in thread* [patch v5 08/12] gdbserver, btrace: add generic btrace support
2012-12-07 10:37 [patch v5 00/12] branch tracing support for Atom markus.t.metzger
` (6 preceding siblings ...)
2012-12-07 10:38 ` [patch v5 10/12] test, btrace: add branch tracing tests markus.t.metzger
@ 2012-12-07 10:38 ` markus.t.metzger
2012-12-07 10:38 ` [patch v5 07/12] btrace, doc: document remote serial protocol markus.t.metzger
` (3 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: markus.t.metzger @ 2012-12-07 10:38 UTC (permalink / raw)
To: gdb-patches
Cc: markus.t.metzger, jan.kratochvil, palves, tromey, kettenis,
Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Add support to gdbserver to understand branch trace related packages.
2012-12-07 Markus Metzger <markus.t.metzger@intel.com>
gdbserver/
* target.h (struct target_ops): Add btrace ops.
(target_supports_btrace): New macro.
(target_btrace_has_changed): New macro.
(target_enable_btrace): New macro.
(target_disable_btrace): New macro.
(target_read_btrace): New macro.
* gdbthread.h (struct thread_info): Add btrace field.
* server.c (handle_btrace_general_set): New function.
(handle_btrace_enable): New function.
(handle_btrace_disable): New function.
(handle_general_set): Call handle_btrace_general_set.
(handle_qxfer_btrace): New function.
(struct qxfer qxfer_packets[]): Add btrace entry.
(handle_btrace_query): New function.
(handle_query): Add btrace to supported query, call handle_btrace_query.
* inferiors.c (remove_thread): Disable btrace.
---
gdb/gdbserver/gdbthread.h | 5 ++
gdb/gdbserver/inferiors.c | 3 +
gdb/gdbserver/server.c | 175 +++++++++++++++++++++++++++++++++++++++++++++
gdb/gdbserver/target.h | 33 +++++++++
4 files changed, 216 insertions(+), 0 deletions(-)
diff --git a/gdb/gdbserver/gdbthread.h b/gdb/gdbserver/gdbthread.h
index adc23da..6238ed2 100644
--- a/gdb/gdbserver/gdbthread.h
+++ b/gdb/gdbserver/gdbthread.h
@@ -22,6 +22,8 @@
#include "server.h"
+struct btrace_target_info;
+
struct thread_info
{
struct inferior_list_entry entry;
@@ -58,6 +60,9 @@ struct thread_info
Each item in the list holds the current step of the while-stepping
action. */
struct wstep_state *while_stepping;
+
+ /* Branch trace target information for this thread. */
+ struct btrace_target_info *btrace;
};
extern struct inferior_list all_threads;
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index 76abaf5..76f5731 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -161,6 +161,9 @@ free_one_thread (struct inferior_list_entry *inf)
void
remove_thread (struct thread_info *thread)
{
+ if (thread->btrace)
+ target_disable_btrace (thread->btrace);
+
remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
free_one_thread (&thread->entry);
}
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index fae9199..090123e 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -440,6 +440,88 @@ write_qxfer_response (char *buf, const void *data, int len, int is_more)
PBUFSIZ - 2) + 1;
}
+/* Handle btrace enabling. */
+
+static const char *
+handle_btrace_enable (struct thread_info *thread)
+{
+ if (thread->btrace)
+ return "E.Btrace already enabled.";
+
+ thread->btrace = target_enable_btrace (thread->entry.id);
+ if (!thread->btrace)
+ return "E.Could not enable btrace.";
+
+ return NULL;
+}
+
+/* Handle btrace disabling. */
+
+static const char *
+handle_btrace_disable (struct thread_info *thread)
+{
+
+ if (!thread->btrace)
+ return "E.Branch tracing not enabled.";
+
+ if (target_disable_btrace (thread->btrace) != 0)
+ return "E.Could not disable branch tracing.";
+
+ thread->btrace = NULL;
+ return NULL;
+}
+
+/* Handle the "Qbtrace" packet. */
+
+static int
+handle_btrace_general_set (char *own_buf)
+{
+ struct thread_info *thread;
+ const char *err;
+ char *op;
+
+ if (strncmp ("Qbtrace:", own_buf, strlen ("Qbtrace:")) != 0)
+ return 0;
+
+ op = own_buf + strlen ("Qbtrace:");
+
+ if (!target_supports_btrace ())
+ {
+ strcpy (own_buf, "E.Target does not support branch tracing.");
+ 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 -1;
+ }
+
+ thread = find_thread_ptid (general_thread);
+ if (!thread)
+ {
+ strcpy (own_buf, "E.No such thread.");
+ return -1;
+ }
+
+ err = NULL;
+
+ if (strncmp ("on", op, strlen ("on")) == 0)
+ err = handle_btrace_enable (thread);
+ else if (strncmp ("off", op, strlen ("off")) == 0)
+ err = handle_btrace_disable (thread);
+ else
+ err = "E.Bad Qbtrace operation. Use on or off.";
+
+ if (err)
+ strcpy (own_buf, err);
+ else
+ write_ok (own_buf);
+
+ return 1;
+}
+
/* Handle all of the extended 'Q' packets. */
static void
@@ -596,6 +678,9 @@ handle_general_set (char *own_buf)
return;
}
+ if (handle_btrace_general_set (own_buf))
+ return;
+
/* Otherwise we didn't know what packet it was. Say we didn't
understand it. */
own_buf[0] = 0;
@@ -1295,9 +1380,66 @@ handle_qxfer_fdpic (const char *annex, gdb_byte *readbuf,
return (*the_target->read_loadmap) (annex, offset, readbuf, len);
}
+/* Handle qXfer:btrace:read. */
+
+static int
+handle_qxfer_btrace (const char *annex,
+ gdb_byte *readbuf, const gdb_byte *writebuf,
+ ULONGEST offset, LONGEST len)
+{
+ static struct buffer cache;
+ struct thread_info *thread;
+
+ if (!the_target->read_btrace || writebuf)
+ return -2;
+
+ if (!target_running () || annex[0] != '\0')
+ 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 -1;
+ }
+
+ thread = find_thread_ptid (general_thread);
+ if (!thread)
+ {
+ strcpy (own_buf, "E.No such thread.");
+ return -1;
+ }
+
+ if (!thread->btrace)
+ {
+ strcpy (own_buf, "E.Btrace not enabled.");
+ return -1;
+ }
+
+ if (!offset)
+ {
+ buffer_free (&cache);
+
+ target_read_btrace (thread->btrace, &cache);
+ }
+ else if (offset > cache.used_size)
+ {
+ buffer_free (&cache);
+ return -1;
+ }
+
+ 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 },
{ "fdpic", handle_qxfer_fdpic},
{ "features", handle_qxfer_features },
{ "libraries", handle_qxfer_libraries },
@@ -1462,6 +1604,29 @@ crc32 (CORE_ADDR base, int len, unsigned int crc)
return (unsigned long long) crc;
}
+/* Handle the "qbtrace" packet. */
+
+static int
+handle_btrace_query (char *own_buf)
+{
+ if (strncmp ("qbtrace:", own_buf, strlen ("qbtrace:")) == 0)
+ {
+ char *ptid_str = own_buf + strlen ("qbtrace:");
+ ptid_t ptid = read_ptid (ptid_str, NULL);
+ struct thread_info *thread = find_thread_ptid (ptid);
+
+ if (!thread)
+ strcpy (own_buf, "E.No such thread.");
+ else if (!thread->btrace)
+ strcpy (own_buf, "E.Btrace not enabled.");
+ else
+ strcpy (own_buf,
+ (target_btrace_has_changed (thread->btrace) ? "yes" : "no"));
+ return 1;
+ }
+ return 0;
+}
+
/* Handle all of the extended 'q' packets. */
void
@@ -1691,6 +1856,13 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
if (target_supports_agent ())
strcat (own_buf, ";QAgent+");
+ if (target_supports_btrace ())
+ {
+ strcat (own_buf, ";qbtrace+");
+ strcat (own_buf, ";Qbtrace+");
+ strcat (own_buf, ";qXfer:btrace:read+");
+ }
+
return;
}
@@ -1881,6 +2053,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
if (target_supports_tracepoints () && handle_tracepoint_query (own_buf))
return;
+ if (handle_btrace_query (own_buf))
+ return;
+
/* Otherwise we didn't know what packet it was. Say we didn't
understand it. */
own_buf[0] = 0;
diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h
index 9f96e04..952c973 100644
--- a/gdb/gdbserver/target.h
+++ b/gdb/gdbserver/target.h
@@ -22,6 +22,8 @@
#define TARGET_H
struct emit_ops;
+struct btrace_target_info;
+struct buffer;
/* Ways to "resume" a thread. */
@@ -397,6 +399,22 @@ struct target_ops
/* Return true if target supports debugging agent. */
int (*supports_agent) (void);
+
+ /* Check whether the target supports branch tracing. */
+ int (*supports_btrace) (void);
+
+ /* 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);
+
+ /* Disable branch tracing. */
+ int (*disable_btrace) (struct btrace_target_info *tinfo);
+
+ /* Check whether branch trace changed on the target. */
+ int (*btrace_has_changed) (struct btrace_target_info *);
+
+ /* Read branch trace data into buffer. */
+ void (*read_btrace) (struct btrace_target_info *, struct buffer *);
};
extern struct target_ops *the_target;
@@ -520,6 +538,21 @@ int kill_inferior (int);
(the_target->supports_agent ? \
(*the_target->supports_agent) () : 0)
+#define target_supports_btrace() \
+ (the_target->supports_btrace ? (*the_target->supports_btrace) () : 0)
+
+#define target_enable_btrace(ptid) \
+ (*the_target->enable_btrace) (ptid)
+
+#define target_disable_btrace(tinfo) \
+ (*the_target->disable_btrace) (tinfo)
+
+#define target_btrace_has_changed(tinfo) \
+ (*the_target->btrace_has_changed) (tinfo)
+
+#define target_read_btrace(tinfo, buffer) \
+ (*the_target->read_btrace) (tinfo, buffer)
+
/* Start non-stop mode, returns 0 on success, -1 on failure. */
int start_non_stop (int nonstop);
--
1.7.1
^ permalink raw reply [flat|nested] 20+ messages in thread* [patch v5 07/12] btrace, doc: document remote serial protocol
2012-12-07 10:37 [patch v5 00/12] branch tracing support for Atom markus.t.metzger
` (7 preceding siblings ...)
2012-12-07 10:38 ` [patch v5 08/12] gdbserver, btrace: add generic btrace support markus.t.metzger
@ 2012-12-07 10:38 ` markus.t.metzger
2012-12-07 15:09 ` Eli Zaretskii
2012-12-07 10:38 ` [patch v5 04/12] linux, i386, amd64: enable btrace for 32bit and 64bit linux native markus.t.metzger
` (2 subsequent siblings)
11 siblings, 1 reply; 20+ messages in thread
From: markus.t.metzger @ 2012-12-07 10:38 UTC (permalink / raw)
To: gdb-patches
Cc: markus.t.metzger, jan.kratochvil, palves, tromey, kettenis,
Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Document the extensions to the remote serial protocol for supporting branch tracing.
2012-12-07 Markus Metzger <markus.t.metzger@intel.com>
doc/
* gdb.texinfo (Requirements): List qXfer:btrace:read requiring expat.
(General Query Packets): Describe qbtrace, Qbtrace, and qXfer:btrace:read.
---
gdb/doc/gdb.texinfo | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 125 insertions(+), 0 deletions(-)
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9ffdb77..6ce34e3 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -34468,6 +34468,8 @@ or alternatively @pxref{Library List Format for SVR4 Targets})
MS-Windows shared libraries (@pxref{Shared Libraries})
@item
Traceframe info (@pxref{Traceframe Info Format})
+@item
+Branch trace (@pxref{Branch Trace Format})
@end itemize
@item zlib
@@ -35329,6 +35331,7 @@ Show the current setting of the target wait timeout.
* Memory Map Format::
* Thread List Format::
* Traceframe Info Format::
+* Branch Trace Format::
@end menu
@node Overview
@@ -36958,11 +36961,21 @@ These are the currently defined stub features and their properties:
@tab @samp{-}
@tab No
+@item @samp{qbtrace}
+@tab No
+@tab @samp{-}
+@tab Yes
+
@item @samp{qXfer:auxv:read}
@tab No
@tab @samp{-}
@tab Yes
+@item @samp{qXfer:btrace:read}
+@tab No
+@tab @samp{-}
+@tab Yes
+
@item @samp{qXfer:features:read}
@tab No
@tab @samp{-}
@@ -37023,6 +37036,11 @@ These are the currently defined stub features and their properties:
@tab @samp{-}
@tab Yes
+@item @samp{Qbtrace}
+@tab Yes
+@tab @samp{-}
+@tab Yes
+
@item @samp{QNonStop}
@tab No
@tab @samp{-}
@@ -37118,6 +37136,10 @@ byte in its buffer for the NUL. If this stub feature is not supported,
The remote stub understands the @samp{qXfer:auxv:read} packet
(@pxref{qXfer auxiliary vector read}).
+@item qXfer:btrace:read
+The remote stub understands the @samp{qXfer:btrace:read}
+packet (@pxref{qXfer btrace read}).
+
@item qXfer:features:read
The remote stub understands the @samp{qXfer:features:read} packet
(@pxref{qXfer target description read}).
@@ -37252,6 +37274,12 @@ See @ref{Bytecode Descriptions} for details about the bytecode.
The remote stub supports running a breakpoint's command list itself,
rather than reporting the hit to @value{GDBN}.
+@item qbtrace
+The remote stub understands the @samp{qbtrace} packet.
+
+@item Qbtrace
+The remote stub understands the @samp{Qbtrace} packet.
+
@end table
@item qSymbol::
@@ -37370,6 +37398,18 @@ auxiliary vector}. Note @var{annex} must be empty.
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:read:@var{annex}:@var{offset},@var{length}
+@anchor{qXfer btrace read}
+
+Return a description of the current branch trace.
+@xref{Branch Trace Format}. The annex part of the generic @samp{qXfer}
+packet contains the thread id (see @ref{thread-id syntax}) for which
+branch trace is to be read (@pxref{qXfer read}). The thread id must
+specify a single thread.
+
+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
@@ -37606,6 +37646,41 @@ The remote server created a new process.
A badly formed request or an error was encountered.
@end table
+@item qbtrace
+Return whether new branch trace data is available for the current thread.
+
+Reply:
+@table @samp
+@item yes
+New branch trace data is available.
+@item no
+No new branch trace data is available.
+@item E.errtext
+A badly formed request or an error was encountered.
+@end table
+
+@item Qbtrace:on
+Enable branch tracing for the current thread.
+
+Reply:
+@table @samp
+@item OK
+Branch tracing has been enabled.
+@item E.errtext
+A badly formed request or an error was encountered.
+@end table
+
+@item Qbtrace:off
+Disable branch tracing for the current thread.
+
+Reply:
+@table @samp
+@item OK
+Branch tracing has been disabled.
+@item E.errtext
+A badly formed request or an error was encountered.
+@end table
+
@end table
@node Architecture-Specific Protocol Details
@@ -40022,6 +40097,56 @@ The formal DTD for the traceframe info format is given below:
length CDATA #REQUIRED>
@end smallexample
+@node Branch Trace Format
+@section Branch Trace Format
+@cindex branch trace format
+
+In order to display the branch trace of an inferior thread,
+@value{GDBN} needs to obtain the list of branches. This list is
+represented as list of sequential code blocks that are connected via
+branches. The code in each block has been executed sequentially.
+
+This list is obtained using the @samp{qXfer:btrace:read}
+(@pxref{qXfer btrace read}) packet and is an XML document.
+
+@value{GDBN} must be linked with the Expat library to support XML
+traceframe info discovery. @xref{Expat}.
+
+The top-level structure of the document is shown below:
+
+@smallexample
+<?xml version="1.0"?>
+<!DOCTYPE btrace
+ PUBLIC "+//IDN gnu.org//DTD GDB Branch Trace V1.0//EN"
+ "http://sourceware.org/gdb/gdb-btrace.dtd">
+<btrace>
+ block...
+</btrace>
+@end smallexample
+
+@itemize
+
+@item
+A block of sequentially executed instructions starting at @var{begin}
+and ending at @var{end}:
+
+@smallexample
+<block begin="@var{begin}" end="@var{end}"/>
+@end smallexample
+
+@end itemize
+
+The formal DTD for the traceframe info format is given below:
+
+@smallexample
+<!ELEMENT btrace (block)* >
+<!ATTLIST btrace version CDATA #FIXED "1.0">
+
+<!ELEMENT block EMPTY>
+<!ATTLIST block begin CDATA #REQUIRED
+ end CDATA #REQUIRED>
+@end smallexample
+
@include agentexpr.texi
@node Target Descriptions
--
1.7.1
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [patch v5 07/12] btrace, doc: document remote serial protocol
2012-12-07 10:38 ` [patch v5 07/12] btrace, doc: document remote serial protocol markus.t.metzger
@ 2012-12-07 15:09 ` Eli Zaretskii
2012-12-13 8:43 ` Metzger, Markus T
0 siblings, 1 reply; 20+ messages in thread
From: Eli Zaretskii @ 2012-12-07 15:09 UTC (permalink / raw)
To: markus.t.metzger; +Cc: gdb-patches, jan.kratochvil, palves, tromey, kettenis
> From: markus.t.metzger@intel.com
> Cc: markus.t.metzger@gmail.com, jan.kratochvil@redhat.com, palves@redhat.com, tromey@redhat.com, kettenis@gnu.org, Markus Metzger <markus.t.metzger@intel.com>
> Date: Fri, 7 Dec 2012 11:37:19 +0100
>
> From: Markus Metzger <markus.t.metzger@intel.com>
>
> Document the extensions to the remote serial protocol for supporting branch tracing.
>
> 2012-12-07 Markus Metzger <markus.t.metzger@intel.com>
>
> doc/
> * gdb.texinfo (Requirements): List qXfer:btrace:read requiring expat.
> (General Query Packets): Describe qbtrace, Qbtrace, and qXfer:btrace:read.
Thanks.
> +Return a description of the current branch trace.
> +@xref{Branch Trace Format}. The annex part of the generic @samp{qXfer}
> +packet contains the thread id (see @ref{thread-id syntax}) for which
^^^^^^^^
Please use @pxref instead of "see @ref".
> +In order to display the branch trace of an inferior thread,
> +@value{GDBN} needs to obtain the list of branches. This list is
Two spaces between sentences, please (here and elsewhere in the
patch).
OK with those changes.
^ permalink raw reply [flat|nested] 20+ messages in thread* RE: [patch v5 07/12] btrace, doc: document remote serial protocol
2012-12-07 15:09 ` Eli Zaretskii
@ 2012-12-13 8:43 ` Metzger, Markus T
2012-12-13 17:02 ` Eli Zaretskii
2012-12-13 17:09 ` Pedro Alves
0 siblings, 2 replies; 20+ messages in thread
From: Metzger, Markus T @ 2012-12-13 8:43 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches, jan.kratochvil, palves, tromey, kettenis
> -----Original Message-----
> From: Eli Zaretskii [mailto:eliz@gnu.org]
> Sent: Friday, December 07, 2012 4:08 PM
Thanks for your review.
I fixed the issues you pointed out.
[...]
> OK with those changes.
I will keep the patch in the series until the entire series has been approved. Do you want me to omit this patch when sending out updates of the series?
Regards,
Markus.
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [patch v5 07/12] btrace, doc: document remote serial protocol
2012-12-13 8:43 ` Metzger, Markus T
@ 2012-12-13 17:02 ` Eli Zaretskii
2012-12-13 17:09 ` Pedro Alves
1 sibling, 0 replies; 20+ messages in thread
From: Eli Zaretskii @ 2012-12-13 17:02 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: gdb-patches, jan.kratochvil, palves, tromey, kettenis
> From: "Metzger, Markus T" <markus.t.metzger@intel.com>
> CC: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>,
> "jan.kratochvil@redhat.com" <jan.kratochvil@redhat.com>, "palves@redhat.com"
> <palves@redhat.com>, "tromey@redhat.com" <tromey@redhat.com>,
> "kettenis@gnu.org" <kettenis@gnu.org>
> Date: Thu, 13 Dec 2012 08:43:15 +0000
>
> Thanks for your review.
>
> I fixed the issues you pointed out.
>
> [...]
>
> > OK with those changes.
>
> I will keep the patch in the series until the entire series has been approved. Do you want me to omit this patch when sending out updates of the series?
It's up to you. If you don't omit that, please just tell that the doc
part is already approved, or something to that effect, thanks.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [patch v5 07/12] btrace, doc: document remote serial protocol
2012-12-13 8:43 ` Metzger, Markus T
2012-12-13 17:02 ` Eli Zaretskii
@ 2012-12-13 17:09 ` Pedro Alves
2012-12-14 7:53 ` Metzger, Markus T
1 sibling, 1 reply; 20+ messages in thread
From: Pedro Alves @ 2012-12-13 17:09 UTC (permalink / raw)
To: Metzger, Markus T
Cc: Eli Zaretskii, gdb-patches, jan.kratochvil, palves, tromey, kettenis
On 12/13/2012 08:43 AM, Metzger, Markus T wrote:
> I will keep the patch in the series until the entire series has been approved. Do you want me to omit this patch when sending out updates of the series?
Please keep it in the series. The mechanics of the docs might be
approved, but someone should still go over the packet's semantics,
and its just to easier on someone looking at the whole thing
if things are kept together, instead of having the reader hunt
for bits and pieces.
--
Pedro Alves
^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [patch v5 07/12] btrace, doc: document remote serial protocol
2012-12-13 17:09 ` Pedro Alves
@ 2012-12-14 7:53 ` Metzger, Markus T
0 siblings, 0 replies; 20+ messages in thread
From: Metzger, Markus T @ 2012-12-14 7:53 UTC (permalink / raw)
To: Pedro Alves; +Cc: Eli Zaretskii, gdb-patches, jan.kratochvil, tromey, kettenis
> -----Original Message-----
> From: Pedro Alves [mailto:palves@redhat.com]
> Sent: Thursday, December 13, 2012 6:09 PM
> To: Metzger, Markus T
> Cc: Eli Zaretskii; gdb-patches@sourceware.org; jan.kratochvil@redhat.com; palves@redhat.com; tromey@redhat.com;
> kettenis@gnu.org
> Subject: Re: [patch v5 07/12] btrace, doc: document remote serial protocol
>
> On 12/13/2012 08:43 AM, Metzger, Markus T wrote:
>
> > I will keep the patch in the series until the entire series has been approved. Do you want me to omit this patch when sending out
> updates of the series?
>
> Please keep it in the series. The mechanics of the docs might be
> approved, but someone should still go over the packet's semantics,
> and its just to easier on someone looking at the whole thing
> if things are kept together, instead of having the reader hunt
> for bits and pieces.
OK, I'll keep sending this patch and add a note to the cover letter that rsp doc has been approved.
Are you OK with the changes I made in response to your feedback, Pedro? I will also address the explicit == NULL and != NULL checks in the next update. Is there anything else that needs changing?
Regards,
Markus.
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052
^ permalink raw reply [flat|nested] 20+ messages in thread
* [patch v5 04/12] linux, i386, amd64: enable btrace for 32bit and 64bit linux native
2012-12-07 10:37 [patch v5 00/12] branch tracing support for Atom markus.t.metzger
` (8 preceding siblings ...)
2012-12-07 10:38 ` [patch v5 07/12] btrace, doc: document remote serial protocol markus.t.metzger
@ 2012-12-07 10:38 ` markus.t.metzger
2012-12-07 10:38 ` [patch v5 12/12] btrace, x86: disable on some processors markus.t.metzger
2012-12-07 10:39 ` [patch v5 11/12] test, btrace: more branch tracing tests markus.t.metzger
11 siblings, 0 replies; 20+ messages in thread
From: markus.t.metzger @ 2012-12-07 10:38 UTC (permalink / raw)
To: gdb-patches
Cc: markus.t.metzger, jan.kratochvil, palves, tromey, kettenis,
Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Install the btrace target ops for i386-linux-nat and amd64-linux-nat.
2012-12-07 Markus Metzger <markus.t.metzger@intel.com>
* amd64-linux-nat.c: Include btrace.h and linux-btrace.h.
(amd64_linux_enable_btrace): New.
(amd64_linux_disable_btrace): New.
(_initialize_amd64_linux_nat): Initialize btrace ops.
* i386-linux.nat.c: Include btrace.h and linux-btrace.h.
(i386_linux_enable_btrace): New.
(i386_linux_disable_btrace): New.
(_initialize_i386_linux_nat): Initialize btrace ops.
* config/i386/linux.mh: Add linux-btrace.o.
* config/i386/linux64.mh: Add linux-btrace.o.
---
gdb/amd64-linux-nat.c | 42 ++++++++++++++++++++++++++++++++++++++++++
gdb/config/i386/linux.mh | 3 ++-
gdb/config/i386/linux64.mh | 2 +-
gdb/i386-linux-nat.c | 42 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 87 insertions(+), 2 deletions(-)
diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
index f4a12db..9cba72a 100644
--- a/gdb/amd64-linux-nat.c
+++ b/gdb/amd64-linux-nat.c
@@ -25,6 +25,8 @@
#include "regset.h"
#include "linux-nat.h"
#include "amd64-linux-tdep.h"
+#include "linux-btrace.h"
+#include "btrace.h"
#include "gdb_assert.h"
#include "gdb_string.h"
@@ -1079,6 +1081,39 @@ amd64_linux_read_description (struct target_ops *ops)
}
}
+/* Enable branch tracing. */
+
+static struct btrace_target_info *
+amd64_linux_enable_btrace (ptid_t ptid)
+{
+ struct btrace_target_info *tinfo;
+ struct gdbarch *gdbarch;
+
+ errno = 0;
+ tinfo = linux_enable_btrace (ptid);
+
+ if (!tinfo)
+ error (_("Could not enable branch tracing for %s: %s."),
+ target_pid_to_str (ptid), safe_strerror (errno));
+
+ /* Fill in the size of a pointer in bits. */
+ gdbarch = target_thread_architecture (ptid);
+ tinfo->ptr_bits = gdbarch_ptr_bit (gdbarch);
+
+ return tinfo;
+}
+
+/* Disable branch tracing. */
+
+static void
+amd64_linux_disable_btrace (struct btrace_target_info *tinfo)
+{
+ int errcode = linux_disable_btrace (tinfo);
+
+ if (errcode)
+ error (_("Could not disable branch tracing: %s."), safe_strerror (errcode));
+}
+
/* Provide a prototype to silence -Wmissing-prototypes. */
void _initialize_amd64_linux_nat (void);
@@ -1117,6 +1152,13 @@ _initialize_amd64_linux_nat (void)
t->to_read_description = amd64_linux_read_description;
+ /* Add btrace methods. */
+ t->to_supports_btrace = linux_supports_btrace;
+ t->to_enable_btrace = amd64_linux_enable_btrace;
+ t->to_disable_btrace = amd64_linux_disable_btrace;
+ t->to_btrace_has_changed = linux_btrace_has_changed;
+ t->to_read_btrace = linux_read_btrace;
+
/* Register the target. */
linux_nat_add_target (t);
linux_nat_set_new_thread (t, amd64_linux_new_thread);
diff --git a/gdb/config/i386/linux.mh b/gdb/config/i386/linux.mh
index 8316d87..7c64e83 100644
--- a/gdb/config/i386/linux.mh
+++ b/gdb/config/i386/linux.mh
@@ -4,7 +4,8 @@ NAT_FILE= config/nm-linux.h
NATDEPFILES= inf-ptrace.o fork-child.o \
i386-nat.o i386-linux-nat.o \
proc-service.o linux-thread-db.o \
- linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
+ linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
+ linux-btrace.o
NAT_CDEPS = $(srcdir)/proc-service.list
# The dynamically loaded libthread_db needs access to symbols in the
diff --git a/gdb/config/i386/linux64.mh b/gdb/config/i386/linux64.mh
index d2b95fd..8d782c1 100644
--- a/gdb/config/i386/linux64.mh
+++ b/gdb/config/i386/linux64.mh
@@ -3,7 +3,7 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
i386-nat.o amd64-nat.o amd64-linux-nat.o \
linux-nat.o linux-osdata.o \
proc-service.o linux-thread-db.o linux-fork.o \
- linux-procfs.o linux-ptrace.o
+ linux-procfs.o linux-ptrace.o linux-btrace.o
NAT_FILE= config/nm-linux.h
NAT_CDEPS = $(srcdir)/proc-service.list
diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c
index 5a65ef6..9abaf78 100644
--- a/gdb/i386-linux-nat.c
+++ b/gdb/i386-linux-nat.c
@@ -25,6 +25,8 @@
#include "regset.h"
#include "target.h"
#include "linux-nat.h"
+#include "linux-btrace.h"
+#include "btrace.h"
#include "gdb_assert.h"
#include "gdb_string.h"
@@ -1008,6 +1010,39 @@ i386_linux_read_description (struct target_ops *ops)
return tdesc_i386_linux;
}
+/* Enable branch tracing. */
+
+static struct btrace_target_info *
+i386_linux_enable_btrace (ptid_t ptid)
+{
+ struct btrace_target_info *tinfo;
+ struct gdbarch *gdbarch;
+
+ errno = 0;
+ tinfo = linux_enable_btrace (ptid);
+
+ if (!tinfo)
+ error (_("Could not enable branch tracing for %s: %s."),
+ target_pid_to_str (ptid), safe_strerror (errno));
+
+ /* Fill in the size of a pointer in bits. */
+ gdbarch = target_thread_architecture (ptid);
+ tinfo->ptr_bits = gdbarch_ptr_bit (gdbarch);
+
+ return tinfo;
+}
+
+/* Disable branch tracing. */
+
+static void
+i386_linux_disable_btrace (struct btrace_target_info *tinfo)
+{
+ int errcode = linux_disable_btrace (tinfo);
+
+ if (errcode)
+ error (_("Could not disable branch tracing: %s."), safe_strerror (errcode));
+}
+
/* -Wmissing-prototypes */
extern initialize_file_ftype _initialize_i386_linux_nat;
@@ -1041,6 +1076,13 @@ _initialize_i386_linux_nat (void)
t->to_read_description = i386_linux_read_description;
+ /* Add btrace methods. */
+ t->to_supports_btrace = linux_supports_btrace;
+ t->to_enable_btrace = i386_linux_enable_btrace;
+ t->to_disable_btrace = i386_linux_disable_btrace;
+ t->to_btrace_has_changed = linux_btrace_has_changed;
+ t->to_read_btrace = linux_read_btrace;
+
/* Register the target. */
linux_nat_add_target (t);
linux_nat_set_new_thread (t, i386_linux_new_thread);
--
1.7.1
^ permalink raw reply [flat|nested] 20+ messages in thread* [patch v5 12/12] btrace, x86: disable on some processors
2012-12-07 10:37 [patch v5 00/12] branch tracing support for Atom markus.t.metzger
` (9 preceding siblings ...)
2012-12-07 10:38 ` [patch v5 04/12] linux, i386, amd64: enable btrace for 32bit and 64bit linux native markus.t.metzger
@ 2012-12-07 10:38 ` markus.t.metzger
2012-12-07 10:39 ` [patch v5 11/12] test, btrace: more branch tracing tests markus.t.metzger
11 siblings, 0 replies; 20+ messages in thread
From: markus.t.metzger @ 2012-12-07 10:38 UTC (permalink / raw)
To: gdb-patches
Cc: markus.t.metzger, jan.kratochvil, palves, tromey, kettenis,
Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
LBR, BTM, or BTS records may have incorrect branch "from" information afer an
EIST transition, T-states, C1E, or Adaptive Thermal Throttling (AAJ122).
This results in sporadic test fails. Disable btrace on those processors.
2012-12-07 Markus Metzger <markus.t.metzger@intel.com>
* common/linux-btrace.c (linux_supports_btrace): Add cpuid check.
---
gdb/common/linux-btrace.c | 43 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 43 insertions(+), 0 deletions(-)
diff --git a/gdb/common/linux-btrace.c b/gdb/common/linux-btrace.c
index 2441816..c703dc2 100644
--- a/gdb/common/linux-btrace.c
+++ b/gdb/common/linux-btrace.c
@@ -247,7 +247,50 @@ perf_event_read_bts (struct btrace_target_info* tinfo, const uint8_t *begin,
int
linux_supports_btrace (void)
{
+#if defined(__i386__) || defined(__x86_64__)
+ {
+ unsigned int cpuid, model, family;
+
+ __asm__ __volatile__ ("movl $1, %%eax;"
+ "cpuid;"
+ : "=a" (cpuid)
+ :: "%ebx", "%ecx", "%edx");
+
+ family = (cpuid >> 8) & 0xf;
+ model = (cpuid >> 4) & 0xf;
+
+ switch (family)
+ {
+ case 6:
+ model += (cpuid >> 12) & 0xf0;
+
+ switch (model)
+ {
+ case 26: /* Nehalem */
+ case 30:
+ case 46:
+ case 37: /* Westmere */
+ case 44:
+ case 47:
+ case 42: /* Sandy Bridge */
+ case 45:
+ case 58: /* Ivy Bridge */
+
+ /* AAJ122: LBR, BTM, or BTS records may have incorrect branch
+ "from" information afer an EIST transition, T-states, C1E, or
+ Adaptive Thermal Throttling. */
+ return 0;
+ }
+ }
+ }
+
return 1;
+
+#else /* defined(__i386__) || defined(__x86_64__) */
+
+ return 0;
+
+#endif /* defined(__i386__) || defined(__x86_64__) */
}
/* See linux-btrace.h. */
--
1.7.1
^ permalink raw reply [flat|nested] 20+ messages in thread* [patch v5 11/12] test, btrace: more branch tracing tests
2012-12-07 10:37 [patch v5 00/12] branch tracing support for Atom markus.t.metzger
` (10 preceding siblings ...)
2012-12-07 10:38 ` [patch v5 12/12] btrace, x86: disable on some processors markus.t.metzger
@ 2012-12-07 10:39 ` markus.t.metzger
11 siblings, 0 replies; 20+ messages in thread
From: markus.t.metzger @ 2012-12-07 10:39 UTC (permalink / raw)
To: gdb-patches
Cc: markus.t.metzger, jan.kratochvil, palves, tromey, kettenis, Barkha Ahuja
From: Barkha Ahuja <barkha.ahuja@intel.com>
Non-stop tests are failing with gdbserver and are thus skipped.
2012-12-07 Barkha Ahuja <barkha.ahuja@intel.com>
testsuite/
* gdb.btrace/a.S: New file
* gdb.btrace/allthreads_trace.exp: New file
* gdb.btrace/b.S: New file
* gdb.btrace/decrement.exp: New file
* gdb.btrace/decrement.S: New file
* gdb.btrace/disable_all.exp: New file
* gdb.btrace/enable_all.exp: New file
* gdb.btrace/enable_range.exp: New file
* gdb.btrace/list_options.exp: New file
* gdb.btrace/main.S: New file
* gdb.btrace/main_asm.exp: New file
* gdb.btrace/main_segv.exp: New file
* gdb.btrace/main_segv.S: New file
* gdb.btrace/sanity_crash.exp: New file
* gdb.btrace/sanity_crash.S: New file
* gdb.btrace/amd64-thr-callback.S: New file
* gdb.btrace/i386-thr-callback.S: New file
* gdb.btrace/threads.c: New file
* gdb.btrace/threads_asm.c: New file
* gdb.btrace/threads_auto.exp: New file
* gdb.btrace/threads_independent.exp: New file
* gdb.btrace/threads_nonstop.exp: New file
* gdb.btrace/trace_iteration.exp: New file
---
gdb/testsuite/gdb.btrace/a.S | 23 ++
gdb/testsuite/gdb.btrace/allthreads_trace.exp | 345 ++++++++++++++++++++++
gdb/testsuite/gdb.btrace/amd64-thr-callback.S | 116 ++++++++
gdb/testsuite/gdb.btrace/b.S | 23 ++
gdb/testsuite/gdb.btrace/decrement.S | 32 ++
gdb/testsuite/gdb.btrace/decrement.exp | 141 +++++++++
gdb/testsuite/gdb.btrace/disable_all.exp | 279 +++++++++++++++++
gdb/testsuite/gdb.btrace/enable_all.exp | 282 ++++++++++++++++++
gdb/testsuite/gdb.btrace/enable_range.exp | 281 ++++++++++++++++++
gdb/testsuite/gdb.btrace/i386-thr-callback.S | 116 ++++++++
gdb/testsuite/gdb.btrace/list_options.exp | 107 +++++++
gdb/testsuite/gdb.btrace/main.S | 36 +++
gdb/testsuite/gdb.btrace/main_asm.exp | 109 +++++++
gdb/testsuite/gdb.btrace/main_segv.S | 32 ++
gdb/testsuite/gdb.btrace/main_segv.exp | 84 ++++++
gdb/testsuite/gdb.btrace/threads.c | 96 ++++++
gdb/testsuite/gdb.btrace/threads_asm.c | 78 +++++
gdb/testsuite/gdb.btrace/threads_auto.exp | 123 ++++++++
gdb/testsuite/gdb.btrace/threads_independent.exp | 125 ++++++++
gdb/testsuite/gdb.btrace/threads_nonstop.exp | 231 +++++++++++++++
gdb/testsuite/gdb.btrace/trace_iteration.exp | 265 +++++++++++++++++
21 files changed, 2924 insertions(+), 0 deletions(-)
create mode 100755 gdb/testsuite/gdb.btrace/a.S
create mode 100755 gdb/testsuite/gdb.btrace/allthreads_trace.exp
create mode 100755 gdb/testsuite/gdb.btrace/amd64-thr-callback.S
create mode 100755 gdb/testsuite/gdb.btrace/b.S
create mode 100755 gdb/testsuite/gdb.btrace/decrement.S
create mode 100755 gdb/testsuite/gdb.btrace/decrement.exp
create mode 100755 gdb/testsuite/gdb.btrace/disable_all.exp
create mode 100755 gdb/testsuite/gdb.btrace/enable_all.exp
create mode 100755 gdb/testsuite/gdb.btrace/enable_range.exp
create mode 100755 gdb/testsuite/gdb.btrace/i386-thr-callback.S
create mode 100755 gdb/testsuite/gdb.btrace/list_options.exp
create mode 100755 gdb/testsuite/gdb.btrace/main.S
create mode 100755 gdb/testsuite/gdb.btrace/main_asm.exp
create mode 100755 gdb/testsuite/gdb.btrace/main_segv.S
create mode 100755 gdb/testsuite/gdb.btrace/main_segv.exp
create mode 100755 gdb/testsuite/gdb.btrace/threads.c
create mode 100755 gdb/testsuite/gdb.btrace/threads_asm.c
create mode 100755 gdb/testsuite/gdb.btrace/threads_auto.exp
create mode 100755 gdb/testsuite/gdb.btrace/threads_independent.exp
create mode 100755 gdb/testsuite/gdb.btrace/threads_nonstop.exp
create mode 100755 gdb/testsuite/gdb.btrace/trace_iteration.exp
diff --git a/gdb/testsuite/gdb.btrace/a.S b/gdb/testsuite/gdb.btrace/a.S
new file mode 100755
index 0000000..b457975
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/a.S
@@ -0,0 +1,23 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@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/>.
+
+ .text
+ .globl callA
+ .type callA, @function
+callA:
+ nop
+ ret
diff --git a/gdb/testsuite/gdb.btrace/allthreads_trace.exp b/gdb/testsuite/gdb.btrace/allthreads_trace.exp
new file mode 100755
index 0000000..8af544c
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/allthreads_trace.exp
@@ -0,0 +1,345 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@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/>.
+
+###############
+#Test Purpose: In GDB non-stop mode, Enable trace for all the threads by "btr enable auto" on primary thread and check the trace availability for all the threads
+# Sourcefiles : threads_asm.c, i386-thr-callback.S, amd64-thr-callback.S
+# Compiled using '-g -lpthread' option.
+#executed as :
+# make check RUNTESTFLAGS="GDB=<path to gdb> gdb.trace/allthreads_trace.exp"
+###############
+
+load_lib btrace.exp
+
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+# the tests do currently not work with gdbserver
+if [is_remote target] {
+ untested "allthreads_trace.exp"
+ return -1
+}
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/threads_asm.c
+set objcallback ${objdir}/${subdir}/thr_callback.o
+set objmain ${objdir}/${subdir}/threads_asm.o
+set binfile ${objdir}/${subdir}/allthreads_trace.x
+set options "{debug}"
+
+if { ![support_displaced_stepping] } {
+ unsupported "displaced stepping"
+ return -1
+}
+
+#Load different callback files for 32 and 64 bit.
+# 32 bit platform
+if {[istarget "i?86-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/i386-thr-callback.S
+} elseif {[istarget "x86_64-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/amd64-thr-callback.S
+} else {
+ warning "host platform not supported "
+ untested allthreads_trace.exp
+ return -1
+}
+set objfiles "${objmain} ${objcallback}"
+
+#compile
+if {[gdb_compile_pthreads ${srcfilemain} ${objmain} "object" ${options}] != ""} {
+ untested allthreads_trace.exp
+ return -1
+}
+if {[gdb_compile ${srccallback} ${objcallback} "object" ${options}] != ""} {
+ untested allthreads_trace.exp
+ return -1
+}
+
+if {[gdb_compile_pthreads ${objfiles} ${binfile} "executable" ${options}] != ""} {
+ untested allthreads_trace.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+gdb_test_no_output "set pagination off"
+gdb_test_no_output "set target-async 1"
+gdb_test_no_output "set non-stop 1"
+
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+# set breakpoint at line 67, at call to mybarrier() for primary thread.
+gdb_breakpoint "67" "Breakpoint 2 at.*: file.*threads_asm.c, line 67." " breakpoint at line 67, 1.1"
+
+# set a breakpoint at mybarrier() to halt all the new threads from exiting.
+gdb_breakpoint "mybarrier" "Breakpoint 3, mybarrier \\(\\) at .*thr-callback.S:114" "Breakpoint at my barrier for all the threads to stop, 1.2"
+
+# enable trace in primary thread, which automatically enables trace in all new threads crated.
+gdb_test "btr enable auto"
+
+set test "continue running..."
+gdb_test_multiple "continue" $test {
+ -re "Breakpoint 3, mybarrier \\(\\) at.*thr-callback.S:114.*"
+ {
+ pass "continuing"
+ }
+ timeout {fail "(timeout) continue into program"}
+}
+# this is added to get the prompt, which is missing.
+gdb_test "" ""
+
+# This "info threads" is needed to get a $gdb_prompt, since gdb seems to get hanged at this particular location.
+set test "info for threads"
+gdb_test_multiple "info threads" $test {
+ -re ".*\n" {
+ pass $test
+ }
+}
+
+# this is added to get the prompt, which is missing.
+gdb_test "" ""
+
+# We need to do a seperate listing from here, since the instr length is different
+# on different platforms.
+gdb_test_multiple "thread 2" "switching to thread 2" {
+ -re ".*Switching to thread 2.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 2, 1.3"
+ }
+ timeout {
+ fail "switching to thread 2 (timeout), 1.3"
+ }
+}
+
+# 64 bit platform
+if {[istarget "x86_64-*-*"]} {
+
+# trace for thread 2
+gdb_test "btr list /a" "
+1 0x\[a-f0-9\]* - 0x\[a-f0-9\]*\r
+2 0x\[a-f0-9\]* - 0x\[a-f0-9\]*\r
+.*" "BTR listing for thread 2, 1.4"
+
+gdb_test "btr /m 1" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> *0x\[a-f0-9\]* <mybarrier\\+4>:\[\[:blank:\]\]*mov.*" " BTR of 1 for thread 2, 1.5"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_a\\+14>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_a\\+19>:\[\[:blank:\]\]*call.*" " BTR of 2 for thread 2, 1.6"
+
+# trace for thread 3
+gdb_test_multiple "thread 3" "switching to thread 3" {
+ -re ".*Switching to thread 3.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 3, 1.7"
+ }
+ timeout {
+ fail "switching to thread 3 (timeout), 1.7"
+ }
+}
+
+gdb_test "btr list /la" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* at .*amd64-thr-callback.S:112-114\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* at .*amd64-thr-callback.S:44-45\r
+3 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* at .*amd64-thr-callback.S:85-89\r
+4 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* at .*amd64-thr-callback.S:40-43\r
+.*" "BTR listing for thread 3, 1.8"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> *0x\[a-f0-9\]* <mybarrier\\+4>:\[\[:blank:\]\]*mov.*" " BTR of 1 for thread 3, 1.9"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_b\\+14>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_b\\+19>:\[\[:blank:\]\]*call.*" " BTR of 2 for thread 3, 1.10"
+
+# trace for thread 4
+gdb_test_multiple "thread 4" "switching to thread 4" {
+ -re ".*Switching to thread 4.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 4, 1.11"
+ }
+ timeout {
+ fail "switching to thread 4 (timeout), 1.11"
+ }
+}
+
+gdb_test "btr list /lf" "
+1 *in mybarrier at.*amd64-thr-callback.S:112-114\r
+2 *in th_c at.*amd64-thr-callback.S:56-57\r
+3 *in call_C at.*amd64-thr-callback.S:94-98\r
+4 *in th_c at.*amd64-thr-callback.S:52-55\r
+.*" "BTR listing for thread 4, 1.12"
+
+gdb_test "btr /m 1" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> *0x\[a-f0-9\]* <mybarrier\\+4>:\[\[:blank:\]\]*mov.*" " BTR of 1 for thread 4, 1.13"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_c\\+14>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_c\\+19>:\[\[:blank:\]\]*call.*" " BTR of 2 for thread 4, 1.14"
+
+# trace for thread 5
+gdb_test_multiple "thread 5" "switching to thread 5" {
+ -re ".*Switching to thread 5.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 5, 1.15"
+ }
+ timeout {
+ fail "switching to thread 5 (timeout), 1.15"
+ }
+}
+
+gdb_test "btr list /fa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in mybarrier\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_d\r
+.*" "BTR listing for thread 5, 1.16"
+
+gdb_test "btr " "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> *0x\[a-f0-9\]* <mybarrier\\+4>:\[\[:blank:\]\]*mov.*" " BTR of 1 for thread 5, 1.17"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_d\\+14>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_d\\+19>:\[\[:blank:\]\]*call.*" " BTR of 2 for thread 5, 1.18"
+
+ gdb_test "btr +" "
+ *0x\[a-f0-9\]* <call_D\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <call_D\\+1>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <call_D\\+4>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <call_D\\+9>:\[\[:blank:\]\]*leave.*\r
+ *0x\[a-f0-9\]* <call_D\\+10>:\[\[:blank:\]\]*ret.*\r" " BTR of 3 for thread 5, 1.19"
+
+} elseif {[istarget "i?86-*-*"]} {
+# 32 bit platform
+
+#trace for thread 2
+gdb_test "btr list /a" "
+1 0x\[a-f0-9\]* - 0x\[a-f0-9\]*\r
+2 0x\[a-f0-9\]* - 0x\[a-f0-9\]*\r
+.*" "BTR listing for thread 2, 1.4"
+
+gdb_test "btr /m 1" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> *0x\[a-f0-9\]* <mybarrier\\+3>:\[\[:blank:\]\]*mov.*" " BTR of 1 for thread 2, 1.5"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_a\\+13>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_a\\+18>:\[\[:blank:\]\]*call.*" " BTR of 2 for thread 2, 1.6"
+
+#switch to thread 3
+gdb_test_multiple "thread 3" "switching to thread 3" {
+ -re ".*Switching to thread 3.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 3, 1.7"
+ }
+ timeout {
+ fail "switching to thread 3 (timeout), 1.7"
+ }
+}
+
+#trace for thread 3
+gdb_test "btr list /la" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* at .*i386-thr-callback.S:112-114\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* at .*i386-thr-callback.S:44-45\r
+3 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* at .*i386-thr-callback.S:85-89\r
+4 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* at .*i386-thr-callback.S:40-43\r
+.*" "BTR listing for thread 3, 1.8"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> *0x\[a-f0-9\]* <mybarrier\\+3>:\[\[:blank:\]\]*mov.*" " BTR of 1 for thread 3, 1.9"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_b\\+13>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_b\\+18>:\[\[:blank:\]\]*call.*" " BTR of 2 for thread 3, 1.10"
+
+#switch to thread 4
+gdb_test_multiple "thread 4" "switching to thread 4" {
+ -re ".*Switching to thread 4.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 4, 1.11"
+ }
+ timeout {
+ fail "switching to thread 4 (timeout), 1.11"
+ }
+}
+
+#trace for thread 4
+gdb_test "btr list /lf" "
+1 *in mybarrier at.*i386-thr-callback.S:112-114\r
+2 *in th_c at.*i386-thr-callback.S:56-57\r
+3 *in call_C at.*i386-thr-callback.S:94-98\r
+4 *in th_c at.*i386-thr-callback.S:52-55\r
+.*" "BTR listing for thread 4, 1.12"
+
+gdb_test "btr /m 1" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> *0x\[a-f0-9\]* <mybarrier\\+3>:\[\[:blank:\]\]*mov.*" " BTR of 1 for thread 4, 1.13"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_c\\+13>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_c\\+18>:\[\[:blank:\]\]*call.*" " BTR of 2 for thread 4, 1.14"
+
+#switch to thread 5
+gdb_test_multiple "thread 5" "switching to thread 5" {
+ -re ".*Switching to thread 5.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 5, 1.15"
+ }
+ timeout {
+ fail "switching to thread 5 (timeout), 1.15"
+ }
+}
+
+#trace for thread 5
+gdb_test "btr list /fa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in mybarrier\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_d\r
+.*" "BTR listing for thread 5, 1.16"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> *0x\[a-f0-9\]* <mybarrier\\+3>:\[\[:blank:\]\]*mov.*" " BTR of 1 for thread 5, 1.17"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_d\\+13>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_d\\+18>:\[\[:blank:\]\]*call.*" " BTR of 2 for thread 5, 1.18"
+
+ gdb_test "btr +" "
+ *0x\[a-f0-9\]* <call_D\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <call_D\\+1>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <call_D\\+3>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <call_D\\+8>:\[\[:blank:\]\]*leave.*\r
+ *0x\[a-f0-9\]* <call_D\\+9>:\[\[:blank:\]\]*ret.*\r" " BTR of 3 for thread 5, 1.19"
+
+} else {
+ note "Platform not supported"
+ untested allthreads_trace.exp
+}
diff --git a/gdb/testsuite/gdb.btrace/amd64-thr-callback.S b/gdb/testsuite/gdb.btrace/amd64-thr-callback.S
new file mode 100755
index 0000000..871f76d
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/amd64-thr-callback.S
@@ -0,0 +1,116 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@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/>.
+#
+#
+###############
+# threads.c calls th_a(), th_b(),th_c() and th_d() as callback methods
+# for 4 threads being created.
+###############
+
+
+ .globl th_a
+ .type th_a, @function
+th_a:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ call call_A
+ movl $0, %eax
+ call mybarrier
+ leave
+ ret
+
+ .globl th_b
+ .type th_b @function
+th_b:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ call call_B
+ movl $0, %eax
+ call mybarrier
+ leave
+ ret
+
+ .globl th_c
+ .type th_c @function
+th_c:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ call call_C
+ movl $0, %eax
+ call mybarrier
+ leave
+ ret
+
+ .globl th_d
+ .type th_d @function
+th_d:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ call call_D
+ movl $0, %eax
+ call mybarrier
+ leave
+ ret
+
+ .globl call_A
+ .type call_A, @function
+call_A:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ leave
+ ret
+
+ .globl call_B
+ .type call_B @function
+call_B:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ leave
+ ret
+
+ .globl call_C
+ .type call_C @function
+call_C:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ leave
+ ret
+
+ .globl call_D
+ .type call_D @function
+call_D:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ leave
+ ret
+
+ .globl mybarrier
+ .type mybarrier @function
+mybarrier:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ leave
+ ret
diff --git a/gdb/testsuite/gdb.btrace/b.S b/gdb/testsuite/gdb.btrace/b.S
new file mode 100755
index 0000000..09d376d
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/b.S
@@ -0,0 +1,23 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@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/>.
+
+ .text
+ .globl callB
+ .type callB, @function
+callB:
+ nop
+ ret
diff --git a/gdb/testsuite/gdb.btrace/decrement.S b/gdb/testsuite/gdb.btrace/decrement.S
new file mode 100755
index 0000000..38bb254
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/decrement.S
@@ -0,0 +1,32 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@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/>.
+#
+#Decrements the number 5 by 1 untill it is 0. The
+ .text
+ .globl _start
+_start:
+ .align 0x10 # 0x400010
+ movl $5, %eax
+ .align 0x10 # 0x400010
+ movl $1, %ebx
+ call L1
+
+L1: cmpl $0, %eax #compare 0 with value in eax
+ je L2 #jump to L2 if 0==eax (je - jump if equal)
+ decl %eax #decrement eax
+ jmp L1 # unconditional jump to L1
+L2: ret
diff --git a/gdb/testsuite/gdb.btrace/decrement.exp b/gdb/testsuite/gdb.btrace/decrement.exp
new file mode 100755
index 0000000..45e4ee1
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/decrement.exp
@@ -0,0 +1,141 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@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/>.
+
+
+###############
+#Test Purpose: Fix a location while linking, where teh debuggee will be loaded and then
+# see that trace gives the correct addresses.
+# Source file: decrement.s
+###############
+
+load_lib btrace.exp
+
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+set srcfile ${srcdir}/${subdir}/decrement.S
+set objfile ${objdir}/${subdir}/decrement.o
+set binfile ${objdir}/${subdir}/decrement.x
+set options "{debug}"
+#compile
+if {[target_assemble ${srcfile} ${objfile} ""] != ""} { return "" }
+#link
+if {[target_link ${objfile} ${binfile} " -Ttext 0x400400 "] != ""} {
+ untested decrement.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+if ![runto L1] then {
+ fail "Can't run to test L1"
+ return 0
+}
+
+#Enable tracing
+gdb_test_no_output "btr enable"
+
+gdb_continue_to_breakpoint "L1"
+
+gdb_test "btr list /lfa" "
+1 *0x0*40041a - 0x0*40041a in L1" "list L1, 1.1"
+
+gdb_continue_to_breakpoint "L1"
+
+if {[istarget "x86_64-*-*"]} {
+#We enter the loop for 5 times from here.
+gdb_test "btr list /lfa" "
+1 *0x0*40041a - 0x0*40041a in L1\r
+2 *0x0*40041a - 0x0*400421 in L1" "list L1 again , 1.2"
+} elseif {[istarget "i?86-*-*"]} {
+#We enter the loop for 5 times from here.
+gdb_test "btr list /lfa" "
+1 *0x0*40041a - 0x0*40041a in L1\r
+2 *0x0*40041a - 0x0*400420 in L1" "list L1 again, 1.2"
+}
+
+#Delete all Breakpoints
+delete_breakpoints
+
+#Set a Breakpoint at L2
+gdb_breakpoint "L2"
+
+#Continue to L2
+gdb_continue_to_breakpoint "L2"
+
+if {[istarget "x86_64-*-*"]} {
+# BTR listing in method L2, when the loop exits
+gdb_test "btr list /lfa" "
+1 *0x0*400423 - 0x0*400423 in L2\r
+2 *0x0*40041a - 0x0*40041d in L1\r
+3 *0x0*40041a - 0x0*400421 in L1\r
+4 *0x0*40041a - 0x0*400421 in L1\r
+5 *0x0*40041a - 0x0*400421 in L1\r
+6 *0x0*40041a - 0x0*400421 in L1\r" "BTR listing at L2, 1.3"
+
+# Exit the loop
+gdb_test "btr /m 1" "
+=> 0x0*400423 *<L2\\+0>:\[\[:blank:\]\]*ret.*\r" "BTR at block 1, 1.4"
+
+# Comparison, if we are exiting the loop
+gdb_test "btr /m 2" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 *<L2>" "BTR at block 2, 1.5"
+
+#in the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400421 *<L1\\+7>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at block 3, 1.6"
+
+} elseif {[istarget "i?86-*-*"]} {
+# BTR listing in method L2, when the loop exits
+gdb_test "btr list /lfa" "
+1 *0x0*400422 - 0x0*400422 in L2\r
+2 *0x0*40041a - 0x0*40041d in L1\r
+3 *0x0*40041a - 0x0*400420 in L1\r
+4 *0x0*40041a - 0x0*400420 in L1\r
+5 *0x0*40041a - 0x0*400420 in L1\r
+6 *0x0*40041a - 0x0*400420 in L1\r" "BTR listing at L2, 1.3"
+
+# Exit the loop
+gdb_test "btr /m 1" "
+=> 0x0*400422 *<L2\\+0>:\[\[:blank:\]\]*ret.*\r" "BTR at block 1, 1.4"
+
+# Comparison, if we are exiting the loop
+gdb_test "btr /m 2" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 *<L2>" "BTR at block 2, 1.5"
+
+#in the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400420 *<L1\\+6>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at block 3, 1.6"
+
+} else {
+ warning "host platform not supported "
+ return -1
+}
+
diff --git a/gdb/testsuite/gdb.btrace/disable_all.exp b/gdb/testsuite/gdb.btrace/disable_all.exp
new file mode 100755
index 0000000..48eb07d
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/disable_all.exp
@@ -0,0 +1,279 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@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/>.
+
+###############
+#Test Purpose: In GDB non-stop mode, Enable trace for all the threads by "btr enable auto" on primary thread and check the trace availability for all the threads
+# Sourcefiles : threads_asm.c, i386-thr-callback.S, amd64-thr-callback.S
+# Compiled using '-g -lpthread' option.
+#executed on 32 bit as
+# make check RUNTESTFLAGS="GDB=/users/bahuja/work_gdb/gdb_32/gdb --host i686-linux-gnu --target i686-linux-gnu gdb.trace/thread_auto.exp"
+#executed on 64 bit as :
+# make check RUNTESTFLAGS="GDB=/users/bahuja/work_gdb/gdb_32/gdb --host x86_64-linux-gnu --target x86_64-linux-gnu gdb.trace/thread_auto.exp"
+###############
+
+load_lib btrace.exp
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+# the tests do currently not work with gdbserver
+if [is_remote target] {
+ untested "disable_all.exp"
+ return -1
+}
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/threads_asm.c
+set objcallback ${objdir}/${subdir}/thr_callback.o
+set objmain ${objdir}/${subdir}/threads_asm.o
+set binfile ${objdir}/${subdir}/disable_all.x
+set options "{debug}"
+
+if { ![support_displaced_stepping] } {
+ unsupported "displaced stepping"
+ return -1
+}
+
+#Load different callback files for 32 and 64 bit.
+# 32 bit platform
+if {[istarget "i?86-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/i386-thr-callback.S
+} elseif {[istarget "x86_64-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/amd64-thr-callback.S
+} else {
+ warning "host platform not supported "
+ untested disable_all.exp
+ return -1
+}
+set objfiles "${objmain} ${objcallback}"
+
+#compile
+if {[gdb_compile_pthreads ${srcfilemain} ${objmain} "object" ${options}] != ""} {
+ untested disable_all.exp
+ return -1
+}
+if {[gdb_compile ${srccallback} ${objcallback} "object" ${options}] != ""} {
+ untested disable_all.exp
+ return -1
+}
+
+if {[gdb_compile_pthreads ${objfiles} ${binfile} "executable" ${options}] != ""} {
+ untested disable_all.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+gdb_test_no_output "set pagination off"
+gdb_test_no_output "set target-async 1"
+gdb_test_no_output "set non-stop 1"
+
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+# set breakpoint at line 67, at call to mybarrier() for primary thread.
+gdb_breakpoint "67" "Breakpoint 2 at.*: file.*threads_asm.c, line 67." " breakpoint at line 67, 1.1"
+
+# set a breakpoint at mybarrier() to halt all the new threads from exiting.
+gdb_breakpoint "mybarrier" "Breakpoint 3, mybarrier \\(\\) at .*thr-callback.S:114" "Breakpoint at my barrier for all the threads to stop, 1.2"
+
+gdb_breakpoint "${srccallback}:35" "Breakpoint 4 at 0x\[a-f0-9\]*: file .*thr-callback.S, line 35." "Breakpoint after the barrier for thread 2, 1.3"
+
+gdb_breakpoint "${srccallback}:47" "Breakpoint 5 at 0x\[a-f0-9\]*: file .*thr-callback.S, line 47." "Breakpoint after the barrier for thread 3, 1.4"
+gdb_breakpoint "${srccallback}:59" "Breakpoint 6 at 0x\[a-f0-9\]*: file .*thr-callback.S, line 59." "Breakpoint after the barrier for thread 4, 1.5"
+gdb_breakpoint "${srccallback}:71" "Breakpoint 7 at 0x\[a-f0-9\]*: file .*thr-callback.S, line 71." "Breakpoint after the barrier for thread 5, 1.6"
+
+# enable trace in primary thread, which automatically enables trace in all new threads crated.
+gdb_test "btr enable auto"
+
+set test "continue running..."
+gdb_test_multiple "continue" $test {
+ -re "Breakpoint 3, mybarrier \\(\\) at.*thr-callback.S:114.*"
+ {
+ pass "continuing"
+ }
+ timeout {fail "(timeout) continue into program"}
+}
+# this is added to get the prompt, which is missing.
+gdb_test "" ""
+
+# This "info threads" is needed to get a $gdb_prompt, since gdb seems to get hanged at this particular location.
+set test "info for threads"
+gdb_test_multiple "info threads" $test {
+ -re ".*\n" {
+ pass $test
+ }
+}
+
+# this is added to get the prompt, which is missing.
+gdb_test "" ""
+
+# Enable btrace on all threads
+gdb_test "btr disable all"
+
+# We need to do a seperate listing from here, since the instr length is different
+# on different platforms.
+# switch to thread 2
+gdb_test_multiple "thread 2" "switching to thread 2" {
+ -re ".*Switching to thread 2.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 2, 1.7"
+ }
+ timeout {
+ fail "switching to thread 2 (timeout), 1.7"
+ }
+}
+
+# 64 bit platform
+if {[istarget "x86_64-*-*"]} {
+
+# trace for thread 2
+gdb_test "continue" ".*
+Breakpoint 4, th_a \\(\\) at .*thr-callback.S:35.*" "BTR listing for thread 2, 1.8"
+
+gdb_test "btr" "
+No trace." " BTR of thread 2, 1.9"
+
+# trace for thread 3
+# switch to thread 3
+gdb_test_multiple "thread 3" "switching to thread 3" {
+ -re ".*Switching to thread 3.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 3, 1.10"
+ }
+ timeout {
+ fail "switching to thread 3 (timeout), 1.10"
+ }
+}
+
+
+gdb_test "continue" ".*
+Breakpoint 5, th_b \\(\\) at .*thr-callback.S:47.*" "BTR listing for thread 3, 1.11"
+
+gdb_test "btr" "
+No trace." " BTR of thread 3, 1.12"
+
+# trace for thread 4
+#gdb_test "thread 4" ".*Switching to thread 4.*mybarrier.*" " switch to thread 4, 1.13"
+#switch to thread 4
+gdb_test_multiple "thread 4" "switching to thread 4" {
+ -re ".*Switching to thread 4.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 4, 1.13"
+ }
+ timeout {
+ fail "switching to thread 4 (timeout), 1.13"
+ }
+}
+
+
+gdb_test "continue" ".*
+Breakpoint 6, th_c \\(\\) at .*thr-callback.S:59.*" "BTR listing for thread 4, 1.14"
+
+gdb_test "btr" "
+No trace." " BTR of thread 4, 1.15"
+
+# trace for thread 5
+# switch to thread 5
+gdb_test_multiple "thread 5" "switching to thread 5" {
+ -re ".*Switching to thread 5.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 5, 1.16"
+ }
+ timeout {
+ fail "switching to thread 5 (timeout), 1.16"
+ }
+}
+
+
+gdb_test "continue" ".*
+Breakpoint 7, th_d \\(\\) at .*thr-callback.S:71.*" "BTR listing for thread 5, 1.17"
+
+gdb_test "btr" "
+No trace." " BTR of thread 5, 1.18"
+
+} elseif {[istarget "i?86-*-*"]} {
+# 32 bit platform
+
+# trace for thread 2
+gdb_test "continue" ".*
+Breakpoint 4, th_a \\(\\) at .*thr-callback.S:35.*" "BTR listing for thread 2, 1.8"
+
+gdb_test "btr" "
+No trace." " BTR of thread 2, 1.9"
+
+# trace for thread 3
+# switch to thread 3
+gdb_test_multiple "thread 3" "switching to thread 3" {
+ -re ".*Switching to thread 3.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 3, 1.10"
+ }
+ timeout {
+ fail "switching to thread 3 (timeout), 1.10"
+ }
+}
+
+
+gdb_test "continue" ".*
+Breakpoint 5, th_b \\(\\) at .*thr-callback.S:47.*" "BTR listing for thread 3, 1.11"
+
+gdb_test "btr" "
+No trace." " BTR of thread 3, 1.12"
+
+# trace for thread 4
+# switch to thread 4
+gdb_test_multiple "thread 4" "switching to thread 4" {
+ -re ".*Switching to thread 4.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 4, 1.13"
+ }
+ timeout {
+ fail "switching to thread 4 (timeout), 1.13"
+ }
+}
+
+
+gdb_test "continue" ".*
+Breakpoint 6, th_c \\(\\) at .*thr-callback.S:59.*" "BTR listing for thread 4, 1.14"
+
+gdb_test "btr" "
+No trace." " BTR of thread 4, 1.15"
+
+# trace for thread 5
+# switch to thread 5
+gdb_test_multiple "thread 5" "switching to thread 5" {
+ -re ".*Switching to thread 5.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 5, 1.16"
+ }
+ timeout {
+ fail "switching to thread 5 (timeout), 1.16"
+ }
+}
+
+
+gdb_test "continue" ".*
+Breakpoint 7, th_d \\(\\) at .*thr-callback.S:71.*" "BTR listing for thread 5, 1.17"
+
+gdb_test "btr" "
+No trace." " BTR of thread 5, 1.18"
+
+} else {
+ note "Platform not supported"
+}
diff --git a/gdb/testsuite/gdb.btrace/enable_all.exp b/gdb/testsuite/gdb.btrace/enable_all.exp
new file mode 100755
index 0000000..53a28ed
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/enable_all.exp
@@ -0,0 +1,282 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@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/>.
+
+###############
+#Test Purpose: In GDB non-stop mode, Enable trace for all the threads by "btr enable auto" on primary thread and check the trace availability for all the threads
+# Sourcefiles : threads_asm.c, i386-thr-callback.S, amd64-thr-callback.S
+# Compiled using '-g -lpthread' option.
+#executed on 32 bit as :
+# make check RUNTESTFLAGS="GDB=<path to gdb> gdb.trace/enable_all.exp"
+###############
+
+load_lib btrace.exp
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+# the tests do currently not work with gdbserver
+if [is_remote target] {
+ untested "enable_all.exp"
+ return -1
+}
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/threads_asm.c
+set objcallback ${objdir}/${subdir}/thr_callback.o
+set objmain ${objdir}/${subdir}/threads_asm.o
+set binfile ${objdir}/${subdir}/enable_all.x
+set options "{debug}"
+
+if { ![support_displaced_stepping] } {
+ unsupported "displaced stepping"
+ return -1
+}
+
+#Load different callback files for 32 and 64 bit.
+# 32 bit platform
+if {[istarget "i?86-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/i386-thr-callback.S
+} elseif {[istarget "x86_64-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/amd64-thr-callback.S
+} else {
+ warning "host platform not supported "
+ untested enable_all.exp
+ return -1
+}
+set objfiles "${objmain} ${objcallback}"
+
+#compile
+if {[gdb_compile_pthreads ${srcfilemain} ${objmain} "object" ${options}] != ""} {
+ untested enable_all.exp
+ return -1
+}
+if {[gdb_compile ${srccallback} ${objcallback} "object" ${options}] != ""} {
+ untested enable_all.exp
+ return -1
+}
+
+if {[gdb_compile_pthreads ${objfiles} ${binfile} "executable" ${options}] != ""} {
+ untested enable_all.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+gdb_test_no_output "set pagination off"
+gdb_test_no_output "set target-async 1"
+gdb_test_no_output "set non-stop 1"
+
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+# set breakpoint at line 67, at call to mybarrier() for primary thread.
+gdb_breakpoint "67" "Breakpoint 2 at.*: file.*threads_asm.c, line 67." " breakpoint at line 67, 1.1"
+
+# set a breakpoint at mybarrier() to halt all the new threads from exiting.
+gdb_breakpoint "mybarrier" "Breakpoint 3, mybarrier \\(\\) at .*-thr-callback.S:114" "Breakpoint at my barrier for all the threads to stop, 1.2"
+
+gdb_breakpoint "${srccallback}:35" "Breakpoint 4 at 0x\[a-f0-9\]*: file .*-thr-callback.S, line 35." "Breakpoint after the barrier for thread 2, 1.3"
+
+gdb_breakpoint "${srccallback}:47" "Breakpoint 5 at 0x\[a-f0-9\]*: file .*-thr-callback.S, line 47." "Breakpoint after the barrier for thread 3, 1.4"
+gdb_breakpoint "${srccallback}:59" "Breakpoint 6 at 0x\[a-f0-9\]*: file .*-thr-callback.S, line 59." "Breakpoint after the barrier for thread 4, 1.5"
+gdb_breakpoint "${srccallback}:71" "Breakpoint 7 at 0x\[a-f0-9\]*: file .*-thr-callback.S, line 71." "Breakpoint after the barrier for thread 5, 1.6"
+
+# enable trace in primary thread, which automatically enables trace in all new threads crated.
+set test "continue running..."
+gdb_test_multiple "continue" $test {
+ -re "Breakpoint 3, mybarrier \\(\\) at.*-thr-callback.S:114.*"
+ {
+ pass "continuing"
+ }
+ timeout {fail "(timeout) continue into program"}
+}
+# this is added to get the prompt, which is missing.
+gdb_test "" ""
+
+# This "info threads" is needed to get a $gdb_prompt, since gdb seems to get hanged at this particular location.
+set test "info for threads"
+gdb_test_multiple "info threads" $test {
+ -re ".*\n$gdb_prompt $" {
+ pass $test
+ }
+}
+
+# this is added to get the prompt, which is missing.
+gdb_test "" ""
+
+# Enable btrace on all threads
+gdb_test "btr enable all"
+
+# We need to do a seperate listing from here, since the instr length is different
+# on different platforms.
+#switch to thread 2
+gdb_test_multiple "thread 2" "switching to thread 2" {
+ -re ".*Switching to thread 2.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 2, 1.7"
+ }
+ timeout {
+ fail "switching to thread 2 (timeout), 1.7"
+ }
+}
+
+# 64 bit platform
+if {[istarget "x86_64-*-*"]} {
+
+# trace for thread 2
+gdb_test "continue" ".*
+Breakpoint 4, th_a \\(\\) at .*-thr-callback.S:35.*" "BTR listing for thread 2, 1.8"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_a\\+24>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_a\\+25>:\[\[:blank:\]\]*ret.*" " BTR of thread 2, 1.9"
+
+# trace for thread 3
+# switch to thread 3
+gdb_test_multiple "thread 3" "switching to thread 3" {
+ -re ".*Switching to thread 3.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 3, 1.10"
+ }
+ timeout {
+ fail "switching to thread 3 (timeout), 1.10"
+ }
+}
+
+
+gdb_test "continue" ".*
+Breakpoint 5, th_b \\(\\) at .*-thr-callback.S:47.*" "BTR listing for thread 3, 1.11"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_b\\+24>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_b\\+25>:\[\[:blank:\]\]*ret.*" " BTR of thread 3, 1.12"
+
+# trace for thread 4
+# switch to thread 4
+gdb_test_multiple "thread 4" "switching to thread 4" {
+ -re ".*Switching to thread 4.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 4, 1.13"
+ }
+ timeout {
+ fail "switching to thread 4 (timeout), 1.13"
+ }
+}
+
+
+gdb_test "continue" ".*
+Breakpoint 6, th_c \\(\\) at .*-thr-callback.S:59.*" "BTR listing for thread 4, 1.14"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_c\\+24>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_c\\+25>:\[\[:blank:\]\]*ret.*" " BTR of thread 4, 1.15"
+
+# trace for thread 5
+# switch to thread 5
+gdb_test_multiple "thread 5" "switching to thread 5" {
+ -re ".*Switching to thread 5.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 5, 1.16"
+ }
+ timeout {
+ fail "switching to thread 5 (timeout), 1.16"
+ }
+}
+
+
+gdb_test "continue" ".*
+Breakpoint 7, th_d \\(\\) at .*-thr-callback.S:71.*" "BTR listing for thread 5, 1.17"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_d\\+24>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_d\\+25>:\[\[:blank:\]\]*ret.*" " BTR of thread 5, 1.18"
+
+} elseif {[istarget "i?86-*-*"]} {
+# 32 bit platform
+
+# trace for thread 2
+gdb_test "continue" ".*
+Breakpoint 4, th_a \\(\\) at .*-thr-callback.S:35.*" "BTR listing for thread 2, 1.8"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_a\\+23>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_a\\+24>:\[\[:blank:\]\]*ret.*" " BTR of thread 2, 1.9"
+
+# trace for thread 3
+# switch to thread 3
+gdb_test_multiple "thread 3" "switching to thread 3" {
+ -re ".*Switching to thread 3.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 3, 1.10"
+ }
+ timeout {
+ fail "switching to thread 3 (timeout), 1.10"
+ }
+}
+
+gdb_test "continue" ".*
+Breakpoint 5, th_b \\(\\) at .*-thr-callback.S:47.*" "BTR listing for thread 3, 1.11"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_b\\+23>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_b\\+24>:\[\[:blank:\]\]*ret.*" " BTR of thread 3, 1.12"
+
+# trace for thread 4
+# switch to thread 4
+gdb_test_multiple "thread 4" "switching to thread 4" {
+ -re ".*Switching to thread 4.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 4, 1.13"
+ }
+ timeout {
+ fail "switching to thread 4 (timeout), 1.13"
+ }
+}
+
+
+gdb_test "continue" ".*
+Breakpoint 6, th_c \\(\\) at .*-thr-callback.S:59.*" "BTR listing for thread 4, 1.14"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_c\\+23>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_c\\+24>:\[\[:blank:\]\]*ret.*" " BTR of thread 4, 1.15"
+
+# trace for thread 5
+# switch to thread 5
+gdb_test_multiple "thread 5" "switching to thread 5" {
+ -re ".*Switching to thread 5.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 5, 1.16"
+ }
+ timeout {
+ fail "switching to thread 5 (timeout), 1.16"
+ }
+}
+
+
+gdb_test "continue" ".*
+Breakpoint 7, th_d \\(\\) at .*-thr-callback.S:71.*" "BTR listing for thread 5, 1.17"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_d\\+23>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_d\\+24>:\[\[:blank:\]\]*ret.*" " BTR of thread 5, 1.18"
+
+} else {
+ note "Platform not supported"
+ untested enable_all.exp
+}
diff --git a/gdb/testsuite/gdb.btrace/enable_range.exp b/gdb/testsuite/gdb.btrace/enable_range.exp
new file mode 100755
index 0000000..ee21246
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/enable_range.exp
@@ -0,0 +1,281 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@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/>.
+
+###############
+#Test Purpose: In GDB non-stop mode, Enable trace for a range of threads on primary thread and check the trace availability for all the threads
+# Sourcefiles : threads_asm.c, i386-thr-callback.S, amd64-thr-callback.S
+# Compiled using '-g -lpthread' option.
+#executed on 32 bit as :
+# make check RUNTESTFLAGS="GDB=<path to gdb> gdb.trace/enable_range.exp"
+###############
+
+load_lib btrace.exp
+
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+# the tests do currently not work with gdbserver
+if [is_remote target] {
+ untested "enable_range.exp"
+ return -1
+}
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/threads_asm.c
+set objcallback ${objdir}/${subdir}/thr_callback.o
+set objmain ${objdir}/${subdir}/threads_asm.o
+set binfile ${objdir}/${subdir}/enable_range.x
+set options "{debug}"
+
+if { ![support_displaced_stepping] } {
+ unsupported "displaced stepping"
+ return -1
+}
+
+#Load different callback files for 32 and 64 bit.
+# 32 bit platform
+if {[istarget "i?86-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/i386-thr-callback.S
+} elseif {[istarget "x86_64-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/amd64-thr-callback.S
+} else {
+ warning "host platform not supported "
+ untested enable_range.exp
+ return -1
+}
+set objfiles "${objmain} ${objcallback}"
+
+#compile
+if {[gdb_compile_pthreads ${srcfilemain} ${objmain} "object" ${options}] != ""} {
+ untested enable_range.exp
+ return -1
+}
+if {[gdb_compile ${srccallback} ${objcallback} "object" ${options}] != ""} {
+ untested enable_range.exp
+ return -1
+}
+
+if {[gdb_compile_pthreads ${objfiles} ${binfile} "executable" ${options}] != ""} {
+ untested enable_range.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+gdb_test_no_output "set pagination off"
+gdb_test_no_output "set target-async 1"
+gdb_test_no_output "set non-stop 1"
+
+if ![runto main] {
+ fail "could not run to main."
+ return -1
+}
+
+# set breakpoint at line 67, at call to mybarrier() for primary thread.
+gdb_breakpoint "67" "Breakpoint 2 at.*: file.*threads_asm.c, line 67." " breakpoint at line 67, 1.1"
+
+# set a breakpoint at mybarrier() to halt all the new threads from exiting.
+gdb_breakpoint "mybarrier" "Breakpoint 3, mybarrier \\(\\) at .*thr-callback.S:114" "Breakpoint at my barrier for all the threads to stop, 1.2"
+
+gdb_breakpoint "${srccallback}:35" "Breakpoint 4 at 0x\[a-f0-9\]*: file .*thr-callback.S, line 35." "Breakpoint after the barrier for thread 2, 1.3"
+
+gdb_breakpoint "${srccallback}:47" "Breakpoint 5 at 0x\[a-f0-9\]*: file .*thr-callback.S, line 47." "Breakpoint after the barrier for thread 3, 1.4"
+gdb_breakpoint "${srccallback}:59" "Breakpoint 6 at 0x\[a-f0-9\]*: file .*thr-callback.S, line 59." "Breakpoint after the barrier for thread 4, 1.5"
+gdb_breakpoint "${srccallback}:71" "Breakpoint 7 at 0x\[a-f0-9\]*: file .*thr-callback.S, line 71." "Breakpoint after the barrier for thread 5, 1.6"
+
+set test "continue running..."
+gdb_test_multiple "continue" $test {
+ -re "Breakpoint 3, mybarrier \\(\\) at.*thr-callback.S:114.*"
+ {
+ pass $test
+ }
+ timeout {fail "(timeout) continue into program"}
+ }
+# this is added to get the prompt, which is missing.
+gdb_test "" ""
+
+# This "info threads" is needed to get a $gdb_prompt, since gdb seems to get hanged at this particular location.
+set test "info for threads"
+gdb_test_multiple "info threads" $test {
+ -re ".*\n$gdb_prompt $" {
+ pass $test
+ }
+}
+
+# this is added to get the prompt, which is missing.
+gdb_test "" ""
+
+# Enable btrace on all threads
+gdb_test "btr enable 2-3"
+
+# We need to do a seperate listing from here, since the instr length is different
+# on different platforms.
+#switch to thread 2
+gdb_test_multiple "thread 2" "switching to thread 2" {
+ -re ".*Switching to thread 2.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 2, 1.7"
+ }
+ timeout {
+ fail "switching to thread 2 (timeout), 1.7"
+ }
+}
+
+# 64 bit platform
+if {[istarget "x86_64-*-*"]} {
+
+
+# trace for thread 2
+gdb_test "continue" ".*
+Breakpoint 4, th_a \\(\\) at .*thr-callback.S:35.*" "BTR listing for thread 2, 1.8"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_a\\+24>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_a\\+25>:\[\[:blank:\]\]*ret.*" " BTR of thread 2, 1.9"
+
+# trace for thread 3
+#switch to thread 3
+gdb_test_multiple "thread 3" "switching to thread 3" {
+ -re ".*Switching to thread 3.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 3, 1.10"
+ }
+ timeout {
+ fail "switching to thread 3 (timeout), 1.10"
+ }
+}
+
+
+gdb_test "continue" ".*
+Breakpoint 5, th_b \\(\\) at .*thr-callback.S:47.*" "BTR listing for thread 3, 1.11"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_b\\+24>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_b\\+25>:\[\[:blank:\]\]*ret.*" " BTR of thread 3, 1.12"
+
+# trace for thread 4
+#switch to thread 4
+gdb_test_multiple "thread 4" "switching to thread 4" {
+ -re ".*Switching to thread 4.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 4, 1.13"
+ }
+ timeout {
+ fail "switching to thread 4 (timeout), 1.13"
+ }
+}
+
+
+gdb_test "continue" ".*
+Breakpoint 6, th_c \\(\\) at .*thr-callback.S:59.*" "BTR listing for thread 4, 1.14"
+
+gdb_test "btr" "
+No trace." " BTR of thread 4, 1.15"
+
+# trace for thread 5
+#switch to thread 5
+gdb_test_multiple "thread 5" "switching to thread 5" {
+ -re ".*Switching to thread 5.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 5, 1.16"
+ }
+ timeout {
+ fail "switching to thread 5 (timeout), 1.16"
+ }
+}
+
+
+gdb_test "continue" ".*
+Breakpoint 7, th_d \\(\\) at .*thr-callback.S:71.*" "BTR listing for thread 5, 1.17"
+
+gdb_test "btr" "
+No trace." " BTR of thread 5, 1.18"
+
+} elseif {[istarget "i?86-*-*"]} {
+# 32 bit platform
+
+# trace for thread 2
+gdb_test "continue" ".*
+Breakpoint 4, th_a \\(\\) at .*thr-callback.S:35.*" "BTR listing for thread 2, 1.8"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_a\\+23>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_a\\+24>:\[\[:blank:\]\]*ret.*" " BTR of thread 2, 1.9"
+
+# trace for thread 3
+#switch to thread 3
+gdb_test_multiple "thread 3" "switching to thread 3" {
+ -re ".*Switching to thread 3.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 3, 1.10"
+ }
+ timeout {
+ fail "switching to thread 3 (timeout), 1.10"
+ }
+}
+
+
+gdb_test "continue" ".*
+Breakpoint 5, th_b \\(\\) at .*thr-callback.S:47.*" "BTR listing for thread 3, 1.11"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_b\\+23>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_b\\+24>:\[\[:blank:\]\]*ret.*" " BTR of thread 3, 1.12"
+
+# trace for thread 4
+#switch to thread 4
+gdb_test_multiple "thread 4" "switching to thread 4" {
+ -re ".*Switching to thread 4.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 4, 1.13"
+ }
+ timeout {
+ fail "switching to thread 4 (timeout), 1.13"
+ }
+}
+
+
+gdb_test "continue" ".*
+Breakpoint 6, th_c \\(\\) at .*thr-callback.S:59.*" "BTR listing for thread 4, 1.14"
+
+gdb_test "btr" "
+No trace." " BTR of thread 4, 1.15"
+
+# trace for thread 5
+#switch to thread 5
+gdb_test_multiple "thread 5" "switching to thread 5" {
+ -re ".*Switching to thread 5.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 5, 1.16"
+ }
+ timeout {
+ fail "switching to thread 5 (timeout), 1.16"
+ }
+}
+
+
+gdb_test "continue" ".*
+Breakpoint 7, th_d \\(\\) at .*thr-callback.S:71.*" "BTR listing for thread 5, 1.17"
+
+gdb_test "btr" "
+No trace." " BTR of thread 5, 1.18"
+
+} else {
+ note "Platform not supported"
+ untested enable_range.exp
+}
diff --git a/gdb/testsuite/gdb.btrace/i386-thr-callback.S b/gdb/testsuite/gdb.btrace/i386-thr-callback.S
new file mode 100755
index 0000000..0356aa4
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/i386-thr-callback.S
@@ -0,0 +1,116 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@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/>.
+#
+#
+###############
+# threads.c calls th_a(), th_b(),th_c() and th_d() as callback methods
+# for 4 threads being created.
+###############
+
+
+ .globl th_a
+ .type th_a, @function
+th_a:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ call call_A
+ movl $0, %eax
+ call mybarrier
+ leave
+ ret
+
+ .globl th_b
+ .type th_b @function
+th_b:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ call call_B
+ movl $0, %eax
+ call mybarrier
+ leave
+ ret
+
+ .globl th_c
+ .type th_c @function
+th_c:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ call call_C
+ movl $0, %eax
+ call mybarrier
+ leave
+ ret
+
+ .globl th_d
+ .type th_d @function
+th_d:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ call call_D
+ movl $0, %eax
+ call mybarrier
+ leave
+ ret
+
+ .globl call_A
+ .type call_A, @function
+call_A:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ leave
+ ret
+
+ .globl call_B
+ .type call_B @function
+call_B:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ leave
+ ret
+
+ .globl call_C
+ .type call_C @function
+call_C:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ leave
+ ret
+
+ .globl call_D
+ .type call_D @function
+call_D:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ leave
+ ret
+
+ .globl mybarrier
+ .type mybarrier @function
+mybarrier:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ leave
+ ret
diff --git a/gdb/testsuite/gdb.btrace/list_options.exp b/gdb/testsuite/gdb.btrace/list_options.exp
new file mode 100755
index 0000000..3faf347
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/list_options.exp
@@ -0,0 +1,107 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@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/>.
+
+
+###############
+#Test Purpose: Testing the other options of btrace list like /t, /af
+#Also tests the other commands like giving a range to btr list "btr list n1-n2"
+# Sourcefiles : main.S, a.S, b.S
+# Compiled using '-g' option.
+###############
+
+load_lib btrace.exp
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+set testfile "main"
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/main.S
+set srcfilea ${srcdir}/${subdir}/a.S
+set srcfileb ${srcdir}/${subdir}/b.S
+set objfilemain ${objdir}/${subdir}/main_asm.o
+set objfilea ${objdir}/${subdir}/a.o
+set objfileb ${objdir}/${subdir}/b.o
+set binfile ${objdir}/${subdir}/list_options.x
+set options " -g "
+#compile
+if {[target_assemble ${srcfilemain} ${objfilemain} ${options}] != ""} { return "" }
+if {[target_assemble ${srcfilea} ${objfilea} ${options}]!= ""} { return "" }
+if {[target_assemble ${srcfileb} ${objfileb} ${options}]!= ""} { return "" }
+
+set objfiles "${objfilemain} ${objfilea} ${objfileb}"
+#link
+if {[target_link ${objfiles} ${binfile} " "] != ""} {
+ untested list_options.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+if ![runto main] { return -1 }
+
+gdb_breakpoint "35" "Breakpoint 3 at .*:.*main\.S, line 35\." "Breakpoint at line 35, 1.2"
+
+# Enable branch trace to trace the startup.
+gdb_test_no_output "btr enable"
+
+gdb_test "c" "Continuing.*Breakpoint.*main\.S:35.*" "continue to end, 1.3"
+
+gdb_test "btr list /t" "total: 4" "total number of btrace blocks, 1.4"
+
+#Get the trace listing after it returns from callB
+gdb_test "btr list /af" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in main\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in callB\r
+3 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in main\r
+4 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in callA\r" "Listing at return, 1.5"
+
+#Get the trace listing for only 1-3
+gdb_test "btr list /lf 1-3" "
+1 *in main at .*main\\.S:34-35\r
+2 *in callB at .*b\.S:22-23\r
+3 *in main at .*main\\.S:32-33\r" "Listing at return, 1.6"
+
+#Get the trace listing for only 2-3
+gdb_test "btr list /lf 2-4" "
+2 *in callB at .*b\.S:22-23\r
+3 *in main at .*main\.S:32-33\r
+4 *in callA at .*a\.S:22-23\r" "Listing at return, 1.7"
+
+gdb_test "btrace /m 3" "
+.*main\.S:32\[\[:blank:\]\]*movl *.0, %eax\r
+ *0x\[a-f0-9\]* <main\\+10>:\[\[:blank:\]\]*mov *.0x0,%eax\r
+\r
+.*main\.S:33\[\[:blank:\]\]*call\[\[:blank:\]\]*callB\r
+ *0x\[a-f0-9\]* <main\\+15>:\[\[:blank:\]\]*call. *0x\[a-f0-9\]* *<callB>" "btrace for 1 to 3, 1.8"
+
+gdb_test "btrace /r 3" "
+ *0x\[a-f0-9\]* <main\\+10>:.*mov *.0x0,%eax\r
+ *0x\[a-f0-9\]* <main\\+15>:.*call. *0x\[a-f0-9\]* <callB>" "btrace with /r options at 3, 1.9"
+
+
+gdb_test "btrace /r -" "
+ *0x\[a-f0-9\]* <callB\\+0>:\[\[:blank:\]\]*90\[\[:blank:\]\]*nop *\r
+ *0x\[a-f0-9\]* <callB\\+1>:\[\[:blank:\]\]*c3\[\[:blank:\]\]*ret. *" " btrace with /r option at 2, 1.10"
diff --git a/gdb/testsuite/gdb.btrace/main.S b/gdb/testsuite/gdb.btrace/main.S
new file mode 100755
index 0000000..916a7f6
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/main.S
@@ -0,0 +1,36 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@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/>.
+###################
+# main.s, uses a.s and b.s
+###################
+
+ .text
+ .globl _start
+ .globl _main
+ .type _start, @function
+ .type _main, @function
+_start:
+ call main
+ hlt
+main:
+ movl $0, %eax
+ call callA
+ movl $0, %eax
+ call callB
+ movl $0, %eax
+ leave
+ ret
diff --git a/gdb/testsuite/gdb.btrace/main_asm.exp b/gdb/testsuite/gdb.btrace/main_asm.exp
new file mode 100755
index 0000000..9d79a73
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/main_asm.exp
@@ -0,0 +1,109 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@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/>.
+
+
+###############
+#Test Purpose: The trace works when we step into multiple source files in '.s' format
+# Sourcefiles : main.s, a.s, b.s
+# Compiled using '-g' option.
+###############
+
+load_lib btrace.exp
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+set testfile "main"
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/main.S
+set srcfilea ${srcdir}/${subdir}/a.S
+set srcfileb ${srcdir}/${subdir}/b.S
+set objfilemain ${objdir}/${subdir}/main_asm.o
+set objfilea ${objdir}/${subdir}/a.o
+set objfileb ${objdir}/${subdir}/b.o
+set binfile ${objdir}/${subdir}/main_asm.x
+set options " -g "
+#compile
+if {[target_assemble ${srcfilemain} ${objfilemain} ${options}] != ""} { return "" }
+if {[target_assemble ${srcfilea} ${objfilea} ${options}]!= ""} { return "" }
+if {[target_assemble ${srcfileb} ${objfileb} ${options}]!= ""} { return "" }
+
+set objfiles "${objfilemain} ${objfilea} ${objfileb}"
+#link
+if {[target_link ${objfiles} ${binfile} " "] != ""} {
+ untested main_asm.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+if ![runto_main] {
+ return -1
+}
+
+# Set the breakpoints we'll need later on.
+gdb_breakpoint "33" "Breakpoint \[0-9\]+ at .*:.*main.S, line 33." "Breakpoint at line 33, 1.1"
+gdb_breakpoint "34" "Breakpoint \[0-9\]+ at .*:.*main.S, line 34." "Breakpoint at line 34, 1.2"
+
+# Enable branch trace to trace the startup.
+gdb_test_no_output "btr enable"
+
+# run to callB
+gdb_test "c" ".*Breakpoint \[0-9\]+, main .* at.*main.S:33\r
+33.*call.*callB" "Run to Breakpoint at line 33, 1.3"
+
+#get BTR listing in CallB
+gdb_test "btr list /f" "
+1 * in main\r
+2 * in callA\r" "BTR listing at line 28, 1.4"
+
+#return to main
+gdb_test "c" ".*Breakpoint \[0-9\]+, main .* at.*main.S:34\r
+34.*movl.*" "Run to Breakpoint at line 30, 1.5"
+
+# we do get trace for main, callB, main, callA here
+gdb_test "btr list /f" "
+1 *in main\r
+2 *in callB\r
+3 *in main\r
+4 *in callA\r" "BTR listing at line 30, 1.6"
+
+
+gdb_test "btr /m 1" "
+.*main.S:34\[\[:blank:\]\]*movl *.0, %eax\r
+=> *0x\[a-f0-9\]* <main\\+20>:\[\[:blank:\]\]*mov *.0x0,%eax" "BTR of 1, 1.7"
+
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <callB\\+0>:\[\[:blank:\]\]*nop\r
+ *0x\[a-f0-9\]* <callB\\+1>:\[\[:blank:\]\]*ret.*" "BTR of 2, 1.8"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <main\\+10>:\[\[:blank:\]\]*mov *.0x0,%eax\r
+ *0x\[a-f0-9\]* <main\\+15>:\[\[:blank:\]\]*call.*<callB>." "BTR of 3, 1.9"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <callA\\+0>:\[\[:blank:\]\]*nop\r
+ *0x\[a-f0-9\]* <callA\\+1>:\[\[:blank:\]\]*ret.*" "BTR of 4, 1.10"
diff --git a/gdb/testsuite/gdb.btrace/main_segv.S b/gdb/testsuite/gdb.btrace/main_segv.S
new file mode 100755
index 0000000..1d3df2e
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/main_segv.S
@@ -0,0 +1,32 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@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/>.
+###################
+# main.s, uses callB from b.s
+###################
+
+ .text
+ .globl _start
+ .type _start, @function
+ .type _main, @function
+_start:
+ call main
+ hlt
+main:
+ call callB
+ movl $0, %eax
+ leave
+ ret
diff --git a/gdb/testsuite/gdb.btrace/main_segv.exp b/gdb/testsuite/gdb.btrace/main_segv.exp
new file mode 100755
index 0000000..be15a69
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/main_segv.exp
@@ -0,0 +1,84 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@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/>.
+
+
+###############
+#Test Purpose: The trace shows up when the debugge crashes with SIGSEGV
+# Sourcefiles : main_segv.S, b.s,
+# Compiled using '-g' option.
+###############
+
+load_lib btrace.exp
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+set testfile "main"
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/main_segv.S
+set srcfileb ${srcdir}/${subdir}/b.S
+set objfilemain ${objdir}/${subdir}/main_segv.o
+set objfileb ${objdir}/${subdir}/b.o
+set binfile ${objdir}/${subdir}/main_segv.x
+set options " -g "
+#compile
+if {[target_assemble ${srcfilemain} ${objfilemain} ${options}] != ""} { return "" }
+if {[target_assemble ${srcfileb} ${objfileb} ${options}]!= ""} { return "" }
+
+set objfiles "${objfilemain} ${objfileb}"
+#link
+if {[target_link ${objfiles} ${binfile} " "] != ""} { return "" }
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+if ![runto_main] {
+ return -1
+}
+
+# Enable branch trace to trace the startup.
+gdb_test_no_output "btr enable"
+
+gdb_test "stepi" ".*22.*" "Stepping into callB, 1.1"
+
+gdb_test "btr list /lfa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in callB at .*b.S.*" "BTR listing in b.S, 1.2"
+
+#check that we got SEGV
+gdb_test "c" ".*Program received signal SIGSEGV, Segmentation fault.\r
+main.*at.*main_segv.S:31.*" "Program received SEGV at line 31, 1.3"
+
+#Check that we do get trace after SEGV too.
+gdb_test "btr list /a" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]*\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]*" "BTR of 1, 1.4"
+
+#Check where we got SEGV
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <main\\+5>:\[\[:blank:\]\]*mov *.0x0,%eax\r
+=> 0x\[a-f0-9\]* <main\\+10>:\[\[:blank:\]\]*leave.*" "BTR of 2, 1.5"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <callB\\+0>:\[\[:blank:\]\]*nop\r
+ *0x\[a-f0-9\]* <callB\\+1>:\[\[:blank:\]\]*ret.*" "BTR of 3, 1.6"
diff --git a/gdb/testsuite/gdb.btrace/threads.c b/gdb/testsuite/gdb.btrace/threads.c
new file mode 100755
index 0000000..9c49563
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/threads.c
@@ -0,0 +1,96 @@
+/*
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@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/>.
+
+
+###############
+#This program spawns 4 threads and each thread has a seperate callback function and
+# a diffierent function call from callback function.
+# Purpose: To check the trace functionality of gdb, ("btr auto on" and "btr enable" for individual threads)
+###############
+*/
+#include <pthread.h>
+#include <stdio.h>
+
+
+//function being called by Thread[0],
+int call_A(){ return 0;}
+//function being called by Thread[1]
+int call_B(){ return 0;}
+//function being called by Thread[2]
+int call_C(){ return 0;}
+//function being called by Thread[3]
+int call_D(){ return 0;}
+
+//Callback function for thread[0]
+void* th_a(void* arg){
+ int number = *((int*) arg);
+ call_A();
+ return arg;
+}
+//Callback function for thread[1]
+void* th_b(void* arg){
+ int number = *((int*) arg);
+ call_B();
+ return arg;
+}
+//Callback function for thread[2]
+void* th_c(void* arg){
+ int number = *((int*) arg);
+ call_C();
+ return arg;
+}
+//Callback function for thread[3]
+void* th_d(void* arg){
+ int number = *((int*) arg);
+ call_D();
+ return arg;
+}
+// Terminate the already created thread
+int join_thread(pthread_t *thr)
+{
+ int* resultp;
+ if (pthread_join(*thr, (void**) &resultp))
+ {
+ printf("ERROR: pthread_join failed, aborting!\n");
+ return(1);
+ }
+ return(0);
+}
+
+int main(){
+ const int THREADS = 4;
+ pthread_t thread[THREADS];
+ int args[THREADS];
+ args[0]=0;
+ args[1]=1;
+ args[2]=2;
+ args[3]=3;
+
+ // To be deterministic, we have to first terminate the
+ // created thread before creating a new one.
+ pthread_create(&thread[0], 0, th_a ,&args[0]);
+ join_thread(&thread[0]);
+ pthread_create(&thread[1], 0, th_b ,&args[1]);
+ join_thread(&thread[1]);
+ pthread_create(&thread[2], 0, th_c ,&args[2]);
+ join_thread(&thread[2]);
+ pthread_create(&thread[3], 0, th_d ,&args[3]);
+ join_thread(&thread[3]);
+
+ return 1;
+}
diff --git a/gdb/testsuite/gdb.btrace/threads_asm.c b/gdb/testsuite/gdb.btrace/threads_asm.c
new file mode 100755
index 0000000..eb58ecf
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/threads_asm.c
@@ -0,0 +1,78 @@
+/*
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@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/>.
+
+
+###############
+#This program spawns 4 threads and each thread has a seperate callback function and
+# a different function call from callback function.
+# th_a(), th_b(), th_c() and th_d are called from file th_callback.s
+#
+# Purpose: To check the trace functionality of gdb, ("btr auto on" and "btr enable" for individual threads and "btr enable" in GDb non-stop mode)
+###############
+*/
+#include <pthread.h>
+#include <stdio.h>
+
+pthread_barrier_t bar;
+
+void* th_a(void* arg);
+void* th_b(void* arg);
+void* th_c(void* arg);
+void* th_d(void* arg);
+
+// Terminate the already created thread
+int join_thread(pthread_t *thr)
+{
+ int* resultp;
+ if (pthread_join(*thr, (void**) &resultp))
+ {
+ printf("ERROR: pthread_join failed, aborting!\n");
+ return(1);
+ }
+ return(-1);
+}
+
+int main(){
+ const int THREADS = 4;
+ pthread_t thread[THREADS];
+ int args[THREADS];
+ int i;
+ args[0]=0;
+ args[1]=1;
+ args[2]=2;
+ args[3]=3;
+ pthread_barrier_init(&bar, NULL, 5);
+
+ //create 4 threads having different callback fucntions.
+ pthread_create(&thread[0], 0, th_a ,&args[0]);
+ pthread_create(&thread[1], 0, th_b ,&args[1]);
+ pthread_create(&thread[2], 0, th_c ,&args[2]);
+ pthread_create(&thread[3], 0, th_d ,&args[3]);
+ mybarrier();
+ printf(" All the threads are created by now ");
+ //wait for all the threads to terminate
+
+ for(i=0;i<4;i++) {
+ join_thread(&thread[i]);
+ }
+ //destroy barrier
+ pthread_barrier_destroy(&bar);
+
+ return 1;
+}
+
diff --git a/gdb/testsuite/gdb.btrace/threads_auto.exp b/gdb/testsuite/gdb.btrace/threads_auto.exp
new file mode 100755
index 0000000..20474c2
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/threads_auto.exp
@@ -0,0 +1,123 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@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/>.
+
+
+###############
+#Test Purpose: The trace works for multi-threaded application and the trace is automatically enabled for all the threads created, if we execute the GDB command "btr enable auto".
+# Sourcefiles : threads.c
+# Compiled using '-g -lpthread' option.
+#executed as :
+# make check RUNTESTFLAGS="GDB=<path to gdb> gdb.trace/threads_auto.exp"
+###############
+
+load_lib btrace.exp
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+# the tests do currently not work with gdbserver
+if [is_remote target] {
+ untested "threads_auto.exp"
+ return -1
+}
+
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/threads.c
+set objfilemain ${objdir}/${subdir}/threads.o
+set binfile ${objdir}/${subdir}/threads_auto.x
+set options "{debug}"
+
+#compile
+if {[gdb_compile_pthreads ${srcfilemain} ${objfilemain} "object" ${options}] != ""} {
+ untested threads_auto.exp
+ return -1
+}
+if {[gdb_compile_pthreads ${objfilemain} ${binfile} "executable" ""] != ""} {
+ untested threads_auto.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+# Make sure we don't die when running to main
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+
+#set a breakpoint at the end of each callback function of each thread
+gdb_breakpoint "43" "Breakpoint 2 at .*:.*, line 43." "Breakpoint at line 42, 1.1"
+
+gdb_breakpoint "49" "Breakpoint 3 at .*:.*, line 49." "Breakpoint at line 48, 1.2"
+
+gdb_breakpoint "55" "Breakpoint 4 at .*:.*, line 55." "Breakpoint at line 54, 1.3"
+
+gdb_breakpoint "61" "Breakpoint 5 at .*:.*, line 61." "Breakpoint at line 60, 1.4"
+
+# Reset branch trace on all new threads automatically
+gdb_test_no_output "btr enable auto"
+
+gdb_test "continue" ".*
+Breakpoint 2, th_a.*threads\.c:43\r
+43\[\[:blank:\]\]*return arg.*" "Stopping at breakpoint 2, line 43, 1.5"
+
+#Get the trace listing after it returns from call_A, while ignoring the trace listing of trace pthread libs.
+gdb_test "btr list /fa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_a\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in call_A\r
+3 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_a\r
+.*\r" "listing is not correct thread\[0\], 1.6"
+
+
+gdb_test "continue" ".*
+Breakpoint 3, th_b.*threads\.c:49\r
+49\[\[:blank:\]\]*return arg.*" "Stopping at breakpoint 32, line 49, 1.7"
+
+#Get the trace listing after it returns from call_B
+gdb_test "btr list /fa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_b\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in call_B\r
+3 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_b\r
+.*\r" "listing is not correct thread\[1\], 1.8"
+
+gdb_test "continue" ".*
+Breakpoint 4, th_c.*threads\.c:55\r
+55\[\[:blank:\]\]*return arg.*" "Stopping at breakpoint 4, line 55, 1.9"
+
+#Get the trace listing after it returns from call_C
+gdb_test "btr list /fa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_c\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in call_C\r
+3 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_c\r
+.*\r" "listing is not correct thread\[2\], 1.10"
+
+gdb_test "continue" ".*
+Breakpoint 5, th_d.*threads\.c:61\r
+61\[\[:blank:\]\]*return arg.*" "Stopping at breakpoint 52, line 61, 1.11"
+
+#Get the trace listing after it returns from call_D
+gdb_test "btr list /fa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_d\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in call_D\r
+3 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_d\r
+.*\r" "listing is not correct for thread\[3\], 1.12"
diff --git a/gdb/testsuite/gdb.btrace/threads_independent.exp b/gdb/testsuite/gdb.btrace/threads_independent.exp
new file mode 100755
index 0000000..ff930f1
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/threads_independent.exp
@@ -0,0 +1,125 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@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/>.
+
+
+###############
+#Test Purpose: The trace works for multi-threaded application and the trace is enabled for only the current thread.
+# Sourcefiles : threads.c
+# Compiled using '-g -lpthread' option.
+#executed as :
+# make check RUNTESTFLAGS="GDB=/users/bahuja/work_gdb/gdb_32/gdb --host i686-linux-gnu --target i686-linux-gnu gdb.trace/threads_independent.exp"
+###############
+
+
+load_lib btrace.exp
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/threads.c
+set objfilemain ${objdir}/${subdir}/threads.o
+set binfile ${objdir}/${subdir}/threads_independent.x
+set options "{debug}"
+
+#compile
+if {[gdb_compile_pthreads ${srcfilemain} ${binfile} "executable" ${options}] != ""} {
+ untested threads_independent.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+# Make sure we don't die when running to main
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+
+#set a breakpoint at the end of each callback function of each thread
+gdb_breakpoint "th_a" "Breakpoint 2 at .*:.*, line 41." "Breakpoint at th_a, 1.1"
+
+gdb_breakpoint "th_c" "Breakpoint 4 at .*:.*, line 53." "Breakpoint at th_c, 1.2"
+
+#set a breakpoint at the end of each callback function of each thread
+gdb_breakpoint "43" "Breakpoint 6 at .*:.*, line 43." "Breakpoint at line 43, 1.3"
+
+gdb_breakpoint "49" "Breakpoint 7 at .*:.*, line 49." "Breakpoint at line 49, 1.4"
+
+gdb_breakpoint "55" "Breakpoint 8 at .*:.*, line 55." "Breakpoint at line 55, 1.5"
+
+gdb_breakpoint "61" "Breakpoint 9 at .*:.*, line 61." "Breakpoint at line 61, 1.6"
+
+# move to th_a for thread[0]and enable trace
+gdb_test "continue" ".*
+Breakpoint 2, th_a.*threads\.c:41\r.*" "Stopping at breakpoint 2, th_a, 1.7"
+
+# Reset branch trace
+gdb_test_no_output "btrace enable"
+
+gdb_test "continue" ".*
+Breakpoint 4, th_a.*threads\.c:43\r
+43\[\[:blank:\]\]*return arg.*" "Stopping at breakpoint 4, line 43, 1.8"
+
+#Get the trace listing after it returns from call_A
+gdb_test "btrace list /fa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_a\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in call_A" "listing of thread\[0\], 1.9"
+
+
+# move to th_b for thread[1]and do not enable trace
+gdb_test "continue" ".*
+Breakpoint 5, th_b.*threads\.c:49\r
+49\[\[:blank:\]\]*return arg.*" "Stopping at breakpoint 5, line 49, 1.10"
+
+#Get the trace listing after it returns from call_B
+gdb_test "btr list" "No trace." "No trace for thread\[1\], 1.11"
+
+
+# move to th_c and enable trace
+gdb_test "continue" ".*
+Breakpoint 3, th_c.*threads\.c:53\r
+53.*" "Stopping at breakpoint 3, th_c, 1.12"
+
+
+# Reset branch trace for thread[2]
+gdb_test_no_output "btrace enable"
+
+gdb_test "continue" ".*
+Breakpoint 6, th_c.*threads\.c:55\r
+55\[\[:blank:\]\]*return arg.*" "Stopping at breakpoint 6, line 55, 1.13"
+
+#Get the trace listing after it returns from call_C
+gdb_test "btr list /fa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_c\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in call_C" "listing of thread\[2\], 1.14"
+
+
+# move to th_d and do not enable trace
+gdb_test "continue" ".*
+Breakpoint 7, th_d.*threads\.c:61\r
+61\[\[:blank:\]\]*return arg.*" "Stopping at breakpoint 7, line 61, 1.15"
+
+#Get the trace listing after it returns from call_D
+gdb_test "btr list" "No trace." "No trace for thread\[3\], 1.16"
diff --git a/gdb/testsuite/gdb.btrace/threads_nonstop.exp b/gdb/testsuite/gdb.btrace/threads_nonstop.exp
new file mode 100755
index 0000000..82dcf2d
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/threads_nonstop.exp
@@ -0,0 +1,231 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@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/>.
+
+###############
+#Test Purpose: In GDB non-stop mode, when btrace is enabled for only one thread (created by pthread_create()), then trace is also generated for only that thread and not for all threads
+# Sourcefiles : threads_asm.c, i386-thr-callback.S, amd64-thr-callback.S
+# Compiled using '-g -lpthread' option.
+#executed as :
+# make check RUNTESTFLAGS="GDB=/users/bahuja/work_gdb/gdb_32/gdb --host i686-linux-gnu --target i686-linux-gnu gdb.trace/threads_nonstop.exp"
+###############
+
+load_lib btrace.exp
+
+#check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+# the tests do currently not work with gdbserver
+if [is_remote target] {
+ untested "threads_nonstop.exp"
+ return -1
+}
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/threads_asm.c
+set objcallback ${objdir}/${subdir}/thr_callback.o
+set objmain ${objdir}/${subdir}/threads_asm.o
+set binfile ${objdir}/${subdir}/threads_nonstop.x
+set options "{debug}"
+
+if { ![support_displaced_stepping] } {
+ unsupported "displaced stepping"
+ return -1
+}
+
+# We need to do a seperate listing from here, since the instr lenght is different
+# on different platforms.
+# 32 bit platform
+if {[istarget "i?86-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/i386-thr-callback.S
+} elseif {[istarget "x86_64-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/amd64-thr-callback.S
+} else {
+ warning "host platform not supported "
+ return -1
+}
+
+set objfiles "${objmain} ${objcallback}"
+
+#compile
+if {[gdb_compile_pthreads ${srcfilemain} ${objmain} "object" ${options}] != ""} { return "" }
+if {[gdb_compile ${srccallback} ${objcallback} "object" ${options}] != ""} { return "" }
+
+if {[gdb_compile_pthreads ${objfiles} ${binfile} "executable" ${options}] != ""} {
+ untested threads_nonstop.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+gdb_test_no_output "set pagination off"
+gdb_test_no_output "set target-async 1"
+gdb_test_no_output "set non-stop 1"
+
+# Make sure we don't die when running to main
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+#set breakpoint at mybarrier to prevent all the pthreads from exiting.
+gdb_breakpoint "mybarrier" "Breakpoint 2 at .*:\[i386|amd64\]-thr-callback.S, line .*." "Breakpoint in reach barrier, 1.1"
+
+#set a breakpoint in callback of thread 3, where we enable trace for only thread 3
+gdb_breakpoint "th_b" "Breakpoint 3 at .*:\[i386|amd64\]-thr-callback.S.*" "Breakpoint in reach barrier, 1.2"
+
+set test "continue running..."
+gdb_test_multiple "continue" $test {
+ -re "Breakpoint 2.*"
+ {
+ pass "continuing"
+ }
+}
+# this is added to get the prompt, which is missing.
+gdb_test "" ""
+
+# This "info threads" is needed to get a $gdb_prompt, since gdb seems to get hanged at this particular location.
+set test "info for threads"
+gdb_test_multiple "info threads" $test {
+ -re ".*\n$gdb_prompt $" {
+ pass $test
+ }
+}
+
+# this is added to get the prompt, which is missing after creating new threads in non-stop mode.
+gdb_test "" ""
+
+# thread 3 reaches its callback th_b(), while all threads wait at mybarrier()
+gdb_test "info threads" " Id Target Id Frame \r
+ 5 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr-callback.S:114\r
+ 4 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr-callback.S:114\r
+ 3 Thread 0x\[a-f0-9\]*.*th_b \\(\\) at.*thr-callback.S:42\r
+ 2 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr-callback.S:114\r
+.* 1 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr-callback.S:114" "info threads before thread 3 reaches mybarrier, 1.3"
+
+#switch to thread 3
+gdb_test_multiple "thread 3" "switching to thread 3" {
+ -re ".*Switching to thread 3.*th_b.*$gdb_prompt $" {
+ pass "switch to thread 3, 1.4"
+ }
+ timeout {
+ fail "switching to thread 3 (timeout), 1.4"
+ }
+}
+
+#enable trace for only thread 3
+
+gdb_test "btr enable"
+# thread 3 also continues to mybarrier()
+
+gdb_test "continue" ".*Breakpoint 2, mybarrier \\(\\) at .*thr-callback.S:114.*" " thread 3 also reached at breakpoint 1 at line 53, 1.5"
+# back trace for thread 3.
+
+gdb_test "btr list /lfa" "
+1 0x\[a-f0-9\]* - 0x\[a-f0-9\]* in mybarrier at.*thr-callback.S:112-114\r
+2 0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_b at.*thr-callback.S:44-45\r
+3 0x\[a-f0-9\]* - 0x\[a-f0-9\]* in call_B at.*thr-callback.S:85-89" "BTR listing at line mybarrier for thread 3, 1.6"
+
+# 32 bit host
+if {[istarget "i?86-*-*"]} {
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> 0x\[a-f0-9\]* <mybarrier\\+3>:\[\[:blank:\]\]*mov.*" "btr 0 for thread 3, 1.7"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_b\\+13>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_b\\+18>:\[\[:blank:\]\]*call.*<mybarrier>" "btr 1 for thread 3, 1.8"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <call_B\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <call_B\\+1>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <call_B\\+3>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <call_B\\+8>:\[\[:blank:\]\]*leave.*\r
+ *0x\[a-f0-9\]* <call_B\\+9>:\[\[:blank:\]\]*ret.*\r" "btr 1 for thread 3, 1.9"
+
+} elseif {[istarget "x86_64-*-*"]} {
+# 64 bit host
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> 0x\[a-f0-9\]* <mybarrier\\+4>:\[\[:blank:\]\]*mov.*" "btr 0 for thread 3, 1.7"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_b\\+14>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_b\\+19>:\[\[:blank:\]\]*call.*<mybarrier>" "btr 1 for thread 3, 1.8"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <call_B\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <call_B\\+1>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <call_B\\+4>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <call_B\\+9>:\[\[:blank:\]\]*leave.*\r
+ *0x\[a-f0-9\]* <call_B\\+10>:\[\[:blank:\]\]*ret.*\r" "btr 1 for thread 3, 1.9"
+
+}
+# All the threads are at mybarrier()
+gdb_test "info threads" " Id Target Id Frame \r
+ 5 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr-callback.S:114\r
+ 4 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr-callback.S:114\r
+.* 3 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr-callback.S:114\r
+ 2 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr-callback.S:114\r
+ 1 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr-callback.S:114" "Info threads, when all threads reached barrier, 1.10"
+
+# trace was enabled for only thread 3, and none other thread has trace
+#switch to thread 2
+gdb_test_multiple "thread 2" "switching to thread 2" {
+ -re ".*Switching to thread 2.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 2, 1.11"
+ }
+ timeout {
+ fail "switching to thread 2 (timeout), 1.11"
+ }
+}
+
+gdb_test "btr list" "No trace\." " no trace for thread 2, 1.12"
+
+#switch to thread 4
+gdb_test_multiple "thread 4" "switching to thread 4" {
+ -re ".*Switching to thread 4.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 4, 1.13"
+ }
+ timeout {
+ fail "switching to thread 4 (timeout), 1.13"
+ }
+}
+
+gdb_test "btr list" "No trace\." " no trace for thread 4, 1.14"
+
+#switch to thread 5
+gdb_test_multiple "thread 5" "switching to thread 5" {
+ -re ".*Switching to thread 5.*mybarrier.*$gdb_prompt $" {
+ pass "switch to thread 5, 1.15"
+ }
+ timeout {
+ fail "switching to thread 5 (timeout), 1.15"
+ }
+}
+
+gdb_test "btr list" "No trace\." " no trace for thread 5, 1.16"
diff --git a/gdb/testsuite/gdb.btrace/trace_iteration.exp b/gdb/testsuite/gdb.btrace/trace_iteration.exp
new file mode 100755
index 0000000..7c4e408
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/trace_iteration.exp
@@ -0,0 +1,265 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@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/>.
+
+
+###############
+#Test Purpose: Fix a location while linking, where the debuggee will be loaded and then
+# see that trace gives the correct addresses.
+# Iterate over the btrace using the commands "btr", "btr +", "btr -", and check that it gives the correct output.
+# Source file: decrement.s
+###############
+
+load_lib btrace.exp
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+set srcfile ${srcdir}/${subdir}/decrement.S
+set objfile ${objdir}/${subdir}/decrement.o
+set binfile ${objdir}/${subdir}/trace_iteration.x
+set options "{debug}"
+#compile
+if {[target_assemble ${srcfile} ${objfile} ""] != ""} { return -1 }
+#link
+if {[target_link ${objfile} ${binfile} " -Ttext 0x400400 "] != ""} {
+ untested trace_iteration.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+if ![runto L1] then {
+ fail "Can't run to L1"
+ return 0
+}
+
+
+# Enable branch trace.
+gdb_test_no_output "btr enable"
+
+gdb_continue_to_breakpoint "L1, 1.2"
+
+gdb_test "btr list /lfa" "
+1 *0x0*40041a - 0x0*40041a in L1" "list L1, 1.1"
+
+gdb_continue_to_breakpoint "L1, 1.2"
+
+if {[istarget "x86_64-*-*"]} {
+#64 bit host
+
+#We enter the loop for 5 times from here.
+gdb_test "btr list /af" "
+1 *0x0*40041a - 0x0*40041a in L1\r
+2 *0x0*40041a - 0x0*400421 in L1" "list L1 again, 1.3"
+
+#Delete all Breakpoints
+delete_breakpoints
+
+#Set a Breakpoint at L2
+gdb_breakpoint "L2"
+
+#Continue to L2
+gdb_continue_to_breakpoint "L2"
+
+# BTR listing in method L2, when the loop exits
+gdb_test "btr list /a" "
+1 *0x0*400423 - 0x0*400423\r
+2 *0x0*40041a - 0x0*40041d\r
+3 *0x0*40041a - 0x0*400421\r
+4 *0x0*40041a - 0x0*400421\r
+5 *0x0*40041a - 0x0*400421\r.*" "BTR listing at L2, 1.4"
+
+# Exit the loop
+gdb_test "btr " "
+=> 0x0*400423 *<L2\\+0>:\[\[:blank:\]\]*retq *" "BTR of 0, 1.5"
+
+#BTR of non existing trace
+gdb_test "btr -" "
+No trace." "BTR of non-existing trace, 1.6"
+
+# Comparison, if we are exiting the loop
+gdb_test "btr -" "
+No trace." "BTR of non-existing trace, 1.7"
+
+gdb_test "btr " "
+=> 0x0*400423 *<L2\\+0>:\[\[:blank:\]\]*retq *" "BTR of 1, 1.8"
+
+#in the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 <L2>\r" "BTR at 2, 1.9"
+
+#in the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400421 *<L1\\+7>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 3, 1.10"
+
+#in the loop
+gdb_test "btr -" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 <L2>\r" "BTR at 2 second time, 1.11"
+
+#in the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400421 *<L1\\+7>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 3 second time, 1.12"
+
+#in the loop
+gdb_test "btr -" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 <L2>\r" "BTR at 2 third time, 1.13"
+
+#in the loop
+gdb_test "btr -" "
+=> 0x0*400423 *<L2\\+0>:\[\[:blank:\]\]*retq *" "BTR at 1 Again, 1.14"
+
+gdb_test "btr 6" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400421 *<L1\\+7>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 6, 1.15"
+
+gdb_test "btr +" "
+No trace." "BTR of non existing at end, 1.16"
+
+gdb_test "btr" "
+No trace." "BTR still at 6 , 1.17"
+
+gdb_test "btr -" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400421 *<L1\\+7>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 6, 1.18"
+
+} elseif {[istarget "i?86-*-*"]} {
+#32 bit host
+
+#We enter the loop for 5 times from here.
+gdb_test "btr list /af" "
+1 *0x0*40041a - 0x0*40041a in L1\r
+2 *0x0*40041a - 0x0*400420 in L1" "list L1 again, 1.3"
+
+#Delete all Breakpoints
+delete_breakpoints
+
+#Set a Breakpoint at L2
+gdb_breakpoint "L2"
+
+#Continue to L2
+gdb_continue_to_breakpoint "L2"
+
+# BTR listing in method L2, when the loop exits
+gdb_test "btr list /a" "
+1 *0x0*400422 - 0x0*400422\r
+2 *0x0*40041a - 0x0*40041d\r
+3 *0x0*40041a - 0x0*400420\r
+4 *0x0*40041a - 0x0*400420\r
+5 *0x0*40041a - 0x0*400420\r
+6 *0x0*40041a - 0x0*400420\r" "BTR listing at L2, 1.4"
+
+# Exit the loop
+gdb_test "btr " "
+=> 0x0*400422 *<L2\\+0>:\[\[:blank:\]\]*ret *" "BTR of 1, 1.5"
+
+#BTR of non existing trace
+gdb_test "btr -" "
+No trace." "BTR of non-existing trace, 1.6"
+
+#BTR of non existing trace
+gdb_test "btr -" "
+No trace." "BTR of non-existing trace, 1.7"
+
+#BTR of non existing trace
+gdb_test "btr " "
+=> 0x0*400422 *<L2\\+0>:\[\[:blank:\]\]*ret *" "BTR of 1, 1.8"
+
+# Comparison, if we are exiting the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 *<L2>" "BTR at 2, 1.9"
+
+#in the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400420 *<L1\\+6>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 3, 1.10"
+
+#in the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400420 *<L1\\+6>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 3, 1.11"
+
+#in the loop
+gdb_test "btr -" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400420 *<L1\\+6>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 2 second time, 1.12"
+
+#in the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400420 *<L1\\+6>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 3 second time, 1.13"
+
+#in the loop
+gdb_test "btr -" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400420 *<L1\\+6>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 2nd third time, 1.14"
+#in the loop
+gdb_test "btr -" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 *<L2>" "BTR at 1 Again, 1.15"
+
+gdb_test "btr 6" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400420 *<L1\\+6>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 6, 1.16"
+
+gdb_test "btr +" "" "BTR of non existing at end, 1.17"
+
+gdb_test "btr" "" "BTR still at 6 , 1.18"
+
+gdb_test "btr -" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400420 *<L1\\+6>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR still at 6 , 1.19"
+
+ } else {
+ warning "host platform not supported "
+}
+
+#reset the trace
+btrace_reset_trace
+
+gdb_test "btr list" "No trace." "No trace should be available now"
--
1.7.1
^ permalink raw reply [flat|nested] 20+ messages in thread