[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