Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Markus Metzger <markus.t.metzger@intel.com>
To: jan.kratochvil@redhat.com
Cc: gdb-patches@sourceware.org, markus.t.metzger@gmail.com
Subject: [patch v9 01/23] thread, btrace: add generic branch trace support
Date: Mon, 04 Mar 2013 17:07:00 -0000	[thread overview]
Message-ID: <1362416770-19750-2-git-send-email-markus.t.metzger@intel.com> (raw)
In-Reply-To: <1362416770-19750-1-git-send-email-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, clear, and fetch a thread's branch trace.

2013-03-04  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 btrace_disable.
	* infcmd.c: Include btrace.h.
	(detach_command): Call btrace_disconnect.
	* common/btrace-common.h: New file.


---
 gdb/Makefile.in            |    4 +-
 gdb/btrace.c               |  467 ++++++++++++++++++++++++++++++++++++++++++++
 gdb/btrace.h               |  135 +++++++++++++
 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, 779 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 ed30db5..1cf8134 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -759,7 +759,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
 
@@ -928,7 +928,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..b6cd1c8
--- /dev/null
+++ b/gdb/btrace.c
@@ -0,0 +1,467 @@
+/* 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 "exceptions.h"
+#include "inferior.h"
+#include "target.h"
+#include "record.h"
+#include "symtab.h"
+#include "disasm.h"
+#include "source.h"
+#include "filenames.h"
+
+/* Print a record debug message.  Use do ... while (0) to avoid ambiguities
+   when used in if statements.  */
+
+#define DEBUG(msg, args...)						\
+  do									\
+    {									\
+      if (record_debug != 0)						\
+        fprintf_unfiltered (gdb_stdlog,					\
+			    "[btrace] " msg "\n", ##args);		\
+    }									\
+  while (0)
+
+#define DEBUG_FTRACE(msg, args...) DEBUG ("[ftrace] " msg, ##args)
+
+/* Initialize the instruction iterator.  */
+
+static void
+btrace_init_insn_iterator (struct btrace_thread_info *btinfo)
+{
+  DEBUG ("init insn iterator");
+
+  btinfo->insn_iterator.begin = 1;
+  btinfo->insn_iterator.end = 0;
+}
+
+/* Initialize the function iterator.  */
+
+static void
+btrace_init_func_iterator (struct btrace_thread_info *btinfo)
+{
+  DEBUG ("init func iterator");
+
+  btinfo->func_iterator.begin = 1;
+  btinfo->func_iterator.end = 0;
+}
+
+/* Compute the instruction trace from the block trace.  */
+
+static VEC (btrace_inst_s) *
+compute_itrace (VEC (btrace_block_s) *btrace)
+{
+  VEC (btrace_inst_s) *itrace;
+  struct gdbarch *gdbarch;
+  unsigned int b;
+
+  DEBUG ("compute itrace");
+
+  itrace = NULL;
+  gdbarch = target_gdbarch ();
+  b = VEC_length (btrace_block_s, btrace);
+
+  while (b-- != 0)
+    {
+      btrace_block_s *block;
+      CORE_ADDR pc;
+
+      block = VEC_index (btrace_block_s, btrace, b);
+      pc = block->begin;
+
+      /* Add instructions for this block.  */
+      for (;;)
+	{
+	  btrace_inst_s *inst;
+	  int size;
+
+	  /* We should hit the end of the block.  Warn if we went too far.  */
+	  if (block->end < pc)
+	    {
+	      warning (_("Recorded trace may be corrupted."));
+	      break;
+	    }
+
+	  inst = VEC_safe_push (btrace_inst_s, itrace, NULL);
+	  inst->pc = pc;
+
+	  /* We're done once we pushed the instruction at the end.  */
+	  if (block->end == pc)
+	    break;
+
+	  size = gdb_insn_length (gdbarch, pc);
+
+	  /* Make sure we terminate if we fail to compute the size.  */
+	  if (size <= 0)
+	    {
+	      warning (_("Recorded trace may be incomplete."));
+	      break;
+	    }
+
+	  pc += size;
+	}
+    }
+
+  return itrace;
+}
+
+/* Return the function name of a recorded function segment for printing.
+   This function never returns NULL.  */
+
+static const char *
+ftrace_print_function_name (struct btrace_func *bfun)
+{
+  struct minimal_symbol *msym;
+  struct symbol *sym;
+
+  msym = bfun->msym;
+  sym = bfun->sym;
+
+  if (sym != NULL)
+    return SYMBOL_PRINT_NAME (sym);
+
+  if (msym != NULL)
+    return SYMBOL_PRINT_NAME (msym);
+
+  return "<unknown>";
+}
+
+/* Return the file name of a recorded function segment for printing.
+   This function never returns NULL.  */
+
+static const char *
+ftrace_print_filename (struct btrace_func *bfun)
+{
+  struct minimal_symbol *msym;
+  struct symbol *sym;
+  const char *filename;
+
+  msym = bfun->msym;
+  sym = bfun->sym;
+
+  if (sym != NULL)
+    filename = symtab_to_filename_for_display (sym->symtab);
+  else if (msym != NULL)
+    {
+      filename = msym->filename;
+      if (filename == NULL || *filename == 0)
+	filename = "<unknown>";
+    }
+  else
+    filename = "<unknown>";
+
+  return filename;
+}
+
+/* Print an ftrace debug status message.  */
+
+static void
+ftrace_debug (struct btrace_func *bfun, const char *prefix)
+{
+  DEBUG_FTRACE ("%s: fun = %s, file = %s, lines = [%d; %d], insn = [%u; %u]",
+		prefix, ftrace_print_function_name (bfun),
+		ftrace_print_filename (bfun), bfun->lbegin, bfun->lend,
+		bfun->ibegin, bfun->iend);
+}
+
+/* Initialize a recorded function segment.  */
+
+static void
+ftrace_init_func (struct btrace_func *bfun, struct minimal_symbol *mfun,
+		  struct symbol *fun, unsigned int idx)
+{
+  bfun->msym = mfun;
+  bfun->sym = fun;
+  bfun->lbegin = INT_MAX;
+  bfun->lend = 0;
+  bfun->ibegin = idx;
+  bfun->iend = idx;
+}
+
+/* Check whether the function has changed.  */
+
+static int
+ftrace_function_switched (struct btrace_func *bfun,
+			  struct minimal_symbol *mfun, struct symbol *fun)
+{
+  struct minimal_symbol *msym;
+  struct symbol *sym;
+
+  /* The function changed if we did not have one before.  */
+  if (bfun == NULL)
+    return 1;
+
+  msym = bfun->msym;
+  sym = bfun->sym;
+
+  /* If the minimal symbol changed, we certainly switched functions.  */
+  if (mfun != NULL && msym != NULL)
+    {
+      const char *bfname, *fname;
+
+      /* Check the function name.  */
+      if (strcmp_iw (SYMBOL_PRINT_NAME (mfun),
+		     SYMBOL_PRINT_NAME (msym)) != 0)
+	return 1;
+
+      /* Check the location of those functions, as well.  */
+      bfname = msym->filename;
+      fname = mfun->filename;
+      if (fname != NULL && bfname != NULL
+	  && filename_cmp (fname, bfname) != 0)
+	return 1;
+    }
+
+  /* If the symbol changed, we certainly switched functions.  */
+  if (fun != NULL && sym != NULL)
+    {
+      const char *bfname, *fname;
+
+      /* Check the function name.  */
+      if (strcmp_iw (SYMBOL_PRINT_NAME (fun),
+		     SYMBOL_PRINT_NAME (sym)) != 0)
+	return 1;
+
+      /* Check the location of those functions, as well.  */
+      bfname = symtab_to_fullname (sym->symtab);
+      fname = symtab_to_fullname (fun->symtab);
+      if (filename_cmp (fname, bfname) != 0)
+	return 1;
+    }
+
+  return 0;
+}
+
+/* Check if we should skip this file when generating the function call
+   history.  We would want to do that if, say, a macro that is defined
+   in another file is expanded in this function.  */
+
+static int
+ftrace_skip_file (struct btrace_func *bfun, const char *filename)
+{
+  struct minimal_symbol *msym;
+  struct symbol *sym;
+  const char *bfile;
+
+  msym = bfun->msym;
+  sym = bfun->sym;
+
+  if (sym != NULL)
+    bfile = symtab_to_fullname (sym->symtab);
+  else if (msym != NULL && msym->filename != NULL)
+    bfile = msym->filename;
+  else
+    bfile = "";
+
+  if (filename == NULL)
+    filename = "";
+
+  return (filename_cmp (bfile, filename) != 0);
+}
+
+/* Compute the function trace from the instruction trace.  */
+
+static VEC (btrace_func_s) *
+compute_ftrace (VEC (btrace_inst_s) *itrace)
+{
+  VEC (btrace_func_s) *ftrace;
+  struct btrace_inst *binst;
+  struct btrace_func *bfun;
+  unsigned int idx;
+
+  DEBUG ("compute ftrace");
+
+  ftrace = NULL;
+  bfun = NULL;
+
+  for (idx = 0; VEC_iterate (btrace_inst_s, itrace, idx, binst); ++idx)
+    {
+      struct symtab_and_line sal;
+      struct minimal_symbol *mfun;
+      struct symbol *fun;
+      const char *filename;
+      CORE_ADDR pc;
+
+      pc = binst->pc;
+
+      /* Try to determine the function we're in.  We use both types of symbols
+	 to avoid surprises when we sometimes get a full symbol and sometimes
+	 only a minimal symbol.  */
+      fun = find_pc_function (pc);
+      mfun = lookup_minimal_symbol_by_pc (pc);
+
+      if (fun == NULL && mfun == NULL)
+	{
+	  DEBUG_FTRACE ("no symbol at %u, pc=%s", idx,
+			core_addr_to_string_nz (pc));
+	  continue;
+	}
+
+      /* If we're switching functions, we start over.  */
+      if (ftrace_function_switched (bfun, mfun, fun))
+	{
+	  bfun = VEC_safe_push (btrace_func_s, ftrace, NULL);
+
+	  ftrace_init_func (bfun, mfun, fun, idx);
+	  ftrace_debug (bfun, "init");
+	}
+
+      /* Update the instruction range.  */
+      bfun->iend = idx;
+      ftrace_debug (bfun, "update insns");
+
+      /* Let's see if we have source correlation, as well.  */
+      sal = find_pc_line (pc, 0);
+      if (sal.symtab == NULL || sal.line == 0)
+	{
+	  DEBUG_FTRACE ("no lines at %u, pc=%s", idx,
+			core_addr_to_string_nz (pc));
+	  continue;
+	}
+
+      /* Check if we switched files.  This could happen if, say, a macro that
+	 is defined in another file is expanded here.  */
+      filename = symtab_to_fullname (sal.symtab);
+      if (ftrace_skip_file (bfun, filename))
+	{
+	  DEBUG_FTRACE ("ignoring file at %u, pc=%s, file=%s", idx,
+			core_addr_to_string_nz (pc), filename);
+	  continue;
+	}
+
+      /* Update the line range.  */
+      bfun->lbegin = min (bfun->lbegin, sal.line);
+      bfun->lend = max (bfun->lend, sal.line);
+      ftrace_debug (bfun, "update lines");
+    }
+
+  return ftrace;
+}
+
+/* See btrace.h.  */
+
+void
+btrace_enable (struct thread_info *tp)
+{
+  if (tp->btrace.target != NULL)
+    return;
+
+  if (!target_supports_btrace ())
+    error (_("Target does not support branch tracing."));
+
+  DEBUG ("enable thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
+
+  tp->btrace.target = target_enable_btrace (tp->ptid);
+}
+
+/* See btrace.h.  */
+
+void
+btrace_disable (struct thread_info *tp)
+{
+  struct btrace_thread_info *btp = &tp->btrace;
+  int errcode = 0;
+
+  if (btp->target == NULL)
+    return;
+
+  DEBUG ("disable thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
+
+  target_disable_btrace (btp->target);
+  btp->target = NULL;
+
+  btrace_clear (tp);
+}
+
+/* See btrace.h.  */
+
+void
+btrace_disconnect (void)
+{
+  struct thread_info *tp;
+
+  DEBUG ("disconnect");
+
+  ALL_THREADS (tp)
+    btrace_disable (tp);
+}
+
+/* See btrace.h.  */
+
+void
+btrace_fetch (struct thread_info *tp)
+{
+  struct btrace_thread_info *btinfo;
+
+  DEBUG ("fetch thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
+
+  btinfo = &tp->btrace;
+  if (btinfo->target == NULL)
+    return;
+
+  if (!target_btrace_has_changed (btinfo->target))
+    return;
+
+  btrace_clear (tp);
+
+  btinfo->btrace = target_read_btrace (btinfo->target);
+  btinfo->itrace = compute_itrace (btinfo->btrace);
+  btinfo->ftrace = compute_ftrace (btinfo->itrace);
+
+  /* Initialize branch trace iterators.  */
+  btrace_init_insn_iterator (btinfo);
+  btrace_init_func_iterator (btinfo);
+}
+
+/* See btrace.h.  */
+
+void
+btrace_clear (struct thread_info *tp)
+{
+  struct btrace_thread_info *btinfo;
+
+  DEBUG ("clear thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
+
+  btinfo = &tp->btrace;
+
+  VEC_free (btrace_block_s, btinfo->btrace);
+  VEC_free (btrace_inst_s, btinfo->itrace);
+  VEC_free (btrace_func_s, btinfo->ftrace);
+
+  btinfo->btrace = NULL;
+  btinfo->itrace = NULL;
+  btinfo->ftrace = NULL;
+}
+
+/* See btrace.h.  */
+
+void
+btrace_free_objfile (struct objfile *objfile)
+{
+  struct thread_info *tp;
+
+  DEBUG ("free objfile");
+
+  ALL_THREADS (tp)
+    btrace_clear (tp);
+}
diff --git a/gdb/btrace.h b/gdb/btrace.h
new file mode 100644
index 0000000..a1b01c8
--- /dev/null
+++ b/gdb/btrace.h
@@ -0,0 +1,135 @@
+/* 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;
+
+/* A branch trace instruction.
+
+   This represents a single instruction in a branch trace.  */
+struct btrace_inst
+{
+  /* The address of this instruction.  */
+  CORE_ADDR pc;
+};
+
+/* A branch trace function.
+
+   This represents a function segment in a branch trace, i.e. a consecutive
+   number of instructions belonging to the same function.  */
+struct btrace_func
+{
+  /* The full and minimal symbol for the function.  One of them may be NULL.  */
+  struct minimal_symbol *msym;
+  struct symbol *sym;
+
+  /* The source line range of this function segment (both inclusive).  */
+  int lbegin, lend;
+
+  /* The instruction number range in the instruction trace corresponding
+     to this function segment.  */
+  unsigned int ibegin, iend;
+};
+
+/* Branch trace may also be represented as a vector of:
+
+   - branch trace instructions starting with the oldest instruction.
+   - branch trace functions starting with the oldest function.  */
+typedef struct btrace_inst btrace_inst_s;
+typedef struct btrace_func btrace_func_s;
+
+/* Define functions operating on branch trace vectors.  */
+DEF_VEC_O (btrace_inst_s);
+DEF_VEC_O (btrace_func_s);
+
+/* Branch trace iteration state for "record instruction-history".  */
+struct btrace_insn_iterator
+{
+  /* The instruction index range [begin; end[ that has been covered last time.
+     If end < begin, the branch trace has just been updated.  */
+  unsigned int begin;
+  unsigned int end;
+};
+
+/* Branch trace iteration state for "record function-call-history".  */
+struct btrace_func_iterator
+{
+  /* The function index range [begin; end[ that has been covered last time.
+     If end < begin, the branch trace has just been updated.  */
+  unsigned int begin;
+  unsigned int end;
+};
+
+/* 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;
+  VEC (btrace_inst_s) *itrace;
+  VEC (btrace_func_s) *ftrace;
+
+  /* The instruction history iterator.  */
+  struct btrace_insn_iterator insn_iterator;
+
+  /* The function call history iterator.  */
+  struct btrace_func_iterator func_iterator;
+};
+
+/* Enable branch tracing for a thread.  */
+extern void btrace_enable (struct thread_info *tp);
+
+/* Disable branch tracing for a thread.
+   This will also delete the current branch trace data.  */
+extern void btrace_disable (struct thread_info *);
+
+/* Disconnect branch tracing on detach.  */
+extern void btrace_disconnect (void);
+
+/* Fetch the branch trace for a single thread.  */
+extern void btrace_fetch (struct thread_info *);
+
+/* Clear the branch trace for a single thread.  */
+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 *);
+
+#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 824e4d0..0846322 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -27,6 +27,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),...  */
@@ -226,6 +227,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 1ef3b48..d808e92 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"
 
 /* Local functions: */
 
@@ -2725,6 +2726,7 @@ detach_command (char *args, int from_tty)
     error (_("The program is not being run."));
 
   disconnect_tracing (from_tty);
+  btrace_disconnect ();
 
   target_detach (args, from_tty);
 
diff --git a/gdb/target.c b/gdb/target.c
index ecb1325..9dfbe08 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -4147,6 +4147,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 1971265..628c108 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 6b53c7a..cffaa42 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -33,6 +33,7 @@
 #include "regcache.h"
 #include "gdb.h"
 #include "gdb_string.h"
+#include "btrace.h"
 
 #include <ctype.h>
 #include <sys/types.h>
@@ -116,6 +117,8 @@ clear_thread_inferior_resources (struct thread_info *tp)
 
   bpstat_clear (&tp->control.stop_bpstat);
 
+  btrace_disable (tp);
+
   do_all_intermediate_continuations_thread (tp, 1);
   do_all_continuations_thread (tp, 1);
 }
-- 
1.7.1


  parent reply	other threads:[~2013-03-04 17:07 UTC|newest]

Thread overview: 102+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-04 17:07 [patch v9 00/23] branch tracing support for Atom Markus Metzger
2013-03-04 17:07 ` [patch v9 10/23] remote, btrace: add branch tracing protocol to Qbtrace packet Markus Metzger
2013-03-05 20:09   ` Jan Kratochvil
2013-03-06  9:19     ` Metzger, Markus T
2013-03-04 17:07 ` [patch v9 07/23] gdbserver, btrace: add generic btrace support Markus Metzger
2013-03-05 20:08   ` Jan Kratochvil
2013-03-06  9:15     ` Metzger, Markus T
2013-03-06 13:22   ` Jan Kratochvil
2013-03-04 17:07 ` [patch v9 04/23] xml, btrace: define btrace xml document style Markus Metzger
2013-03-05 20:07   ` Jan Kratochvil
2013-03-04 17:07 ` [patch v9 02/23] linux, btrace: perf_event based branch tracing Markus Metzger
2013-03-05 20:06   ` Jan Kratochvil
2013-03-06 10:11   ` Mark Kettenis
2013-03-06 10:29     ` Metzger, Markus T
2013-03-04 17:07 ` [patch v9 08/23] gdbserver, linux, btrace: add btrace support for linux-low Markus Metzger
2013-03-05 20:09   ` Jan Kratochvil
2013-03-06  9:17     ` Metzger, Markus T
2013-03-06 13:33   ` Jan Kratochvil
2013-03-04 17:07 ` [patch v9 03/23] linux, i386, amd64: enable btrace for 32bit and 64bit linux native Markus Metzger
2013-03-05 20:06   ` Jan Kratochvil
2013-03-04 17:07 ` Markus Metzger [this message]
2013-03-05 20:06   ` [patch v9 01/23] thread, btrace: add generic branch trace support Jan Kratochvil
2013-03-05 22:02     ` Tom Tromey
2013-03-06 21:11   ` Doug Evans
2013-03-07  7:50     ` Metzger, Markus T
2013-03-07 22:57       ` Doug Evans
2013-03-04 17:07 ` [patch v9 05/23] remote, btrace: add branch trace remote ops Markus Metzger
2013-03-05 20:07   ` Jan Kratochvil
2013-03-06  9:00     ` Metzger, Markus T
2013-03-04 17:07 ` [patch v9 16/23] record: default target methods Markus Metzger
2013-03-05 20:10   ` Jan Kratochvil
2013-03-04 17:08 ` [patch v9 22/23] testsuite, gdb.btrace: add btrace tests Markus Metzger
2013-03-04 19:47   ` Jan Kratochvil
2013-03-05  6:39     ` Metzger, Markus T
2013-03-05 20:14   ` Jan Kratochvil
2013-03-06 15:32     ` christian.himpel
2013-03-06 16:35       ` Jan Kratochvil
2013-03-04 17:08 ` [patch v9 06/23] btrace, doc: document remote serial protocol Markus Metzger
2013-03-04 18:08   ` Eli Zaretskii
2013-03-05 20:08   ` Jan Kratochvil
2013-03-06  9:06     ` Metzger, Markus T
2013-03-06  9:50       ` Jan Kratochvil
2013-03-06 10:01         ` Metzger, Markus T
2013-03-06 12:07           ` Jan Kratochvil
2013-03-06 12:13             ` Metzger, Markus T
2013-03-06 12:17               ` Jan Kratochvil
2013-03-04 17:08 ` [patch v9 11/23] target: add add_deprecated_target_alias Markus Metzger
2013-03-05 20:09   ` Jan Kratochvil
2013-03-04 17:08 ` [patch v9 20/23] record-btrace, disas: omit pc prefix Markus Metzger
2013-03-05 20:13   ` Jan Kratochvil
2013-03-04 17:08 ` [patch v9 19/23] record, btrace: add record-btrace target Markus Metzger
2013-03-05 20:13   ` Jan Kratochvil
2013-03-06  9:57     ` Metzger, Markus T
2013-03-06 13:35       ` Jan Kratochvil
2013-03-06 14:01         ` Metzger, Markus T
2013-03-06 16:28   ` Jan Kratochvil
2013-03-04 17:08 ` [patch v9 09/23] btrace, x86: disable on some processors Markus Metzger
2013-03-05 20:09   ` Jan Kratochvil
2013-03-04 17:09 ` [patch v9 17/23] record: add "record instruction-history" command Markus Metzger
2013-03-04 18:14   ` Eli Zaretskii
2013-03-05 20:11   ` Jan Kratochvil
2013-03-04 17:09 ` [patch v9 15/23] record-full.h: rename record_ into record_full_ Markus Metzger
2013-03-05 20:10   ` Jan Kratochvil
2013-03-04 17:09 ` [patch v9 13/23] record: make it build again Markus Metzger
2013-03-05 20:10   ` Jan Kratochvil
2013-03-04 17:09 ` [patch v9 14/23] record-full.c: rename record_ in record_full_ Markus Metzger
2013-03-05 20:10   ` Jan Kratochvil
2013-03-04 17:09 ` [patch v9 18/23] record: add "record function-call-history" command Markus Metzger
2013-03-04 18:07   ` Eli Zaretskii
2013-03-05 20:12   ` Jan Kratochvil
2013-03-04 17:09 ` [patch v9 21/23] doc, record: document record changes Markus Metzger
2013-03-04 18:13   ` Eli Zaretskii
2013-03-05 20:13   ` Jan Kratochvil
2013-03-04 17:09 ` [patch v9 23/23] btrace, remote: drop qbtrace packet Markus Metzger
2013-03-04 18:15   ` Eli Zaretskii
2013-03-05 20:15   ` Jan Kratochvil
2013-03-04 17:10 ` [patch v9 12/23] record: split record Markus Metzger
2013-03-05 20:09   ` Jan Kratochvil
2013-03-06 12:43 ` Crash of GDB with gdbserver btrace enabled [Re: [patch v9 00/23] branch tracing support for Atom] Jan Kratochvil
2013-03-06 14:40   ` Metzger, Markus T
2013-03-06 15:31     ` Metzger, Markus T
2013-03-06 17:06       ` Jan Kratochvil
2013-03-06 18:08         ` Metzger, Markus T
2013-03-07  9:06           ` Jan Kratochvil
2013-03-07  9:41             ` Metzger, Markus T
2013-03-07 10:00               ` Metzger, Markus T
2013-03-07 10:14                 ` Jan Kratochvil
2013-03-07 10:33                   ` Metzger, Markus T
2013-03-07 12:07                     ` Jan Kratochvil
2013-03-07 12:33                       ` Metzger, Markus T
2013-03-07 14:45                         ` Jan Kratochvil
2013-03-07 15:22                           ` Metzger, Markus T
2013-03-07 15:46                             ` Jan Kratochvil
2013-03-07 15:12                         ` Pedro Alves
2013-03-07 15:33                           ` Metzger, Markus T
2013-03-07 15:39                             ` Jan Kratochvil
2013-03-07 15:41                             ` Pedro Alves
     [not found]                           ` <20130318170643.GA15625@host2.jankratochvil.net>
     [not found]                             ` <514758DA.2060905@redhat.com>
2013-03-20 15:52                               ` [commit] [patch] Code cleanup: Remove parameter quitting [Re: Crash of GDB with gdbserver btrace enabled] Jan Kratochvil
     [not found]                               ` <20130318192604.GA2786@host2.jankratochvil.net>
     [not found]                                 ` <51477828.30000@redhat.com>
2013-03-26  0:15                                   ` Jan Kratochvil
2013-04-03 18:05                                     ` Pedro Alves
2013-03-07 10:08               ` Crash of GDB with gdbserver btrace enabled [Re: [patch v9 00/23] branch tracing support for Atom] Jan Kratochvil
2013-03-06 15:41   ` Jan Kratochvil

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1362416770-19750-2-git-send-email-markus.t.metzger@intel.com \
    --to=markus.t.metzger@intel.com \
    --cc=gdb-patches@sourceware.org \
    --cc=jan.kratochvil@redhat.com \
    --cc=markus.t.metzger@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox