* [patch v6 08/12] gdbserver, btrace: add generic btrace support
2012-12-17 16:02 [patch v6 00/12] branch tracing support for Atom markus.t.metzger
@ 2012-12-17 16:02 ` markus.t.metzger
2012-12-17 20:43 ` Jan Kratochvil
2012-12-17 16:02 ` [patch v6 01/12] thread, btrace: add generic branch trace support markus.t.metzger
` (12 subsequent siblings)
13 siblings, 1 reply; 46+ messages in thread
From: markus.t.metzger @ 2012-12-17 16:02 UTC (permalink / raw)
To: jan.kratochvil, palves, tromey, kettenis
Cc: gdb-patches, markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Add support to gdbserver to understand branch trace related packages.
2012-12-17 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..8969b9b 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 != NULL)
+ 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 fb7322c..9a95d93 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -397,6 +397,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 != NULL)
+ return "E.Btrace already enabled.";
+
+ thread->btrace = target_enable_btrace (thread->entry.id);
+ if (thread->btrace == NULL)
+ return "E.Could not enable btrace.";
+
+ return NULL;
+}
+
+/* Handle btrace disabling. */
+
+static const char *
+handle_btrace_disable (struct thread_info *thread)
+{
+
+ if (thread->btrace == NULL)
+ 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 == NULL)
+ {
+ 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 != 0)
+ strcpy (own_buf, err);
+ else
+ write_ok (own_buf);
+
+ return 1;
+}
+
/* Handle all of the extended 'Q' packets. */
static void
@@ -553,6 +635,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;
@@ -1252,9 +1337,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 == NULL || writebuf)
+ return -2;
+
+ if (target_running () == 0 || 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 == NULL)
+ {
+ strcpy (own_buf, "E.No such thread.");
+ return -1;
+ }
+
+ if (thread->btrace == NULL)
+ {
+ strcpy (own_buf, "E.Btrace not enabled.");
+ return -1;
+ }
+
+ if (offset == 0)
+ {
+ 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 },
@@ -1419,6 +1561,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 == NULL)
+ strcpy (own_buf, "E.No such thread.");
+ else if (thread->btrace == NULL)
+ 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
@@ -1648,6 +1813,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;
}
@@ -1838,6 +2010,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.6.5
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [patch v6 08/12] gdbserver, btrace: add generic btrace support
2012-12-17 16:02 ` [patch v6 08/12] gdbserver, btrace: add generic btrace support markus.t.metzger
@ 2012-12-17 20:43 ` Jan Kratochvil
0 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2012-12-17 20:43 UTC (permalink / raw)
To: markus.t.metzger; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
On Mon, 17 Dec 2012 17:01:37 +0100, markus.t.metzger@intel.com wrote:
[...]
> +/* 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 == NULL)
> + {
> + strcpy (own_buf, "E.No such thread.");
> + return -1;
> + }
> +
> + err = NULL;
> +
> + if (strncmp ("on", op, strlen ("on")) == 0)
Here
> + err = handle_btrace_enable (thread);
> + else if (strncmp ("off", op, strlen ("off")) == 0)
and here should be just strcmp, otherwise it falsely matches for example
future keyword "official" or whatever.
> + err = handle_btrace_disable (thread);
> + else
> + err = "E.Bad Qbtrace operation. Use on or off.";
> +
> + if (err != 0)
> + strcpy (own_buf, err);
> + else
> + write_ok (own_buf);
> +
> + return 1;
> +}
> +
[...]
> +/* 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 == NULL)
> + strcpy (own_buf, "E.No such thread.");
Incorrect indentation.
> + else if (thread->btrace == NULL)
> + strcpy (own_buf, "E.Btrace not enabled.");
Incorrect indentation.
> + else
> + strcpy (own_buf,
> + (target_btrace_has_changed (thread->btrace) ? "yes" : "no"));
Use tabs, not spaces. Also below and everywhere in this patch (or patchset?)
[...]
> --- a/gdb/gdbserver/target.h
> +++ b/gdb/gdbserver/target.h
[...]
> +#define target_supports_btrace() \
> + (the_target->supports_btrace ? (*the_target->supports_btrace) () : 0)
> +
> +#define target_enable_btrace(ptid) \
Use tabs for the \ backslash indentation.
> + (*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.6.5
Thanks,
Jan
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch v6 01/12] thread, btrace: add generic branch trace support
2012-12-17 16:02 [patch v6 00/12] branch tracing support for Atom markus.t.metzger
2012-12-17 16:02 ` [patch v6 08/12] gdbserver, btrace: add generic btrace support markus.t.metzger
@ 2012-12-17 16:02 ` markus.t.metzger
2012-12-17 16:02 ` [patch v6 12/12] btrace, x86: disable on some processors markus.t.metzger
` (11 subsequent siblings)
13 siblings, 0 replies; 46+ messages in thread
From: markus.t.metzger @ 2012-12-17 16:02 UTC (permalink / raw)
To: jan.kratochvil, palves, tromey, kettenis
Cc: gdb-patches, markus.t.metzger, 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-17 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.
(clear_thread_inferior_resources): 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 | 3 +
9 files changed, 428 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 244694c..d6e1dbb 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -754,7 +754,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
@@ -921,7 +921,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..667a738
--- /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 != NULL)
+ 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 == NULL)
+ 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 != NULL && 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 != NULL && head->end == 0)
+ 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 4e38725..56e4403 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 ebd8085..db7a3c6 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 a832ef8..4f6f35b 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?
*/
@@ -1897,4 +1914,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..47d8a6e 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>
@@ -117,6 +118,8 @@ clear_thread_inferior_resources (struct thread_info *tp)
bpstat_clear (&tp->control.stop_bpstat);
+ disable_btrace (tp);
+
do_all_intermediate_continuations_thread (tp, 1);
do_all_continuations_thread (tp, 1);
}
--
1.7.6.5
^ permalink raw reply [flat|nested] 46+ messages in thread* [patch v6 12/12] btrace, x86: disable on some processors
2012-12-17 16:02 [patch v6 00/12] branch tracing support for Atom markus.t.metzger
2012-12-17 16:02 ` [patch v6 08/12] gdbserver, btrace: add generic btrace support markus.t.metzger
2012-12-17 16:02 ` [patch v6 01/12] thread, btrace: add generic branch trace support markus.t.metzger
@ 2012-12-17 16:02 ` markus.t.metzger
2012-12-17 17:11 ` Mark Kettenis
` (2 more replies)
2012-12-17 16:02 ` [patch v6 06/12] remote, btrace: add branch trace remote ops markus.t.metzger
` (10 subsequent siblings)
13 siblings, 3 replies; 46+ messages in thread
From: markus.t.metzger @ 2012-12-17 16:02 UTC (permalink / raw)
To: jan.kratochvil, palves, tromey, kettenis
Cc: gdb-patches, markus.t.metzger, 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-17 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 1231ccc..b5a41a5 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.6.5
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [patch v6 12/12] btrace, x86: disable on some processors
2012-12-17 16:02 ` [patch v6 12/12] btrace, x86: disable on some processors markus.t.metzger
@ 2012-12-17 17:11 ` Mark Kettenis
2012-12-19 16:13 ` Metzger, Markus T
2012-12-17 17:37 ` H.J. Lu
2012-12-17 20:35 ` Jan Kratochvil
2 siblings, 1 reply; 46+ messages in thread
From: Mark Kettenis @ 2012-12-17 17:11 UTC (permalink / raw)
To: markus.t.metzger
Cc: jan.kratochvil, palves, tromey, gdb-patches, markus.t.metzger,
markus.t.metzger
> From: <markus.t.metzger@intel.com>
> Date: Mon, 17 Dec 2012 17:01:41 +0100
>
> 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-17 Markus Metzger <markus.t.metzger@intel.com>
>
> * common/linux-btrace.c (linux_supports_btrace): Add cpuid check.
I think this approach is a reasonable compromise. However, AFAICT the
linux_supports_btrace() is called unconditionally. Therefore this
will break GDB on old CPUs that don't implement the cpuid
instructions. And AFAIK the family/model values are specific to
Intel, so you should check that you're on an Intel CPU before
interpreting these values. And I still think you should check whether
the kernel supports BTS on the CPU you're running on first before
disabling it on certain CPUs.
^ permalink raw reply [flat|nested] 46+ messages in thread
* RE: [patch v6 12/12] btrace, x86: disable on some processors
2012-12-17 17:11 ` Mark Kettenis
@ 2012-12-19 16:13 ` Metzger, Markus T
2012-12-19 16:36 ` Mark Kettenis
2012-12-21 10:38 ` Jan Kratochvil
0 siblings, 2 replies; 46+ messages in thread
From: Metzger, Markus T @ 2012-12-19 16:13 UTC (permalink / raw)
To: Mark Kettenis
Cc: jan.kratochvil, palves, tromey, gdb-patches, markus.t.metzger
> -----Original Message-----
> From: Mark Kettenis [mailto:mark.kettenis@xs4all.nl]
> Sent: Monday, December 17, 2012 6:11 PM
Thanks for your review.
> > 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-17 Markus Metzger <markus.t.metzger@intel.com>
> >
> > * common/linux-btrace.c (linux_supports_btrace): Add cpuid check.
>
> I think this approach is a reasonable compromise. However, AFAICT the
> linux_supports_btrace() is called unconditionally. Therefore this
> will break GDB on old CPUs that don't implement the cpuid
> instructions. And AFAIK the family/model values are specific to
> Intel, so you should check that you're on an Intel CPU before
> interpreting these values. And I still think you should check whether
> the kernel supports BTS on the CPU you're running on first before
> disabling it on certain CPUs.
This function is only called if the kernel provides a perf_event.h header file, which requires a recent enough kernel. Will a recent kernel run on those old cpu's that don't implement cpuid?
In order to check whether the kernel supports BTS, I would need to enable tracing. Let's see if I can use the gdb or gdbserver process for this, since I don't necessarily have an inferior. If you think that it is necessary, I could try to add such a check.
I added a vendor check.
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] 46+ messages in thread
* Re: [patch v6 12/12] btrace, x86: disable on some processors
2012-12-19 16:13 ` Metzger, Markus T
@ 2012-12-19 16:36 ` Mark Kettenis
2012-12-21 10:38 ` Jan Kratochvil
1 sibling, 0 replies; 46+ messages in thread
From: Mark Kettenis @ 2012-12-19 16:36 UTC (permalink / raw)
To: markus.t.metzger
Cc: jan.kratochvil, palves, tromey, gdb-patches, markus.t.metzger
> From: "Metzger, Markus T" <markus.t.metzger@intel.com>
> Date: Wed, 19 Dec 2012 16:11:41 +0000
>
> > > 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-17 Markus Metzger <markus.t.metzger@intel.com>
> > >
> > > * common/linux-btrace.c (linux_supports_btrace): Add cpuid check.
> >
> > I think this approach is a reasonable compromise. However, AFAICT the
> > linux_supports_btrace() is called unconditionally. Therefore this
> > will break GDB on old CPUs that don't implement the cpuid
> > instructions. And AFAIK the family/model values are specific to
> > Intel, so you should check that you're on an Intel CPU before
> > interpreting these values. And I still think you should check whether
> > the kernel supports BTS on the CPU you're running on first before
> > disabling it on certain CPUs.
>
> This function is only called if the kernel provides a perf_event.h
> header file, which requires a recent enough kernel. Will a recent
> kernel run on those old cpu's that don't implement cpuid?
Linus decided only very recently to drop i386 support, starting with
the (yet to be realeased) 3.8. And the i486 (which also lacks cpuid)
remains supported.
> In order to check whether the kernel supports BTS, I would need to
> enable tracing. Let's see if I can use the gdb or gdbserver process
> for this, since I don't necessarily have an inferior. If you think
> that it is necessary, I could try to add such a check.
I think it would make sense to do so. Would probably solve the cpuid
issue as well, since you could assume that cpuid is supported if the
kernel actually supports BTS. So do that check first and then only
disable it if you're running on a known-to-be-broken CPU.
> I added a vendor check.
Thanks,
Mark
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [patch v6 12/12] btrace, x86: disable on some processors
2012-12-19 16:13 ` Metzger, Markus T
2012-12-19 16:36 ` Mark Kettenis
@ 2012-12-21 10:38 ` Jan Kratochvil
1 sibling, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2012-12-21 10:38 UTC (permalink / raw)
To: Metzger, Markus T
Cc: Mark Kettenis, palves, tromey, gdb-patches, markus.t.metzger
On Wed, 19 Dec 2012 17:11:41 +0100, Metzger, Markus T wrote:
> In order to check whether the kernel supports BTS, I would need to enable
> tracing. Let's see if I can use the gdb or gdbserver process for this, since
> I don't necessarily have an inferior.
There is already gdb/common/linux-ptrace.c linux_ptrace_test_ret_to_nx for one
such test.
Thanks,
Jan
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [patch v6 12/12] btrace, x86: disable on some processors
2012-12-17 16:02 ` [patch v6 12/12] btrace, x86: disable on some processors markus.t.metzger
2012-12-17 17:11 ` Mark Kettenis
@ 2012-12-17 17:37 ` H.J. Lu
2012-12-19 15:58 ` Metzger, Markus T
2012-12-17 20:35 ` Jan Kratochvil
2 siblings, 1 reply; 46+ messages in thread
From: H.J. Lu @ 2012-12-17 17:37 UTC (permalink / raw)
To: markus.t.metzger
Cc: jan.kratochvil, palves, tromey, kettenis, gdb-patches, markus.t.metzger
On Mon, Dec 17, 2012 at 8:01 AM, <markus.t.metzger@intel.com> wrote:
> 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-17 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 1231ccc..b5a41a5 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;
Do you need to verify that it is an Intel processor before
checking extended family/model?
> + switch (model)
> + {
> + case 26: /* Nehalem */
> + case 30:
> + case 46:
I believe model 31 is also Nehalem. BTW, most Intel documents
use hex number, not decimal for model numbers.
> + 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.6.5
>
--
H.J.
^ permalink raw reply [flat|nested] 46+ messages in thread* RE: [patch v6 12/12] btrace, x86: disable on some processors
2012-12-17 17:37 ` H.J. Lu
@ 2012-12-19 15:58 ` Metzger, Markus T
0 siblings, 0 replies; 46+ messages in thread
From: Metzger, Markus T @ 2012-12-19 15:58 UTC (permalink / raw)
To: H.J. Lu
Cc: jan.kratochvil, palves, tromey, kettenis, gdb-patches, markus.t.metzger
> -----Original Message-----
> From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-owner@sourceware.org] On Behalf Of H.J. Lu
> Sent: Monday, December 17, 2012 6:37 PM
Thanks for your review.
I added a vendor check, changed the numbers to hex, and added 0x1f for Nehalem.
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] 46+ messages in thread
* Re: [patch v6 12/12] btrace, x86: disable on some processors
2012-12-17 16:02 ` [patch v6 12/12] btrace, x86: disable on some processors markus.t.metzger
2012-12-17 17:11 ` Mark Kettenis
2012-12-17 17:37 ` H.J. Lu
@ 2012-12-17 20:35 ` Jan Kratochvil
2 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2012-12-17 20:35 UTC (permalink / raw)
To: markus.t.metzger; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
On Mon, 17 Dec 2012 17:01:41 +0100, markus.t.metzger@intel.com wrote:
> --- 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__)
> + {
[...]
> +
> +#else /* defined(__i386__) || defined(__x86_64__) */
BTW defined (__i386__) or defined __i386__ .
http://www.gnu.org/prep/standards/standards.html#Comments
Therefore:
#if defined __i386__ || defined __x86_64__
but then negative:
#else /* !defined __i386__ && !defined __x86_64__ */
#endif /* !defined __i386__ && !defined __x86_64__ */
(+cpuid comments in other mails)
> +
> + return 0;
> +
> +#endif /* defined(__i386__) || defined(__x86_64__) */
> }
>
> /* See linux-btrace.h. */
> --
> 1.7.6.5
Thanks,
Jan
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch v6 06/12] remote, btrace: add branch trace remote ops
2012-12-17 16:02 [patch v6 00/12] branch tracing support for Atom markus.t.metzger
` (2 preceding siblings ...)
2012-12-17 16:02 ` [patch v6 12/12] btrace, x86: disable on some processors markus.t.metzger
@ 2012-12-17 16:02 ` markus.t.metzger
2012-12-17 19:57 ` Jan Kratochvil
2012-12-17 16:02 ` [patch v6 02/12] cli, btrace: add btrace cli markus.t.metzger
` (9 subsequent siblings)
13 siblings, 1 reply; 46+ messages in thread
From: markus.t.metzger @ 2012-12-17 16:02 UTC (permalink / raw)
To: jan.kratochvil, palves, tromey, kettenis
Cc: gdb-patches, markus.t.metzger, 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-17 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 a6a6227..fcd04ff
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -68,6 +68,7 @@
#include "ax.h"
#include "ax-gdb.h"
#include "agent.h"
+#include "btrace.h"
/* Temp hacks for tracepoint encoding migration. */
static char *target_buf;
@@ -1284,6 +1285,9 @@ enum {
PACKET_qXfer_fdpic,
PACKET_QDisableRandomization,
PACKET_QAgent,
+ PACKET_qbtrace,
+ PACKET_Qbtrace,
+ PACKET_qXfer_btrace,
PACKET_MAX
};
@@ -3929,6 +3933,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;
@@ -8723,6 +8731,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;
}
@@ -11042,6 +11054,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 != NULL)
+ {
+ struct cleanup *cleanup = make_cleanup (xfree, xml);
+
+ btrace = parse_xml_btrace (xml);
+ do_cleanups (cleanup);
+ }
+
+ return btrace;
+}
+
static void
init_remote_ops (void)
{
@@ -11158,6 +11315,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
@@ -11682,6 +11844,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 4f6f35b..1d29906 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.6.5
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [patch v6 06/12] remote, btrace: add branch trace remote ops
2012-12-17 16:02 ` [patch v6 06/12] remote, btrace: add branch trace remote ops markus.t.metzger
@ 2012-12-17 19:57 ` Jan Kratochvil
0 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2012-12-17 19:57 UTC (permalink / raw)
To: markus.t.metzger; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
On Mon, 17 Dec 2012 17:01:35 +0100, markus.t.metzger@intel.com wrote:
> --- a/gdb/remote.c
> +++ b/gdb/remote.c
[...]
> +/* Send the Qbtrace packet and check the response. */
> +
> +static void
> +send_Qbtrace (ptid_t ptid, int enable)
> +{
[...]
> + 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" and "disable" could be localized. (+use tab, not 8x space)
[...]
> +/* Check whether branch trace data has changed. */
> +
> +static int
> +remote_btrace_has_changed (struct btrace_target_info *tinfo)
> +{
[...]
> + if (strcmp (rs->buf, "yes") == 0)
> + return 1;
Incorrect indentation.
> +
> + if (strcmp (rs->buf, "no") == 0)
> + return 0;
Incorrect indentation.
> +
> + error (_("Bad remote reply: %s."), rs->buf);
> +
> + return 0;
> +}
Thanks,
Jan
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch v6 02/12] cli, btrace: add btrace cli
2012-12-17 16:02 [patch v6 00/12] branch tracing support for Atom markus.t.metzger
` (3 preceding siblings ...)
2012-12-17 16:02 ` [patch v6 06/12] remote, btrace: add branch trace remote ops markus.t.metzger
@ 2012-12-17 16:02 ` markus.t.metzger
2012-12-17 18:32 ` Jan Kratochvil
2012-12-18 9:04 ` Jan Kratochvil
2012-12-17 16:02 ` [patch v6 09/12] gdbserver, linux, btrace: add btrace support for linux-low markus.t.metzger
` (8 subsequent siblings)
13 siblings, 2 replies; 46+ messages in thread
From: markus.t.metzger @ 2012-12-17 16:02 UTC (permalink / raw)
To: jan.kratochvil, palves, tromey, kettenis
Cc: gdb-patches, markus.t.metzger, 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-17 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 667a738..488fd09 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 != NULL)
+ 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 != NULL)
+ warning (_("%s"), error.message);
+}
+
+/* The "btrace enable" command. */
+
+static void
+cmd_btrace_enable (char *args, int from_tty)
+{
+ struct thread_info *tp;
+
+ if (args != NULL && *args != 0)
+ {
+ ALL_THREADS (tp)
+ if (number_is_in_list (args, tp->num))
+ warn_enable_btrace (tp);
+ }
+ else
+ {
+ tp = find_thread_ptid (inferior_ptid);
+ if (tp == NULL)
+ 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 != NULL && *args != 0)
+ 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 != NULL && *args != 0)
+ error (_("Invalid argument."));
+
+ if (btrace_thread_observer != NULL)
+ 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 != NULL && *args != 0)
+ {
+ ALL_THREADS (tp)
+ if (number_is_in_list (args, tp->num))
+ warn_enable_btrace (tp);
+ }
+ else
+ {
+ tp = find_thread_ptid (inferior_ptid);
+ if (tp == NULL)
+ 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 != NULL && *args != 0)
+ 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 != NULL && *args != 0)
+ error (_("Invalid argument."));
+
+ if (btrace_thread_observer == NULL)
+ 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 != NULL)
+ func = SYMBOL_PRINT_NAME (symbol);
+ else
+ {
+ msymbol = lookup_minimal_symbol_by_pc (trace->begin);
+ if (msymbol != NULL)
+ 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 != NULL)
+ symtab = symbol->symtab;
+ if (symtab == NULL)
+ symtab = find_pc_symtab (trace->begin);
+ if (symtab != NULL)
+ {
+ linetable = symtab->linetable;
+ filename = symtab->filename;
+ }
+
+ if (filename != NULL)
+ {
+ ui_out_text (current_uiout, " at ");
+ ui_out_field_string (current_uiout, "file", filename);
+
+ if (linetable != NULL)
+ {
+ 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 == NULL)
+ error (_("No thread."));
+
+ btrace = get_btrace (tp);
+
+ /* Parse modifier. */
+ if (args != NULL && *args != 0)
+ {
+ 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 != NULL)
+ 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 == NULL)
+ 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 == 0)
+ error (_("Args must be numbers or '$' variables."));
+
+ trace = read_btrace (tp, index - 1);
+ if (trace == NULL)
+ 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] != 0)
+ skip = get_number (&args);
+
+ while (skip-- != 0)
+ trace = prev_btrace (tp);
+
+ if (args[0] != 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] != 0)
+ skip = get_number (&args);
+
+ while (skip-- != 0)
+ trace = next_btrace (tp);
+
+ if (args[0] != 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 == NULL)
+ error (_("No thread."));
+
+ /* Parse modifier. We accept the same modifiers as the disas command. */
+ if (args != NULL && *args != 0)
+ {
+ 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 == NULL || *args == 0)
+ 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, include source lines (if available).\n\
+With a /r modifier, include raw instructions in hex.\n\n\
+Without arguments, select the chronologically preceding block.\n\
+With \"+[<n>]\" argument, select the n-th chronologically preceding block.\n\
+With \"-[<n>]\" argument, select the n-th chronologically succeeding block.\n\
+With one positive integer argument, select the respective block.\n\
+With a range argument \"<l>-<h>\", select the h-th block and disassemble \
+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 new threads.\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 new threads.\n"),
+ &btdiscmdlist);
+
+ add_cmd ("list", class_btrace, cmd_btrace_list, _("\
+List branch trace blocks.\n\n\
+Print a list of all blocks for which branch trace is available.\n\
+With a /a modifier, include addresses.\n\
+With a /f modifier, include the function name (if available).\n\
+With a /l modifier, include source lines (if available).\n\
+With a /t modifier, print the total number of trace blocks and stop.\n\
+By default, include the function name and source lines.\n\n\
+Without arguments, list the full list of blocks.\n\
+With a range (<start>[-<end>]) argument, list 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.6.5
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [patch v6 02/12] cli, btrace: add btrace cli
2012-12-17 16:02 ` [patch v6 02/12] cli, btrace: add btrace cli markus.t.metzger
@ 2012-12-17 18:32 ` Jan Kratochvil
2012-12-18 7:36 ` Metzger, Markus T
2012-12-18 9:04 ` Jan Kratochvil
1 sibling, 1 reply; 46+ messages in thread
From: Jan Kratochvil @ 2012-12-17 18:32 UTC (permalink / raw)
To: markus.t.metzger; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
On Mon, 17 Dec 2012 17:01:31 +0100, markus.t.metzger@intel.com wrote:
[...]
> --- a/gdb/btrace.c
> +++ b/gdb/btrace.c
[...]
> @@ -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 != NULL)
> + warning (_("%s"), error.message);
"%s" does not need localization.
> +}
> +
> +/* 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 != NULL)
> + warning (_("%s"), error.message);
"%s" does not need localization.
> +}
[...]
> +static void
> +cmd_btrace_disable (char *args, int from_tty)
> +{
> + struct thread_info *tp;
> +
> + if (args != NULL && *args != 0)
> + {
> + ALL_THREADS (tp)
> + if (number_is_in_list (args, tp->num))
> + warn_enable_btrace (tp);
Here should be warn_disable_btrace.
> + }
> + else
> + {
> + tp = find_thread_ptid (inferior_ptid);
> + if (tp == NULL)
> + error (_("Couldn't disable branch tracing: no inferior thread."));
> +
> + disable_btrace (tp);
> + }
> +}
[...]
> +static void
> +do_btrace_list_function (struct btrace_block *trace)
> +{
> + struct minimal_symbol *msymbol;
> + struct symbol *symbol;
> + const char* func;
GDB is using 'const char *' style.
> +
> + func = "??";
> + symbol = find_pc_function (trace->begin);
> + if (symbol != NULL)
> + func = SYMBOL_PRINT_NAME (symbol);
[...]
> +static void
> +do_btrace_list_item (struct btrace_block *trace, enum btrace_list_flags flags)
> +{
> + if (flags & BTR_LIST_ADDRESS)
if ((flags & BTR_LIST_ADDRESS) != 0)
> + do_btrace_list_address (trace);
> +
> + if (flags & BTR_LIST_FUNCTION)
dtto
> + do_btrace_list_function (trace);
> +
> + if (flags & BTR_LIST_LINE)
dtto
> + do_btrace_list_line (trace);
> +}
[...]
> +/* The "btrace list" command. */
> +
> +static void
> +cmd_btrace_list (char *args, int from_tty)
[...]
> + if (flags & BTR_LIST_TOTAL)
if ((flags & BTR_LIST_TOTAL) != 0)
> + {
[...]
> +/* Print the disassembly of a btrace block. */
> +
> +static void
> +do_btrace (struct btrace_block *trace, int flags)
> +{
> + struct gdbarch *gdbarch = target_gdbarch ();
> +
> + if (trace == NULL)
> + error (_("No trace."));
> +
> + if (trace->end < trace->begin)
> + warning (_("Bad trace: %s - %s"), paddress (gdbarch, trace->begin),
> + paddress (gdbarch, trace->end));
Shouldn't this be rather gdb_assert? How to create such case?
> +
> + gdb_disassembly (gdbarch, current_uiout, 0, flags, -1,
> + trace->begin, trace->end + 1);
> +}
[...]
No need for a repost wrt the changes above.
Thanks,
Jan
^ permalink raw reply [flat|nested] 46+ messages in thread* RE: [patch v6 02/12] cli, btrace: add btrace cli
2012-12-17 18:32 ` Jan Kratochvil
@ 2012-12-18 7:36 ` Metzger, Markus T
2012-12-18 8:35 ` Jan Kratochvil
0 siblings, 1 reply; 46+ messages in thread
From: Metzger, Markus T @ 2012-12-18 7:36 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
> -----Original Message-----
> From: Jan Kratochvil [mailto:jan.kratochvil@redhat.com]
> Sent: Monday, December 17, 2012 7:32 PM
Thanks for your review.
[...]
> > + if (trace->end < trace->begin)
> > + warning (_("Bad trace: %s - %s"), paddress (gdbarch, trace->begin),
> > + paddress (gdbarch, trace->end));
>
> Shouldn't this be rather gdb_assert? How to create such case?
I have not seen such a case, yet. This would indicate some corrupted trace buffer or problems reading the trace data correctly. It should normally not happen.
I didn't use gdb_assert since this is not checking gdb's internal state. Gdb would still function correctly even if we saw such unexpected trace.
I'm OK to change it to gdb_assert, if you want.
> No need for a repost wrt the changes above.
Does that mean you approve the patch?
Thanks,
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] 46+ messages in thread* Re: [patch v6 02/12] cli, btrace: add btrace cli
2012-12-18 7:36 ` Metzger, Markus T
@ 2012-12-18 8:35 ` Jan Kratochvil
0 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2012-12-18 8:35 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
On Tue, 18 Dec 2012 08:36:47 +0100, Metzger, Markus T wrote:
> I didn't use gdb_assert since this is not checking gdb's internal state. Gdb
> would still function correctly even if we saw such unexpected trace.
Sorry, I read a later patch where the data is read from XML from gdbserver so
I agree it should not be gdb_assert.
> > No need for a repost wrt the changes above.
>
> Does that mean you approve the patch?
Not yet, going to post yet a [patch 00/12] reply.
Thanks,
Jan
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [patch v6 02/12] cli, btrace: add btrace cli
2012-12-17 16:02 ` [patch v6 02/12] cli, btrace: add btrace cli markus.t.metzger
2012-12-17 18:32 ` Jan Kratochvil
@ 2012-12-18 9:04 ` Jan Kratochvil
2012-12-18 9:11 ` Metzger, Markus T
1 sibling, 1 reply; 46+ messages in thread
From: Jan Kratochvil @ 2012-12-18 9:04 UTC (permalink / raw)
To: markus.t.metzger; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
Hi Markus,
I find new class excessive, feature specific to a single arch has a new "help"
main menu entry now. For example existing - more powerful "record" feature is
now under class_obscure. Maybe it could be class_run but so far I would put
it together to "record", that is a bit unfortunate class_obscure.
Thanks,
Jan
On Mon, 17 Dec 2012 17:01:31 +0100, markus.t.metzger@intel.com wrote:
> 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.6.5
^ permalink raw reply [flat|nested] 46+ messages in thread* RE: [patch v6 02/12] cli, btrace: add btrace cli
2012-12-18 9:04 ` Jan Kratochvil
@ 2012-12-18 9:11 ` Metzger, Markus T
0 siblings, 0 replies; 46+ messages in thread
From: Metzger, Markus T @ 2012-12-18 9:11 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
> -----Original Message-----
> From: Jan Kratochvil [mailto:jan.kratochvil@redhat.com]
> Sent: Tuesday, December 18, 2012 10:04 AM
> To: Metzger, Markus T
> Cc: palves@redhat.com; tromey@redhat.com; kettenis@gnu.org; gdb-patches@sourceware.org; markus.t.metzger@gmail.com
> Subject: Re: [patch v6 02/12] cli, btrace: add btrace cli
>
> Hi Markus,
>
> I find new class excessive, feature specific to a single arch has a new "help"
> main menu entry now. For example existing - more powerful "record" feature is
> now under class_obscure. Maybe it could be class_run but so far I would put
> it together to "record", that is a bit unfortunate class_obscure.
OK, I'll change the class to class_obscure.
Regards,
Markus.
>
>
> Thanks,
> Jan
>
>
> On Mon, 17 Dec 2012 17:01:31 +0100, markus.t.metzger@intel.com wrote:
> > 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.6.5
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] 46+ messages in thread
* [patch v6 09/12] gdbserver, linux, btrace: add btrace support for linux-low
2012-12-17 16:02 [patch v6 00/12] branch tracing support for Atom markus.t.metzger
` (4 preceding siblings ...)
2012-12-17 16:02 ` [patch v6 02/12] cli, btrace: add btrace cli markus.t.metzger
@ 2012-12-17 16:02 ` markus.t.metzger
2012-12-17 16:03 ` [patch v6 11/12] test, btrace: more branch tracing tests markus.t.metzger
` (7 subsequent siblings)
13 siblings, 0 replies; 46+ messages in thread
From: markus.t.metzger @ 2012-12-17 16:02 UTC (permalink / raw)
To: jan.kratochvil, palves, tromey, kettenis
Cc: gdb-patches, markus.t.metzger, 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-17 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 9ec9340..e2403a3 100755
--- a/gdb/gdbserver/configure
+++ b/gdb/gdbserver/configure
@@ -5144,6 +5144,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 6493c0f..66b9c73 100644
--- a/gdb/gdbserver/configure.ac
+++ b/gdb/gdbserver/configure.ac
@@ -291,6 +291,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..d1a01f1 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 != NULL)
+ 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.6.5
^ permalink raw reply [flat|nested] 46+ messages in thread* [patch v6 11/12] test, btrace: more branch tracing tests
2012-12-17 16:02 [patch v6 00/12] branch tracing support for Atom markus.t.metzger
` (5 preceding siblings ...)
2012-12-17 16:02 ` [patch v6 09/12] gdbserver, linux, btrace: add btrace support for linux-low markus.t.metzger
@ 2012-12-17 16:03 ` markus.t.metzger
2012-12-17 16:03 ` [patch v6 03/12] linux, btrace: perf_event based branch tracing markus.t.metzger
` (6 subsequent siblings)
13 siblings, 0 replies; 46+ messages in thread
From: markus.t.metzger @ 2012-12-17 16:03 UTC (permalink / raw)
To: jan.kratochvil, palves, tromey, kettenis
Cc: gdb-patches, markus.t.metzger, Barkha Ahuja
From: Barkha Ahuja <barkha.ahuja@intel.com>
Non-stop tests are failing with gdbserver and are thus skipped.
2012-12-17 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.6.5
^ permalink raw reply [flat|nested] 46+ messages in thread* [patch v6 03/12] linux, btrace: perf_event based branch tracing
2012-12-17 16:02 [patch v6 00/12] branch tracing support for Atom markus.t.metzger
` (6 preceding siblings ...)
2012-12-17 16:03 ` [patch v6 11/12] test, btrace: more branch tracing tests markus.t.metzger
@ 2012-12-17 16:03 ` markus.t.metzger
2012-12-17 16:03 ` [patch v6 07/12] btrace, doc: document remote serial protocol markus.t.metzger
` (5 subsequent siblings)
13 siblings, 0 replies; 46+ messages in thread
From: markus.t.metzger @ 2012-12-17 16:03 UTC (permalink / raw)
To: jan.kratochvil, palves, tromey, kettenis
Cc: gdb-patches, markus.t.metzger, 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-17 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 d6e1dbb..4ee7067 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -830,7 +830,7 @@ 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/queue.h \
common/linux-osdata.h gdb-dlfcn.h auto-load.h probe.h stap-probe.h \
-gdb_bfd.h sparc-ravenscar-thread.h ppc-ravenscar-thread.h
+gdb_bfd.h sparc-ravenscar-thread.h ppc-ravenscar-thread.h common/linux-btrace.h
# Header files that already have srcdir in them, or which are in objdir.
@@ -1952,6 +1952,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..1231ccc
--- /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 == 0)
+ 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) == 0)
+ {
+ warning (_("Branch trace may be incomplete."));
+ break;
+ }
+
+ if (perf_event_skip_record (tinfo, &psample->bts) != 0)
+ 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 == 0)
+ pid = ptid_get_pid (ptid);
+
+ errno = 0;
+ tinfo->file = syscall (SYS_perf_event_open, &tinfo->attr, pid, -1, -1, 0);
+ if (tinfo->file < 0)
+ 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 != 0)
+ 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 c4f1a2d..cdb6918 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -155,7 +155,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@
@@ -423,6 +423,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
@@ -542,6 +544,9 @@ agent.o: ../common/agent.c
$(COMPILE) $<
$(POSTCOMPILE)
+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.6.5
^ permalink raw reply [flat|nested] 46+ messages in thread* [patch v6 07/12] btrace, doc: document remote serial protocol
2012-12-17 16:02 [patch v6 00/12] branch tracing support for Atom markus.t.metzger
` (7 preceding siblings ...)
2012-12-17 16:03 ` [patch v6 03/12] linux, btrace: perf_event based branch tracing markus.t.metzger
@ 2012-12-17 16:03 ` markus.t.metzger
2012-12-17 16:03 ` [patch v6 05/12] xml, btrace: define btrace xml document style markus.t.metzger
` (4 subsequent siblings)
13 siblings, 0 replies; 46+ messages in thread
From: markus.t.metzger @ 2012-12-17 16:03 UTC (permalink / raw)
To: jan.kratochvil, palves, tromey, kettenis
Cc: gdb-patches, markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Document the extensions to the remote serial protocol for supporting branch tracing.
This patch has been reviewed and approved by Eli Zaretskii.
2012-12-17 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 5abcd93..66cff6f 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -34561,6 +34561,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
@@ -35422,6 +35424,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
@@ -37051,11 +37054,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{-}
@@ -37116,6 +37129,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{-}
@@ -37211,6 +37229,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}).
@@ -37345,6 +37367,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::
@@ -37463,6 +37491,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 (@pxref{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
@@ -37699,6 +37739,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
@@ -40115,6 +40190,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 branch trace 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.6.5
^ permalink raw reply [flat|nested] 46+ messages in thread* [patch v6 05/12] xml, btrace: define btrace xml document style
2012-12-17 16:02 [patch v6 00/12] branch tracing support for Atom markus.t.metzger
` (8 preceding siblings ...)
2012-12-17 16:03 ` [patch v6 07/12] btrace, doc: document remote serial protocol markus.t.metzger
@ 2012-12-17 16:03 ` markus.t.metzger
2012-12-17 19:53 ` Jan Kratochvil
2012-12-17 16:03 ` [patch v6 10/12] test, btrace: add branch tracing tests markus.t.metzger
` (3 subsequent siblings)
13 siblings, 1 reply; 46+ messages in thread
From: markus.t.metzger @ 2012-12-17 16:03 UTC (permalink / raw)
To: jan.kratochvil, palves, tromey, kettenis
Cc: gdb-patches, markus.t.metzger, 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-17 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 4ee7067..7f01c7e 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -495,7 +495,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 488fd09..06a4b87 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 != 0)
+ {
+ 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.6.5
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [patch v6 05/12] xml, btrace: define btrace xml document style
2012-12-17 16:03 ` [patch v6 05/12] xml, btrace: define btrace xml document style markus.t.metzger
@ 2012-12-17 19:53 ` Jan Kratochvil
2012-12-18 7:43 ` Metzger, Markus T
0 siblings, 1 reply; 46+ messages in thread
From: Jan Kratochvil @ 2012-12-17 19:53 UTC (permalink / raw)
To: markus.t.metzger; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
On Mon, 17 Dec 2012 17:01:34 +0100, markus.t.metzger@intel.com wrote:
> 2012-12-17 Markus Metzger <markus.t.metzger@intel.com>
The correct ChangeLog line is:
2012-12-17 Markus Metzger <markus.t.metzger@intel.com>
I see the current ChangeLog file already contains some such incorrectly
formatted entries, please fix those up (either separately or with this
patchset, it does not matter).
Thanks,
Jan
^ permalink raw reply [flat|nested] 46+ messages in thread
* RE: [patch v6 05/12] xml, btrace: define btrace xml document style
2012-12-17 19:53 ` Jan Kratochvil
@ 2012-12-18 7:43 ` Metzger, Markus T
0 siblings, 0 replies; 46+ messages in thread
From: Metzger, Markus T @ 2012-12-18 7:43 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
> -----Original Message-----
> From: Jan Kratochvil [mailto:jan.kratochvil@redhat.com]
> Sent: Monday, December 17, 2012 8:53 PM
> To: Metzger, Markus T
> Cc: palves@redhat.com; tromey@redhat.com; kettenis@gnu.org; gdb-patches@sourceware.org; markus.t.metzger@gmail.com
> Subject: Re: [patch v6 05/12] xml, btrace: define btrace xml document style
>
> On Mon, 17 Dec 2012 17:01:34 +0100, markus.t.metzger@intel.com wrote:
> > 2012-12-17 Markus Metzger <markus.t.metzger@intel.com>
>
> The correct ChangeLog line is:
>
> 2012-12-17 Markus Metzger <markus.t.metzger@intel.com>
>
> I see the current ChangeLog file already contains some such incorrectly
> formatted entries, please fix those up (either separately or with this
> patchset, it does not matter).
I'll fix them right now with a separate commit.
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] 46+ messages in thread
* [patch v6 10/12] test, btrace: add branch tracing tests
2012-12-17 16:02 [patch v6 00/12] branch tracing support for Atom markus.t.metzger
` (9 preceding siblings ...)
2012-12-17 16:03 ` [patch v6 05/12] xml, btrace: define btrace xml document style markus.t.metzger
@ 2012-12-17 16:03 ` markus.t.metzger
2012-12-17 20:26 ` Jan Kratochvil
2012-12-17 16:03 ` [patch v6 04/12] linux, i386, amd64: enable btrace for 32bit and 64bit linux native markus.t.metzger
` (2 subsequent siblings)
13 siblings, 1 reply; 46+ messages in thread
From: markus.t.metzger @ 2012-12-17 16:03 UTC (permalink / raw)
To: jan.kratochvil, palves, tromey, kettenis
Cc: gdb-patches, markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Add tests covering btrace enable/disable/auto and btrace list.
2012-12-17 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.6.5
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [patch v6 10/12] test, btrace: add branch tracing tests
2012-12-17 16:03 ` [patch v6 10/12] test, btrace: add branch tracing tests markus.t.metzger
@ 2012-12-17 20:26 ` Jan Kratochvil
0 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2012-12-17 20:26 UTC (permalink / raw)
To: markus.t.metzger; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
On Mon, 17 Dec 2012 17:01:39 +0100, markus.t.metzger@intel.com wrote:
[...]
> --- /dev/null
> +++ b/gdb/testsuite/gdb.btrace/enable.exp
> @@ -0,0 +1,89 @@
[...]
> +# 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-*-*"] } {
All these tests could be limited to "XXX-*-linux*" I think, couldn't they?
> + verbose "Tests ignored for all but x86 based targets."
> + return
> +}
[...]
> +# we don't have trace, yet
> +gdb_test "btrace" "No thread\." "btrace enable 2.2"
This way it is equivalent to "No thread\." as \. is no special Tcl sequence so
it equals to '.'. You wanted "No thread\\." so that backslash gets parsed by
the regex parser and not the Tcl parser.
Alternatively one can use {No thread\.} which skips the Tcl unbackslashing
(but then some characters like \n or \r or $variables are not available).
It is more times here.
> +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"
Please do not override $testfile to non-basename of the .exp file, see below
for standard_testfile recommendation instead.
> +
> +# start a debuggee program
> +if { [set binfile [btrace_assemble ${testfile}]] == "" } {
> + untested ${testfile}.exp
> + return -1
> +}
> +
> +gdb_reinitialize_dir $srcdir/$subdir
> +gdb_load $binfile
Why not clean_restart?
> +# automatic enabling is off.
> +if ![runto test_1] {
> + fail "runto test function, 1"
> + return -1
> +}
[...]
> --- /dev/null
> +++ b/gdb/testsuite/gdb.btrace/list_function.c
> @@ -0,0 +1,31 @@
[...]
> + 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)
I find "extern" excessive/unusual during function definiton.
> +{
> + 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 @@
[...]
> +load_lib btrace.exp
> +
> +set testfile "list_function"
> +set sources [list $testfile.c inc.c dec.c]
Use standard_testfile instead of these two sets.
> +
> +# check for btrace support
> +if { [skip_btrace_tests] } { return -1 }
[...]
> --- /dev/null
> +++ b/gdb/testsuite/lib/btrace.exp
> @@ -0,0 +1,78 @@
[...]
> +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 "" }
Why is here -Ttext? It requires at least a comment but I would prefer to
remove it. Can't you just use additional_flags=-nostdlib for the build?
And can't you just not use -nostdlib, use standard system crt1 and just use
runto_main and no longer define "_start" in your .S file?
This btrace_assemble I find overengineered a bit, there should be
standard_testfile called in each *.exp file which will set srcfile/binfile.
> +
> + return ${binfile}
> +}
> +
> +proc skip_btrace_tests {} {
> + global gdb_prompt
> +
> + set testfile "x86-list"
Please do not override $testfile. $testfile is set by stadnard_testfile and
it should always match the gdb.btrace/TESTFILE.exp name TESTFILE.
> + set skip 0
> +
> + if { [set binfile [btrace_assemble ${testfile}]] == "" } {
> + return 1
> + }
> +
> + gdb_exit
> + gdb_start
> + gdb_load $binfile
> +
> + runto main
You could use clean_restart, couldn't you?
> +
> + 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"
> + }
Tabs vs. spaces are wrong here. Tab is always 8 characters.
> + }
> + 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.6.5
Thanks,
Jan
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch v6 04/12] linux, i386, amd64: enable btrace for 32bit and 64bit linux native
2012-12-17 16:02 [patch v6 00/12] branch tracing support for Atom markus.t.metzger
` (10 preceding siblings ...)
2012-12-17 16:03 ` [patch v6 10/12] test, btrace: add branch tracing tests markus.t.metzger
@ 2012-12-17 16:03 ` markus.t.metzger
2012-12-17 18:45 ` [patch v6 00/12] branch tracing support for Atom Jan Kratochvil
2012-12-18 9:20 ` Jan Kratochvil
13 siblings, 0 replies; 46+ messages in thread
From: markus.t.metzger @ 2012-12-17 16:03 UTC (permalink / raw)
To: jan.kratochvil, palves, tromey, kettenis
Cc: gdb-patches, markus.t.metzger, 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-17 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..56fb242 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 == NULL)
+ 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 != 0)
+ 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..e246ad8 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 == NULL)
+ 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 != 0)
+ 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.6.5
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [patch v6 00/12] branch tracing support for Atom
2012-12-17 16:02 [patch v6 00/12] branch tracing support for Atom markus.t.metzger
` (11 preceding siblings ...)
2012-12-17 16:03 ` [patch v6 04/12] linux, i386, amd64: enable btrace for 32bit and 64bit linux native markus.t.metzger
@ 2012-12-17 18:45 ` Jan Kratochvil
2012-12-17 19:34 ` Tom Tromey
2012-12-18 9:20 ` Jan Kratochvil
13 siblings, 1 reply; 46+ messages in thread
From: Jan Kratochvil @ 2012-12-17 18:45 UTC (permalink / raw)
To: markus.t.metzger; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
On Mon, 17 Dec 2012 17:01:29 +0100, markus.t.metzger@intel.com wrote:
> Is the patch series OK to commit?
sorry but the patchset no longer applies to FSF GDB HEAD. I tried some
guessed commit but it also did not apply.
You will have to rebase it anyway now, please repost new series as you
probably post it by GIT so it should be easy enough. Maybe also send a GIT
commit you base the patchset on.
Thanks,
Jan
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [patch v6 00/12] branch tracing support for Atom
2012-12-17 18:45 ` [patch v6 00/12] branch tracing support for Atom Jan Kratochvil
@ 2012-12-17 19:34 ` Tom Tromey
2012-12-18 7:24 ` Metzger, Markus T
0 siblings, 1 reply; 46+ messages in thread
From: Tom Tromey @ 2012-12-17 19:34 UTC (permalink / raw)
To: Jan Kratochvil
Cc: markus.t.metzger, palves, kettenis, gdb-patches, markus.t.metzger
>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:
Jan> You will have to rebase it anyway now, please repost new series as you
Jan> probably post it by GIT so it should be easy enough. Maybe also send a GIT
Jan> commit you base the patchset on.
I can hook you up with archer.git access if you want to just push it.
This doesn't eliminate the need for patch email but it makes it simpler
to share things.
Tom
^ permalink raw reply [flat|nested] 46+ messages in thread
* RE: [patch v6 00/12] branch tracing support for Atom
2012-12-17 19:34 ` Tom Tromey
@ 2012-12-18 7:24 ` Metzger, Markus T
0 siblings, 0 replies; 46+ messages in thread
From: Metzger, Markus T @ 2012-12-18 7:24 UTC (permalink / raw)
To: Tom Tromey, Jan Kratochvil
Cc: palves, kettenis, gdb-patches, markus.t.metzger
> -----Original Message-----
> From: Tom Tromey [mailto:tromey@redhat.com]
> Sent: Monday, December 17, 2012 8:33 PM
> To: Jan Kratochvil
> Cc: Metzger, Markus T; palves@redhat.com; kettenis@gnu.org; gdb-patches@sourceware.org; markus.t.metzger@gmail.com
> Subject: Re: [patch v6 00/12] branch tracing support for Atom
>
> >>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:
>
> Jan> You will have to rebase it anyway now, please repost new series as you
> Jan> probably post it by GIT so it should be easy enough. Maybe also send a GIT
> Jan> commit you base the patchset on.
Hmmm, I have rebased the series just before I sent it. There are meanwhile 9 new commits on top. I'll send it again when I addressed the review comments.
> I can hook you up with archer.git access if you want to just push it.
> This doesn't eliminate the need for patch email but it makes it simpler
> to share things.
Sounds good.
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] 46+ messages in thread
* Re: [patch v6 00/12] branch tracing support for Atom
2012-12-17 16:02 [patch v6 00/12] branch tracing support for Atom markus.t.metzger
` (12 preceding siblings ...)
2012-12-17 18:45 ` [patch v6 00/12] branch tracing support for Atom Jan Kratochvil
@ 2012-12-18 9:20 ` Jan Kratochvil
2012-12-18 10:14 ` Metzger, Markus T
13 siblings, 1 reply; 46+ messages in thread
From: Jan Kratochvil @ 2012-12-18 9:20 UTC (permalink / raw)
To: markus.t.metzger; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
Hi Markus,
already posted about it before:
http://sourceware.org/ml/gdb-patches/2012-11/msg00724.html
Currently there are two separate history APIs - the "record" one implemented
as new target_ops implementing reverse execution via to_resume/to_wait hooks.
And now the new API with specific new *btrace* target_ops methods.
Without implementing the virtual btrace frames discussed in the thread above
one still could implement "reverse-stepi" (and therefore also "reverse-step")
on top of btrace by chopping the btrace ranges by lengths of each instruction.
There is even existing "record goto" command which is similar to the new
command "btrace +[<n>]/-[<n>]" interface which partially duplicates
stepi/reverse-stepi. While the diassembling and "list" feature would be
useful also with the record target.
record.c has similar "record_list" history, it could be abstracted for both
backends via target_ops.
OTOH I should have reacted much earlier and be more explicit in the mail above
so not going to block it but neither approve it. IMO the two interfaces
should be unified.
Thanks,
Jan
^ permalink raw reply [flat|nested] 46+ messages in thread* RE: [patch v6 00/12] branch tracing support for Atom
2012-12-18 9:20 ` Jan Kratochvil
@ 2012-12-18 10:14 ` Metzger, Markus T
2012-12-18 13:55 ` Jan Kratochvil
0 siblings, 1 reply; 46+ messages in thread
From: Metzger, Markus T @ 2012-12-18 10:14 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
> -----Original Message-----
> From: Jan Kratochvil [mailto:jan.kratochvil@redhat.com]
> Sent: Tuesday, December 18, 2012 10:20 AM
> To: Metzger, Markus T
> Cc: palves@redhat.com; tromey@redhat.com; kettenis@gnu.org; gdb-patches@sourceware.org; markus.t.metzger@gmail.com
> Subject: Re: [patch v6 00/12] branch tracing support for Atom
>
> Hi Markus,
>
> already posted about it before:
> http://sourceware.org/ml/gdb-patches/2012-11/msg00724.html
>
> Currently there are two separate history APIs - the "record" one implemented
> as new target_ops implementing reverse execution via to_resume/to_wait hooks.
> And now the new API with specific new *btrace* target_ops methods.
>
> Without implementing the virtual btrace frames discussed in the thread above
> one still could implement "reverse-stepi" (and therefore also "reverse-step")
> on top of btrace by chopping the btrace ranges by lengths of each instruction.
>
> There is even existing "record goto" command which is similar to the new
> command "btrace +[<n>]/-[<n>]" interface which partially duplicates
> stepi/reverse-stepi. While the diassembling and "list" feature would be
> useful also with the record target.
>
> record.c has similar "record_list" history, it could be abstracted for both
> backends via target_ops.
>
> OTOH I should have reacted much earlier and be more explicit in the mail above
> so not going to block it but neither approve it. IMO the two interfaces
> should be unified.
I like the idea of adding BTS as a configuration option to "record" to provide a control-flow only trace for the reverse- commands. This will be quite limited since the only thing you can really do is iterate over disassembly and source lines - plus some fake back trace. On the other hand, recording is faster and control-flow-only trace may suffice in some cases.
We should not remove the existing btrace commands, though. They provide a compact means of viewing the control-flow trace. With a single "btrace list" command, you get a compact overview of the control flow that led to the current location. With a single "btrace 1-8" command, you get the full disassembly of the last 8 blocks in control-flow order. Using the remote- commands, you would need a sequence of reverse-stepi or reverse-step commands. And even then, the output would be clobbered with intermixed prompts and would be in reverse control-flow order, unless you navigated back and forth again.
Depending on your use case, either the btrace or the remote- commands are more effective.
As far as I understand, the btrace commands could also be implemented for "record" to provide a more compact view of the recorded control-flow. They could thus also help improve the "record" feature.
Given the different use cases, it would make sense to establish two sets of commands for all kinds of control-flow tracing/replay: one for viewing and one for navigating. In a first step, BTS tracing will only implement the former and "record" will only implement the latter. In a second step, "record" could implement the viewing commands, and in third step, BTS tracing can implement the navigation commands.
Would that be OK with you?
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] 46+ messages in thread
* Re: [patch v6 00/12] branch tracing support for Atom
2012-12-18 10:14 ` Metzger, Markus T
@ 2012-12-18 13:55 ` Jan Kratochvil
2012-12-19 9:59 ` Metzger, Markus T
0 siblings, 1 reply; 46+ messages in thread
From: Jan Kratochvil @ 2012-12-18 13:55 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
On Tue, 18 Dec 2012 11:12:49 +0100, Metzger, Markus T wrote:
> I like the idea of adding BTS as a configuration option to "record" to
> provide a control-flow only trace for the reverse- commands. This will be
> quite limited since the only thing you can really do is iterate over
> disassembly and source lines
Yes. But without teaching users new commands, one of the issues of GDB.
I find myself to prefer the already used reverse-stepi even with BTS.
> - plus some fake back trace.
I would exclude that feature from the current discussion as it can be
implemented as an add-on patch without changing much other code.
> We should not remove the existing btrace commands, though.
In general I agree. Just they should be moved under the "record" prefix.
Command "btrace" then should be renamed to some "record disassemble".
And for example the "btrace" current position should be shared with
"reverse-*" current position and the btrace args parser/syntax should be
unified with "record goto" syntax. That means only supporting start/begin/end
as otherwise btrace syntax is more rich than the record one - but the goal is
to make the syntax compatible for users.
> Using the remote- commands, you would need a sequence of reverse-stepi or
> reverse-step commands. And even then, the output would be clobbered with
> intermixed prompts and would be in reverse control-flow order, unless you
> navigated back and forth again.
I agree. Just "reverse-step" is a more general command - even for record
- while still usable for the basic use case of BTS.
> Depending on your use case, either the btrace or the remote- commands are
> more effective.
Yes.
> As far as I understand, the btrace commands could also be implemented for
> "record" to provide a more compact view of the recorded control-flow. They
> could thus also help improve the "record" feature.
Exactly. That both record navigation commands are useful (or at least usable)
for BTS and that BTS view commands are definitely useful for record proves to
me they should share the same backend/data.
> Given the different use cases, it would make sense to establish two sets of
> commands for all kinds of control-flow tracing/replay: one for viewing and
> one for navigating. In a first step, BTS tracing will only implement the
> former and "record" will only implement the latter. In a second step,
> "record" could implement the viewing commands, and in third step, BTS
> tracing can implement the navigation commands.
>
> Would that be OK with you?
I believe you a heading for an approval of this patchset as is, so that the
unification can be implemented in an add-on patch series.
I do not think the unification patch series will get checked-in soon enough
for gdb-7.6. That means the currently defined commands will need to remain
backward comparible indefinitely in the future. So one should make the
commands syntax final already (there is deprecate_cmd but it is not good to
plan its use).
I believe the internal API will change a lot for the unification with record
backend/data so it seems to me a large part of the patch will need to get
replaced afterwards.
But I am OK with that if we at least make the commands unified with record
with some hope the backend functionality unification will come later.
Thanks,
Jan
^ permalink raw reply [flat|nested] 46+ messages in thread
* RE: [patch v6 00/12] branch tracing support for Atom
2012-12-18 13:55 ` Jan Kratochvil
@ 2012-12-19 9:59 ` Metzger, Markus T
2012-12-19 12:13 ` Mark Kettenis
` (2 more replies)
0 siblings, 3 replies; 46+ messages in thread
From: Metzger, Markus T @ 2012-12-19 9:59 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
> -----Original Message-----
> From: Jan Kratochvil [mailto:jan.kratochvil@redhat.com]
> Sent: Tuesday, December 18, 2012 2:55 PM
> In general I agree. Just they should be moved under the "record" prefix.
> Command "btrace" then should be renamed to some "record disassemble".
I see how this could be done. This would require the btrace command to work on instructions, though, instead of blocks.
One typical command that I do after stopping is "btrace list 1-8" to get a rough idea where I came from.
Translated to record, this would become "info record" followed by "record list 18914-18989".
After the next step, this would become " info record" followed by "record list 18917-18993".
That's clumsy.
I guess what we would want is something like "record list end-80, +80". Although this gives the impression that "end" or "start" can be used in expressions. Not sure if we want that generality. We would need to rename them to $end and $start, respectively, to avoid name clashes.
Btw, "record goto" silently discards junk following "end" or "start" and "help record goto" does not mention "start" or "end". On the other hand, it seems to accept arbitrary expressions as argument.
> > Given the different use cases, it would make sense to establish two sets of
> > commands for all kinds of control-flow tracing/replay: one for viewing and
> > one for navigating. In a first step, BTS tracing will only implement the
> > former and "record" will only implement the latter. In a second step,
> > "record" could implement the viewing commands, and in third step, BTS
> > tracing can implement the navigation commands.
> >
> > Would that be OK with you?
>
> I believe you a heading for an approval of this patchset as is, so that the
> unification can be implemented in an add-on patch series.
This patch series is sitting around for a long time, already. Yes, I would like to see it approved to show that there is progress.
> I do not think the unification patch series will get checked-in soon enough
> for gdb-7.6. That means the currently defined commands will need to remain
> backward comparible indefinitely in the future. So one should make the
> commands syntax final already (there is deprecate_cmd but it is not good to
> plan its use).
I don't know how strict gdb is with regards to backwards compatibility. I also don't know how strict it needs to be.
It would certainly be nice if we could just rename the btrace commands and proceed. I'm afraid, though, that it will not be that simple and that we will end up doing the full integration and also some changes to record/replay in the process, before there will be any support for branch tracing in gdb.
> I believe the internal API will change a lot for the unification with record
> backend/data so it seems to me a large part of the patch will need to get
> replaced afterwards.
>
> But I am OK with that if we at least make the commands unified with record
> with some hope the backend functionality unification will come later.
I played around with record/replay and reverse debugging a bit. One thing that I did not understand is how multi-threading is handled.
For exact replay, the interleaving of threads needs to be recorded. I would thus expect a single "timeline" or "history" for all threads. Stepping commands that operate in replay mode may operate on a single thread, but they should also move other threads as a side-effect. You should be able to see this via "info threads" and also when switching to other threads.
When I do "info record" in combination with switching threads, it seems as if all threads would share a common history. They all have the same number of instructions and the same current instruction. When I do reverse stepping, however, it seems as if I would only step a single thread. For each "rsi" command, the current instruction is decremented by one and the location of the current thread changes. When I do "info threads", the location of other threads does not change. When I switch to other threads, they are at the location I left them. Yet when I do "info record" again, the current instruction is the same as it had been for the thread I stepped. The same current instruction showed two different locations for the same thread.
Comparing record/replay with BTS tracing, there is a fundamental difference: record/replay needs a common history for all threads, whereas BTS has separate histories for each thread and no means of correlating those histories. Record/replay is per-process; branch tracing is per-thread.
This is bound to cause problems when we're trying to share the same infrastructure internally. The commands will also behave differently depending on whether record/replay or BTS is used. I hope that does not cause more confusion than a separate set of commands would.
I see how I could add a command "record config" that takes "replay" and "bts" as arguments and switches between the two. I also see how I could implement "record disassemble", "record list", and "record goto" for BTS. The commands would check the config and go one way or another - quite dirty, but the only thing doable without spending lots of effort. There's still the problem of listing or disassembling the last n instructions/blocks (see above) or listing +/- n from the current position. This would need to be added to record/replay, as well.
I would simply mark other "record" commands as not supported for the BTS configuration. Since I'm not actually moving the location of any thread, all other gdb commands will operate on the location the thread has been stopped. Only "record disassemble" and "record list" would work on the current instruction for the current thread. And each thread would have a different number of instructions as well as current instruction. I do hope that all this is acceptable to all maintainers.
There's one thing (well, one that I am currently aware of) I don't know how to do: enable/disable. Due to the high cost of branch tracing, it makes sense to allow selective tracing of one or more threads. For one, it is not guaranteed that all threads in a process can be traced - you may run out of resources at some point. Also not tracing all threads may allow you to use bigger buffers for the threads that are traced.
At the same time, I wanted some always-on functionality so I didn't have to repeatedly enable tracing. I therefore added two different versions: "btrace enable [all, <range>]" and "btrace enable auto". Record/replay uses another target on top of the current. It needs to be enabled for a running process each time and it does not allow selective enabling/disabling per thread. If I just followed the "target record" command, I would lose the selective enabling as well as the automatic enabling - and I would risk that not all threads will be traced when running out of resources. Do you have an idea how this could be done?
Thanks,
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] 46+ messages in thread* Re: [patch v6 00/12] branch tracing support for Atom
2012-12-19 9:59 ` Metzger, Markus T
@ 2012-12-19 12:13 ` Mark Kettenis
2012-12-19 12:37 ` Jan Kratochvil
2012-12-20 7:17 ` Jan Kratochvil
2012-12-22 13:08 ` Jan Kratochvil
2 siblings, 1 reply; 46+ messages in thread
From: Mark Kettenis @ 2012-12-19 12:13 UTC (permalink / raw)
To: markus.t.metzger
Cc: jan.kratochvil, palves, tromey, gdb-patches, markus.t.metzger
FWIW, I think btrace functionality would be useful even without full
record support. Some form of branch tracing is available on a lot of
RISCy processors. And I can see people wanting to add support for it
without implementing the full record machinery (which is a lot of
work).
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [patch v6 00/12] branch tracing support for Atom
2012-12-19 12:13 ` Mark Kettenis
@ 2012-12-19 12:37 ` Jan Kratochvil
0 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2012-12-19 12:37 UTC (permalink / raw)
To: Mark Kettenis
Cc: markus.t.metzger, palves, tromey, gdb-patches, markus.t.metzger
On Wed, 19 Dec 2012 13:13:03 +0100, Mark Kettenis wrote:
> FWIW, I think btrace functionality would be useful even without full
> record support. Some form of branch tracing is available on a lot of
> RISCy processors. And I can see people wanting to add support for it
> without implementing the full record machinery (which is a lot of
> work).
Intel BTS does not provide "full record machinery", it can be used only for
the btranch tracing.
It is only questionable whether the new branch tracing should share the same
user interface with the existing full record machinery interface "record".
Regards,
Jan
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [patch v6 00/12] branch tracing support for Atom
2012-12-19 9:59 ` Metzger, Markus T
2012-12-19 12:13 ` Mark Kettenis
@ 2012-12-20 7:17 ` Jan Kratochvil
2012-12-20 9:14 ` Metzger, Markus T
2012-12-22 13:08 ` Jan Kratochvil
2 siblings, 1 reply; 46+ messages in thread
From: Jan Kratochvil @ 2012-12-20 7:17 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
On Wed, 19 Dec 2012 10:59:37 +0100, Metzger, Markus T wrote:
> I see how this could be done. This would require the btrace command to work
> on instructions, though, instead of blocks.
Yes, that should be easy as the block is contiguous, its starting address is
at an instruction boundary and gdb_buffered_insn_length gives instruction
length for an address.
> One typical command that I do after stopping is "btrace list 1-8" to get
> a rough idea where I came from.
> Translated to record, this would become "info record" followed by "record
> list 18914-18989".
One can make extension of the syntax to give "record list last 8"
or even just "record last 8". GDB even provides "alias" command to even
shorten it for specific user to just "last 8" etc.
> Btw, "record goto" silently discards junk following "end" or "start" and
> "help record goto" does not mention "start" or "end". On the other hand, it
> seems to accept arbitrary expressions as argument.
These are bugs in existing code, it can be fixed.
> I don't know how strict gdb is with regards to backwards compatibility.
Generally it is.
> I'm afraid, though, that it will not be that simple and that we
> will end up doing the full integration and also some changes to
> record/replay in the process, before there will be any support for branch
> tracing in gdb.
AFAIK currently any Intel CPUs available in the market do not provide BTS
anyway. I doubt Atom CPUs are used by developers and/or enterprise
troubleshooting. It would be a different question if there was a way to force
use of the buggy Nehalem BTS which should be good enough in common cases
(maybe) but there is no such option currently available.
> I played around with record/replay and reverse debugging a bit. One thing
> that I did not understand is how multi-threading is handled.
It is not, it is a bug. One should use "set scheduler-locking on".
In reality one cannot record too long sequences due to performance reasons so
one does not want to record multiple threads anyway.
[...]
> I see how I could add a command "record config" that takes "replay" and
> "bts" as arguments and switches between the two.
Currently one uses just "record" to start the full-recording. I was expecting
it could print an error and one would use in newer versions of GDB
"record btrace" vs. "record full" or something like that. "record config"
does not seem convenient enough for daily use to me.
> I also see how I could
> implement "record disassemble", "record list", and "record goto" for BTS.
> The commands would check the config and go one way or another - quite dirty,
> but the only thing doable without spending lots of effort.
I do not see anything dirty there but otherwise I agree
"would check" should be implemented by pushing "target_ops" from record.c vs.
pushing "target_ops" from btrace.c to the GDB target stack when starting the
record session, so that the target methods get used automatically when
target_* dispatchers get called.
> There's still the problem of listing or disassembling
> the last n instructions/blocks (see above) or listing +/- n from the current
> position. This would need to be added to record/replay, as well.
I suggested adding "last" keyword prefix. Yes.
> I would simply mark other "record" commands as not supported for the BTS
> configuration. Since I'm not actually moving the location of any thread, all
> other gdb commands will operate on the location the thread has been stopped.
> Only "record disassemble" and "record list" would work on the current
> instruction for the current thread. And each thread would have a different
> number of instructions as well as current instruction. I do hope that all
> this is acceptable to all maintainers.
It is important that BTS would also modify inferior PC so that normal commands
like "list" work on the current BTS position and "step" or "reverse-step" move
in the BTS position list.
> There's one thing (well, one that I am currently aware of) I don't know how
> to do: enable/disable.
Current full-tracing uses "record" (for BTS "record btrace") and "record stop"
is also already used.
> Due to the high cost of branch tracing, it makes
> sense to allow selective tracing of one or more threads. For one, it is not
> guaranteed that all threads in a process can be traced - you may run out of
> resources at some point. Also not tracing all threads may allow you to use
> bigger buffers for the threads that are traced.
"record btrace" can parse parameters like "btrace enable" does.
> At the same time, I wanted some always-on functionality so I didn't have to
> repeatedly enable tracing. I therefore added two different versions: "btrace
> enable [all, <range>]" and "btrace enable auto". Record/replay uses another
> target on top of the current.
btrace also needs to - so that "step" and "reverse-step" work there as they
catch target_resume/target_wait.
> It needs to be enabled for a running process
> each time and it does not allow selective enabling/disabling per thread. If
> I just followed the "target record" command, I would lose the selective
> enabling as well as the automatic enabling - and I would risk that not all
> threads will be traced when running out of resources. Do you have an idea
> how this could be done?
Going to look at it today.
Thanks,
Jan
^ permalink raw reply [flat|nested] 46+ messages in thread
* RE: [patch v6 00/12] branch tracing support for Atom
2012-12-20 7:17 ` Jan Kratochvil
@ 2012-12-20 9:14 ` Metzger, Markus T
2012-12-20 11:43 ` Jan Kratochvil
0 siblings, 1 reply; 46+ messages in thread
From: Metzger, Markus T @ 2012-12-20 9:14 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
> -----Original Message-----
> From: Jan Kratochvil [mailto:jan.kratochvil@redhat.com]
> Sent: Thursday, December 20, 2012 8:17 AM
> > One typical command that I do after stopping is "btrace list 1-8" to get
> > a rough idea where I came from.
> > Translated to record, this would become "info record" followed by "record
> > list 18914-18989".
>
> One can make extension of the syntax to give "record list last 8"
> or even just "record last 8". GDB even provides "alias" command to even
> shorten it for specific user to just "last 8" etc.
I will think about the "record list" and "record disas" command syntax.
How do you like temporarily adding debugger variables "$end", "$start", and "$here" and accepting the same syntax that list and disas accept? I don't know how difficult that will be to implement, though.
> > I'm afraid, though, that it will not be that simple and that we
> > will end up doing the full integration and also some changes to
> > record/replay in the process, before there will be any support for branch
> > tracing in gdb.
>
> AFAIK currently any Intel CPUs available in the market do not provide BTS
> anyway. I doubt Atom CPUs are used by developers and/or enterprise
> troubleshooting. It would be a different question if there was a way to force
> use of the buggy Nehalem BTS which should be good enough in common cases
> (maybe) but there is no such option currently available.
Atom might be relevant for Android developers.
A force option would have been possible had we not disabled it in the kernel.
> > I played around with record/replay and reverse debugging a bit. One thing
> > that I did not understand is how multi-threading is handled.
>
> It is not, it is a bug. One should use "set scheduler-locking on".
> In reality one cannot record too long sequences due to performance reasons so
> one does not want to record multiple threads anyway.
Ah. I always wondered whether GDB is able to step individual threads.
In that case, branch tracing would already be an improvement over record/replay for multi-threaded programs.
Btw, is anybody actively working on fixing record/replay?
> > I see how I could add a command "record config" that takes "replay" and
> > "bts" as arguments and switches between the two.
>
> Currently one uses just "record" to start the full-recording. I was expecting
> it could print an error and one would use in newer versions of GDB
> "record btrace" vs. "record full" or something like that. "record config"
> does not seem convenient enough for daily use to me.
OK.
> > I also see how I could
> > implement "record disassemble", "record list", and "record goto" for BTS.
> > The commands would check the config and go one way or another - quite dirty,
> > but the only thing doable without spending lots of effort.
>
> I do not see anything dirty there but otherwise I agree
Good.
> "would check" should be implemented by pushing "target_ops" from record.c vs.
> pushing "target_ops" from btrace.c to the GDB target stack when starting the
> record session, so that the target methods get used automatically when
> target_* dispatchers get called.
For "goto", "list", and "disas", I don't need to overwrite any target ops.
> > I would simply mark other "record" commands as not supported for the BTS
> > configuration. Since I'm not actually moving the location of any thread, all
> > other gdb commands will operate on the location the thread has been stopped.
> > Only "record disassemble" and "record list" would work on the current
> > instruction for the current thread. And each thread would have a different
> > number of instructions as well as current instruction. I do hope that all
> > this is acceptable to all maintainers.
>
> It is important that BTS would also modify inferior PC so that normal commands
> like "list" work on the current BTS position and "step" or "reverse-step" move
> in the BTS position list.
That would be the second step. Otherwise, I will really end up implementing the entire record/replay machinery for branch tracing.
Regarding stepping, reverse-next and reverse-finish will have to operate on a fake call stack we compute from collecting calls and rets in the branch trace. As will next and finish when inside the history. I don't know how much I will be able to reuse from the record/replay implementation.
All stepping commands on branch trace will further only affect the current thread, independent of scheduler-locking. This will be a major difference to record/replay once that is fixed.
> > There's one thing (well, one that I am currently aware of) I don't know how
> > to do: enable/disable.
>
> Current full-tracing uses "record" (for BTS "record btrace") and "record stop"
> is also already used.
>
>
> > Due to the high cost of branch tracing, it makes
> > sense to allow selective tracing of one or more threads. For one, it is not
> > guaranteed that all threads in a process can be traced - you may run out of
> > resources at some point. Also not tracing all threads may allow you to use
> > bigger buffers for the threads that are traced.
>
> "record btrace" can parse parameters like "btrace enable" does.
OK.
> > At the same time, I wanted some always-on functionality so I didn't have to
> > repeatedly enable tracing. I therefore added two different versions: "btrace
> > enable [all, <range>]" and "btrace enable auto". Record/replay uses another
> > target on top of the current.
>
> btrace also needs to - so that "step" and "reverse-step" work there as they
> catch target_resume/target_wait.
This will not be enough (see above).
> > It needs to be enabled for a running process
> > each time and it does not allow selective enabling/disabling per thread. If
> > I just followed the "target record" command, I would lose the selective
> > enabling as well as the automatic enabling - and I would risk that not all
> > threads will be traced when running out of resources. Do you have an idea
> > how this could be done?
>
> Going to look at it today.
Thanks.
Btw, are you the record/replay maintainer?
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] 46+ messages in thread
* Re: [patch v6 00/12] branch tracing support for Atom
2012-12-20 9:14 ` Metzger, Markus T
@ 2012-12-20 11:43 ` Jan Kratochvil
2012-12-20 15:20 ` Metzger, Markus T
0 siblings, 1 reply; 46+ messages in thread
From: Jan Kratochvil @ 2012-12-20 11:43 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
On Thu, 20 Dec 2012 10:13:26 +0100, Metzger, Markus T wrote:
> > One can make extension of the syntax to give "record list last 8"
> > or even just "record last 8". GDB even provides "alias" command to even
> > shorten it for specific user to just "last 8" etc.
>
> I will think about the "record list" and "record disas" command syntax.
>
> How do you like temporarily adding debugger variables "$end", "$start", and
> "$here" and accepting the same syntax that list and disas accept? I don't
> know how difficult that will be to implement, though.
I find it overengineered, "record list $end-42" I find already more
complicated than a new command "btrace list 42".
I do not find great that current record.c numbers history one way and btrace
would number history the opposite way. I find the default direction should be
the same and it should be easy enough to type each time.
> Btw, is anybody actively working on fixing record/replay?
Unaware of. Recording of newer features like VEX seems to be missing.
> Regarding stepping, reverse-next and reverse-finish will have to operate on
> a fake call stack we compute from collecting calls and rets in the branch
> trace.
I was mentioning only reverse-step. Not reverse-next or reverse-finish, so
that one should not need the fake call stack.
But as I checked now reverse-step itself already needs a fake call stack for
various checks it does.
But I find / you are right that implementing even reverse-step is an add-on
work, not requiring much to rewrite the existing code. The storage of history
information between record.c a btrace.c needs to be completely different
anyway.
So I agree now the reverse-* compatibility is outside of the scope of the
initial commit.
> As will next and finish when inside the history. I don't know how
> much I will be able to reuse from the record/replay implementation.
Probably not at all. Just there should remain the same to_resume/to_wait
hooking.
> All stepping commands on branch trace will further only affect the current
> thread, independent of scheduler-locking. This will be a major difference to
> record/replay once that is fixed.
OK.
> Btw, are you the record/replay maintainer?
No, only a user (with IIRC just one fix).
Thanks,
Jan
^ permalink raw reply [flat|nested] 46+ messages in thread
* RE: [patch v6 00/12] branch tracing support for Atom
2012-12-20 11:43 ` Jan Kratochvil
@ 2012-12-20 15:20 ` Metzger, Markus T
2012-12-21 19:12 ` Jan Kratochvil
0 siblings, 1 reply; 46+ messages in thread
From: Metzger, Markus T @ 2012-12-20 15:20 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
> -----Original Message-----
> From: Jan Kratochvil [mailto:jan.kratochvil@redhat.com]
> Sent: Thursday, December 20, 2012 12:30 PM
> > How do you like temporarily adding debugger variables "$end", "$start", and
> > "$here" and accepting the same syntax that list and disas accept? I don't
> > know how difficult that will be to implement, though.
>
> I find it overengineered, "record list $end-42" I find already more
> complicated than a new command "btrace list 42".
My use case is to start with looking at the last 20 or so instructions. If that's not enough, I want to look at the next 20. This would not be supported by just adding "record list last <n>".
> I do not find great that current record.c numbers history one way and btrace
> would number history the opposite way. I find the default direction should be
> the same and it should be easy enough to type each time.
I wanted to keep the numbering of record/replay. That's why I added those variables to be able to express what I want.
Personally, I find the opposite numbering, i.e. from newest to oldest, more intuitive and more useful, since I'm typically more interested in the tail of the trace than the head.
Is the instruction number used anywhere outside "record goto"?
> But I find / you are right that implementing even reverse-step is an add-on
> work, not requiring much to rewrite the existing code. The storage of history
> information between record.c a btrace.c needs to be completely different
> anyway.
>
> So I agree now the reverse-* compatibility is outside of the scope of the
> initial commit.
Glad to hear that.
> > As will next and finish when inside the history. I don't know how
> > much I will be able to reuse from the record/replay implementation.
>
> Probably not at all. Just there should remain the same to_resume/to_wait
> hooking.
I'm not familiar with the implementation. I would expect, though, that it won't be enough to implement to_resume and to_wait hooks. I would rather expect that I will need to implement new stepping commands. I further expect that I would need to replace frame unwinding. For all other commands, I can only hope that gdb is OK with a target that can read (not write) RIP but no other register and that can access only code memory.
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] 46+ messages in thread
* Re: [patch v6 00/12] branch tracing support for Atom
2012-12-20 15:20 ` Metzger, Markus T
@ 2012-12-21 19:12 ` Jan Kratochvil
0 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2012-12-21 19:12 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
On Thu, 20 Dec 2012 16:20:13 +0100, Metzger, Markus T wrote:
> My use case is to start with looking at the last 20 or so instructions. If
> that's not enough, I want to look at the next 20. This would not be
> supported by just adding "record list last <n>".
I believe the current "view" style command of btrace should behave like normal
"list" for the native GDB behavior.
"btrace 2" shows:
(gdb) btrace 2
0x000000000048bda0 <poll@plt+0>: jmpq *0x17a599a(%rip) # 0x1c31740 <poll@got.plt>
(gdb)
0x000000000048bda0 <poll@plt+0>: jmpq *0x17a599a(%rip) # 0x1c31740 <poll@got.plt>
(gdb)
But then hitting just enter does not go further (to "btrace 3"), it repeats
still the same output. In such case there should have been at least
"dont_repeat ();". But I believe it would be more convenient to list the next
btrace records.
"btrace list" behaves the same, repeating the same content. And after
"btrace list 1-9" one has to add the numbers to display "btrace list 1-19",
single newline could advance on its own. "btrace list -" could go backwards,
"btrace list" forward - like the "list" command does. But here is the
question of positive/negative numbers direction, discussed below.
I am fine with changing the cosmetic issues above in an additional patchset,
as long as it is all done before the next release 7.6.
> I wanted to keep the numbering of record/replay. That's why I added those
> variables to be able to express what I want.
>
> Personally, I find the opposite numbering, i.e. from newest to oldest, more
> intuitive and more useful, since I'm typically more interested in the tail
> of the trace than the head.
I agree one is interested in the tail but there is at least the established
standard of "record" numbering direction. (+FYI I find the existing "record"
direction more logical myself.)
> Is the instruction number used anywhere outside "record goto"?
From record.c also in "info record" and for bookmarks ("info bookmark",
"goto-bookmark" etc.).
> > Probably not at all. Just there should remain the same to_resume/to_wait
> > hooking.
>
> I'm not familiar with the implementation. I would expect, though, that it
> won't be enough to implement to_resume and to_wait hooks. I would rather
> expect that I will need to implement new stepping commands.
The idea of the "record" implementation is that the same standard stepping
commands work the same for "record" history, by emulating the target events.
So that even new commands/features will work with the existing "record"
implementation.
to_wait updates real hardware registers/memory when moving in history so
"everything just works".
> I further expect that I would need to replace frame unwinding.
Just to provide another unwinder, besides the several existing ones. Some
unwinders are dwarf2_frame_unwind, inline_frame_unwind,
dwarf2_tailcall_frame_unwind, then the hardware ones like i386_frame_unwind.
The other possibility is to use existing unwinder (typically
dwarf2_frame_unwind) and simulate memory as if it had the simulated/expected
frames pointers; but for various reasons I do not find it right for btrace
unwinding - as it already needs to know how the frame looked at that point, so
I find cleaner to create the appropriate GDB frame structures instead of
faking the target memory so that the existing unwinders create them that way.
> For all other commands, I can
> only hope that gdb is OK with a target that can read (not write) RIP but no
> other register and that can access only code memory.
GDB accesses stack memory each time, so the virtual btrace unwinder would need
to be really ahead of all the other unwinders so that it prevents such
accesses.
GDB also inserts/removes breakpoints each time, this could be reused from
record.c and its record_insert_breakpoint / record_remove_breakpoint.
("set breakpoint always-inserted on" reduces these accesses but it is not
a default yet.)
Then it could work I hope, "set debug target 1" shows the accesses.
I believe one could rather just ask user
Do you really want to read possibly stale memory? (y or n)
or possibly just to print each time
warning: The reported memory content may be stale!
as one may want to print just some global variable when already
reverse-stepped in a btrace history. Doing some "bookmark", "continue",
"print errno", "goto-bookmark 5" may be too inconvenient.
Thanks,
Jan
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [patch v6 00/12] branch tracing support for Atom
2012-12-19 9:59 ` Metzger, Markus T
2012-12-19 12:13 ` Mark Kettenis
2012-12-20 7:17 ` Jan Kratochvil
@ 2012-12-22 13:08 ` Jan Kratochvil
2013-01-01 16:35 ` Jan Kratochvil
2 siblings, 1 reply; 46+ messages in thread
From: Jan Kratochvil @ 2012-12-22 13:08 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
On Wed, 19 Dec 2012 10:59:37 +0100, Metzger, Markus T wrote:
> At the same time, I wanted some always-on functionality so I didn't have to
> repeatedly enable tracing. I therefore added two different versions: "btrace
> enable [all, <range>]" and "btrace enable auto".
I miss a bit (1) some resulting message saying "New threads will get branch
tracing turned on automatically." and message like "Thread 2 already has
branch tracing turned on." + "Thread 3 branch tracing has been turned on." or
something like that.
And (2) "info btrace" - or with the new move under record - "info record"
where it displays for each thread whether the tracing is on or off and whether
new threads get traced or not. Maybe it could be also added to "info threads",
if you want to / there is no objection to it.
With existing "record" one knows unfortunately very well whether the tracing
is turned on (=it is very slow).
> Record/replay uses another target on top of the current. It needs to be
> enabled for a running process each time
I do not think it is appropriate for "record". As it is very slow one wants
to record on the interesting last spot of the execution.
But in principle I think the feature should apply for all (both) record
backends - both the current and the btrace one.
> and it does not allow selective enabling/disabling per thread.
This may be a missing feature for the "record" functionality, it would be also
good to share it with btrace, at least for the CLI interface design for now.
> If I just followed the "target record" command, I would lose the selective
> enabling as well as the automatic enabling
Pushing of the new target could be hooked to to_post_startup_inferior and
to_post_attach, I hope that's enough.
> - and I would risk that not all threads will be traced when running out of
> resources.
I do not understand here which resources may be unavailable and what GDB can
about it.
Thanks,
Jan
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [patch v6 00/12] branch tracing support for Atom
2012-12-22 13:08 ` Jan Kratochvil
@ 2013-01-01 16:35 ` Jan Kratochvil
0 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2013-01-01 16:35 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: palves, tromey, kettenis, gdb-patches, markus.t.metzger
On Sat, 22 Dec 2012 14:08:12 +0100, Jan Kratochvil wrote:
> On Wed, 19 Dec 2012 10:59:37 +0100, Metzger, Markus T wrote:
> > If I just followed the "target record" command, I would lose the selective
> > enabling as well as the automatic enabling
>
> Pushing of the new target could be hooked to to_post_startup_inferior and
> to_post_attach, I hope that's enough.
When thinking about it the btrace target should stay pushed
after "record btrace auto". And contrary to the current record.c practice it
would no longer unpush itself during to_mourn_inferior, to_kill etc.
(The same wouhld apply to a new feature "record auto" as it is the same issue.
Just I do not want to get you into a too much work of improving record.c,
I can take some parts of record.c if you ask for.)
Also the keeping up to date of observer_attach_new_thread and
observer_detach_new_thread could be simplified by creating a new to_target
method would would be called together with observer_notify_new_thread.
Then one can forget about to_post_startup_inferior/to_post_attach, that was
a wrong advice.
Thanks,
Jan
^ permalink raw reply [flat|nested] 46+ messages in thread