+2016-10-28 Markus Metzger <markus.t.metzger@intel.com>
+
+ * btrace.c (btrace_compute_ftrace_bts, ftrace_add_pt): Allow
+ leading gaps.
+ * record-btrace.c (record_btrace_single_step_forward)
+ (record_btrace_single_step_backward): Jump back to last
+ instruction if step ends at a gap.
+ (record_btrace_goto_begin): Skip gaps.
+
2016-10-28 Markus Metzger <markus.t.metzger@intel.com>
* btrace.c (ftrace_add_pt): Fix gap indication. Add warning for non-
/* We should hit the end of the block. Warn if we went too far. */
if (block->end < pc)
{
- /* Indicate the gap in the trace - unless we're at the
- beginning. */
- if (begin != NULL)
- {
- end = ftrace_new_gap (end, BDE_BTS_OVERFLOW);
- ngaps += 1;
+ /* Indicate the gap in the trace. */
+ end = ftrace_new_gap (end, BDE_BTS_OVERFLOW);
+ if (begin == NULL)
+ begin = end;
+
+ ngaps += 1;
+
+ warning (_("Recorded trace may be corrupted at instruction "
+ "%u (pc = %s)."), end->insn_offset - 1,
+ core_addr_to_string_nz (pc));
- warning (_("Recorded trace may be corrupted at instruction "
- "%u (pc = %s)."), end->insn_offset - 1,
- core_addr_to_string_nz (pc));
- }
break;
}
"= 0x%" PRIx64 ", pc = 0x%" PRIx64 ")."),
end->insn_offset - 1, offset, insn.ip);
}
+ }
- /* Indicate trace overflows. */
- if (insn.resynced)
- {
- *pend = end = ftrace_new_gap (end, BDE_PT_OVERFLOW);
- *ngaps += 1;
+ /* Indicate trace overflows. */
+ if (insn.resynced)
+ {
+ *pend = end = ftrace_new_gap (end, BDE_PT_OVERFLOW);
+ if (begin == NULL)
+ *pbegin = begin = end;
- pt_insn_get_offset (decoder, &offset);
+ *ngaps += 1;
- warning (_("Overflow at instruction %u (offset = 0x%" PRIx64
- ", pc = 0x%" PRIx64 ")."), end->insn_offset - 1,
- offset, insn.ip);
- }
+ pt_insn_get_offset (decoder, &offset);
+
+ warning (_("Overflow at instruction %u (offset = 0x%" PRIx64
+ ", pc = 0x%" PRIx64 ")."), end->insn_offset - 1,
+ offset, insn.ip);
}
upd = ftrace_update_function (end, insn.ip);
if (errcode == -pte_eos)
break;
- /* If the gap is at the very beginning, we ignore it - we will have
- less trace, but we won't have any holes in the trace. */
- if (begin == NULL)
- continue;
-
/* Indicate the gap in the trace. */
*pend = end = ftrace_new_gap (end, errcode);
+ if (begin == NULL)
+ *pbegin = begin = end;
*ngaps += 1;
pt_insn_get_offset (decoder, &offset);
static struct target_waitstatus
record_btrace_single_step_forward (struct thread_info *tp)
{
- struct btrace_insn_iterator *replay, end;
+ struct btrace_insn_iterator *replay, end, start;
struct btrace_thread_info *btinfo;
btinfo = &tp->btrace;
if (record_btrace_replay_at_breakpoint (tp))
return btrace_step_stopped ();
- /* Skip gaps during replay. */
+ /* Skip gaps during replay. If we end up at a gap (at the end of the trace),
+ jump back to the instruction at which we started. */
+ start = *replay;
do
{
unsigned int steps;
of the execution history. */
steps = btrace_insn_next (replay, 1);
if (steps == 0)
- return btrace_step_no_history ();
+ {
+ *replay = start;
+ return btrace_step_no_history ();
+ }
}
while (btrace_insn_get (replay) == NULL);
static struct target_waitstatus
record_btrace_single_step_backward (struct thread_info *tp)
{
- struct btrace_insn_iterator *replay;
+ struct btrace_insn_iterator *replay, start;
struct btrace_thread_info *btinfo;
btinfo = &tp->btrace;
replay = record_btrace_start_replaying (tp);
/* If we can't step any further, we reached the end of the history.
- Skip gaps during replay. */
+ Skip gaps during replay. If we end up at a gap (at the beginning of
+ the trace), jump back to the instruction at which we started. */
+ start = *replay;
do
{
unsigned int steps;
steps = btrace_insn_prev (replay, 1);
if (steps == 0)
- return btrace_step_no_history ();
+ {
+ *replay = start;
+ return btrace_step_no_history ();
+ }
}
while (btrace_insn_get (replay) == NULL);
tp = require_btrace_thread ();
btrace_insn_begin (&begin, &tp->btrace);
+
+ /* Skip gaps at the beginning of the trace. */
+ while (btrace_insn_get (&begin) == NULL)
+ {
+ unsigned int steps;
+
+ steps = btrace_insn_next (&begin, 1);
+ if (steps == 0)
+ error (_("No trace."));
+ }
+
record_btrace_set_replay (tp, &begin);
}