static void btrace_insn_history (struct ui_out *uiout, const struct btrace_insn_iterator *begin, const struct btrace_insn_iterator *end, int flags) { struct gdbarch *gdbarch; struct btrace_insn_iterator it; DEBUG ("itrace (0x%x): [%u; %u)", flags, btrace_insn_number (begin), btrace_insn_number (end)); gdbarch = target_gdbarch (); for (it = *begin; btrace_insn_cmp (&it, end) != 0; btrace_insn_next (&it, 1)) { const struct btrace_insn *insn; insn = btrace_insn_get (&it); /* Print the instruction index. */ ui_out_field_uint (uiout, "index", btrace_insn_number (&it)); ui_out_text (uiout, "\t"); /* Disassembly with '/m' flag may not produce the expected result. See PR gdb/11833. */ gdb_disassembly (gdbarch, uiout, NULL, flags, 1, insn->pc, insn->pc + 1); } }
static void record_btrace_fetch_registers (struct target_ops *ops, struct regcache *regcache, int regno) { struct btrace_insn_iterator *replay; struct thread_info *tp; tp = find_thread_ptid (inferior_ptid); gdb_assert (tp != NULL); replay = tp->btrace.replay; if (replay != NULL) { const struct btrace_insn *insn; struct gdbarch *gdbarch; int pcreg; gdbarch = get_regcache_arch (regcache); pcreg = gdbarch_pc_regnum (gdbarch); if (pcreg < 0) return; /* We can only provide the PC register. */ if (regno >= 0 && regno != pcreg) return; insn = btrace_insn_get (replay); gdb_assert (insn != NULL); regcache_raw_supply (regcache, regno, &insn->pc); } else { struct target_ops *t; for (t = ops->beneath; t != NULL; t = t->beneath) if (t->to_fetch_registers != NULL) { t->to_fetch_registers (t, regcache, regno); break; } } }
static const btrace_insn * btrace_insn_from_recpy_insn (const PyObject * const pyobject) { const btrace_insn *insn; const recpy_element_object *obj; thread_info *tinfo; btrace_insn_iterator iter; if (Py_TYPE (pyobject) != &recpy_insn_type) { PyErr_Format (gdbpy_gdb_error, _("Must be gdb.RecordInstruction")); return NULL; } obj = (const recpy_element_object *) pyobject; tinfo = obj->thread; if (tinfo == NULL || btrace_is_empty (tinfo)) { PyErr_Format (gdbpy_gdb_error, _("No such instruction.")); return NULL; } if (btrace_find_insn_by_number (&iter, &tinfo->btrace, obj->number) == 0) { PyErr_Format (gdbpy_gdb_error, _("No such instruction.")); return NULL; } insn = btrace_insn_get (&iter); if (insn == NULL) { PyErr_Format (gdbpy_gdb_error, _("Not a valid instruction.")); return NULL; } return insn; }
static struct target_waitstatus record_btrace_step_thread (struct thread_info *tp) { struct btrace_insn_iterator *replay, end; struct btrace_thread_info *btinfo; struct address_space *aspace; struct inferior *inf; enum btrace_thread_flag flags; unsigned int steps; btinfo = &tp->btrace; replay = btinfo->replay; flags = btinfo->flags & BTHR_MOVE; btinfo->flags &= ~BTHR_MOVE; DEBUG ("stepping %d (%s): %u", tp->num, target_pid_to_str (tp->ptid), flags); switch (flags) { default: internal_error (__FILE__, __LINE__, _("invalid stepping type.")); case BTHR_STEP: /* We're done if we're not replaying. */ if (replay == NULL) return btrace_step_no_history (); /* We are always able to step at least once. */ steps = btrace_insn_next (replay, 1); gdb_assert (steps == 1); /* Determine the end of the instruction trace. */ btrace_insn_end (&end, btinfo); /* We stop replaying if we reached the end of the trace. */ if (btrace_insn_cmp (replay, &end) == 0) record_btrace_stop_replaying (tp); return btrace_step_stopped (); case BTHR_RSTEP: /* Start replaying if we're not already doing so. */ if (replay == NULL) replay = record_btrace_start_replaying (tp); /* If we can't step any further, we reached the end of the history. */ steps = btrace_insn_prev (replay, 1); if (steps == 0) return btrace_step_no_history (); return btrace_step_stopped (); case BTHR_CONT: /* We're done if we're not replaying. */ if (replay == NULL) return btrace_step_no_history (); inf = find_inferior_pid (ptid_get_pid (tp->ptid)); aspace = inf->aspace; /* Determine the end of the instruction trace. */ btrace_insn_end (&end, btinfo); for (;;) { const struct btrace_insn *insn; /* We are always able to step at least once. */ steps = btrace_insn_next (replay, 1); gdb_assert (steps == 1); /* We stop replaying if we reached the end of the trace. */ if (btrace_insn_cmp (replay, &end) == 0) { record_btrace_stop_replaying (tp); return btrace_step_no_history (); } insn = btrace_insn_get (replay); gdb_assert (insn); DEBUG ("stepping %d (%s) ... %s", tp->num, target_pid_to_str (tp->ptid), core_addr_to_string_nz (insn->pc)); if (breakpoint_here_p (aspace, insn->pc)) return btrace_step_stopped (); } case BTHR_RCONT: /* Start replaying if we're not already doing so. */ if (replay == NULL) replay = record_btrace_start_replaying (tp); inf = find_inferior_pid (ptid_get_pid (tp->ptid)); aspace = inf->aspace; for (;;) { const struct btrace_insn *insn; /* If we can't step any further, we're done. */ steps = btrace_insn_prev (replay, 1); if (steps == 0) return btrace_step_no_history (); insn = btrace_insn_get (replay); gdb_assert (insn); DEBUG ("reverse-stepping %d (%s) ... %s", tp->num, target_pid_to_str (tp->ptid), core_addr_to_string_nz (insn->pc)); if (breakpoint_here_p (aspace, insn->pc)) return btrace_step_stopped (); } } }