This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH v3 01/15] btrace: add struct btrace_data


Add a structure to hold the branch trace data and an enum to describe
the format of that data.  So far, only BTS is supported.  Also added
a NONE format to indicate that no branch trace data is available.

This will make it easier to support different branch trace formats in
the future.

2015-01-29  Markus Metzger  <markus.t.metzger@intel.com>

	* Makefile.in (SFILES): Add common/btrace-common.c.
	(COMMON_OBS): Add common/btrace-common.o.
	(btrace-common.o): Add build rules.
	* btrace.c (parse_xml_btrace): Update parameters.
	(parse_xml_btrace_block): Set format field.
	(btrace_add_pc, btrace_fetch): Use struct btrace_data.
	(do_btrace_data_cleanup, make_cleanup_btrace_data): New.
	(btrace_compute_ftrace): Split into this and...
	(btrace_compute_ftrace_bts): ...this.
	(btrace_stitch_trace): Split into this and...
	(btrace_stitch_bts): ...this.
	* btrace.h (parse_xml_btrace): Update parameters.
	(make_cleanup_btrace_data): New.
	* common/btrace-common.c: New.
	* common/btrace-common.h: Include common-defs.h.
	(btrace_block_s): Update comment.
	(btrace_format): New.
	(btrace_format_string): New.
	(btrace_data_bts): New.
	(btrace_data): New.
	(btrace_data_init, btrace_data_fini, btrace_data_empty): New.
	* remote.c (remote_read_btrace): Update parameters.
	* target.c (target_read_btrace): Update parameters.
	* target.h (target_read_btrace): Update parameters.
	(target_ops)<to_read_btrace>: Update parameters.
	* x86-linux-nat.c (x86_linux_read_btrace): Update parameters.
	* target-delegates.c: Regenerate.
	* target-debug (target_debug_print_struct_btrace_data_p): New.

nat/
	* linux-btrace.c (linux_read_btrace): Split into this and...
	(linux_read_bts): ...this.
	* linux-btrace.h (linux_read_btrace): Update parameters.

gdbserver/
	* Makefile.in (SFILES): Add common/btrace-common.c.
	(OBS): Add common/btrace-common.o.
	(btrace-common.o): Add build rules.
	* linux-low: Include btrace-common.h.
	(linux_low_read_btrace): Use struct btrace_data.  Call
	btrace_data_init and btrace_data_fini.
---
 gdb/Makefile.in            |   7 ++-
 gdb/btrace.c               | 154 ++++++++++++++++++++++++++++++++-------------
 gdb/btrace.h               |   6 +-
 gdb/common/btrace-common.c |  83 ++++++++++++++++++++++++
 gdb/common/btrace-common.h |  49 +++++++++++++--
 gdb/gdbserver/Makefile.in  |   8 ++-
 gdb/gdbserver/linux-low.c  |  37 ++++++++---
 gdb/nat/linux-btrace.c     |  36 ++++++++---
 gdb/nat/linux-btrace.h     |   2 +-
 gdb/remote.c               |   4 +-
 gdb/target-debug.h         |   2 +
 gdb/target-delegates.c     |   8 +--
 gdb/target.c               |   2 +-
 gdb/target.h               |   8 +--
 gdb/x86-linux-nat.c        |   2 +-
 15 files changed, 324 insertions(+), 84 deletions(-)
 create mode 100644 gdb/common/btrace-common.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 8addef4..bfebf61 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -873,6 +873,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	common/format.c common/filestuff.c btrace.c record-btrace.c ctf.c \
 	target/waitstatus.c common/print-utils.c common/rsp-low.c \
 	common/errors.c common/common-debug.c common/common-exceptions.c \
+	common/btrace-common.c \
 	$(SUBDIR_GCC_COMPILE_SRCS)
 
 LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
@@ -1060,7 +1061,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	common-utils.o buffer.o ptid.o gdb-dlfcn.o common-agent.o \
 	format.o registry.o btrace.o record-btrace.o waitstatus.o \
 	print-utils.o rsp-low.o errors.o common-debug.o debug.o \
-	common-exceptions.o \
+	common-exceptions.o btrace-common.o \
 	$(SUBDIR_GCC_COMPILE_OBS)
 
 TSOBS = inflow.o
@@ -2234,6 +2235,10 @@ mingw-strerror.o: ${srcdir}/common/mingw-strerror.c
 	$(COMPILE) $(srcdir)/common/mingw-strerror.c
 	$(POSTCOMPILE)
 
+btrace-common.o: ${srcdir}/common/btrace-common.c
+	$(COMPILE) $(srcdir)/common/btrace-common.c
+	$(POSTCOMPILE)
+
 #
 # gdb/target/ dependencies
 #
diff --git a/gdb/btrace.c b/gdb/btrace.c
index b6e6bf7..3b20981 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -585,25 +585,22 @@ ftrace_update_insns (struct btrace_function *bfun, CORE_ADDR pc)
     ftrace_debug (bfun, "update insn");
 }
 
-/* Compute the function branch trace from a block branch trace BTRACE for
-   a thread given by BTINFO.  */
+/* Compute the function branch trace from BTS trace.  */
 
 static void
-btrace_compute_ftrace (struct btrace_thread_info *btinfo,
-		       VEC (btrace_block_s) *btrace)
+btrace_compute_ftrace_bts (struct btrace_thread_info *btinfo,
+			   const struct btrace_data_bts *btrace)
 {
   struct btrace_function *begin, *end;
   struct gdbarch *gdbarch;
   unsigned int blk;
   int level;
 
-  DEBUG ("compute ftrace");
-
   gdbarch = target_gdbarch ();
   begin = btinfo->begin;
   end = btinfo->end;
   level = begin != NULL ? -btinfo->level : INT_MAX;
-  blk = VEC_length (btrace_block_s, btrace);
+  blk = VEC_length (btrace_block_s, btrace->blocks);
 
   while (blk != 0)
     {
@@ -612,7 +609,7 @@ btrace_compute_ftrace (struct btrace_thread_info *btinfo,
 
       blk -= 1;
 
-      block = VEC_index (btrace_block_s, btrace, blk);
+      block = VEC_index (btrace_block_s, btrace->blocks, blk);
       pc = block->begin;
 
       for (;;)
@@ -675,12 +672,34 @@ btrace_compute_ftrace (struct btrace_thread_info *btinfo,
   btinfo->level = -level;
 }
 
+/* Compute the function branch trace from a block branch trace BTRACE for
+   a thread given by BTINFO.  */
+
+static void
+btrace_compute_ftrace (struct btrace_thread_info *btinfo,
+		       struct btrace_data *btrace)
+{
+  DEBUG ("compute ftrace");
+
+  switch (btrace->format)
+    {
+    case BTRACE_FORMAT_NONE:
+      return;
+
+    case BTRACE_FORMAT_BTS:
+      btrace_compute_ftrace_bts (btinfo, &btrace->variant.bts);
+      return;
+    }
+
+  internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
+}
+
 /* Add an entry for the current PC.  */
 
 static void
 btrace_add_pc (struct thread_info *tp)
 {
-  VEC (btrace_block_s) *btrace;
+  struct btrace_data btrace;
   struct btrace_block *block;
   struct regcache *regcache;
   struct cleanup *cleanup;
@@ -689,14 +708,17 @@ btrace_add_pc (struct thread_info *tp)
   regcache = get_thread_regcache (tp->ptid);
   pc = regcache_read_pc (regcache);
 
-  btrace = NULL;
-  cleanup = make_cleanup (VEC_cleanup (btrace_block_s), &btrace);
+  btrace_data_init (&btrace);
+  btrace.format = BTRACE_FORMAT_BTS;
+  btrace.variant.bts.blocks = NULL;
 
-  block = VEC_safe_push (btrace_block_s, btrace, NULL);
+  cleanup = make_cleanup_btrace_data (&btrace);
+
+  block = VEC_safe_push (btrace_block_s, btrace.variant.bts.blocks, NULL);
   block->begin = pc;
   block->end = pc;
 
-  btrace_compute_ftrace (&tp->btrace, btrace);
+  btrace_compute_ftrace (&tp->btrace, &btrace);
 
   do_cleanups (cleanup);
 }
@@ -760,31 +782,24 @@ btrace_teardown (struct thread_info *tp)
   btrace_clear (tp);
 }
 
-/* Adjust the block trace in order to stitch old and new trace together.
-   BTRACE is the new delta trace between the last and the current stop.
-   BTINFO is the old branch trace until the last stop.
-   May modify BTRACE as well as the existing trace in BTINFO.
-   Return 0 on success, -1 otherwise.  */
+/* Stitch branch trace in BTS format.  */
 
 static int
-btrace_stitch_trace (VEC (btrace_block_s) **btrace,
-		     const struct btrace_thread_info *btinfo)
+btrace_stitch_bts (struct btrace_data_bts *btrace,
+		   const struct btrace_thread_info *btinfo)
 {
   struct btrace_function *last_bfun;
   struct btrace_insn *last_insn;
   btrace_block_s *first_new_block;
 
-  /* If we don't have trace, there's nothing to do.  */
-  if (VEC_empty (btrace_block_s, *btrace))
-    return 0;
-
   last_bfun = btinfo->end;
   gdb_assert (last_bfun != NULL);
 
   /* Beware that block trace starts with the most recent block, so the
      chronologically first block in the new trace is the last block in
      the new trace's block vector.  */
-  first_new_block = VEC_last (btrace_block_s, *btrace);
+  gdb_assert (!VEC_empty (btrace_block_s, btrace->blocks));
+  first_new_block = VEC_last (btrace_block_s, btrace->blocks);
   last_insn = VEC_last (btrace_insn_s, last_bfun->insn);
 
   /* If the current PC at the end of the block is the same as in our current
@@ -796,9 +811,9 @@ btrace_stitch_trace (VEC (btrace_block_s) **btrace,
      In the second case, the delta trace vector should contain exactly one
      entry for the partial block containing the current PC.  Remove it.  */
   if (first_new_block->end == last_insn->pc
-      && VEC_length (btrace_block_s, *btrace) == 1)
+      && VEC_length (btrace_block_s, btrace->blocks) == 1)
     {
-      VEC_pop (btrace_block_s, *btrace);
+      VEC_pop (btrace_block_s, btrace->blocks);
       return 0;
     }
 
@@ -834,6 +849,32 @@ btrace_stitch_trace (VEC (btrace_block_s) **btrace,
   return 0;
 }
 
+/* Adjust the block trace in order to stitch old and new trace together.
+   BTRACE is the new delta trace between the last and the current stop.
+   BTINFO is the old branch trace until the last stop.
+   May modifx BTRACE as well as the existing trace in BTINFO.
+   Return 0 on success, -1 otherwise.  */
+
+static int
+btrace_stitch_trace (struct btrace_data *btrace,
+		     const struct btrace_thread_info *btinfo)
+{
+  /* If we don't have trace, there's nothing to do.  */
+  if (btrace_data_empty (btrace))
+    return 0;
+
+  switch (btrace->format)
+    {
+    case BTRACE_FORMAT_NONE:
+      return 0;
+
+    case BTRACE_FORMAT_BTS:
+      return btrace_stitch_bts (&btrace->variant.bts, btinfo);
+    }
+
+  internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
+}
+
 /* Clear the branch trace histories in BTINFO.  */
 
 static void
@@ -855,13 +896,12 @@ btrace_fetch (struct thread_info *tp)
 {
   struct btrace_thread_info *btinfo;
   struct btrace_target_info *tinfo;
-  VEC (btrace_block_s) *btrace;
+  struct btrace_data btrace;
   struct cleanup *cleanup;
   int errcode;
 
   DEBUG ("fetch thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
 
-  btrace = NULL;
   btinfo = &tp->btrace;
   tinfo = btinfo->target;
   if (tinfo == NULL)
@@ -873,7 +913,8 @@ btrace_fetch (struct thread_info *tp)
   if (btinfo->replay != NULL)
     return;
 
-  cleanup = make_cleanup (VEC_cleanup (btrace_block_s), &btrace);
+  btrace_data_init (&btrace);
+  cleanup = make_cleanup_btrace_data (&btrace);
 
   /* Let's first try to extend the trace we already have.  */
   if (btinfo->end != NULL)
@@ -890,7 +931,7 @@ btrace_fetch (struct thread_info *tp)
 	  errcode = target_read_btrace (&btrace, tinfo, BTRACE_READ_NEW);
 
 	  /* If we got any new trace, discard what we have.  */
-	  if (errcode == 0 && !VEC_empty (btrace_block_s, btrace))
+	  if (errcode == 0 && !btrace_data_empty (&btrace))
 	    btrace_clear (tp);
 	}
 
@@ -909,10 +950,10 @@ btrace_fetch (struct thread_info *tp)
     error (_("Failed to read branch trace."));
 
   /* Compute the trace, provided we have any.  */
-  if (!VEC_empty (btrace_block_s, btrace))
+  if (!btrace_data_empty (&btrace))
     {
       btrace_clear_history (btinfo);
-      btrace_compute_ftrace (btinfo, btrace);
+      btrace_compute_ftrace (btinfo, &btrace);
     }
 
   do_cleanups (cleanup);
@@ -984,16 +1025,30 @@ 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_data *btrace;
   struct btrace_block *block;
   ULONGEST *begin, *end;
 
   btrace = user_data;
-  block = VEC_safe_push (btrace_block_s, *btrace, NULL);
+
+  switch (btrace->format)
+    {
+    case BTRACE_FORMAT_BTS:
+      break;
+
+    case BTRACE_FORMAT_NONE:
+      btrace->format = BTRACE_FORMAT_BTS;
+      btrace->variant.bts.blocks = NULL;
+      break;
+
+    default:
+      gdb_xml_error (parser, _("Btrace format error."));
+    }
 
   begin = xml_find_attribute (attributes, "begin")->value;
   end = xml_find_attribute (attributes, "end")->value;
 
+  block = VEC_safe_push (btrace_block_s, btrace->variant.bts.blocks, NULL);
   block->begin = *begin;
   block->end = *end;
 }
@@ -1025,18 +1080,19 @@ static const struct gdb_xml_element btrace_elements[] = {
 
 /* See btrace.h.  */
 
-VEC (btrace_block_s) *
-parse_xml_btrace (const char *buffer)
+void
+parse_xml_btrace (struct btrace_data *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);
+  btrace->format = BTRACE_FORMAT_NONE;
+
+  cleanup = make_cleanup_btrace_data (btrace);
   errcode = gdb_xml_parse_quick (_("btrace"), "btrace.dtd", btrace_elements,
-				 buffer, &btrace);
+				 buffer, btrace);
   if (errcode != 0)
     error (_("Error parsing branch trace."));
 
@@ -1048,8 +1104,6 @@ parse_xml_btrace (const char *buffer)
   error (_("Cannot process branch trace.  XML parsing is not supported."));
 
 #endif  /* !defined (HAVE_LIBEXPAT) */
-
-  return btrace;
 }
 
 /* See btrace.h.  */
@@ -1526,3 +1580,19 @@ btrace_is_empty (struct thread_info *tp)
 
   return btrace_insn_cmp (&begin, &end) == 0;
 }
+
+/* Forward the cleanup request.  */
+
+static void
+do_btrace_data_cleanup (void *arg)
+{
+  btrace_data_fini (arg);
+}
+
+/* See btrace.h.  */
+
+struct cleanup *
+make_cleanup_btrace_data (struct btrace_data *data)
+{
+  return make_cleanup (do_btrace_data_cleanup, data);
+}
diff --git a/gdb/btrace.h b/gdb/btrace.h
index e3a2419..730cb5f 100644
--- a/gdb/btrace.h
+++ b/gdb/btrace.h
@@ -235,8 +235,8 @@ extern void btrace_clear (struct thread_info *);
 /* Clear the branch trace for all threads when an object file goes away.  */
 extern void btrace_free_objfile (struct objfile *);
 
-/* Parse a branch trace xml document into a block vector.  */
-extern VEC (btrace_block_s) *parse_xml_btrace (const char*);
+/* Parse a branch trace xml document XML into DATA.  */
+extern void parse_xml_btrace (struct btrace_data *data, const char *xml);
 
 /* Dereference a branch trace instruction iterator.  Return a pointer to the
    instruction the iterator points to.  */
@@ -339,5 +339,7 @@ extern int btrace_is_replaying (struct thread_info *tp);
 /* Return non-zero if the branch trace for TP is empty; zero otherwise.  */
 extern int btrace_is_empty (struct thread_info *tp);
 
+/* Create a cleanup for DATA.  */
+extern struct cleanup *make_cleanup_btrace_data (struct btrace_data *data);
 
 #endif /* BTRACE_H */
diff --git a/gdb/common/btrace-common.c b/gdb/common/btrace-common.c
new file mode 100644
index 0000000..878cfed
--- /dev/null
+++ b/gdb/common/btrace-common.c
@@ -0,0 +1,83 @@
+/* Copyright (C) 2014 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 "common-defs.h"
+#include "btrace-common.h"
+
+
+/* See btrace-common.h.  */
+
+const char *
+btrace_format_string (enum btrace_format format)
+{
+  switch (format)
+    {
+    case BTRACE_FORMAT_NONE:
+      return _("No or unknown format");
+
+    case BTRACE_FORMAT_BTS:
+      return _("Intel(R) Branch Trace Store");
+    }
+
+  internal_error (__FILE__, __LINE__, _("Unknown branch trace format"));
+}
+
+/* See btrace-common.h.  */
+
+void
+btrace_data_init (struct btrace_data *data)
+{
+  data->format = BTRACE_FORMAT_NONE;
+}
+
+/* See btrace-common.h.  */
+
+void
+btrace_data_fini (struct btrace_data *data)
+{
+  switch (data->format)
+    {
+    case BTRACE_FORMAT_NONE:
+      /* Nothing to do.  */
+      return;
+
+    case BTRACE_FORMAT_BTS:
+      VEC_free (btrace_block_s, data->variant.bts.blocks);
+      return;
+    }
+
+  internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
+}
+
+/* See btrace-common.h.  */
+
+int
+btrace_data_empty (struct btrace_data *data)
+{
+  switch (data->format)
+    {
+    case BTRACE_FORMAT_NONE:
+      return 1;
+
+    case BTRACE_FORMAT_BTS:
+      return VEC_empty (btrace_block_s, data->variant.bts.blocks);
+    }
+
+  internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
+}
diff --git a/gdb/common/btrace-common.h b/gdb/common/btrace-common.h
index 6118c0d..a289e8a 100644
--- a/gdb/common/btrace-common.h
+++ b/gdb/common/btrace-common.h
@@ -45,13 +45,42 @@ struct btrace_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.  */
+typedef struct btrace_block btrace_block_s;
 DEF_VEC_O (btrace_block_s);
 
+/* Enumeration of btrace formats.  */
+
+enum btrace_format
+{
+  /* No branch trace format.  */
+  BTRACE_FORMAT_NONE,
+
+  /* Branch trace is in Branch Trace Store format.
+     Actually, the format is a sequence of blocks derived from BTS.  */
+  BTRACE_FORMAT_BTS
+};
+
+/* Branch trace in BTS format.  */
+struct btrace_data_bts
+{
+  /* Branch trace is represented as a vector of branch trace blocks starting
+     with the most recent block.  */
+  VEC (btrace_block_s) *blocks;
+};
+
+/* The branch trace data.  */
+struct btrace_data
+{
+  enum btrace_format format;
+
+  union
+  {
+    /* Format == BTRACE_FORMAT_BTS.  */
+    struct btrace_data_bts bts;
+  } variant;
+};
+
 /* Target specific branch trace information.  */
 struct btrace_target_info;
 
@@ -87,4 +116,16 @@ enum btrace_error
   BTRACE_ERR_OVERFLOW
 };
 
+/* Return a string representation of FORMAT.  */
+extern const char *btrace_format_string (enum btrace_format format);
+
+/* Initialize DATA.  */
+extern void btrace_data_init (struct btrace_data *data);
+
+/* Cleanup DATA.  */
+extern void btrace_data_fini (struct btrace_data *data);
+
+/* Return non-zero if DATA is empty; zero otherwise.  */
+extern int btrace_data_empty (struct btrace_data *data);
+
 #endif /* BTRACE_COMMON_H */
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index b455c5b..e479c7c 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -173,7 +173,8 @@ SFILES=	$(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
 	$(srcdir)/nat/mips-linux-watch.c $(srcdir)/common/print-utils.c \
 	$(srcdir)/common/rsp-low.c $(srcdir)/common/errors.c \
 	$(srcdir)/common/common-debug.c $(srcdir)/common/cleanups.c \
-	$(srcdir)/common/common-exceptions.c $(srcdir)/symbol.c
+	$(srcdir)/common/common-exceptions.c $(srcdir)/symbol.c \
+	$(srcdir)/common/btrace-common.c
 
 DEPFILES = @GDBSERVER_DEPFILES@
 
@@ -187,7 +188,7 @@ OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o \
       mem-break.o hostio.o event-loop.o tracepoint.o xml-utils.o \
       common-utils.o ptid.o buffer.o format.o filestuff.o dll.o notif.o \
       tdesc.o print-utils.o rsp-low.o errors.o common-debug.o cleanups.o \
-      common-exceptions.o symbol.o \
+      common-exceptions.o symbol.o btrace-common.o \
       $(XML_BUILTIN) $(DEPFILES) $(LIBOBJS)
 GDBREPLAY_OBS = gdbreplay.o version.o
 GDBSERVER_LIBS = @GDBSERVER_LIBS@
@@ -594,6 +595,9 @@ ppc-linux.o: ../nat/ppc-linux.c
 linux-personality.o: ../nat/linux-personality.c
 	$(COMPILE) $<
 	$(POSTCOMPILE)
+btrace-common.o: ../common/btrace-common.c
+	$(COMPILE) $<
+	$(POSTCOMPILE)
 
 aarch64.c : $(srcdir)/../regformats/aarch64.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/aarch64.dat aarch64.c
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 5e37dd5..c82e563 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -103,6 +103,7 @@
 
 #ifdef HAVE_LINUX_BTRACE
 # include "nat/linux-btrace.h"
+# include "btrace-common.h"
 #endif
 
 #ifndef HAVE_ELF32_AUXV_T
@@ -5958,12 +5959,13 @@ static int
 linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer,
 		       int type)
 {
-  VEC (btrace_block_s) *btrace;
+  struct btrace_data btrace;
   struct btrace_block *block;
   enum btrace_error err;
   int i;
 
-  btrace = NULL;
+  btrace_data_init (&btrace);
+
   err = linux_read_btrace (&btrace, tinfo, type);
   if (err != BTRACE_ERR_NONE)
     {
@@ -5972,20 +5974,37 @@ linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer,
       else
 	buffer_grow_str0 (buffer, "E.Generic Error.");
 
+      btrace_data_fini (&btrace);
       return -1;
     }
 
-  buffer_grow_str (buffer, "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n");
-  buffer_grow_str (buffer, "<btrace version=\"1.0\">\n");
+  switch (btrace.format)
+    {
+    case BTRACE_FORMAT_NONE:
+      buffer_grow_str0 (buffer, "E.No Trace.");
+      break;
+
+    case BTRACE_FORMAT_BTS:
+      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));
+      for (i = 0;
+	   VEC_iterate (btrace_block_s, btrace.variant.bts.blocks, i, block);
+	   i++)
+	buffer_xml_printf (buffer, "<block begin=\"0x%s\" end=\"0x%s\"/>\n",
+			   paddress (block->begin), paddress (block->end));
 
-  buffer_grow_str0 (buffer, "</btrace>\n");
+      buffer_grow_str0 (buffer, "</btrace>\n");
+      break;
+
+    default:
+      buffer_grow_str0 (buffer, "E.Unknown Trace Format.");
 
-  VEC_free (btrace_block_s, btrace);
+      btrace_data_fini (&btrace);
+      return -1;
+    }
 
+  btrace_data_fini (&btrace);
   return 0;
 }
 #endif /* HAVE_LINUX_BTRACE */
diff --git a/gdb/nat/linux-btrace.c b/gdb/nat/linux-btrace.c
index 1181a4c..6cec5d0 100644
--- a/gdb/nat/linux-btrace.c
+++ b/gdb/nat/linux-btrace.c
@@ -495,12 +495,13 @@ linux_btrace_has_changed (struct btrace_target_info *tinfo)
   return header->data_head != tinfo->data_head;
 }
 
-/* See linux-btrace.h.  */
+/* Read branch trace data in BTS format for the thread given by TINFO into
+   BTRACE using the TYPE reading method.  */
 
-enum btrace_error
-linux_read_btrace (VEC (btrace_block_s) **btrace,
-		   struct btrace_target_info *tinfo,
-		   enum btrace_read_type type)
+static enum btrace_error
+linux_read_bts (struct btrace_data_bts *btrace,
+		struct btrace_target_info *tinfo,
+		enum btrace_read_type type)
 {
   volatile struct perf_event_mmap_page *header;
   const uint8_t *begin, *end, *start;
@@ -522,7 +523,7 @@ linux_read_btrace (VEC (btrace_block_s) **btrace,
       data_head = header->data_head;
 
       /* Delete any leftover trace from the previous iteration.  */
-      VEC_free (btrace_block_s, *btrace);
+      VEC_free (btrace_block_s, btrace->blocks);
 
       if (type == BTRACE_READ_DELTA)
 	{
@@ -559,7 +560,7 @@ linux_read_btrace (VEC (btrace_block_s) **btrace,
       else
 	end = perf_event_buffer_end (tinfo);
 
-      *btrace = perf_event_read_bts (tinfo, begin, end, start, size);
+      btrace->blocks = perf_event_read_bts (tinfo, begin, end, start, size);
 
       /* The stopping thread notifies its ptracer before it is scheduled out.
 	 On multi-core systems, the debugger might therefore run while the
@@ -575,12 +576,27 @@ linux_read_btrace (VEC (btrace_block_s) **btrace,
   /* Prune the incomplete last block (i.e. the first one of inferior execution)
      if we're not doing a delta read.  There is no way of filling in its zeroed
      BEGIN element.  */
-  if (!VEC_empty (btrace_block_s, *btrace) && type != BTRACE_READ_DELTA)
-    VEC_pop (btrace_block_s, *btrace);
+  if (!VEC_empty (btrace_block_s, btrace->blocks)
+      && type != BTRACE_READ_DELTA)
+    VEC_pop (btrace_block_s, btrace->blocks);
 
   return BTRACE_ERR_NONE;
 }
 
+/* See linux-btrace.h.  */
+
+enum btrace_error
+linux_read_btrace (struct btrace_data *btrace,
+		   struct btrace_target_info *tinfo,
+		   enum btrace_read_type type)
+{
+  /* We read btrace in BTS format.  */
+  btrace->format = BTRACE_FORMAT_BTS;
+  btrace->variant.bts.blocks = NULL;
+
+  return linux_read_bts (&btrace->variant.bts, tinfo, type);
+}
+
 #else /* !HAVE_LINUX_PERF_EVENT_H */
 
 /* See linux-btrace.h.  */
@@ -610,7 +626,7 @@ linux_disable_btrace (struct btrace_target_info *tinfo)
 /* See linux-btrace.h.  */
 
 enum btrace_error
-linux_read_btrace (VEC (btrace_block_s) **btrace,
+linux_read_btrace (struct btrace_data *btrace,
 		   struct btrace_target_info *tinfo,
 		   enum btrace_read_type type)
 {
diff --git a/gdb/nat/linux-btrace.h b/gdb/nat/linux-btrace.h
index 3bfb798..1b11aba 100644
--- a/gdb/nat/linux-btrace.h
+++ b/gdb/nat/linux-btrace.h
@@ -70,7 +70,7 @@ extern struct btrace_target_info *linux_enable_btrace (ptid_t ptid);
 extern enum btrace_error linux_disable_btrace (struct btrace_target_info *ti);
 
 /* See to_read_btrace in target.h.  */
-extern enum btrace_error linux_read_btrace (VEC (btrace_block_s) **btrace,
+extern enum btrace_error linux_read_btrace (struct btrace_data *btrace,
 					    struct btrace_target_info *btinfo,
 					    enum btrace_read_type type);
 
diff --git a/gdb/remote.c b/gdb/remote.c
index c4d09ba..e73cdde 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -11419,7 +11419,7 @@ remote_teardown_btrace (struct target_ops *self,
 
 static enum btrace_error
 remote_read_btrace (struct target_ops *self,
-		    VEC (btrace_block_s) **btrace,
+		    struct btrace_data *btrace,
 		    struct btrace_target_info *tinfo,
 		    enum btrace_read_type type)
 {
@@ -11459,7 +11459,7 @@ remote_read_btrace (struct target_ops *self,
     return BTRACE_ERR_UNKNOWN;
 
   cleanup = make_cleanup (xfree, xml);
-  *btrace = parse_xml_btrace (xml);
+  parse_xml_btrace (btrace, xml);
   do_cleanups (cleanup);
 
   return BTRACE_ERR_NONE;
diff --git a/gdb/target-debug.h b/gdb/target-debug.h
index 65db5d9..8a32810 100644
--- a/gdb/target-debug.h
+++ b/gdb/target-debug.h
@@ -144,6 +144,8 @@
   target_debug_do_print (host_address_to_string (X))
 #define target_debug_print_const_struct_frame_unwind_p(X)	\
   target_debug_do_print (host_address_to_string (X))
+#define target_debug_print_struct_btrace_data_p(X)	\
+  target_debug_do_print (host_address_to_string (X))
 
 static void
 target_debug_print_struct_target_waitstatus_p (struct target_waitstatus *status)
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index 9beb5ff..00956ba 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -3191,20 +3191,20 @@ debug_teardown_btrace (struct target_ops *self, struct btrace_target_info *arg1)
 }
 
 static enum btrace_error
-delegate_read_btrace (struct target_ops *self, VEC (btrace_block_s) **arg1, struct btrace_target_info *arg2, enum btrace_read_type arg3)
+delegate_read_btrace (struct target_ops *self, struct btrace_data *arg1, struct btrace_target_info *arg2, enum btrace_read_type arg3)
 {
   self = self->beneath;
   return self->to_read_btrace (self, arg1, arg2, arg3);
 }
 
 static enum btrace_error
-tdefault_read_btrace (struct target_ops *self, VEC (btrace_block_s) **arg1, struct btrace_target_info *arg2, enum btrace_read_type arg3)
+tdefault_read_btrace (struct target_ops *self, struct btrace_data *arg1, struct btrace_target_info *arg2, enum btrace_read_type arg3)
 {
   tcomplain ();
 }
 
 static enum btrace_error
-debug_read_btrace (struct target_ops *self, VEC (btrace_block_s) **arg1, struct btrace_target_info *arg2, enum btrace_read_type arg3)
+debug_read_btrace (struct target_ops *self, struct btrace_data *arg1, struct btrace_target_info *arg2, enum btrace_read_type arg3)
 {
   enum btrace_error result;
   fprintf_unfiltered (gdb_stdlog, "-> %s->to_read_btrace (...)\n", debug_target.to_shortname);
@@ -3212,7 +3212,7 @@ debug_read_btrace (struct target_ops *self, VEC (btrace_block_s) **arg1, struct
   fprintf_unfiltered (gdb_stdlog, "<- %s->to_read_btrace (", debug_target.to_shortname);
   target_debug_print_struct_target_ops_p (&debug_target);
   fputs_unfiltered (", ", gdb_stdlog);
-  target_debug_print_VEC__btrace_block_s__pp (arg1);
+  target_debug_print_struct_btrace_data_p (arg1);
   fputs_unfiltered (", ", gdb_stdlog);
   target_debug_print_struct_btrace_target_info_p (arg2);
   fputs_unfiltered (", ", gdb_stdlog);
diff --git a/gdb/target.c b/gdb/target.c
index 5f0ed6f..763ddcb 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -3414,7 +3414,7 @@ target_teardown_btrace (struct btrace_target_info *btinfo)
 /* See target.h.  */
 
 enum btrace_error
-target_read_btrace (VEC (btrace_block_s) **btrace,
+target_read_btrace (struct btrace_data *btrace,
 		    struct btrace_target_info *btinfo,
 		    enum btrace_read_type type)
 {
diff --git a/gdb/target.h b/gdb/target.h
index 2a40cd1..36fa3c6 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -1022,11 +1022,9 @@ struct target_ops
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Read branch trace data for the thread indicated by BTINFO into DATA.
-       DATA is cleared before new trace is added.
-       The branch trace will start with the most recent block and continue
-       towards older blocks.  */
+       DATA is cleared before new trace is added.  */
     enum btrace_error (*to_read_btrace) (struct target_ops *self,
-					 VEC (btrace_block_s) **data,
+					 struct btrace_data *data,
 					 struct btrace_target_info *btinfo,
 					 enum btrace_read_type type)
       TARGET_DEFAULT_NORETURN (tcomplain ());
@@ -2230,7 +2228,7 @@ extern void target_disable_btrace (struct btrace_target_info *btinfo);
 extern void target_teardown_btrace (struct btrace_target_info *btinfo);
 
 /* See to_read_btrace in struct target_ops.  */
-extern enum btrace_error target_read_btrace (VEC (btrace_block_s) **,
+extern enum btrace_error target_read_btrace (struct btrace_data *,
 					     struct btrace_target_info *,
 					     enum btrace_read_type);
 
diff --git a/gdb/x86-linux-nat.c b/gdb/x86-linux-nat.c
index f7e9037..78b547b 100644
--- a/gdb/x86-linux-nat.c
+++ b/gdb/x86-linux-nat.c
@@ -470,7 +470,7 @@ x86_linux_teardown_btrace (struct target_ops *self,
 
 static enum btrace_error
 x86_linux_read_btrace (struct target_ops *self,
-		       VEC (btrace_block_s) **data,
+		       struct btrace_data *data,
 		       struct btrace_target_info *btinfo,
 		       enum btrace_read_type type)
 {
-- 
1.8.3.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]