Class-ify ui_out
[deliverable/binutils-gdb.git] / gdb / record-btrace.c
index d14e6cf09cf251af89cda46ab0c383d2e60d2827..c44668245edaa63882329b7d9cb5ac069a66469c 100644 (file)
@@ -1,6 +1,6 @@
 /* Branch trace support for GDB, the GNU debugger.
 
-   Copyright (C) 2013-2015 Free Software Foundation, Inc.
+   Copyright (C) 2013-2016 Free Software Foundation, Inc.
 
    Contributed by Intel Corp. <markus.t.metzger@intel.com>
 
@@ -21,6 +21,7 @@
 
 #include "defs.h"
 #include "record.h"
+#include "record-btrace.h"
 #include "gdbthread.h"
 #include "target.h"
 #include "gdbcmd.h"
@@ -38,6 +39,7 @@
 #include "event-loop.h"
 #include "inf-loop.h"
 #include "vec.h"
+#include <algorithm>
 
 /* The target_ops of record-btrace.  */
 static struct target_ops record_btrace_ops;
@@ -160,9 +162,7 @@ record_btrace_enable_warn (struct thread_info *tp)
 static void
 record_btrace_disable_callback (void *arg)
 {
-  struct thread_info *tp;
-
-  tp = arg;
+  struct thread_info *tp = (struct thread_info *) arg;
 
   btrace_disable (tp);
 }
@@ -201,6 +201,26 @@ record_btrace_handle_async_inferior_event (gdb_client_data data)
   inferior_event_handler (INF_REG_EVENT, NULL);
 }
 
+/* See record-btrace.h.  */
+
+void
+record_btrace_push_target (void)
+{
+  const char *format;
+
+  record_btrace_auto_enable ();
+
+  push_target (&record_btrace_ops);
+
+  record_btrace_async_inferior_event_handler
+    = create_async_event_handler (record_btrace_handle_async_inferior_event,
+                                 NULL);
+  record_btrace_generating_corefile = 0;
+
+  format = btrace_format_short_string (record_btrace_conf.format);
+  observer_notify_record_changed (current_inferior (), 1, "btrace", format);
+}
+
 /* The to_open method of target record-btrace.  */
 
 static void
@@ -220,23 +240,14 @@ record_btrace_open (const char *args, int from_tty)
 
   disable_chain = make_cleanup (null_cleanup, NULL);
   ALL_NON_EXITED_THREADS (tp)
-    if (args == NULL || *args == 0 || number_is_in_list (args, tp->num))
+    if (args == NULL || *args == 0 || number_is_in_list (args, tp->global_num))
       {
        btrace_enable (tp, &record_btrace_conf);
 
        make_cleanup (record_btrace_disable_callback, tp);
       }
 
-  record_btrace_auto_enable ();
-
-  push_target (&record_btrace_ops);
-
-  record_btrace_async_inferior_event_handler
-    = create_async_event_handler (record_btrace_handle_async_inferior_event,
-                                 NULL);
-  record_btrace_generating_corefile = 0;
-
-  observer_notify_record_changed (current_inferior (),  1);
+  record_btrace_push_target ();
 
   discard_cleanups (disable_chain);
 }
@@ -257,6 +268,21 @@ record_btrace_stop_recording (struct target_ops *self)
       btrace_disable (tp);
 }
 
+/* The to_disconnect method of target record-btrace.  */
+
+static void
+record_btrace_disconnect (struct target_ops *self, const char *args,
+                         int from_tty)
+{
+  struct target_ops *beneath = self->beneath;
+
+  /* Do not stop recording, just clean up GDB side.  */
+  unpush_target (self);
+
+  /* Forward disconnect.  */
+  beneath->to_disconnect (beneath, args, from_tty);
+}
+
 /* The to_close method of target record-btrace.  */
 
 static void
@@ -334,7 +360,7 @@ record_btrace_print_bts_conf (const struct btrace_config_bts *conf)
     }
 }
 
-/* Print an Intel(R) Processor Trace configuration.  */
+/* Print an Intel Processor Trace configuration.  */
 
 static void
 record_btrace_print_pt_conf (const struct btrace_config_pt *conf)
@@ -440,8 +466,8 @@ record_btrace_info (struct target_ops *self)
     }
 
   printf_unfiltered (_("Recorded %u instructions in %u functions (%u gaps) "
-                      "for thread %d (%s).\n"), insns, calls, gaps,
-                    tp->num, target_pid_to_str (tp->ptid));
+                      "for thread %s (%s).\n"), insns, calls, gaps,
+                    print_thread_id (tp), target_pid_to_str (tp->ptid));
 
   if (btrace_is_replaying (tp))
     printf_unfiltered (_("Replay in progress.  At instruction %u.\n"),
@@ -509,15 +535,15 @@ btrace_ui_out_decode_error (struct ui_out *uiout, int errcode,
 #endif /* defined (HAVE_LIBIPT)  */
     }
 
-  ui_out_text (uiout, _("["));
+  uiout->text (_("["));
   if (is_error)
     {
-      ui_out_text (uiout, _("decode error ("));
-      ui_out_field_int (uiout, "errcode", errcode);
-      ui_out_text (uiout, _("): "));
+      uiout->text (_("decode error ("));
+      uiout->field_int ("errcode", errcode);
+      uiout->text (_("): "));
     }
-  ui_out_text (uiout, errstr);
-  ui_out_text (uiout, _("]\n"));
+  uiout->text (errstr);
+  uiout->text (_("]\n"));
 }
 
 /* Print an unsigned int.  */
@@ -525,7 +551,141 @@ btrace_ui_out_decode_error (struct ui_out *uiout, int errcode,
 static void
 ui_out_field_uint (struct ui_out *uiout, const char *fld, unsigned int val)
 {
-  ui_out_field_fmt (uiout, fld, "%u", val);
+  uiout->field_fmt (fld, "%u", val);
+}
+
+/* A range of source lines.  */
+
+struct btrace_line_range
+{
+  /* The symtab this line is from.  */
+  struct symtab *symtab;
+
+  /* The first line (inclusive).  */
+  int begin;
+
+  /* The last line (exclusive).  */
+  int end;
+};
+
+/* Construct a line range.  */
+
+static struct btrace_line_range
+btrace_mk_line_range (struct symtab *symtab, int begin, int end)
+{
+  struct btrace_line_range range;
+
+  range.symtab = symtab;
+  range.begin = begin;
+  range.end = end;
+
+  return range;
+}
+
+/* Add a line to a line range.  */
+
+static struct btrace_line_range
+btrace_line_range_add (struct btrace_line_range range, int line)
+{
+  if (range.end <= range.begin)
+    {
+      /* This is the first entry.  */
+      range.begin = line;
+      range.end = line + 1;
+    }
+  else if (line < range.begin)
+    range.begin = line;
+  else if (range.end < line)
+    range.end = line;
+
+  return range;
+}
+
+/* Return non-zero if RANGE is empty, zero otherwise.  */
+
+static int
+btrace_line_range_is_empty (struct btrace_line_range range)
+{
+  return range.end <= range.begin;
+}
+
+/* Return non-zero if LHS contains RHS, zero otherwise.  */
+
+static int
+btrace_line_range_contains_range (struct btrace_line_range lhs,
+                                 struct btrace_line_range rhs)
+{
+  return ((lhs.symtab == rhs.symtab)
+         && (lhs.begin <= rhs.begin)
+         && (rhs.end <= lhs.end));
+}
+
+/* Find the line range associated with PC.  */
+
+static struct btrace_line_range
+btrace_find_line_range (CORE_ADDR pc)
+{
+  struct btrace_line_range range;
+  struct linetable_entry *lines;
+  struct linetable *ltable;
+  struct symtab *symtab;
+  int nlines, i;
+
+  symtab = find_pc_line_symtab (pc);
+  if (symtab == NULL)
+    return btrace_mk_line_range (NULL, 0, 0);
+
+  ltable = SYMTAB_LINETABLE (symtab);
+  if (ltable == NULL)
+    return btrace_mk_line_range (symtab, 0, 0);
+
+  nlines = ltable->nitems;
+  lines = ltable->item;
+  if (nlines <= 0)
+    return btrace_mk_line_range (symtab, 0, 0);
+
+  range = btrace_mk_line_range (symtab, 0, 0);
+  for (i = 0; i < nlines - 1; i++)
+    {
+      if ((lines[i].pc == pc) && (lines[i].line != 0))
+       range = btrace_line_range_add (range, lines[i].line);
+    }
+
+  return range;
+}
+
+/* Print source lines in LINES to UIOUT.
+
+   UI_ITEM_CHAIN is a cleanup chain for the last source line and the
+   instructions corresponding to that source line.  When printing a new source
+   line, we do the cleanups for the open chain and open a new cleanup chain for
+   the new source line.  If the source line range in LINES is not empty, this
+   function will leave the cleanup chain for the last printed source line open
+   so instructions can be added to it.  */
+
+static void
+btrace_print_lines (struct btrace_line_range lines, struct ui_out *uiout,
+                   struct cleanup **ui_item_chain, int flags)
+{
+  print_source_lines_flags psl_flags;
+  int line;
+
+  psl_flags = 0;
+  if (flags & DISASSEMBLY_FILENAME)
+    psl_flags |= PRINT_SOURCE_LINES_FILENAME;
+
+  for (line = lines.begin; line < lines.end; ++line)
+    {
+      if (*ui_item_chain != NULL)
+       do_cleanups (*ui_item_chain);
+
+      *ui_item_chain
+       = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line");
+
+      print_source_lines (lines.symtab, line, line + 1, psl_flags);
+
+      make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
+    }
 }
 
 /* Disassemble a section of the recorded instruction trace.  */
@@ -536,13 +696,29 @@ btrace_insn_history (struct ui_out *uiout,
                     const struct btrace_insn_iterator *begin,
                     const struct btrace_insn_iterator *end, int flags)
 {
+  struct ui_file *stb;
+  struct cleanup *cleanups, *ui_item_chain;
+  struct disassemble_info di;
   struct gdbarch *gdbarch;
   struct btrace_insn_iterator it;
+  struct btrace_line_range last_lines;
 
   DEBUG ("itrace (0x%x): [%u; %u)", flags, btrace_insn_number (begin),
         btrace_insn_number (end));
 
+  flags |= DISASSEMBLY_SPECULATIVE;
+
   gdbarch = target_gdbarch ();
+  stb = mem_fileopen ();
+  cleanups = make_cleanup_ui_file_delete (stb);
+  di = gdb_disassemble_info (gdbarch, stb);
+  last_lines = btrace_mk_line_range (NULL, 0, 0);
+
+  make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
+
+  /* UI_ITEM_CHAIN is a cleanup chain for the last source line and the
+     instructions corresponding to that line.  */
+  ui_item_chain = NULL;
 
   for (it = *begin; btrace_insn_cmp (&it, end) != 0; btrace_insn_next (&it, 1))
     {
@@ -565,37 +741,43 @@ btrace_insn_history (struct ui_out *uiout,
        }
       else
        {
-         char prefix[4];
+         struct disasm_insn dinsn;
 
-         /* We may add a speculation prefix later.  We use the same space
-            that is used for the pc prefix.  */
-         if ((flags & DISASSEMBLY_OMIT_PC) == 0)
-           strncpy (prefix, pc_prefix (insn->pc), 3);
-         else
+         if ((flags & DISASSEMBLY_SOURCE) != 0)
            {
-             prefix[0] = ' ';
-             prefix[1] = ' ';
-             prefix[2] = ' ';
+             struct btrace_line_range lines;
+
+             lines = btrace_find_line_range (insn->pc);
+             if (!btrace_line_range_is_empty (lines)
+                 && !btrace_line_range_contains_range (last_lines, lines))
+               {
+                 btrace_print_lines (lines, uiout, &ui_item_chain, flags);
+                 last_lines = lines;
+               }
+             else if (ui_item_chain == NULL)
+               {
+                 ui_item_chain
+                   = make_cleanup_ui_out_tuple_begin_end (uiout,
+                                                          "src_and_asm_line");
+                 /* No source information.  */
+                 make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
+               }
+
+             gdb_assert (ui_item_chain != NULL);
            }
-         prefix[3] = 0;
 
-         /* Print the instruction index.  */
-         ui_out_field_uint (uiout, "index", btrace_insn_number (&it));
-         ui_out_text (uiout, "\t");
+         memset (&dinsn, 0, sizeof (dinsn));
+         dinsn.number = btrace_insn_number (&it);
+         dinsn.addr = insn->pc;
 
-         /* Indicate speculative execution by a leading '?'.  */
          if ((insn->flags & BTRACE_INSN_FLAG_SPECULATIVE) != 0)
-           prefix[0] = '?';
+           dinsn.is_speculative = 1;
 
-         /* Print the prefix; we tell gdb_disassembly below to omit it.  */
-         ui_out_field_fmt (uiout, "prefix", "%s", prefix);
-
-         /* Disassembly with '/m' flag may not produce the expected result.
-            See PR gdb/11833.  */
-         gdb_disassembly (gdbarch, uiout, NULL, flags | DISASSEMBLY_OMIT_PC,
-                          1, insn->pc, insn->pc + 1);
+         gdb_pretty_print_insn (gdbarch, uiout, &di, &dinsn, flags, stb);
        }
     }
+
+  do_cleanups (cleanups);
 }
 
 /* The to_insn_history method of target record-btrace.  */
@@ -786,7 +968,7 @@ btrace_call_history_insn_range (struct ui_out *uiout,
   end = begin + size - 1;
 
   ui_out_field_uint (uiout, "insn begin", begin);
-  ui_out_text (uiout, ",");
+  uiout->text (",");
   ui_out_field_uint (uiout, "insn end", end);
 }
 
@@ -822,8 +1004,8 @@ btrace_compute_src_line_range (const struct btrace_function *bfun,
       if (sal.symtab != symtab || sal.line == 0)
        continue;
 
-      begin = min (begin, sal.line);
-      end = max (end, sal.line);
+      begin = std::min (begin, sal.line);
+      end = std::max (end, sal.line);
     }
 
  out:
@@ -844,21 +1026,21 @@ btrace_call_history_src_line (struct ui_out *uiout,
   if (sym == NULL)
     return;
 
-  ui_out_field_string (uiout, "file",
+  uiout->field_string ("file",
                       symtab_to_filename_for_display (symbol_symtab (sym)));
 
   btrace_compute_src_line_range (bfun, &begin, &end);
   if (end < begin)
     return;
 
-  ui_out_text (uiout, ":");
-  ui_out_field_int (uiout, "min line", begin);
+  uiout->text (":");
+  uiout->field_int ("min line", begin);
 
   if (end == begin)
     return;
 
-  ui_out_text (uiout, ",");
-  ui_out_field_int (uiout, "max line", end);
+  uiout->text (",");
+  uiout->field_int ("max line", end);
 }
 
 /* Get the name of a branch trace function.  */
@@ -890,11 +1072,12 @@ btrace_call_history (struct ui_out *uiout,
                     const struct btrace_thread_info *btinfo,
                     const struct btrace_call_iterator *begin,
                     const struct btrace_call_iterator *end,
-                    enum record_print_flag flags)
+                    int int_flags)
 {
   struct btrace_call_iterator it;
+  record_print_flags flags = (enum record_print_flag) int_flags;
 
-  DEBUG ("ftrace (0x%x): [%u; %u)", flags, btrace_call_number (begin),
+  DEBUG ("ftrace (0x%x): [%u; %u)", int_flags, btrace_call_number (begin),
         btrace_call_number (end));
 
   for (it = *begin; btrace_call_cmp (&it, end) < 0; btrace_call_next (&it, 1))
@@ -909,7 +1092,7 @@ btrace_call_history (struct ui_out *uiout,
 
       /* Print the function index.  */
       ui_out_field_uint (uiout, "index", bfun->number);
-      ui_out_text (uiout, "\t");
+      uiout->text ("\t");
 
       /* Indicate gaps in the trace.  */
       if (bfun->errcode != 0)
@@ -931,36 +1114,36 @@ btrace_call_history (struct ui_out *uiout,
          int level = bfun->level + btinfo->level, i;
 
          for (i = 0; i < level; ++i)
-           ui_out_text (uiout, "  ");
+           uiout->text ("  ");
        }
 
       if (sym != NULL)
-       ui_out_field_string (uiout, "function", SYMBOL_PRINT_NAME (sym));
+       uiout->field_string ("function", SYMBOL_PRINT_NAME (sym));
       else if (msym != NULL)
-       ui_out_field_string (uiout, "function", MSYMBOL_PRINT_NAME (msym));
-      else if (!ui_out_is_mi_like_p (uiout))
-       ui_out_field_string (uiout, "function", "??");
+       uiout->field_string ("function", MSYMBOL_PRINT_NAME (msym));
+      else if (!uiout->is_mi_like_p ())
+       uiout->field_string ("function", "??");
 
       if ((flags & RECORD_PRINT_INSN_RANGE) != 0)
        {
-         ui_out_text (uiout, _("\tinst "));
+         uiout->text (_("\tinst "));
          btrace_call_history_insn_range (uiout, bfun);
        }
 
       if ((flags & RECORD_PRINT_SRC_LINE) != 0)
        {
-         ui_out_text (uiout, _("\tat "));
+         uiout->text (_("\tat "));
          btrace_call_history_src_line (uiout, bfun);
        }
 
-      ui_out_text (uiout, "\n");
+      uiout->text ("\n");
     }
 }
 
 /* The to_call_history method of target record-btrace.  */
 
 static void
-record_btrace_call_history (struct target_ops *self, int size, int flags)
+record_btrace_call_history (struct target_ops *self, int size, int int_flags)
 {
   struct btrace_thread_info *btinfo;
   struct btrace_call_history *history;
@@ -968,6 +1151,7 @@ record_btrace_call_history (struct target_ops *self, int size, int flags)
   struct cleanup *uiout_cleanup;
   struct ui_out *uiout;
   unsigned int context, covered;
+  record_print_flags flags = (enum record_print_flag) int_flags;
 
   uiout = current_uiout;
   uiout_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout,
@@ -982,7 +1166,7 @@ record_btrace_call_history (struct target_ops *self, int size, int flags)
     {
       struct btrace_insn_iterator *replay;
 
-      DEBUG ("call-history (0x%x): %d", flags, size);
+      DEBUG ("call-history (0x%x): %d", int_flags, size);
 
       /* If we're replaying, we start at the replay position.  Otherwise, we
         start at the tail of the trace.  */
@@ -1017,7 +1201,7 @@ record_btrace_call_history (struct target_ops *self, int size, int flags)
       begin = history->begin;
       end = history->end;
 
-      DEBUG ("call-history (0x%x): %d, prev: [%u; %u)", flags, size,
+      DEBUG ("call-history (0x%x): %d, prev: [%u; %u)", int_flags, size,
             btrace_call_number (&begin), btrace_call_number (&end));
 
       if (size < 0)
@@ -1050,7 +1234,8 @@ record_btrace_call_history (struct target_ops *self, int size, int flags)
 
 static void
 record_btrace_call_history_range (struct target_ops *self,
-                                 ULONGEST from, ULONGEST to, int flags)
+                                 ULONGEST from, ULONGEST to,
+                                 int int_flags)
 {
   struct btrace_thread_info *btinfo;
   struct btrace_call_history *history;
@@ -1059,6 +1244,7 @@ record_btrace_call_history_range (struct target_ops *self,
   struct ui_out *uiout;
   unsigned int low, high;
   int found;
+  record_print_flags flags = (enum record_print_flag) int_flags;
 
   uiout = current_uiout;
   uiout_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout,
@@ -1066,7 +1252,7 @@ record_btrace_call_history_range (struct target_ops *self,
   low = from;
   high = to;
 
-  DEBUG ("call-history (0x%x): [%u; %u)", flags, low, high);
+  DEBUG ("call-history (0x%x): [%u; %u)", int_flags, low, high);
 
   /* Check for wrap-arounds.  */
   if (low != from || high != to)
@@ -1103,9 +1289,11 @@ record_btrace_call_history_range (struct target_ops *self,
 
 static void
 record_btrace_call_history_from (struct target_ops *self,
-                                ULONGEST from, int size, int flags)
+                                ULONGEST from, int size,
+                                int int_flags)
 {
   ULONGEST begin, end, context;
+  record_print_flags flags = (enum record_print_flag) int_flags;
 
   context = abs (size);
   if (context == 0)
@@ -1193,7 +1381,7 @@ record_btrace_xfer_partial (struct target_ops *ops, enum target_object object,
                     & SEC_READONLY) != 0)
                  {
                    /* Truncate the request to fit into this section.  */
-                   len = min (len, section->endaddr - offset);
+                   len = std::min (len, section->endaddr - offset);
                    break;
                  }
              }
@@ -1246,7 +1434,8 @@ record_btrace_insert_breakpoint (struct target_ops *ops,
 static int
 record_btrace_remove_breakpoint (struct target_ops *ops,
                                 struct gdbarch *gdbarch,
-                                struct bp_target_info *bp_tgt)
+                                struct bp_target_info *bp_tgt,
+                                enum remove_bp_reason reason)
 {
   const char *old;
   int ret;
@@ -1259,7 +1448,8 @@ record_btrace_remove_breakpoint (struct target_ops *ops,
   ret = 0;
   TRY
     {
-      ret = ops->beneath->to_remove_breakpoint (ops->beneath, gdbarch, bp_tgt);
+      ret = ops->beneath->to_remove_breakpoint (ops->beneath, gdbarch, bp_tgt,
+                                               reason);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -1370,7 +1560,8 @@ static htab_t bfcache;
 static hashval_t
 bfcache_hash (const void *arg)
 {
-  const struct btrace_frame_cache *cache = arg;
+  const struct btrace_frame_cache *cache
+    = (const struct btrace_frame_cache *) arg;
 
   return htab_hash_pointer (cache->frame);
 }
@@ -1380,8 +1571,10 @@ bfcache_hash (const void *arg)
 static int
 bfcache_eq (const void *arg1, const void *arg2)
 {
-  const struct btrace_frame_cache *cache1 = arg1;
-  const struct btrace_frame_cache *cache2 = arg2;
+  const struct btrace_frame_cache *cache1
+    = (const struct btrace_frame_cache *) arg1;
+  const struct btrace_frame_cache *cache2
+    = (const struct btrace_frame_cache *) arg2;
 
   return cache1->frame == cache2->frame;
 }
@@ -1420,7 +1613,7 @@ btrace_get_frame_function (struct frame_info *frame)
   if (slot == NULL)
     return NULL;
 
-  cache = *slot;
+  cache = (const struct btrace_frame_cache *) *slot;
   return cache->bfun;
 }
 
@@ -1433,7 +1626,7 @@ record_btrace_frame_unwind_stop_reason (struct frame_info *this_frame,
   const struct btrace_frame_cache *cache;
   const struct btrace_function *bfun;
 
-  cache = *this_cache;
+  cache = (const struct btrace_frame_cache *) *this_cache;
   bfun = cache->bfun;
   gdb_assert (bfun != NULL);
 
@@ -1453,7 +1646,7 @@ record_btrace_frame_this_id (struct frame_info *this_frame, void **this_cache,
   const struct btrace_function *bfun;
   CORE_ADDR code, special;
 
-  cache = *this_cache;
+  cache = (const struct btrace_frame_cache *) *this_cache;
 
   bfun = cache->bfun;
   gdb_assert (bfun != NULL);
@@ -1492,7 +1685,7 @@ record_btrace_frame_prev_register (struct frame_info *this_frame,
     throw_error (NOT_AVAILABLE_ERROR,
                 _("Registers are not available in btrace record history"));
 
-  cache = *this_cache;
+  cache = (const struct btrace_frame_cache *) *this_cache;
   bfun = cache->bfun;
   gdb_assert (bfun != NULL);
 
@@ -1615,7 +1808,7 @@ record_btrace_frame_dealloc_cache (struct frame_info *self, void *this_cache)
   struct btrace_frame_cache *cache;
   void **slot;
 
-  cache = this_cache;
+  cache = (struct btrace_frame_cache *) this_cache;
 
   slot = htab_find_slot (bfcache, cache, NO_INSERT);
   gdb_assert (slot != NULL);
@@ -1701,7 +1894,7 @@ record_btrace_resume_thread (struct thread_info *tp,
 {
   struct btrace_thread_info *btinfo;
 
-  DEBUG ("resuming thread %d (%s): %x (%s)", tp->num,
+  DEBUG ("resuming thread %s (%s): %x (%s)", print_thread_id (tp),
         target_pid_to_str (tp->ptid), flag, btrace_thread_flag_to_str (flag));
 
   btinfo = &tp->btrace;
@@ -1909,7 +2102,8 @@ record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step,
       && !record_btrace_is_replaying (ops, minus_one_ptid))
     {
       ops = ops->beneath;
-      return ops->to_resume (ops, ptid, step, signal);
+      ops->to_resume (ops, ptid, step, signal);
+      return;
     }
 
   /* Compute the btrace thread flag for the requested move.  */
@@ -1956,6 +2150,16 @@ record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step,
     }
 }
 
+/* The to_commit_resume method of target record-btrace.  */
+
+static void
+record_btrace_commit_resume (struct target_ops *ops)
+{
+  if ((execution_direction != EXEC_REVERSE)
+      && !record_btrace_is_replaying (ops, minus_one_ptid))
+    ops->beneath->to_commit_resume (ops->beneath);
+}
+
 /* Cancel resuming TP.  */
 
 static void
@@ -1967,7 +2171,8 @@ record_btrace_cancel_resume (struct thread_info *tp)
   if (flags == 0)
     return;
 
-  DEBUG ("cancel resume thread %d (%s): %x (%s)", tp->num,
+  DEBUG ("cancel resume thread %s (%s): %x (%s)",
+        print_thread_id (tp),
         target_pid_to_str (tp->ptid), flags,
         btrace_thread_flag_to_str (flags));
 
@@ -2095,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;
@@ -2109,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;
@@ -2118,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);
 
@@ -2139,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;
@@ -2150,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);
 
@@ -2190,7 +2405,7 @@ record_btrace_step_thread (struct thread_info *tp)
   flags = btinfo->flags & (BTHR_MOVE | BTHR_STOP);
   btinfo->flags &= ~(BTHR_MOVE | BTHR_STOP);
 
-  DEBUG ("stepping thread %d (%s): %x (%s)", tp->num,
+  DEBUG ("stepping thread %s (%s): %x (%s)", print_thread_id (tp),
         target_pid_to_str (tp->ptid), flags,
         btrace_thread_flag_to_str (flags));
 
@@ -2399,7 +2614,8 @@ record_btrace_wait (struct target_ops *ops, ptid_t ptid,
   /* We moved the replay position but did not update registers.  */
   registers_changed_ptid (eventing->ptid);
 
-  DEBUG ("wait ended by thread %d (%s): %s", eventing->num,
+  DEBUG ("wait ended by thread %s (%s): %s",
+        print_thread_id (eventing),
         target_pid_to_str (eventing->ptid),
         target_waitstatus_to_string (status));
 
@@ -2566,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);
 }
 
@@ -2656,7 +2883,7 @@ init_record_btrace_ops (void)
   ops->to_close = record_btrace_close;
   ops->to_async = record_btrace_async;
   ops->to_detach = record_detach;
-  ops->to_disconnect = record_disconnect;
+  ops->to_disconnect = record_btrace_disconnect;
   ops->to_mourn_inferior = record_mourn_inferior;
   ops->to_kill = record_kill;
   ops->to_stop_recording = record_btrace_stop_recording;
@@ -2679,6 +2906,7 @@ init_record_btrace_ops (void)
   ops->to_get_unwinder = &record_btrace_to_get_unwinder;
   ops->to_get_tailcall_unwinder = &record_btrace_to_get_tailcall_unwinder;
   ops->to_resume = record_btrace_resume;
+  ops->to_commit_resume = record_btrace_commit_resume;
   ops->to_wait = record_btrace_wait;
   ops->to_stop = record_btrace_stop;
   ops->to_update_thread_list = record_btrace_update_thread_list;
@@ -2722,7 +2950,7 @@ cmd_record_btrace_bts_start (char *args, int from_tty)
   END_CATCH
 }
 
-/* Start recording Intel(R) Processor Trace.  */
+/* Start recording in Intel Processor Trace format.  */
 
 static void
 cmd_record_btrace_pt_start (char *args, int from_tty)
@@ -2884,7 +3112,7 @@ This format may not be available on all processors."),
 
   add_cmd ("pt", class_obscure, cmd_record_btrace_pt_start,
           _("\
-Start branch trace recording in Intel(R) Processor Trace format.\n\n\
+Start branch trace recording in Intel Processor Trace format.\n\n\
 This format may not be available on all processors."),
           &record_btrace_cmdlist);
   add_alias_cmd ("pt", "btrace pt", class_obscure, 1, &record_cmdlist);
This page took 0.046687 seconds and 4 git commands to generate.