ELF: Add run-time tests for -z now
[deliverable/binutils-gdb.git] / gdb / btrace.c
index 9f5657df867336c730fa069952ea0faa41d32285..238df0a123b4b805ca01ab51829e287033df53c9 100644 (file)
@@ -1112,16 +1112,27 @@ pt_reclassify_insn (enum pt_insn_class iclass)
 /* Return the btrace instruction flags for INSN.  */
 
 static btrace_insn_flags
-pt_btrace_insn_flags (const struct pt_insn *insn)
+pt_btrace_insn_flags (const struct pt_insn &insn)
 {
   btrace_insn_flags flags = 0;
 
-  if (insn->speculative)
+  if (insn.speculative)
     flags |= BTRACE_INSN_FLAG_SPECULATIVE;
 
   return flags;
 }
 
+/* Return the btrace instruction for INSN.  */
+
+static btrace_insn
+pt_btrace_insn (const struct pt_insn &insn)
+{
+  return {(CORE_ADDR) insn.ip, (gdb_byte) insn.size,
+         pt_reclassify_insn (insn.iclass),
+         pt_btrace_insn_flags (insn)};
+}
+
+
 /* Add function branch trace using DECODER.  */
 
 static void
@@ -1138,7 +1149,6 @@ ftrace_add_pt (struct pt_insn_decoder *decoder,
   end = *pend;
   for (;;)
     {
-      struct btrace_insn btinsn;
       struct pt_insn insn;
 
       errcode = pt_insn_sync_forward (decoder);
@@ -1150,7 +1160,6 @@ ftrace_add_pt (struct pt_insn_decoder *decoder,
          break;
        }
 
-      memset (&btinsn, 0, sizeof (btinsn));
       for (;;)
        {
          errcode = pt_insn_next (decoder, &insn, sizeof(insn));
@@ -1207,11 +1216,7 @@ ftrace_add_pt (struct pt_insn_decoder *decoder,
          /* Maintain the function level offset.  */
          *plevel = std::min (*plevel, end->level);
 
-         btinsn.pc = (CORE_ADDR) insn.ip;
-         btinsn.size = (gdb_byte) insn.size;
-         btinsn.iclass = pt_reclassify_insn (insn.iclass);
-         btinsn.flags = pt_btrace_insn_flags (&insn);
-
+         btrace_insn btinsn = pt_btrace_insn (insn);
          ftrace_update_insns (end, &btinsn);
        }
 
@@ -1725,6 +1730,55 @@ btrace_maint_clear (struct btrace_thread_info *btinfo)
 
 /* See btrace.h.  */
 
+const char *
+btrace_decode_error (enum btrace_format format, int errcode)
+{
+  switch (format)
+    {
+    case BTRACE_FORMAT_BTS:
+      switch (errcode)
+       {
+       case BDE_BTS_OVERFLOW:
+         return _("instruction overflow");
+
+       case BDE_BTS_INSN_SIZE:
+         return _("unknown instruction");
+
+       default:
+         break;
+       }
+      break;
+
+#if defined (HAVE_LIBIPT)
+    case BTRACE_FORMAT_PT:
+      switch (errcode)
+       {
+       case BDE_PT_USER_QUIT:
+         return _("trace decode cancelled");
+
+       case BDE_PT_DISABLED:
+         return _("disabled");
+
+       case BDE_PT_OVERFLOW:
+         return _("overflow");
+
+       default:
+         if (errcode < 0)
+           return pt_errstr (pt_errcode (errcode));
+         break;
+       }
+      break;
+#endif /* defined (HAVE_LIBIPT)  */
+
+    default:
+      break;
+    }
+
+  return _("unknown");
+}
+
+/* See btrace.h.  */
+
 void
 btrace_fetch (struct thread_info *tp)
 {
@@ -1790,13 +1844,19 @@ btrace_fetch (struct thread_info *tp)
   /* Compute the trace, provided we have any.  */
   if (!btrace_data_empty (&btrace))
     {
+      struct btrace_function *bfun;
+
       /* 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_maint_clear (btinfo);
 
+      VEC_truncate (btrace_fun_p, btinfo->functions, 0);
       btrace_clear_history (btinfo);
       btrace_compute_ftrace (tp, &btrace);
+
+      for (bfun = btinfo->begin; bfun != NULL; bfun = bfun->flow.next)
+       VEC_safe_push (btrace_fun_p, btinfo->functions, bfun);
     }
 
   do_cleanups (cleanup);
@@ -1819,6 +1879,8 @@ btrace_clear (struct thread_info *tp)
 
   btinfo = &tp->btrace;
 
+  VEC_free (btrace_fun_p, btinfo->functions);
+
   it = btinfo->begin;
   while (it != NULL)
     {
@@ -2409,20 +2471,45 @@ btrace_find_insn_by_number (struct btrace_insn_iterator *it,
                            unsigned int number)
 {
   const struct btrace_function *bfun;
+  unsigned int upper, lower;
 
-  for (bfun = btinfo->end; bfun != NULL; bfun = bfun->flow.prev)
-    if (bfun->insn_offset <= number)
-      break;
+  if (VEC_empty (btrace_fun_p, btinfo->functions))
+      return 0;
 
-  if (bfun == NULL)
+  lower = 0;
+  bfun = VEC_index (btrace_fun_p, btinfo->functions, lower);
+  if (number < bfun->insn_offset)
     return 0;
 
-  if (bfun->insn_offset + ftrace_call_num_insn (bfun) <= number)
+  upper = VEC_length (btrace_fun_p, btinfo->functions) - 1;
+  bfun = VEC_index (btrace_fun_p, btinfo->functions, upper);
+  if (number >= bfun->insn_offset + ftrace_call_num_insn (bfun))
     return 0;
 
+  /* We assume that there are no holes in the numbering.  */
+  for (;;)
+    {
+      const unsigned int average = lower + (upper - lower) / 2;
+
+      bfun = VEC_index (btrace_fun_p, btinfo->functions, average);
+
+      if (number < bfun->insn_offset)
+       {
+         upper = average - 1;
+         continue;
+       }
+
+      if (number >= bfun->insn_offset + ftrace_call_num_insn (bfun))
+       {
+         lower = average + 1;
+         continue;
+       }
+
+      break;
+    }
+
   it->function = bfun;
   it->index = number - bfun->insn_offset;
-
   return 1;
 }
 
This page took 0.025586 seconds and 4 git commands to generate.