This is the mail archive of the gdb-cvs@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]

[binutils-gdb] btrace: support decoder events


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=13ace07792fa75aa276e2d7c3cb03cec117d63a4

commit 13ace07792fa75aa276e2d7c3cb03cec117d63a4
Author: Markus Metzger <markus.t.metzger@intel.com>
Date:   Mon Nov 21 14:27:57 2016 +0100

    btrace: support decoder events
    
    Newer versions of libipt support instruction flow decoder events instead of
    indicating those events with flags in struct pt_insn.  Add support for them in
    GDB.
    
    gdb/
    	* btrace.c (handle_pt_insn_events): New.
    	(ftrace_add_pt): Call handle_pt_insn_events.  Rename ERRCODE into
    	STATUS.  Split into this and ...
    	(handle_pt_insn_event_flags): ... this.

Diff:
---
 gdb/ChangeLog |   7 +++
 gdb/btrace.c  | 155 ++++++++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 121 insertions(+), 41 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ac2394f..158670d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,12 @@
 2017-05-31  Markus Metzger  <markus.t.metzger@intel.com>
 
+	* btrace.c (handle_pt_insn_events): New.
+	(ftrace_add_pt): Call handle_pt_insn_events.  Rename ERRCODE into
+	STATUS.  Split into this and ...
+	(handle_pt_insn_event_flags): ... this.
+
+2017-05-31  Markus Metzger  <markus.t.metzger@intel.com>
+
 	* configure.ac: Check for pt_insn_event, struct pt_insn.enabled,
 	and struct pt_insn.resynced.
 	* configure: Regenerated.
diff --git a/gdb/btrace.c b/gdb/btrace.c
index 34572b0..10224c5 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -1187,6 +1187,103 @@ pt_btrace_insn (const struct pt_insn &insn)
 	  pt_btrace_insn_flags (insn)};
 }
 
+/* Handle instruction decode events (libipt-v2).  */
+
+static int
+handle_pt_insn_events (struct btrace_thread_info *btinfo,
+		       struct pt_insn_decoder *decoder,
+		       std::vector<unsigned int> &gaps, int status)
+{
+#if defined (HAVE_PT_INSN_EVENT)
+  while (status & pts_event_pending)
+    {
+      struct btrace_function *bfun;
+      struct pt_event event;
+      uint64_t offset;
+
+      status = pt_insn_event (decoder, &event, sizeof (event));
+      if (status < 0)
+	break;
+
+      switch (event.type)
+	{
+	default:
+	  break;
+
+	case ptev_enabled:
+	  if (event.variant.enabled.resumed == 0 && !btinfo->functions.empty ())
+	    {
+	      bfun = ftrace_new_gap (btinfo, BDE_PT_DISABLED, gaps);
+
+	      pt_insn_get_offset (decoder, &offset);
+
+	      warning (_("Non-contiguous trace at instruction %u (offset = 0x%"
+			 PRIx64 ")."), bfun->insn_offset - 1, offset);
+	    }
+
+	  break;
+
+	case ptev_overflow:
+	  bfun = ftrace_new_gap (btinfo, BDE_PT_OVERFLOW, gaps);
+
+	  pt_insn_get_offset (decoder, &offset);
+
+	  warning (_("Overflow at instruction %u (offset = 0x%" PRIx64 ")."),
+		   bfun->insn_offset - 1, offset);
+
+	  break;
+	}
+    }
+#endif /* defined (HAVE_PT_INSN_EVENT) */
+
+  return status;
+}
+
+/* Handle events indicated by flags in INSN (libipt-v1).  */
+
+static void
+handle_pt_insn_event_flags (struct btrace_thread_info *btinfo,
+			    struct pt_insn_decoder *decoder,
+			    const struct pt_insn &insn,
+			    std::vector<unsigned int> &gaps)
+{
+#if defined (HAVE_STRUCT_PT_INSN_ENABLED)
+  /* Tracing is disabled and re-enabled each time we enter the kernel.  Most
+     times, we continue from the same instruction we stopped before.  This is
+     indicated via the RESUMED instruction flag.  The ENABLED instruction flag
+     means that we continued from some other instruction.  Indicate this as a
+     trace gap except when tracing just started.  */
+  if (insn.enabled && !btinfo->functions.empty ())
+    {
+      struct btrace_function *bfun;
+      uint64_t offset;
+
+      bfun = ftrace_new_gap (btinfo, BDE_PT_DISABLED, gaps);
+
+      pt_insn_get_offset (decoder, &offset);
+
+      warning (_("Non-contiguous trace at instruction %u (offset = 0x%" PRIx64
+		 ", pc = 0x%" PRIx64 ")."), bfun->insn_offset - 1, offset,
+	       insn.ip);
+    }
+#endif /* defined (HAVE_STRUCT_PT_INSN_ENABLED) */
+
+#if defined (HAVE_STRUCT_PT_INSN_RESYNCED)
+  /* Indicate trace overflows.  */
+  if (insn.resynced)
+    {
+      struct btrace_function *bfun;
+      uint64_t offset;
+
+      bfun = ftrace_new_gap (btinfo, BDE_PT_OVERFLOW, gaps);
+
+      pt_insn_get_offset (decoder, &offset);
+
+      warning (_("Overflow at instruction %u (offset = 0x%" PRIx64 ", pc = 0x%"
+		 PRIx64 ")."), bfun->insn_offset - 1, offset, insn.ip);
+    }
+#endif /* defined (HAVE_STRUCT_PT_INSN_RESYNCED) */
+}
 
 /* Add function branch trace to BTINFO using DECODER.  */
 
@@ -1198,58 +1295,34 @@ ftrace_add_pt (struct btrace_thread_info *btinfo,
 {
   struct btrace_function *bfun;
   uint64_t offset;
-  int errcode;
+  int status;
 
   for (;;)
     {
       struct pt_insn insn;
 
-      errcode = pt_insn_sync_forward (decoder);
-      if (errcode < 0)
+      status = pt_insn_sync_forward (decoder);
+      if (status < 0)
 	{
-	  if (errcode != -pte_eos)
+	  if (status != -pte_eos)
 	    warning (_("Failed to synchronize onto the Intel Processor "
-		       "Trace stream: %s."), pt_errstr (pt_errcode (errcode)));
+		       "Trace stream: %s."), pt_errstr (pt_errcode (status)));
 	  break;
 	}
 
       for (;;)
 	{
-	  errcode = pt_insn_next (decoder, &insn, sizeof(insn));
-	  if (errcode < 0)
+	  /* Handle events from the previous iteration or synchronization.  */
+	  status = handle_pt_insn_events (btinfo, decoder, gaps, status);
+	  if (status < 0)
 	    break;
 
-	  /* Look for gaps in the trace - unless we're at the beginning.  */
-	  if (!btinfo->functions.empty ())
-	    {
-	      /* Tracing is disabled and re-enabled each time we enter the
-		 kernel.  Most times, we continue from the same instruction we
-		 stopped before.  This is indicated via the RESUMED instruction
-		 flag.  The ENABLED instruction flag means that we continued
-		 from some other instruction.  Indicate this as a trace gap.  */
-	      if (insn.enabled)
-		{
-		  bfun = ftrace_new_gap (btinfo, BDE_PT_DISABLED, gaps);
-
-		  pt_insn_get_offset (decoder, &offset);
-
-		  warning (_("Non-contiguous trace at instruction %u (offset "
-			     "= 0x%" PRIx64 ", pc = 0x%" PRIx64 ")."),
-			   bfun->insn_offset - 1, offset, insn.ip);
-		}
-	    }
-
-	  /* Indicate trace overflows.  */
-	  if (insn.resynced)
-	    {
-	      bfun = ftrace_new_gap (btinfo, BDE_PT_OVERFLOW, gaps);
-
-	      pt_insn_get_offset (decoder, &offset);
+	  status = pt_insn_next (decoder, &insn, sizeof(insn));
+	  if (status < 0)
+	    break;
 
-	      warning (_("Overflow at instruction %u (offset = 0x%" PRIx64
-			 ", pc = 0x%" PRIx64 ")."), bfun->insn_offset - 1,
-		       offset, insn.ip);
-	    }
+	  /* Handle events indicated by flags in INSN.  */
+	  handle_pt_insn_event_flags (btinfo, decoder, insn, gaps);
 
 	  bfun = ftrace_update_function (btinfo, insn.ip);
 
@@ -1260,17 +1333,17 @@ ftrace_add_pt (struct btrace_thread_info *btinfo,
 	  ftrace_update_insns (bfun, &btinsn);
 	}
 
-      if (errcode == -pte_eos)
+      if (status == -pte_eos)
 	break;
 
       /* Indicate the gap in the trace.  */
-      bfun = ftrace_new_gap (btinfo, errcode, gaps);
+      bfun = ftrace_new_gap (btinfo, status, gaps);
 
       pt_insn_get_offset (decoder, &offset);
 
       warning (_("Decode error (%d) at instruction %u (offset = 0x%" PRIx64
-		 ", pc = 0x%" PRIx64 "): %s."), errcode, bfun->insn_offset - 1,
-	       offset, insn.ip, pt_errstr (pt_errcode (errcode)));
+		 ", pc = 0x%" PRIx64 "): %s."), status, bfun->insn_offset - 1,
+	       offset, insn.ip, pt_errstr (pt_errcode (status)));
     }
 }


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