btrace: add replay position to btrace thread info
authorMarkus Metzger <markus.t.metzger@intel.com>
Fri, 26 Apr 2013 06:37:06 +0000 (08:37 +0200)
committerMarkus Metzger <markus.t.metzger@intel.com>
Thu, 16 Jan 2014 12:06:09 +0000 (13:06 +0100)
Add a branch trace instruction iterator pointing to the current replay position
to the branch trace thread info struct.

Free the iterator when btrace is cleared.

Start at the replay position for the instruction and function-call histories.

2014-01-16  Markus Metzger  <markus.t.metzger@intel.com>

* btrace.h (replay) <replay>: New.
(btrace_is_replaying): New.
* btrace.c (btrace_clear): Free replay iterator.
(btrace_is_replaying): New.
* record-btrace.c (record_btrace_is_replaying): New.
(record_btrace_info): Print insn number if replaying.
(record_btrace_insn_history): Start at replay position.
(record_btrace_call_history): Start at replay position.
(init_record_btrace_ops): Init to_record_is_replaying.

gdb/ChangeLog
gdb/btrace.c
gdb/btrace.h
gdb/record-btrace.c

index 8239d172278eacdd67fc425a92f9aaf09a6582cd..d8d296147e97ab64a33d48e6cd25420661566ba4 100644 (file)
@@ -1,3 +1,15 @@
+2014-01-16  Markus Metzger  <markus.t.metzger@intel.com>
+
+       * btrace.h (replay) <replay>: New.
+       (btrace_is_replaying): New.
+       * btrace.c (btrace_clear): Free replay iterator.
+       (btrace_is_replaying): New.
+       * record-btrace.c (record_btrace_is_replaying): New.
+       (record_btrace_info): Print insn number if replaying.
+       (record_btrace_insn_history): Start at replay position.
+       (record_btrace_call_history): Start at replay position.
+       (init_record_btrace_ops): Init to_record_is_replaying.
+
 2014-01-16  Markus Metzger  <markus.t.metzger@intel.com>
 
        * record-btrace.c (record_btrace_insn_history_range): Include
index 1d060d3eb8efcb5fc94377571e7e9f9ceecf62e0..632ebe10cbb7add2c1f6dc57dfbdc690cc3940c5 100644 (file)
@@ -781,9 +781,11 @@ btrace_clear (struct thread_info *tp)
 
   xfree (btinfo->insn_history);
   xfree (btinfo->call_history);
+  xfree (btinfo->replay);
 
   btinfo->insn_history = NULL;
   btinfo->call_history = NULL;
+  btinfo->replay = NULL;
 }
 
 /* See btrace.h.  */
@@ -1339,3 +1341,11 @@ btrace_set_call_history (struct btrace_thread_info *btinfo,
   btinfo->call_history->begin = *begin;
   btinfo->call_history->end = *end;
 }
+
+/* See btrace.h.  */
+
+int
+btrace_is_replaying (struct thread_info *tp)
+{
+  return tp->btrace.replay != NULL;
+}
index d219f696966c226a5eec9878521252f703318321..93e6940c0627828cbd747da380c71a9dd71389a1 100644 (file)
@@ -187,6 +187,9 @@ struct btrace_thread_info
 
   /* The function call history iterator.  */
   struct btrace_call_history *call_history;
+
+  /* The current replay position.  NULL if not replaying.  */
+  struct btrace_insn_iterator *replay;
 };
 
 /* Enable branch tracing for a thread.  */
@@ -308,4 +311,7 @@ extern void btrace_set_call_history (struct btrace_thread_info *,
                                     const struct btrace_call_iterator *begin,
                                     const struct btrace_call_iterator *end);
 
+/* Determine if branch tracing is currently replaying TP.  */
+extern int btrace_is_replaying (struct thread_info *tp);
+
 #endif /* BTRACE_H */
index 34aee40e5eb16038bd72774d63ee6f1cd5e45760..9a65146532a821e1801bb9d8ae18e219fa90b6b8 100644 (file)
@@ -236,6 +236,10 @@ record_btrace_info (void)
   printf_unfiltered (_("Recorded %u instructions in %u functions for thread "
                       "%d (%s).\n"), insns, calls, tp->num,
                     target_pid_to_str (tp->ptid));
+
+  if (btrace_is_replaying (tp))
+    printf_unfiltered (_("Replay in progress.  At instruction %u.\n"),
+                      btrace_insn_number (btinfo->replay));
 }
 
 /* Print an unsigned int.  */
@@ -300,13 +304,34 @@ record_btrace_insn_history (int size, int flags)
   history = btinfo->insn_history;
   if (history == NULL)
     {
-      /* No matter the direction, we start with the tail of the trace.  */
-      btrace_insn_end (&begin, btinfo);
-      end = begin;
+      struct btrace_insn_iterator *replay;
 
       DEBUG ("insn-history (0x%x): %d", flags, size);
 
-      covered = btrace_insn_prev (&begin, context);
+      /* If we're replaying, we start at the replay position.  Otherwise, we
+        start at the tail of the trace.  */
+      replay = btinfo->replay;
+      if (replay != NULL)
+       begin = *replay;
+      else
+       btrace_insn_end (&begin, btinfo);
+
+      /* We start from here and expand in the requested direction.  Then we
+        expand in the other direction, as well, to fill up any remaining
+        context.  */
+      end = begin;
+      if (size < 0)
+       {
+         /* We want the current position covered, as well.  */
+         covered = btrace_insn_next (&end, 1);
+         covered += btrace_insn_prev (&begin, context - covered);
+         covered += btrace_insn_next (&end, context - covered);
+       }
+      else
+       {
+         covered = btrace_insn_next (&end, context);
+         covered += btrace_insn_prev (&begin, context - covered);
+       }
     }
   else
     {
@@ -560,13 +585,37 @@ record_btrace_call_history (int size, int flags)
   history = btinfo->call_history;
   if (history == NULL)
     {
-      /* No matter the direction, we start with the tail of the trace.  */
-      btrace_call_end (&begin, btinfo);
-      end = begin;
+      struct btrace_insn_iterator *replay;
 
       DEBUG ("call-history (0x%x): %d", flags, size);
 
-      covered = btrace_call_prev (&begin, context);
+      /* If we're replaying, we start at the replay position.  Otherwise, we
+        start at the tail of the trace.  */
+      replay = btinfo->replay;
+      if (replay != NULL)
+       {
+         begin.function = replay->function;
+         begin.btinfo = btinfo;
+       }
+      else
+       btrace_call_end (&begin, btinfo);
+
+      /* We start from here and expand in the requested direction.  Then we
+        expand in the other direction, as well, to fill up any remaining
+        context.  */
+      end = begin;
+      if (size < 0)
+       {
+         /* We want the current position covered, as well.  */
+         covered = btrace_call_next (&end, 1);
+         covered += btrace_call_prev (&begin, context - covered);
+         covered += btrace_call_next (&end, context - covered);
+       }
+      else
+       {
+         covered = btrace_call_next (&end, context);
+         covered += btrace_call_prev (&begin, context- covered);
+       }
     }
   else
     {
@@ -687,6 +736,20 @@ record_btrace_call_history_from (ULONGEST from, int size, int flags)
   record_btrace_call_history_range (begin, end, flags);
 }
 
+/* The to_record_is_replaying method of target record-btrace.  */
+
+static int
+record_btrace_is_replaying (void)
+{
+  struct thread_info *tp;
+
+  ALL_THREADS (tp)
+    if (btrace_is_replaying (tp))
+      return 1;
+
+  return 0;
+}
+
 /* Initialize the record-btrace target ops.  */
 
 static void
@@ -713,6 +776,7 @@ init_record_btrace_ops (void)
   ops->to_call_history = record_btrace_call_history;
   ops->to_call_history_from = record_btrace_call_history_from;
   ops->to_call_history_range = record_btrace_call_history_range;
+  ops->to_record_is_replaying = record_btrace_is_replaying;
   ops->to_stratum = record_stratum;
   ops->to_magic = OPS_MAGIC;
 }