btrace: store raw btrace data
authorMarkus Metzger <markus.t.metzger@intel.com>
Mon, 3 Feb 2014 10:40:50 +0000 (11:40 +0100)
committerMarkus Metzger <markus.t.metzger@intel.com>
Thu, 2 Jul 2015 10:54:20 +0000 (12:54 +0200)
Store the raw branch trace data that has been read from the target.

This data can be used for maintenance commands as well as for generating
a core file for the "record save" command.

gdb/
* btrace.c (btrace_fetch): Append the new trace data.
(btrace_clear): Clear the stored trace data.
* btrace.h (btrace_thread_info) <data>: New.
* common/btrace-common.h (btrace_data_clear)
(btrace_data_append): New.
* common/btrace-common.c (btrace_data_clear)
(btrace_data_append): New.

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

index a4cce4d..807d19f 100644 (file)
@@ -1,5 +1,15 @@
 2015-07-02  Markus Metzger  <markus.t.metzger@intel.com>
 
+       * btrace.c (btrace_fetch): Append the new trace data.
+       (btrace_clear): Clear the stored trace data.
+       * btrace.h (btrace_thread_info) <data>: New.
+       * common/btrace-common.h (btrace_data_clear)
+       (btrace_data_append): New.
+       * common/btrace-common.c (btrace_data_clear)
+       (btrace_data_append): New.
+
+2015-07-02  Markus Metzger  <markus.t.metzger@intel.com>
+
        * nat/linux-btrace.c (linux_enable_bts): Check for
        PERF_ATTR_SIZE_VER5.
        Check for data_offset and data_size fields.  Use them.
index 561ee7c..87b2601 100644 (file)
@@ -1260,6 +1260,10 @@ btrace_fetch (struct thread_info *tp)
   /* Compute the trace, provided we have any.  */
   if (!btrace_data_empty (&btrace))
     {
+      /* Store the raw trace data.  The stored data will be cleared in
+        btrace_clear, so we always append the new trace.  */
+      btrace_data_append (&btinfo->data, &btrace);
+
       btrace_clear_history (btinfo);
       btrace_compute_ftrace (tp, &btrace);
     }
@@ -1296,6 +1300,7 @@ btrace_clear (struct thread_info *tp)
   btinfo->end = NULL;
   btinfo->ngaps = 0;
 
+  btrace_data_clear (&btinfo->data);
   btrace_clear_history (btinfo);
 }
 
index c25dc84..0845b78 100644 (file)
@@ -248,6 +248,9 @@ struct btrace_thread_info
      the underlying architecture.  */
   struct btrace_target_info *target;
 
+  /* The raw branch trace data for the below branch trace.  */
+  struct btrace_data data;
+
   /* The current branch trace for this thread (both inclusive).
 
      The last instruction of END is the current instruction, which is not
index 676428e..95193eb 100644 (file)
@@ -91,3 +91,90 @@ btrace_data_empty (struct btrace_data *data)
 
   internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
 }
+
+/* See btrace-common.h.  */
+
+void
+btrace_data_clear (struct btrace_data *data)
+{
+  btrace_data_fini (data);
+  btrace_data_init (data);
+}
+
+/* See btrace-common.h.  */
+
+int
+btrace_data_append (struct btrace_data *dst,
+                   const struct btrace_data *src)
+{
+  switch (src->format)
+    {
+    case BTRACE_FORMAT_NONE:
+      return 0;
+
+    case BTRACE_FORMAT_BTS:
+      switch (dst->format)
+       {
+       default:
+         return -1;
+
+       case BTRACE_FORMAT_NONE:
+         dst->format = BTRACE_FORMAT_BTS;
+         dst->variant.bts.blocks = NULL;
+
+         /* Fall-through.  */
+       case BTRACE_FORMAT_BTS:
+         {
+           unsigned int blk;
+
+           /* We copy blocks in reverse order to have the oldest block at
+              index zero.  */
+           blk = VEC_length (btrace_block_s, src->variant.bts.blocks);
+           while (blk != 0)
+             {
+               btrace_block_s *block;
+
+               block = VEC_index (btrace_block_s, src->variant.bts.blocks,
+                                  --blk);
+
+               VEC_safe_push (btrace_block_s, dst->variant.bts.blocks, block);
+             }
+         }
+       }
+      return 0;
+
+    case BTRACE_FORMAT_PT:
+      switch (dst->format)
+       {
+       default:
+         return -1;
+
+       case BTRACE_FORMAT_NONE:
+         dst->format = BTRACE_FORMAT_PT;
+         dst->variant.pt.data = NULL;
+         dst->variant.pt.size = 0;
+
+         /* fall-through.  */
+       case BTRACE_FORMAT_BTS:
+         {
+           gdb_byte *data;
+           unsigned long size;
+
+           size = src->variant.pt.size + dst->variant.pt.size;
+           data = xmalloc (size);
+
+           memcpy (data, dst->variant.pt.data, dst->variant.pt.size);
+           memcpy (data + dst->variant.pt.size, src->variant.pt.data,
+                   src->variant.pt.size);
+
+           xfree (dst->variant.pt.data);
+
+           dst->variant.pt.data = data;
+           dst->variant.pt.size = size;
+         }
+       }
+      return 0;
+    }
+
+  internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
+}
index ebae17e..f22efc5 100644 (file)
@@ -214,7 +214,16 @@ extern void btrace_data_init (struct btrace_data *data);
 /* Cleanup DATA.  */
 extern void btrace_data_fini (struct btrace_data *data);
 
+/* Clear DATA.  */
+extern void btrace_data_clear (struct btrace_data *data);
+
 /* Return non-zero if DATA is empty; zero otherwise.  */
 extern int btrace_data_empty (struct btrace_data *data);
 
+/* Append the branch trace data from SRC to the end of DST.
+   Both SRC and DST must use the same format.
+   Returns zero on success; a negative number otherwise.  */
+extern int btrace_data_append (struct btrace_data *dst,
+                              const struct btrace_data *src);
+
 #endif /* BTRACE_COMMON_H */