diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 988a50a6d67..350e5a627dd 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2016-10-28 Markus Metzger + + * 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 * btrace.c (ftrace_add_pt): Fix gap indication. Add warning for non- diff --git a/gdb/btrace.c b/gdb/btrace.c index 3b4e60d4a45..648d49532bb 100644 --- a/gdb/btrace.c +++ b/gdb/btrace.c @@ -626,17 +626,17 @@ btrace_compute_ftrace_bts (struct thread_info *tp, /* 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; } @@ -796,19 +796,22 @@ ftrace_add_pt (struct pt_insn_decoder *decoder, "= 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); @@ -834,13 +837,10 @@ ftrace_add_pt (struct pt_insn_decoder *decoder, 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); diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index 4808129d855..7c0e39f4af4 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -2300,7 +2300,7 @@ record_btrace_replay_at_breakpoint (struct thread_info *tp) 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; @@ -2314,7 +2314,9 @@ record_btrace_single_step_forward (struct thread_info *tp) 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; @@ -2323,7 +2325,10 @@ record_btrace_single_step_forward (struct thread_info *tp) 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); @@ -2344,7 +2349,7 @@ record_btrace_single_step_forward (struct thread_info *tp) 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; @@ -2355,14 +2360,19 @@ record_btrace_single_step_backward (struct thread_info *tp) 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); @@ -2772,6 +2782,17 @@ record_btrace_goto_begin (struct target_ops *self) 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); }