[PATCH 3/3] btrace: support decoder events

Markus Metzger markus.t.metzger@intel.com
Fri Apr 28 14:44:00 GMT 2017


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.

2017-04-28  Markus Metzger  <markus.t.metzger@intel.com>

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.


---
 gdb/btrace.c | 174 +++++++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 127 insertions(+), 47 deletions(-)

diff --git a/gdb/btrace.c b/gdb/btrace.c
index 6780e22..21d0be9 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -1132,6 +1132,116 @@ 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 pt_insn_decoder *decoder,
+		       struct btrace_function **pbegin,
+		       struct btrace_function **pend,
+		       VEC (bfun_s) **gaps, int status)
+{
+#if defined (HAVE_PT_INSN_EVENT)
+  while (status & pts_event_pending)
+    {
+      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 (*pbegin != NULL && event.variant.enabled.resumed == 0)
+	    {
+	      *pend = ftrace_new_gap (*pend, BDE_PT_DISABLED);
+	      if (*pbegin == NULL)
+		*pbegin = *pend;
+
+	      VEC_safe_push (bfun_s, *gaps, *pend);
+
+	      pt_insn_get_offset (decoder, &offset);
+
+	      warning (_("Non-contiguous trace at instruction %u (offset = 0x%"
+			 PRIx64 ")."), (*pend)->insn_offset - 1, offset);
+	    }
+
+	  break;
+
+	case ptev_overflow:
+	  *pend = ftrace_new_gap (*pend, BDE_PT_OVERFLOW);
+	  if (*pbegin == NULL)
+	    *pbegin = *pend;
+
+	  VEC_safe_push (bfun_s, *gaps, *pend);
+
+	  pt_insn_get_offset (decoder, &offset);
+
+	  warning (_("Overflow at instruction %u (offset = 0x%" PRIx64 ")."),
+		   (*pend)->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 pt_insn_decoder *decoder,
+			    const struct pt_insn *insn,
+			    struct btrace_function **pbegin,
+			    struct btrace_function **pend,
+			    VEC (bfun_s) **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 && (*begin != NULL))
+    {
+      uint64_t offset;
+
+      *end = ftrace_new_gap (*end, BDE_PT_DISABLED);
+
+      VEC_safe_push (bfun_s, *gaps, *end);
+
+      pt_insn_get_offset (decoder, &offset);
+
+      warning (_("Non-contiguous trace at instruction %u (offset = 0x%" PRIx64
+		 ", pc = 0x%" PRIx64 ")."), (*end)->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)
+    {
+      uint64_t offset;
+
+      *end = ftrace_new_gap (*end, BDE_PT_OVERFLOW);
+      if (*begin == NULL)
+	*begin = *end;
+
+      VEC_safe_push (bfun_s, *gaps, *end);
+
+      pt_insn_get_offset (decoder, &offset);
+
+      warning (_("Overflow at instruction %u (offset = 0x%" PRIx64 ", pc = 0x%"
+		 PRIx64 ")."), (*end)->insn_offset - 1, offset, insn.ip);
+    }
+#endif /* defined (HAVE_STRUCT_PT_INSN_RESYNCED) */
+}
 
 /* Add function branch trace using DECODER.  */
 
@@ -1142,64 +1252,34 @@ ftrace_add_pt (struct pt_insn_decoder *decoder,
 	       VEC (bfun_s) **gaps)
 {
   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 (decoder, begin, end, gaps, status);
+	  if (status < 0)
 	    break;
 
-	  /* Look for gaps in the trace - unless we're at the beginning.  */
-	  if (*begin != NULL)
-	    {
-	      /* 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)
-		{
-		  *end = ftrace_new_gap (*end, BDE_PT_DISABLED);
-
-		  VEC_safe_push (bfun_s, *gaps, *end);
-
-		  pt_insn_get_offset (decoder, &offset);
-
-		  warning (_("Non-contiguous trace at instruction %u (offset "
-			     "= 0x%" PRIx64 ", pc = 0x%" PRIx64 ")."),
-			   (*end)->insn_offset - 1, offset, insn.ip);
-		}
-	    }
-
-	  /* Indicate trace overflows.  */
-	  if (insn.resynced)
-	    {
-	      *end = ftrace_new_gap (*end, BDE_PT_OVERFLOW);
-	      if (*begin == NULL)
-		*begin = *end;
-
-	      VEC_safe_push (bfun_s, *gaps, *end);
-
-	      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 ")."), (*end)->insn_offset - 1,
-		       offset, insn.ip);
-	    }
+	  /* Handle events indicated by flags in INSN.  */
+	  handle_pt_insn_event_flags (decoder, &insn, begin, end, gaps);
 
 	  *end = ftrace_update_function (*end, insn.ip);
 	  if (*begin == NULL)
@@ -1212,11 +1292,11 @@ ftrace_add_pt (struct pt_insn_decoder *decoder,
 	  ftrace_update_insns (*end, &btinsn);
 	}
 
-      if (errcode == -pte_eos)
+      if (status == -pte_eos)
 	break;
 
       /* Indicate the gap in the trace.  */
-      *end = ftrace_new_gap (*end, errcode);
+      *end = ftrace_new_gap (*end, status);
       if (*begin == NULL)
 	*begin = *end;
 
@@ -1225,9 +1305,9 @@ ftrace_add_pt (struct pt_insn_decoder *decoder,
       pt_insn_get_offset (decoder, &offset);
 
       warning (_("Decode error (%d) at instruction %u (offset = 0x%" PRIx64
-		 ", pc = 0x%" PRIx64 "): %s."), errcode,
+		 ", pc = 0x%" PRIx64 "): %s."), status,
 	       (*end)->insn_offset - 1, offset, insn.ip,
-	       pt_errstr (pt_errcode (errcode)));
+	       pt_errstr (pt_errcode (status)));
     }
 }
 
-- 
1.8.3.1



More information about the Gdb-patches mailing list