Re: Optimise away eh_frame advance_loc 0
[deliverable/binutils-gdb.git] / gdb / btrace.c
index f0b8eebdcf9c9f43d60f6fb135257e084ad5e9b3..cf0a4e747fd3d8bb1ef4a3969039f93e861bc516 100644 (file)
@@ -1,6 +1,6 @@
 /* Branch trace support for GDB, the GNU debugger.
 
 /* Branch trace support for GDB, the GNU debugger.
 
-   Copyright (C) 2013-2017 Free Software Foundation, Inc.
+   Copyright (C) 2013-2019 Free Software Foundation, Inc.
 
    Contributed by Intel Corp. <markus.t.metzger@intel.com>
 
 
    Contributed by Intel Corp. <markus.t.metzger@intel.com>
 
 #include "filenames.h"
 #include "xml-support.h"
 #include "regcache.h"
 #include "filenames.h"
 #include "xml-support.h"
 #include "regcache.h"
-#include "rsp-low.h"
+#include "gdbsupport/rsp-low.h"
 #include "gdbcmd.h"
 #include "cli/cli-utils.h"
 #include "gdbcmd.h"
 #include "cli/cli-utils.h"
+#include "gdbarch.h"
+
+/* For maintenance commands.  */
+#include "record-btrace.h"
 
 #include <inttypes.h>
 #include <ctype.h>
 
 #include <inttypes.h>
 #include <ctype.h>
@@ -47,11 +51,7 @@ static struct cmd_list_element *maint_btrace_pt_set_cmdlist;
 static struct cmd_list_element *maint_btrace_pt_show_cmdlist;
 
 /* Control whether to skip PAD packets when computing the packet history.  */
 static struct cmd_list_element *maint_btrace_pt_show_cmdlist;
 
 /* Control whether to skip PAD packets when computing the packet history.  */
-static int maint_btrace_pt_skip_pad = 1;
-
-/* A vector of function segments.  */
-typedef struct btrace_function * bfun_s;
-DEF_VEC_P (bfun_s);
+static bool maint_btrace_pt_skip_pad = true;
 
 static void btrace_add_pc (struct thread_info *tp);
 
 
 static void btrace_add_pc (struct thread_info *tp);
 
@@ -135,7 +135,7 @@ ftrace_debug (const struct btrace_function *bfun, const char *prefix)
   level = bfun->level;
 
   ibegin = bfun->insn_offset;
   level = bfun->level;
 
   ibegin = bfun->insn_offset;
-  iend = ibegin + VEC_length (btrace_insn_s, bfun->insn);
+  iend = ibegin + bfun->insn.size ();
 
   DEBUG_FTRACE ("%s: fun = %s, file = %s, level = %d, insn = [%u; %u)",
                prefix, fun, file, level, ibegin, iend);
 
   DEBUG_FTRACE ("%s: fun = %s, file = %s, level = %d, insn = [%u; %u)",
                prefix, fun, file, level, ibegin, iend);
@@ -153,20 +153,32 @@ ftrace_call_num_insn (const struct btrace_function* bfun)
   if (bfun->errcode != 0)
     return 1;
 
   if (bfun->errcode != 0)
     return 1;
 
-  return VEC_length (btrace_insn_s, bfun->insn);
+  return bfun->insn.size ();
 }
 
 /* Return the function segment with the given NUMBER or NULL if no such segment
    exists.  BTINFO is the branch trace information for the current thread.  */
 
 static struct btrace_function *
 }
 
 /* Return the function segment with the given NUMBER or NULL if no such segment
    exists.  BTINFO is the branch trace information for the current thread.  */
 
 static struct btrace_function *
+ftrace_find_call_by_number (struct btrace_thread_info *btinfo,
+                           unsigned int number)
+{
+  if (number == 0 || number > btinfo->functions.size ())
+    return NULL;
+
+  return &btinfo->functions[number - 1];
+}
+
+/* A const version of the function above.  */
+
+static const struct btrace_function *
 ftrace_find_call_by_number (const struct btrace_thread_info *btinfo,
                            unsigned int number)
 {
   if (number == 0 || number > btinfo->functions.size ())
     return NULL;
 
 ftrace_find_call_by_number (const struct btrace_thread_info *btinfo,
                            unsigned int number)
 {
   if (number == 0 || number > btinfo->functions.size ())
     return NULL;
 
-  return btinfo->functions[number - 1];
+  return &btinfo->functions[number - 1];
 }
 
 /* Return non-zero if BFUN does not match MFUN and FUN,
 }
 
 /* Return non-zero if BFUN does not match MFUN and FUN,
@@ -218,41 +230,34 @@ ftrace_function_switched (const struct btrace_function *bfun,
 /* Allocate and initialize a new branch trace function segment at the end of
    the trace.
    BTINFO is the branch trace information for the current thread.
 /* Allocate and initialize a new branch trace function segment at the end of
    the trace.
    BTINFO is the branch trace information for the current thread.
-   MFUN and FUN are the symbol information we have for this function.  */
+   MFUN and FUN are the symbol information we have for this function.
+   This invalidates all struct btrace_function pointer currently held.  */
 
 static struct btrace_function *
 ftrace_new_function (struct btrace_thread_info *btinfo,
                     struct minimal_symbol *mfun,
                     struct symbol *fun)
 {
 
 static struct btrace_function *
 ftrace_new_function (struct btrace_thread_info *btinfo,
                     struct minimal_symbol *mfun,
                     struct symbol *fun)
 {
-  struct btrace_function *bfun;
-
-  bfun = XCNEW (struct btrace_function);
-
-  bfun->msym = mfun;
-  bfun->sym = fun;
+  int level;
+  unsigned int number, insn_offset;
 
   if (btinfo->functions.empty ())
     {
 
   if (btinfo->functions.empty ())
     {
-      /* Start counting at one.  */
-      bfun->number = 1;
-      bfun->insn_offset = 1;
+      /* Start counting NUMBER and INSN_OFFSET at one.  */
+      level = 0;
+      number = 1;
+      insn_offset = 1;
     }
   else
     {
     }
   else
     {
-      struct btrace_function *prev = btinfo->functions.back ();
-
-      gdb_assert (prev->flow.next == NULL);
-      prev->flow.next = bfun;
-      bfun->flow.prev = prev;
-
-      bfun->number = prev->number + 1;
-      bfun->insn_offset = prev->insn_offset + ftrace_call_num_insn (prev);
-      bfun->level = prev->level;
+      const struct btrace_function *prev = &btinfo->functions.back ();
+      level = prev->level;
+      number = prev->number + 1;
+      insn_offset = prev->insn_offset + ftrace_call_num_insn (prev);
     }
 
     }
 
-  btinfo->functions.push_back (bfun);
-  return bfun;
+  btinfo->functions.emplace_back (mfun, fun, number, insn_offset, level);
+  return &btinfo->functions.back ();
 }
 
 /* Update the UP field of a function segment.  */
 }
 
 /* Update the UP field of a function segment.  */
@@ -275,20 +280,29 @@ ftrace_update_caller (struct btrace_function *bfun,
 /* Fix up the caller for all segments of a function.  */
 
 static void
 /* Fix up the caller for all segments of a function.  */
 
 static void
-ftrace_fixup_caller (struct btrace_function *bfun,
+ftrace_fixup_caller (struct btrace_thread_info *btinfo,
+                    struct btrace_function *bfun,
                     struct btrace_function *caller,
                     enum btrace_function_flag flags)
 {
                     struct btrace_function *caller,
                     enum btrace_function_flag flags)
 {
-  struct btrace_function *prev, *next;
+  unsigned int prev, next;
 
 
+  prev = bfun->prev;
+  next = bfun->next;
   ftrace_update_caller (bfun, caller, flags);
 
   /* Update all function segments belonging to the same function.  */
   ftrace_update_caller (bfun, caller, flags);
 
   /* Update all function segments belonging to the same function.  */
-  for (prev = bfun->segment.prev; prev != NULL; prev = prev->segment.prev)
-    ftrace_update_caller (prev, caller, flags);
+  for (; prev != 0; prev = bfun->prev)
+    {
+      bfun = ftrace_find_call_by_number (btinfo, prev);
+      ftrace_update_caller (bfun, caller, flags);
+    }
 
 
-  for (next = bfun->segment.next; next != NULL; next = next->segment.next)
-    ftrace_update_caller (next, caller, flags);
+  for (; next != 0; next = bfun->next)
+    {
+      bfun = ftrace_find_call_by_number (btinfo, next);
+      ftrace_update_caller (bfun, caller, flags);
+    }
 }
 
 /* Add a new function segment for a call at the end of the trace.
 }
 
 /* Add a new function segment for a call at the end of the trace.
@@ -380,15 +394,13 @@ ftrace_find_call (struct btrace_thread_info *btinfo,
 {
   for (; bfun != NULL; bfun = ftrace_find_call_by_number (btinfo, bfun->up))
     {
 {
   for (; bfun != NULL; bfun = ftrace_find_call_by_number (btinfo, bfun->up))
     {
-      struct btrace_insn *last;
-
       /* Skip gaps.  */
       if (bfun->errcode != 0)
        continue;
 
       /* Skip gaps.  */
       if (bfun->errcode != 0)
        continue;
 
-      last = VEC_last (btrace_insn_s, bfun->insn);
+      btrace_insn &last = bfun->insn.back ();
 
 
-      if (last->iclass == BTRACE_INSN_CALL)
+      if (last.iclass == BTRACE_INSN_CALL)
        break;
     }
 
        break;
     }
 
@@ -405,10 +417,10 @@ ftrace_new_return (struct btrace_thread_info *btinfo,
                   struct minimal_symbol *mfun,
                   struct symbol *fun)
 {
                   struct minimal_symbol *mfun,
                   struct symbol *fun)
 {
-  struct btrace_function *prev = btinfo->functions.back ();
-  struct btrace_function *bfun, *caller;
+  struct btrace_function *prev, *bfun, *caller;
 
   bfun = ftrace_new_function (btinfo, mfun, fun);
 
   bfun = ftrace_new_function (btinfo, mfun, fun);
+  prev = ftrace_find_call_by_number (btinfo, bfun->number - 1);
 
   /* It is important to start at PREV's caller.  Otherwise, we might find
      PREV itself, if PREV is a recursive function.  */
 
   /* It is important to start at PREV's caller.  Otherwise, we might find
      PREV itself, if PREV is a recursive function.  */
@@ -418,10 +430,10 @@ ftrace_new_return (struct btrace_thread_info *btinfo,
     {
       /* The caller of PREV is the preceding btrace function segment in this
         function instance.  */
     {
       /* The caller of PREV is the preceding btrace function segment in this
         function instance.  */
-      gdb_assert (caller->segment.next == NULL);
+      gdb_assert (caller->next == 0);
 
 
-      caller->segment.next = bfun;
-      bfun->segment.prev = caller;
+      caller->next = bfun->number;
+      bfun->prev = caller->number;
 
       /* Maintain the function level.  */
       bfun->level = caller->level;
 
       /* Maintain the function level.  */
       bfun->level = caller->level;
@@ -453,7 +465,7 @@ ftrace_new_return (struct btrace_thread_info *btinfo,
          bfun->level = prev->level - 1;
 
          /* Fix up the call stack for PREV.  */
          bfun->level = prev->level - 1;
 
          /* Fix up the call stack for PREV.  */
-         ftrace_fixup_caller (prev, bfun, BFUN_UP_LINKS_TO_RET);
+         ftrace_fixup_caller (btinfo, prev, bfun, BFUN_UP_LINKS_TO_RET);
 
          ftrace_debug (bfun, "new return - no caller");
        }
 
          ftrace_debug (bfun, "new return - no caller");
        }
@@ -487,12 +499,12 @@ ftrace_new_switch (struct btrace_thread_info *btinfo,
                   struct minimal_symbol *mfun,
                   struct symbol *fun)
 {
                   struct minimal_symbol *mfun,
                   struct symbol *fun)
 {
-  struct btrace_function *prev = btinfo->functions.back ();
-  struct btrace_function *bfun;
+  struct btrace_function *prev, *bfun;
 
   /* This is an unexplained function switch.  We can't really be sure about the
      call stack, yet the best I can think of right now is to preserve it.  */
   bfun = ftrace_new_function (btinfo, mfun, fun);
 
   /* This is an unexplained function switch.  We can't really be sure about the
      call stack, yet the best I can think of right now is to preserve it.  */
   bfun = ftrace_new_function (btinfo, mfun, fun);
+  prev = ftrace_find_call_by_number (btinfo, bfun->number - 1);
   bfun->up = prev->up;
   bfun->flags = prev->flags;
 
   bfun->up = prev->up;
   bfun->flags = prev->flags;
 
@@ -507,7 +519,8 @@ ftrace_new_switch (struct btrace_thread_info *btinfo,
    ERRCODE is the format-specific error code.  */
 
 static struct btrace_function *
    ERRCODE is the format-specific error code.  */
 
 static struct btrace_function *
-ftrace_new_gap (struct btrace_thread_info *btinfo, int errcode)
+ftrace_new_gap (struct btrace_thread_info *btinfo, int errcode,
+               std::vector<unsigned int> &gaps)
 {
   struct btrace_function *bfun;
 
 {
   struct btrace_function *bfun;
 
@@ -516,12 +529,13 @@ ftrace_new_gap (struct btrace_thread_info *btinfo, int errcode)
   else
     {
       /* We hijack the previous function segment if it was empty.  */
   else
     {
       /* We hijack the previous function segment if it was empty.  */
-      bfun = btinfo->functions.back ();
-      if (bfun->errcode != 0 || !VEC_empty (btrace_insn_s, bfun->insn))
+      bfun = &btinfo->functions.back ();
+      if (bfun->errcode != 0 || !bfun->insn.empty ())
        bfun = ftrace_new_function (btinfo, NULL, NULL);
     }
 
   bfun->errcode = errcode;
        bfun = ftrace_new_function (btinfo, NULL, NULL);
     }
 
   bfun->errcode = errcode;
+  gaps.push_back (bfun->number);
 
   ftrace_debug (bfun, "new gap");
 
 
   ftrace_debug (bfun, "new gap");
 
@@ -538,7 +552,6 @@ ftrace_update_function (struct btrace_thread_info *btinfo, CORE_ADDR pc)
   struct bound_minimal_symbol bmfun;
   struct minimal_symbol *mfun;
   struct symbol *fun;
   struct bound_minimal_symbol bmfun;
   struct minimal_symbol *mfun;
   struct symbol *fun;
-  struct btrace_insn *last;
   struct btrace_function *bfun;
 
   /* Try to determine the function we're in.  We use both types of symbols
   struct btrace_function *bfun;
 
   /* Try to determine the function we're in.  We use both types of symbols
@@ -556,16 +569,16 @@ ftrace_update_function (struct btrace_thread_info *btinfo, CORE_ADDR pc)
     return ftrace_new_function (btinfo, mfun, fun);
 
   /* If we had a gap before, we create a function.  */
     return ftrace_new_function (btinfo, mfun, fun);
 
   /* If we had a gap before, we create a function.  */
-  bfun = btinfo->functions.back ();
+  bfun = &btinfo->functions.back ();
   if (bfun->errcode != 0)
     return ftrace_new_function (btinfo, mfun, fun);
 
   /* Check the last instruction, if we have one.
      We do this check first, since it allows us to fill in the call stack
      links in addition to the normal flow links.  */
   if (bfun->errcode != 0)
     return ftrace_new_function (btinfo, mfun, fun);
 
   /* Check the last instruction, if we have one.
      We do this check first, since it allows us to fill in the call stack
      links in addition to the normal flow links.  */
-  last = NULL;
-  if (!VEC_empty (btrace_insn_s, bfun->insn))
-    last = VEC_last (btrace_insn_s, bfun->insn);
+  btrace_insn *last = NULL;
+  if (!bfun->insn.empty ())
+    last = &bfun->insn.back ();
 
   if (last != NULL)
     {
 
   if (last != NULL)
     {
@@ -608,6 +621,20 @@ ftrace_update_function (struct btrace_thread_info *btinfo, CORE_ADDR pc)
            if (start == pc)
              return ftrace_new_tailcall (btinfo, mfun, fun);
 
            if (start == pc)
              return ftrace_new_tailcall (btinfo, mfun, fun);
 
+           /* Some versions of _Unwind_RaiseException use an indirect
+              jump to 'return' to the exception handler of the caller
+              handling the exception instead of a return.  Let's restrict
+              this heuristic to that and related functions.  */
+           const char *fname = ftrace_print_function_name (bfun);
+           if (strncmp (fname, "_Unwind_", strlen ("_Unwind_")) == 0)
+             {
+               struct btrace_function *caller
+                 = ftrace_find_call_by_number (btinfo, bfun->up);
+               caller = ftrace_find_caller (btinfo, caller, mfun, fun);
+               if (caller != NULL)
+                 return ftrace_new_return (btinfo, mfun, fun);
+             }
+
            /* If we can't determine the function for PC, we treat a jump at
               the end of the block as tail call if we're switching functions
               and as an intra-function branch if we don't.  */
            /* If we can't determine the function for PC, we treat a jump at
               the end of the block as tail call if we're switching functions
               and as an intra-function branch if we don't.  */
@@ -636,10 +663,9 @@ ftrace_update_function (struct btrace_thread_info *btinfo, CORE_ADDR pc)
 /* Add the instruction at PC to BFUN's instructions.  */
 
 static void
 /* Add the instruction at PC to BFUN's instructions.  */
 
 static void
-ftrace_update_insns (struct btrace_function *bfun,
-                    const struct btrace_insn *insn)
+ftrace_update_insns (struct btrace_function *bfun, const btrace_insn &insn)
 {
 {
-  VEC_safe_push (btrace_insn_s, bfun->insn, insn);
+  bfun->insn.push_back (insn);
 
   if (record_debug > 1)
     ftrace_debug (bfun, "update insn");
 
   if (record_debug > 1)
     ftrace_debug (bfun, "update insn");
@@ -653,7 +679,7 @@ ftrace_classify_insn (struct gdbarch *gdbarch, CORE_ADDR pc)
   enum btrace_insn_class iclass;
 
   iclass = BTRACE_INSN_OTHER;
   enum btrace_insn_class iclass;
 
   iclass = BTRACE_INSN_OTHER;
-  TRY
+  try
     {
       if (gdbarch_insn_is_call (gdbarch, pc))
        iclass = BTRACE_INSN_CALL;
     {
       if (gdbarch_insn_is_call (gdbarch, pc))
        iclass = BTRACE_INSN_CALL;
@@ -662,10 +688,9 @@ ftrace_classify_insn (struct gdbarch *gdbarch, CORE_ADDR pc)
       else if (gdbarch_insn_is_jump (gdbarch, pc))
        iclass = BTRACE_INSN_JUMP;
     }
       else if (gdbarch_insn_is_jump (gdbarch, pc))
        iclass = BTRACE_INSN_JUMP;
     }
-  CATCH (error, RETURN_MASK_ERROR)
+  catch (const gdb_exception_error &error)
     {
     }
     {
     }
-  END_CATCH
 
   return iclass;
 }
 
   return iclass;
 }
@@ -693,10 +718,12 @@ ftrace_match_backtrace (struct btrace_thread_info *btinfo,
   return matches;
 }
 
   return matches;
 }
 
-/* Add ADJUSTMENT to the level of BFUN and succeeding function segments.  */
+/* Add ADJUSTMENT to the level of BFUN and succeeding function segments.
+   BTINFO is the branch trace information for the current thread.  */
 
 static void
 
 static void
-ftrace_fixup_level (struct btrace_function *bfun, int adjustment)
+ftrace_fixup_level (struct btrace_thread_info *btinfo,
+                   struct btrace_function *bfun, int adjustment)
 {
   if (adjustment == 0)
     return;
 {
   if (adjustment == 0)
     return;
@@ -704,8 +731,11 @@ ftrace_fixup_level (struct btrace_function *bfun, int adjustment)
   DEBUG_FTRACE ("fixup level (%+d)", adjustment);
   ftrace_debug (bfun, "..bfun");
 
   DEBUG_FTRACE ("fixup level (%+d)", adjustment);
   ftrace_debug (bfun, "..bfun");
 
-  for (; bfun != NULL; bfun = bfun->flow.next)
-    bfun->level += adjustment;
+  while (bfun != NULL)
+    {
+      bfun->level += adjustment;
+      bfun = ftrace_find_call_by_number (btinfo, bfun->number + 1);
+    }
 }
 
 /* Recompute the global level offset.  Traverse the function trace and compute
 }
 
 /* Recompute the global level offset.  Traverse the function trace and compute
@@ -724,13 +754,13 @@ ftrace_compute_global_level_offset (struct btrace_thread_info *btinfo)
 
   unsigned int length = btinfo->functions.size() - 1;
   for (unsigned int i = 0; i < length; ++i)
 
   unsigned int length = btinfo->functions.size() - 1;
   for (unsigned int i = 0; i < length; ++i)
-    level = std::min (level, btinfo->functions[i]->level);
+    level = std::min (level, btinfo->functions[i].level);
 
   /* The last function segment contains the current instruction, which is not
      really part of the trace.  If it contains just this one instruction, we
      ignore the segment.  */
 
   /* The last function segment contains the current instruction, which is not
      really part of the trace.  If it contains just this one instruction, we
      ignore the segment.  */
-  struct btrace_function *last = btinfo->functions.back();
-  if (VEC_length (btrace_insn_s, last->insn) != 1)
+  struct btrace_function *last = &btinfo->functions.back();
+  if (last->insn.size () != 1)
     level = std::min (level, last->level);
 
   DEBUG_FTRACE ("setting global level offset: %d", -level);
     level = std::min (level, last->level);
 
   DEBUG_FTRACE ("setting global level offset: %d", -level);
@@ -751,14 +781,14 @@ ftrace_connect_bfun (struct btrace_thread_info *btinfo,
   ftrace_debug (next, "..next");
 
   /* The function segments are not yet connected.  */
   ftrace_debug (next, "..next");
 
   /* The function segments are not yet connected.  */
-  gdb_assert (prev->segment.next == NULL);
-  gdb_assert (next->segment.prev == NULL);
+  gdb_assert (prev->next == 0);
+  gdb_assert (next->prev == 0);
 
 
-  prev->segment.next = next;
-  next->segment.prev = prev;
+  prev->next = next->number;
+  next->prev = prev->number;
 
   /* We may have moved NEXT to a different function level.  */
 
   /* We may have moved NEXT to a different function level.  */
-  ftrace_fixup_level (next, prev->level - next->level);
+  ftrace_fixup_level (btinfo, next, prev->level - next->level);
 
   /* If we run out of back trace for one, let's use the other's.  */
   if (prev->up == 0)
 
   /* If we run out of back trace for one, let's use the other's.  */
   if (prev->up == 0)
@@ -769,7 +799,7 @@ ftrace_connect_bfun (struct btrace_thread_info *btinfo,
       if (next != NULL)
        {
          DEBUG_FTRACE ("using next's callers");
       if (next != NULL)
        {
          DEBUG_FTRACE ("using next's callers");
-         ftrace_fixup_caller (prev, next, flags);
+         ftrace_fixup_caller (btinfo, prev, next, flags);
        }
     }
   else if (next->up == 0)
        }
     }
   else if (next->up == 0)
@@ -780,7 +810,7 @@ ftrace_connect_bfun (struct btrace_thread_info *btinfo,
       if (prev != NULL)
        {
          DEBUG_FTRACE ("using prev's callers");
       if (prev != NULL)
        {
          DEBUG_FTRACE ("using prev's callers");
-         ftrace_fixup_caller (next, prev, flags);
+         ftrace_fixup_caller (btinfo, next, prev, flags);
        }
     }
   else
        }
     }
   else
@@ -808,7 +838,7 @@ ftrace_connect_bfun (struct btrace_thread_info *btinfo,
          DEBUG_FTRACE ("adding prev's tail calls to next");
 
          prev = ftrace_find_call_by_number (btinfo, prev->up);
          DEBUG_FTRACE ("adding prev's tail calls to next");
 
          prev = ftrace_find_call_by_number (btinfo, prev->up);
-         ftrace_fixup_caller (next, prev, prev_flags);
+         ftrace_fixup_caller (btinfo, next, prev, prev_flags);
 
          for (; prev != NULL; prev = ftrace_find_call_by_number (btinfo,
                                                                  prev->up))
 
          for (; prev != NULL; prev = ftrace_find_call_by_number (btinfo,
                                                                  prev->up))
@@ -820,7 +850,7 @@ ftrace_connect_bfun (struct btrace_thread_info *btinfo,
                  ftrace_debug (prev, "..top");
                  ftrace_debug (caller, "..up");
 
                  ftrace_debug (prev, "..top");
                  ftrace_debug (caller, "..up");
 
-                 ftrace_fixup_caller (prev, caller, next_flags);
+                 ftrace_fixup_caller (btinfo, prev, caller, next_flags);
 
                  /* If we skipped any tail calls, this may move CALLER to a
                     different function level.
 
                  /* If we skipped any tail calls, this may move CALLER to a
                     different function level.
@@ -831,7 +861,8 @@ ftrace_connect_bfun (struct btrace_thread_info *btinfo,
 
                     Otherwise we will fix up CALLER's level when we connect it
                     to PREV's caller in the next iteration.  */
 
                     Otherwise we will fix up CALLER's level when we connect it
                     to PREV's caller in the next iteration.  */
-                 ftrace_fixup_level (caller, prev->level - caller->level - 1);
+                 ftrace_fixup_level (btinfo, caller,
+                                     prev->level - caller->level - 1);
                  break;
                }
 
                  break;
                }
 
@@ -895,7 +926,7 @@ ftrace_bridge_gap (struct btrace_thread_info *btinfo,
   best_r = NULL;
 
   /* We search the back traces of LHS and RHS for valid connections and connect
   best_r = NULL;
 
   /* We search the back traces of LHS and RHS for valid connections and connect
-     the two functon segments that give the longest combined back trace.  */
+     the two function segments that give the longest combined back trace.  */
 
   for (cand_l = lhs; cand_l != NULL;
        cand_l = ftrace_get_caller (btinfo, cand_l))
 
   for (cand_l = lhs; cand_l != NULL;
        cand_l = ftrace_get_caller (btinfo, cand_l))
@@ -929,7 +960,7 @@ ftrace_bridge_gap (struct btrace_thread_info *btinfo,
      To catch this, we already fix up the level here where we can start at RHS
      instead of at BEST_R.  We will ignore the level fixup when connecting
      BEST_L to BEST_R as they will already be on the same level.  */
      To catch this, we already fix up the level here where we can start at RHS
      instead of at BEST_R.  We will ignore the level fixup when connecting
      BEST_L to BEST_R as they will already be on the same level.  */
-  ftrace_fixup_level (rhs, best_l->level - best_r->level);
+  ftrace_fixup_level (btinfo, rhs, best_l->level - best_r->level);
 
   ftrace_connect_backtrace (btinfo, best_l, best_r);
 
 
   ftrace_connect_backtrace (btinfo, best_l, best_r);
 
@@ -940,17 +971,14 @@ ftrace_bridge_gap (struct btrace_thread_info *btinfo,
    function segments that are separated by the gap.  */
 
 static void
    function segments that are separated by the gap.  */
 
 static void
-btrace_bridge_gaps (struct thread_info *tp, VEC (bfun_s) **gaps)
+btrace_bridge_gaps (struct thread_info *tp, std::vector<unsigned int> &gaps)
 {
 {
-  VEC (bfun_s) *remaining;
-  struct cleanup *old_chain;
+  struct btrace_thread_info *btinfo = &tp->btrace;
+  std::vector<unsigned int> remaining;
   int min_matches;
 
   DEBUG ("bridge gaps");
 
   int min_matches;
 
   DEBUG ("bridge gaps");
 
-  remaining = NULL;
-  old_chain = make_cleanup (VEC_cleanup (bfun_s), &remaining);
-
   /* We require a minimum amount of matches for bridging a gap.  The number of
      required matches will be lowered with each iteration.
 
   /* We require a minimum amount of matches for bridging a gap.  The number of
      required matches will be lowered with each iteration.
 
@@ -961,65 +989,60 @@ btrace_bridge_gaps (struct thread_info *tp, VEC (bfun_s) **gaps)
     {
       /* Let's try to bridge as many gaps as we can.  In some cases, we need to
         skip a gap and revisit it again after we closed later gaps.  */
     {
       /* Let's try to bridge as many gaps as we can.  In some cases, we need to
         skip a gap and revisit it again after we closed later gaps.  */
-      while (!VEC_empty (bfun_s, *gaps))
+      while (!gaps.empty ())
        {
        {
-         struct btrace_function *gap;
-         unsigned int idx;
-
-         for (idx = 0; VEC_iterate (bfun_s, *gaps, idx, gap); ++idx)
+         for (const unsigned int number : gaps)
            {
            {
-             struct btrace_function *lhs, *rhs;
+             struct btrace_function *gap, *lhs, *rhs;
              int bridged;
 
              int bridged;
 
+             gap = ftrace_find_call_by_number (btinfo, number);
+
              /* We may have a sequence of gaps if we run from one error into
                 the next as we try to re-sync onto the trace stream.  Ignore
                 all but the leftmost gap in such a sequence.
 
                 Also ignore gaps at the beginning of the trace.  */
              /* We may have a sequence of gaps if we run from one error into
                 the next as we try to re-sync onto the trace stream.  Ignore
                 all but the leftmost gap in such a sequence.
 
                 Also ignore gaps at the beginning of the trace.  */
-             lhs = gap->flow.prev;
+             lhs = ftrace_find_call_by_number (btinfo, gap->number - 1);
              if (lhs == NULL || lhs->errcode != 0)
                continue;
 
              /* Skip gaps to the right.  */
              if (lhs == NULL || lhs->errcode != 0)
                continue;
 
              /* Skip gaps to the right.  */
-             for (rhs = gap->flow.next; rhs != NULL; rhs = rhs->flow.next)
-               if (rhs->errcode == 0)
-                 break;
+             rhs = ftrace_find_call_by_number (btinfo, gap->number + 1);
+             while (rhs != NULL && rhs->errcode != 0)
+               rhs = ftrace_find_call_by_number (btinfo, rhs->number + 1);
 
              /* Ignore gaps at the end of the trace.  */
              if (rhs == NULL)
                continue;
 
 
              /* Ignore gaps at the end of the trace.  */
              if (rhs == NULL)
                continue;
 
-             bridged = ftrace_bridge_gap (&tp->btrace, lhs, rhs, min_matches);
+             bridged = ftrace_bridge_gap (btinfo, lhs, rhs, min_matches);
 
              /* Keep track of gaps we were not able to bridge and try again.
                 If we just pushed them to the end of GAPS we would risk an
                 infinite loop in case we simply cannot bridge a gap.  */
              if (bridged == 0)
 
              /* Keep track of gaps we were not able to bridge and try again.
                 If we just pushed them to the end of GAPS we would risk an
                 infinite loop in case we simply cannot bridge a gap.  */
              if (bridged == 0)
-               VEC_safe_push (bfun_s, remaining, gap);
+               remaining.push_back (number);
            }
 
          /* Let's see if we made any progress.  */
            }
 
          /* Let's see if we made any progress.  */
-         if (VEC_length (bfun_s, remaining) == VEC_length (bfun_s, *gaps))
+         if (remaining.size () == gaps.size ())
            break;
 
            break;
 
-         VEC_free (bfun_s, *gaps);
-
-         *gaps = remaining;
-         remaining = NULL;
+         gaps.clear ();
+         gaps.swap (remaining);
        }
 
       /* We get here if either GAPS is empty or if GAPS equals REMAINING.  */
        }
 
       /* We get here if either GAPS is empty or if GAPS equals REMAINING.  */
-      if (VEC_empty (bfun_s, *gaps))
+      if (gaps.empty ())
        break;
 
        break;
 
-      VEC_free (bfun_s, remaining);
+      remaining.clear ();
     }
 
     }
 
-  do_cleanups (old_chain);
-
   /* We may omit this in some cases.  Not sure it is worth the extra
      complication, though.  */
   /* We may omit this in some cases.  Not sure it is worth the extra
      complication, though.  */
-  ftrace_compute_global_level_offset (&tp->btrace);
+  ftrace_compute_global_level_offset (btinfo);
 }
 
 /* Compute the function branch trace from BTS trace.  */
 }
 
 /* Compute the function branch trace from BTS trace.  */
@@ -1027,7 +1050,7 @@ btrace_bridge_gaps (struct thread_info *tp, VEC (bfun_s) **gaps)
 static void
 btrace_compute_ftrace_bts (struct thread_info *tp,
                           const struct btrace_data_bts *btrace,
 static void
 btrace_compute_ftrace_bts (struct thread_info *tp,
                           const struct btrace_data_bts *btrace,
-                          VEC (bfun_s) **gaps)
+                          std::vector<unsigned int> &gaps)
 {
   struct btrace_thread_info *btinfo;
   struct gdbarch *gdbarch;
 {
   struct btrace_thread_info *btinfo;
   struct gdbarch *gdbarch;
@@ -1036,7 +1059,7 @@ btrace_compute_ftrace_bts (struct thread_info *tp,
 
   gdbarch = target_gdbarch ();
   btinfo = &tp->btrace;
 
   gdbarch = target_gdbarch ();
   btinfo = &tp->btrace;
-  blk = VEC_length (btrace_block_s, btrace->blocks);
+  blk = btrace->blocks->size ();
 
   if (btinfo->functions.empty ())
     level = INT_MAX;
 
   if (btinfo->functions.empty ())
     level = INT_MAX;
@@ -1045,13 +1068,12 @@ btrace_compute_ftrace_bts (struct thread_info *tp,
 
   while (blk != 0)
     {
 
   while (blk != 0)
     {
-      btrace_block_s *block;
       CORE_ADDR pc;
 
       blk -= 1;
 
       CORE_ADDR pc;
 
       blk -= 1;
 
-      block = VEC_index (btrace_block_s, btrace->blocks, blk);
-      pc = block->begin;
+      const btrace_block &block = btrace->blocks->at (blk);
+      pc = block.begin;
 
       for (;;)
        {
 
       for (;;)
        {
@@ -1060,12 +1082,10 @@ btrace_compute_ftrace_bts (struct thread_info *tp,
          int size;
 
          /* We should hit the end of the block.  Warn if we went too far.  */
          int size;
 
          /* We should hit the end of the block.  Warn if we went too far.  */
-         if (block->end < pc)
+         if (block.end < pc)
            {
              /* Indicate the gap in the trace.  */
            {
              /* Indicate the gap in the trace.  */
-             bfun = ftrace_new_gap (btinfo, BDE_BTS_OVERFLOW);
-
-             VEC_safe_push (bfun_s, *gaps, bfun);
+             bfun = ftrace_new_gap (btinfo, BDE_BTS_OVERFLOW, gaps);
 
              warning (_("Recorded trace may be corrupted at instruction "
                         "%u (pc = %s)."), bfun->insn_offset - 1,
 
              warning (_("Recorded trace may be corrupted at instruction "
                         "%u (pc = %s)."), bfun->insn_offset - 1,
@@ -1082,24 +1102,23 @@ btrace_compute_ftrace_bts (struct thread_info *tp,
            level = std::min (level, bfun->level);
 
          size = 0;
            level = std::min (level, bfun->level);
 
          size = 0;
-         TRY
+         try
            {
              size = gdb_insn_length (gdbarch, pc);
            }
            {
              size = gdb_insn_length (gdbarch, pc);
            }
-         CATCH (error, RETURN_MASK_ERROR)
+         catch (const gdb_exception_error &error)
            {
            }
            {
            }
-         END_CATCH
 
          insn.pc = pc;
          insn.size = size;
          insn.iclass = ftrace_classify_insn (gdbarch, pc);
          insn.flags = 0;
 
 
          insn.pc = pc;
          insn.size = size;
          insn.iclass = ftrace_classify_insn (gdbarch, pc);
          insn.flags = 0;
 
-         ftrace_update_insns (bfun, &insn);
+         ftrace_update_insns (bfun, insn);
 
          /* We're done once we pushed the instruction at the end.  */
 
          /* We're done once we pushed the instruction at the end.  */
-         if (block->end == pc)
+         if (block.end == pc)
            break;
 
          /* We can't continue if we fail to compute the size.  */
            break;
 
          /* We can't continue if we fail to compute the size.  */
@@ -1107,9 +1126,7 @@ btrace_compute_ftrace_bts (struct thread_info *tp,
            {
              /* Indicate the gap in the trace.  We just added INSN so we're
                 not at the beginning.  */
            {
              /* Indicate the gap in the trace.  We just added INSN so we're
                 not at the beginning.  */
-             bfun = ftrace_new_gap (btinfo, BDE_BTS_INSN_SIZE);
-
-             VEC_safe_push (bfun_s, *gaps, bfun);
+             bfun = ftrace_new_gap (btinfo, BDE_BTS_INSN_SIZE, gaps);
 
              warning (_("Recorded trace may be incomplete at instruction %u "
                         "(pc = %s)."), bfun->insn_offset - 1,
 
              warning (_("Recorded trace may be incomplete at instruction %u "
                         "(pc = %s)."), bfun->insn_offset - 1,
@@ -1181,6 +1198,103 @@ pt_btrace_insn (const struct pt_insn &insn)
          pt_btrace_insn_flags (insn)};
 }
 
          pt_btrace_insn_flags (insn)};
 }
 
+/* Handle instruction decode events (libipt-v2).  */
+
+static int
+handle_pt_insn_events (struct btrace_thread_info *btinfo,
+                      struct pt_insn_decoder *decoder,
+                      std::vector<unsigned int> &gaps, int status)
+{
+#if defined (HAVE_PT_INSN_EVENT)
+  while (status & pts_event_pending)
+    {
+      struct btrace_function *bfun;
+      struct pt_event event;
+      uint64_t offset;
+
+      status = pt_insn_event (decoder, &event, sizeof (event));
+      if (status < 0)
+       break;
+
+      switch (event.type)
+       {
+       default:
+         break;
+
+       case ptev_enabled:
+         if (event.variant.enabled.resumed == 0 && !btinfo->functions.empty ())
+           {
+             bfun = ftrace_new_gap (btinfo, BDE_PT_DISABLED, gaps);
+
+             pt_insn_get_offset (decoder, &offset);
+
+             warning (_("Non-contiguous trace at instruction %u (offset = 0x%"
+                        PRIx64 ")."), bfun->insn_offset - 1, offset);
+           }
+
+         break;
+
+       case ptev_overflow:
+         bfun = ftrace_new_gap (btinfo, BDE_PT_OVERFLOW, gaps);
+
+         pt_insn_get_offset (decoder, &offset);
+
+         warning (_("Overflow at instruction %u (offset = 0x%" PRIx64 ")."),
+                  bfun->insn_offset - 1, offset);
+
+         break;
+       }
+    }
+#endif /* defined (HAVE_PT_INSN_EVENT) */
+
+  return status;
+}
+
+/* Handle events indicated by flags in INSN (libipt-v1).  */
+
+static void
+handle_pt_insn_event_flags (struct btrace_thread_info *btinfo,
+                           struct pt_insn_decoder *decoder,
+                           const struct pt_insn &insn,
+                           std::vector<unsigned int> &gaps)
+{
+#if defined (HAVE_STRUCT_PT_INSN_ENABLED)
+  /* Tracing is disabled and re-enabled each time we enter the kernel.  Most
+     times, we continue from the same instruction we stopped before.  This is
+     indicated via the RESUMED instruction flag.  The ENABLED instruction flag
+     means that we continued from some other instruction.  Indicate this as a
+     trace gap except when tracing just started.  */
+  if (insn.enabled && !btinfo->functions.empty ())
+    {
+      struct btrace_function *bfun;
+      uint64_t offset;
+
+      bfun = ftrace_new_gap (btinfo, BDE_PT_DISABLED, gaps);
+
+      pt_insn_get_offset (decoder, &offset);
+
+      warning (_("Non-contiguous trace at instruction %u (offset = 0x%" PRIx64
+                ", pc = 0x%" PRIx64 ")."), bfun->insn_offset - 1, offset,
+              insn.ip);
+    }
+#endif /* defined (HAVE_STRUCT_PT_INSN_ENABLED) */
+
+#if defined (HAVE_STRUCT_PT_INSN_RESYNCED)
+  /* Indicate trace overflows.  */
+  if (insn.resynced)
+    {
+      struct btrace_function *bfun;
+      uint64_t offset;
+
+      bfun = ftrace_new_gap (btinfo, BDE_PT_OVERFLOW, gaps);
+
+      pt_insn_get_offset (decoder, &offset);
+
+      warning (_("Overflow at instruction %u (offset = 0x%" PRIx64 ", pc = 0x%"
+                PRIx64 ")."), bfun->insn_offset - 1, offset, insn.ip);
+    }
+#endif /* defined (HAVE_STRUCT_PT_INSN_RESYNCED) */
+}
 
 /* Add function branch trace to BTINFO using DECODER.  */
 
 
 /* Add function branch trace to BTINFO using DECODER.  */
 
@@ -1188,89 +1302,58 @@ static void
 ftrace_add_pt (struct btrace_thread_info *btinfo,
               struct pt_insn_decoder *decoder,
               int *plevel,
 ftrace_add_pt (struct btrace_thread_info *btinfo,
               struct pt_insn_decoder *decoder,
               int *plevel,
-              VEC (bfun_s) **gaps)
+              std::vector<unsigned int> &gaps)
 {
   struct btrace_function *bfun;
   uint64_t offset;
 {
   struct btrace_function *bfun;
   uint64_t offset;
-  int errcode;
+  int status;
 
   for (;;)
     {
       struct pt_insn insn;
 
 
   for (;;)
     {
       struct pt_insn insn;
 
-      errcode = pt_insn_sync_forward (decoder);
-      if (errcode < 0)
+      status = pt_insn_sync_forward (decoder);
+      if (status < 0)
        {
        {
-         if (errcode != -pte_eos)
+         if (status != -pte_eos)
            warning (_("Failed to synchronize onto the Intel Processor "
            warning (_("Failed to synchronize onto the Intel Processor "
-                      "Trace stream: %s."), pt_errstr (pt_errcode (errcode)));
+                      "Trace stream: %s."), pt_errstr (pt_errcode (status)));
          break;
        }
 
       for (;;)
        {
          break;
        }
 
       for (;;)
        {
-         errcode = pt_insn_next (decoder, &insn, sizeof(insn));
-         if (errcode < 0)
+         /* Handle events from the previous iteration or synchronization.  */
+         status = handle_pt_insn_events (btinfo, decoder, gaps, status);
+         if (status < 0)
            break;
 
            break;
 
-         /* Look for gaps in the trace - unless we're at the beginning.  */
-         if (!btinfo->functions.empty ())
-           {
-             /* Tracing is disabled and re-enabled each time we enter the
-                kernel.  Most times, we continue from the same instruction we
-                stopped before.  This is indicated via the RESUMED instruction
-                flag.  The ENABLED instruction flag means that we continued
-                from some other instruction.  Indicate this as a trace gap.  */
-             if (insn.enabled)
-               {
-                 bfun = ftrace_new_gap (btinfo, BDE_PT_DISABLED);
-
-                 VEC_safe_push (bfun_s, *gaps, bfun);
-
-                 pt_insn_get_offset (decoder, &offset);
-
-                 warning (_("Non-contiguous trace at instruction %u (offset "
-                            "= 0x%" PRIx64 ", pc = 0x%" PRIx64 ")."),
-                          bfun->insn_offset - 1, offset, insn.ip);
-               }
-           }
-
-         /* Indicate trace overflows.  */
-         if (insn.resynced)
-           {
-             bfun = ftrace_new_gap (btinfo, BDE_PT_OVERFLOW);
-
-             VEC_safe_push (bfun_s, *gaps, bfun);
-
-             pt_insn_get_offset (decoder, &offset);
+         status = pt_insn_next (decoder, &insn, sizeof(insn));
+         if (status < 0)
+           break;
 
 
-             warning (_("Overflow at instruction %u (offset = 0x%" PRIx64
-                        ", pc = 0x%" PRIx64 ")."), bfun->insn_offset - 1,
-                      offset, insn.ip);
-           }
+         /* Handle events indicated by flags in INSN.  */
+         handle_pt_insn_event_flags (btinfo, decoder, insn, gaps);
 
          bfun = ftrace_update_function (btinfo, insn.ip);
 
          /* Maintain the function level offset.  */
          *plevel = std::min (*plevel, bfun->level);
 
 
          bfun = ftrace_update_function (btinfo, insn.ip);
 
          /* Maintain the function level offset.  */
          *plevel = std::min (*plevel, bfun->level);
 
-         btrace_insn btinsn = pt_btrace_insn (insn);
-         ftrace_update_insns (bfun, &btinsn);
+         ftrace_update_insns (bfun, pt_btrace_insn (insn));
        }
 
        }
 
-      if (errcode == -pte_eos)
+      if (status == -pte_eos)
        break;
 
       /* Indicate the gap in the trace.  */
        break;
 
       /* Indicate the gap in the trace.  */
-      bfun = ftrace_new_gap (btinfo, errcode);
-
-      VEC_safe_push (bfun_s, *gaps, bfun);
+      bfun = ftrace_new_gap (btinfo, status, gaps);
 
       pt_insn_get_offset (decoder, &offset);
 
       warning (_("Decode error (%d) at instruction %u (offset = 0x%" PRIx64
 
       pt_insn_get_offset (decoder, &offset);
 
       warning (_("Decode error (%d) at instruction %u (offset = 0x%" PRIx64
-                ", pc = 0x%" PRIx64 "): %s."), errcode, bfun->insn_offset - 1,
-              offset, insn.ip, pt_errstr (pt_errcode (errcode)));
+                ", pc = 0x%" PRIx64 "): %s."), status, bfun->insn_offset - 1,
+              offset, insn.ip, pt_errstr (pt_errcode (status)));
     }
 }
 
     }
 }
 
@@ -1285,17 +1368,16 @@ btrace_pt_readmem_callback (gdb_byte *buffer, size_t size,
   int result, errcode;
 
   result = (int) size;
   int result, errcode;
 
   result = (int) size;
-  TRY
+  try
     {
       errcode = target_read_code ((CORE_ADDR) pc, buffer, size);
       if (errcode != 0)
        result = -pte_nomap;
     }
     {
       errcode = target_read_code ((CORE_ADDR) pc, buffer, size);
       if (errcode != 0)
        result = -pte_nomap;
     }
-  CATCH (error, RETURN_MASK_ERROR)
+  catch (const gdb_exception_error &error)
     {
       result = -pte_nomap;
     }
     {
       result = -pte_nomap;
     }
-  END_CATCH
 
   return result;
 }
 
   return result;
 }
@@ -1340,7 +1422,7 @@ static void btrace_finalize_ftrace_pt (struct pt_insn_decoder *decoder,
 static void
 btrace_compute_ftrace_pt (struct thread_info *tp,
                          const struct btrace_data_pt *btrace,
 static void
 btrace_compute_ftrace_pt (struct thread_info *tp,
                          const struct btrace_data_pt *btrace,
-                         VEC (bfun_s) **gaps)
+                         std::vector<unsigned int> &gaps)
 {
   struct btrace_thread_info *btinfo;
   struct pt_insn_decoder *decoder;
 {
   struct btrace_thread_info *btinfo;
   struct pt_insn_decoder *decoder;
@@ -1360,21 +1442,26 @@ btrace_compute_ftrace_pt (struct thread_info *tp,
   config.begin = btrace->data;
   config.end = btrace->data + btrace->size;
 
   config.begin = btrace->data;
   config.end = btrace->data + btrace->size;
 
-  config.cpu.vendor = pt_translate_cpu_vendor (btrace->config.cpu.vendor);
-  config.cpu.family = btrace->config.cpu.family;
-  config.cpu.model = btrace->config.cpu.model;
-  config.cpu.stepping = btrace->config.cpu.stepping;
+  /* We treat an unknown vendor as 'no errata'.  */
+  if (btrace->config.cpu.vendor != CV_UNKNOWN)
+    {
+      config.cpu.vendor
+       = pt_translate_cpu_vendor (btrace->config.cpu.vendor);
+      config.cpu.family = btrace->config.cpu.family;
+      config.cpu.model = btrace->config.cpu.model;
+      config.cpu.stepping = btrace->config.cpu.stepping;
 
 
-  errcode = pt_cpu_errata (&config.errata, &config.cpu);
-  if (errcode < 0)
-    error (_("Failed to configure the Intel Processor Trace decoder: %s."),
-          pt_errstr (pt_errcode (errcode)));
+      errcode = pt_cpu_errata (&config.errata, &config.cpu);
+      if (errcode < 0)
+       error (_("Failed to configure the Intel Processor Trace "
+                "decoder: %s."), pt_errstr (pt_errcode (errcode)));
+    }
 
   decoder = pt_insn_alloc_decoder (&config);
   if (decoder == NULL)
     error (_("Failed to allocate the Intel Processor Trace decoder."));
 
 
   decoder = pt_insn_alloc_decoder (&config);
   if (decoder == NULL)
     error (_("Failed to allocate the Intel Processor Trace decoder."));
 
-  TRY
+  try
     {
       struct pt_image *image;
 
     {
       struct pt_image *image;
 
@@ -1389,23 +1476,16 @@ btrace_compute_ftrace_pt (struct thread_info *tp,
 
       ftrace_add_pt (btinfo, decoder, &level, gaps);
     }
 
       ftrace_add_pt (btinfo, decoder, &level, gaps);
     }
-  CATCH (error, RETURN_MASK_ALL)
+  catch (const gdb_exception &error)
     {
       /* Indicate a gap in the trace if we quit trace processing.  */
       if (error.reason == RETURN_QUIT && !btinfo->functions.empty ())
     {
       /* Indicate a gap in the trace if we quit trace processing.  */
       if (error.reason == RETURN_QUIT && !btinfo->functions.empty ())
-       {
-         struct btrace_function *bfun;
-
-         bfun = ftrace_new_gap (btinfo, BDE_PT_USER_QUIT);
-
-         VEC_safe_push (bfun_s, *gaps, bfun);
-       }
+       ftrace_new_gap (btinfo, BDE_PT_USER_QUIT, gaps);
 
       btrace_finalize_ftrace_pt (decoder, tp, level);
 
 
       btrace_finalize_ftrace_pt (decoder, tp, level);
 
-      throw_exception (error);
+      throw;
     }
     }
-  END_CATCH
 
   btrace_finalize_ftrace_pt (decoder, tp, level);
 }
 
   btrace_finalize_ftrace_pt (decoder, tp, level);
 }
@@ -1415,7 +1495,7 @@ btrace_compute_ftrace_pt (struct thread_info *tp,
 static void
 btrace_compute_ftrace_pt (struct thread_info *tp,
                          const struct btrace_data_pt *btrace,
 static void
 btrace_compute_ftrace_pt (struct thread_info *tp,
                          const struct btrace_data_pt *btrace,
-                         VEC (bfun_s) **gaps)
+                         std::vector<unsigned int> &gaps)
 {
   internal_error (__FILE__, __LINE__, _("Unexpected branch trace format."));
 }
 {
   internal_error (__FILE__, __LINE__, _("Unexpected branch trace format."));
 }
@@ -1423,11 +1503,15 @@ btrace_compute_ftrace_pt (struct thread_info *tp,
 #endif /* defined (HAVE_LIBIPT)  */
 
 /* Compute the function branch trace from a block branch trace BTRACE for
 #endif /* defined (HAVE_LIBIPT)  */
 
 /* Compute the function branch trace from a block branch trace BTRACE for
-   a thread given by BTINFO.  */
+   a thread given by BTINFO.  If CPU is not NULL, overwrite the cpu in the
+   branch trace configuration.  This is currently only used for the PT
+   format.  */
 
 static void
 
 static void
-btrace_compute_ftrace_1 (struct thread_info *tp, struct btrace_data *btrace,
-                        VEC (bfun_s) **gaps)
+btrace_compute_ftrace_1 (struct thread_info *tp,
+                        struct btrace_data *btrace,
+                        const struct btrace_cpu *cpu,
+                        std::vector<unsigned int> &gaps)
 {
   DEBUG ("compute ftrace");
 
 {
   DEBUG ("compute ftrace");
 
@@ -1441,6 +1525,10 @@ btrace_compute_ftrace_1 (struct thread_info *tp, struct btrace_data *btrace,
       return;
 
     case BTRACE_FORMAT_PT:
       return;
 
     case BTRACE_FORMAT_PT:
+      /* Overwrite the cpu we use for enabling errata workarounds.  */
+      if (cpu != nullptr)
+       btrace->variant.pt.config.cpu = *cpu;
+
       btrace_compute_ftrace_pt (tp, &btrace->variant.pt, gaps);
       return;
     }
       btrace_compute_ftrace_pt (tp, &btrace->variant.pt, gaps);
       return;
     }
@@ -1449,39 +1537,33 @@ btrace_compute_ftrace_1 (struct thread_info *tp, struct btrace_data *btrace,
 }
 
 static void
 }
 
 static void
-btrace_finalize_ftrace (struct thread_info *tp, VEC (bfun_s) **gaps)
+btrace_finalize_ftrace (struct thread_info *tp, std::vector<unsigned int> &gaps)
 {
 {
-  if (!VEC_empty (bfun_s, *gaps))
+  if (!gaps.empty ())
     {
     {
-      tp->btrace.ngaps += VEC_length (bfun_s, *gaps);
+      tp->btrace.ngaps += gaps.size ();
       btrace_bridge_gaps (tp, gaps);
     }
 }
 
 static void
       btrace_bridge_gaps (tp, gaps);
     }
 }
 
 static void
-btrace_compute_ftrace (struct thread_info *tp, struct btrace_data *btrace)
+btrace_compute_ftrace (struct thread_info *tp, struct btrace_data *btrace,
+                      const struct btrace_cpu *cpu)
 {
 {
-  VEC (bfun_s) *gaps;
-  struct cleanup *old_chain;
+  std::vector<unsigned int> gaps;
 
 
-  gaps = NULL;
-  old_chain = make_cleanup (VEC_cleanup (bfun_s), &gaps);
-
-  TRY
+  try
     {
     {
-      btrace_compute_ftrace_1 (tp, btrace, &gaps);
+      btrace_compute_ftrace_1 (tp, btrace, cpu, gaps);
     }
     }
-  CATCH (error, RETURN_MASK_ALL)
+  catch (const gdb_exception &error)
     {
     {
-      btrace_finalize_ftrace (tp, &gaps);
+      btrace_finalize_ftrace (tp, gaps);
 
 
-      throw_exception (error);
+      throw;
     }
     }
-  END_CATCH
-
-  btrace_finalize_ftrace (tp, &gaps);
 
 
-  do_cleanups (old_chain);
+  btrace_finalize_ftrace (tp, gaps);
 }
 
 /* Add an entry for the current PC.  */
 }
 
 /* Add an entry for the current PC.  */
@@ -1490,27 +1572,18 @@ static void
 btrace_add_pc (struct thread_info *tp)
 {
   struct btrace_data btrace;
 btrace_add_pc (struct thread_info *tp)
 {
   struct btrace_data btrace;
-  struct btrace_block *block;
   struct regcache *regcache;
   struct regcache *regcache;
-  struct cleanup *cleanup;
   CORE_ADDR pc;
 
   CORE_ADDR pc;
 
-  regcache = get_thread_regcache (tp->ptid);
+  regcache = get_thread_regcache (tp);
   pc = regcache_read_pc (regcache);
 
   pc = regcache_read_pc (regcache);
 
-  btrace_data_init (&btrace);
   btrace.format = BTRACE_FORMAT_BTS;
   btrace.format = BTRACE_FORMAT_BTS;
-  btrace.variant.bts.blocks = NULL;
+  btrace.variant.bts.blocks = new std::vector<btrace_block>;
 
 
-  cleanup = make_cleanup_btrace_data (&btrace);
+  btrace.variant.bts.blocks->emplace_back (pc, pc);
 
 
-  block = VEC_safe_push (btrace_block_s, btrace.variant.bts.blocks, NULL);
-  block->begin = pc;
-  block->end = pc;
-
-  btrace_compute_ftrace (tp, &btrace);
-
-  do_cleanups (cleanup);
+  btrace_compute_ftrace (tp, &btrace, NULL);
 }
 
 /* See btrace.h.  */
 }
 
 /* See btrace.h.  */
@@ -1523,14 +1596,11 @@ btrace_enable (struct thread_info *tp, const struct btrace_config *conf)
 
 #if !defined (HAVE_LIBIPT)
   if (conf->format == BTRACE_FORMAT_PT)
 
 #if !defined (HAVE_LIBIPT)
   if (conf->format == BTRACE_FORMAT_PT)
-    error (_("GDB does not support Intel Processor Trace."));
+    error (_("Intel Processor Trace support was disabled at compile time."));
 #endif /* !defined (HAVE_LIBIPT) */
 
 #endif /* !defined (HAVE_LIBIPT) */
 
-  if (!target_supports_btrace (conf->format))
-    error (_("Target does not support branch tracing."));
-
   DEBUG ("enable thread %s (%s)", print_thread_id (tp),
   DEBUG ("enable thread %s (%s)", print_thread_id (tp),
-        target_pid_to_str (tp->ptid));
+        target_pid_to_str (tp->ptid).c_str ());
 
   tp->btrace.target = target_enable_btrace (tp->ptid, conf);
 
 
   tp->btrace.target = target_enable_btrace (tp->ptid, conf);
 
@@ -1539,7 +1609,7 @@ btrace_enable (struct thread_info *tp, const struct btrace_config *conf)
     return;
 
   /* We need to undo the enable in case of errors.  */
     return;
 
   /* We need to undo the enable in case of errors.  */
-  TRY
+  try
     {
       /* Add an entry for the current PC so we start tracing from where we
         enabled it.
     {
       /* Add an entry for the current PC so we start tracing from where we
         enabled it.
@@ -1551,16 +1621,15 @@ btrace_enable (struct thread_info *tp, const struct btrace_config *conf)
         This is not relevant for BTRACE_FORMAT_PT since the trace will already
         start at the PC at which tracing was enabled.  */
       if (conf->format != BTRACE_FORMAT_PT
         This is not relevant for BTRACE_FORMAT_PT since the trace will already
         start at the PC at which tracing was enabled.  */
       if (conf->format != BTRACE_FORMAT_PT
-         && can_access_registers_ptid (tp->ptid))
+         && can_access_registers_thread (tp))
        btrace_add_pc (tp);
     }
        btrace_add_pc (tp);
     }
-  CATCH (exception, RETURN_MASK_ALL)
+  catch (const gdb_exception &exception)
     {
       btrace_disable (tp);
 
     {
       btrace_disable (tp);
 
-      throw_exception (exception);
+      throw;
     }
     }
-  END_CATCH
 }
 
 /* See btrace.h.  */
 }
 
 /* See btrace.h.  */
@@ -1580,13 +1649,12 @@ void
 btrace_disable (struct thread_info *tp)
 {
   struct btrace_thread_info *btp = &tp->btrace;
 btrace_disable (struct thread_info *tp)
 {
   struct btrace_thread_info *btp = &tp->btrace;
-  int errcode = 0;
 
   if (btp->target == NULL)
     return;
 
   DEBUG ("disable thread %s (%s)", print_thread_id (tp),
 
   if (btp->target == NULL)
     return;
 
   DEBUG ("disable thread %s (%s)", print_thread_id (tp),
-        target_pid_to_str (tp->ptid));
+        target_pid_to_str (tp->ptid).c_str ());
 
   target_disable_btrace (btp->target);
   btp->target = NULL;
 
   target_disable_btrace (btp->target);
   btp->target = NULL;
@@ -1600,13 +1668,12 @@ void
 btrace_teardown (struct thread_info *tp)
 {
   struct btrace_thread_info *btp = &tp->btrace;
 btrace_teardown (struct thread_info *tp)
 {
   struct btrace_thread_info *btp = &tp->btrace;
-  int errcode = 0;
 
   if (btp->target == NULL)
     return;
 
   DEBUG ("teardown thread %s (%s)", print_thread_id (tp),
 
   if (btp->target == NULL)
     return;
 
   DEBUG ("teardown thread %s (%s)", print_thread_id (tp),
-        target_pid_to_str (tp->ptid));
+        target_pid_to_str (tp->ptid).c_str ());
 
   target_teardown_btrace (btp->target);
   btp->target = NULL;
 
   target_teardown_btrace (btp->target);
   btp->target = NULL;
@@ -1621,29 +1688,28 @@ btrace_stitch_bts (struct btrace_data_bts *btrace, struct thread_info *tp)
 {
   struct btrace_thread_info *btinfo;
   struct btrace_function *last_bfun;
 {
   struct btrace_thread_info *btinfo;
   struct btrace_function *last_bfun;
-  struct btrace_insn *last_insn;
-  btrace_block_s *first_new_block;
+  btrace_block *first_new_block;
 
   btinfo = &tp->btrace;
   gdb_assert (!btinfo->functions.empty ());
 
   btinfo = &tp->btrace;
   gdb_assert (!btinfo->functions.empty ());
-  gdb_assert (!VEC_empty (btrace_block_s, btrace->blocks));
+  gdb_assert (!btrace->blocks->empty ());
 
 
-  last_bfun = btinfo->functions.back ();
+  last_bfun = &btinfo->functions.back ();
 
   /* If the existing trace ends with a gap, we just glue the traces
      together.  We need to drop the last (i.e. chronologically first) block
      of the new trace,  though, since we can't fill in the start address.*/
 
   /* If the existing trace ends with a gap, we just glue the traces
      together.  We need to drop the last (i.e. chronologically first) block
      of the new trace,  though, since we can't fill in the start address.*/
-  if (VEC_empty (btrace_insn_s, last_bfun->insn))
+  if (last_bfun->insn.empty ())
     {
     {
-      VEC_pop (btrace_block_s, btrace->blocks);
+      btrace->blocks->pop_back ();
       return 0;
     }
 
   /* Beware that block trace starts with the most recent block, so the
      chronologically first block in the new trace is the last block in
      the new trace's block vector.  */
       return 0;
     }
 
   /* Beware that block trace starts with the most recent block, so the
      chronologically first block in the new trace is the last block in
      the new trace's block vector.  */
-  first_new_block = VEC_last (btrace_block_s, btrace->blocks);
-  last_insn = VEC_last (btrace_insn_s, last_bfun->insn);
+  first_new_block = &btrace->blocks->back ();
+  const btrace_insn &last_insn = last_bfun->insn.back ();
 
   /* If the current PC at the end of the block is the same as in our current
      trace, there are two explanations:
 
   /* If the current PC at the end of the block is the same as in our current
      trace, there are two explanations:
@@ -1653,19 +1719,18 @@ btrace_stitch_bts (struct btrace_data_bts *btrace, struct thread_info *tp)
      entries.
      In the second case, the delta trace vector should contain exactly one
      entry for the partial block containing the current PC.  Remove it.  */
      entries.
      In the second case, the delta trace vector should contain exactly one
      entry for the partial block containing the current PC.  Remove it.  */
-  if (first_new_block->end == last_insn->pc
-      && VEC_length (btrace_block_s, btrace->blocks) == 1)
+  if (first_new_block->end == last_insn.pc && btrace->blocks->size () == 1)
     {
     {
-      VEC_pop (btrace_block_s, btrace->blocks);
+      btrace->blocks->pop_back ();
       return 0;
     }
 
       return 0;
     }
 
-  DEBUG ("stitching %s to %s", ftrace_print_insn_addr (last_insn),
+  DEBUG ("stitching %s to %s", ftrace_print_insn_addr (&last_insn),
         core_addr_to_string_nz (first_new_block->end));
 
   /* Do a simple sanity check to make sure we don't accidentally end up
      with a bad block.  This should not occur in practice.  */
         core_addr_to_string_nz (first_new_block->end));
 
   /* Do a simple sanity check to make sure we don't accidentally end up
      with a bad block.  This should not occur in practice.  */
-  if (first_new_block->end < last_insn->pc)
+  if (first_new_block->end < last_insn.pc)
     {
       warning (_("Error while trying to read delta trace.  Falling back to "
                 "a full read."));
     {
       warning (_("Error while trying to read delta trace.  Falling back to "
                 "a full read."));
@@ -1674,16 +1739,16 @@ btrace_stitch_bts (struct btrace_data_bts *btrace, struct thread_info *tp)
 
   /* We adjust the last block to start at the end of our current trace.  */
   gdb_assert (first_new_block->begin == 0);
 
   /* We adjust the last block to start at the end of our current trace.  */
   gdb_assert (first_new_block->begin == 0);
-  first_new_block->begin = last_insn->pc;
+  first_new_block->begin = last_insn.pc;
 
   /* We simply pop the last insn so we can insert it again as part of
      the normal branch trace computation.
      Since instruction iterators are based on indices in the instructions
      vector, we don't leave any pointers dangling.  */
   DEBUG ("pruning insn at %s for stitching",
 
   /* We simply pop the last insn so we can insert it again as part of
      the normal branch trace computation.
      Since instruction iterators are based on indices in the instructions
      vector, we don't leave any pointers dangling.  */
   DEBUG ("pruning insn at %s for stitching",
-        ftrace_print_insn_addr (last_insn));
+        ftrace_print_insn_addr (&last_insn));
 
 
-  VEC_pop (btrace_insn_s, last_bfun->insn);
+  last_bfun->insn.pop_back ();
 
   /* The instructions vector may become empty temporarily if this has
      been the only instruction in this function segment.
 
   /* The instructions vector may become empty temporarily if this has
      been the only instruction in this function segment.
@@ -1694,7 +1759,7 @@ btrace_stitch_bts (struct btrace_data_bts *btrace, struct thread_info *tp)
      of just that one instruction.  If we remove it, we might turn the now
      empty btrace function segment into a gap.  But we don't want gaps at
      the beginning.  To avoid this, we remove the entire old trace.  */
      of just that one instruction.  If we remove it, we might turn the now
      empty btrace function segment into a gap.  But we don't want gaps at
      the beginning.  To avoid this, we remove the entire old trace.  */
-  if (last_bfun->number == 1 && VEC_empty (btrace_insn_s, last_bfun->insn))
+  if (last_bfun->number == 1 && last_bfun->insn.empty ())
     btrace_clear (tp);
 
   return 0;
     btrace_clear (tp);
 
   return 0;
@@ -1710,7 +1775,7 @@ static int
 btrace_stitch_trace (struct btrace_data *btrace, struct thread_info *tp)
 {
   /* If we don't have trace, there's nothing to do.  */
 btrace_stitch_trace (struct btrace_data *btrace, struct thread_info *tp)
 {
   /* If we don't have trace, there's nothing to do.  */
-  if (btrace_data_empty (btrace))
+  if (btrace->empty ())
     return 0;
 
   switch (btrace->format)
     return 0;
 
   switch (btrace->format)
@@ -1760,7 +1825,7 @@ btrace_maint_clear (struct btrace_thread_info *btinfo)
 
 #if defined (HAVE_LIBIPT)
     case BTRACE_FORMAT_PT:
 
 #if defined (HAVE_LIBIPT)
     case BTRACE_FORMAT_PT:
-      xfree (btinfo->maint.variant.pt.packets);
+      delete btinfo->maint.variant.pt.packets;
 
       btinfo->maint.variant.pt.packets = NULL;
       btinfo->maint.variant.pt.packet_history.begin = 0;
 
       btinfo->maint.variant.pt.packets = NULL;
       btinfo->maint.variant.pt.packet_history.begin = 0;
@@ -1822,16 +1887,15 @@ btrace_decode_error (enum btrace_format format, int errcode)
 /* See btrace.h.  */
 
 void
 /* See btrace.h.  */
 
 void
-btrace_fetch (struct thread_info *tp)
+btrace_fetch (struct thread_info *tp, const struct btrace_cpu *cpu)
 {
   struct btrace_thread_info *btinfo;
   struct btrace_target_info *tinfo;
   struct btrace_data btrace;
 {
   struct btrace_thread_info *btinfo;
   struct btrace_target_info *tinfo;
   struct btrace_data btrace;
-  struct cleanup *cleanup;
   int errcode;
 
   DEBUG ("fetch thread %s (%s)", print_thread_id (tp),
   int errcode;
 
   DEBUG ("fetch thread %s (%s)", print_thread_id (tp),
-        target_pid_to_str (tp->ptid));
+        target_pid_to_str (tp->ptid).c_str ());
 
   btinfo = &tp->btrace;
   tinfo = btinfo->target;
 
   btinfo = &tp->btrace;
   tinfo = btinfo->target;
@@ -1847,14 +1911,11 @@ btrace_fetch (struct thread_info *tp)
   /* With CLI usage, TP->PTID always equals INFERIOR_PTID here.  Now that we
      can store a gdb.Record object in Python referring to a different thread
      than the current one, temporarily set INFERIOR_PTID.  */
   /* With CLI usage, TP->PTID always equals INFERIOR_PTID here.  Now that we
      can store a gdb.Record object in Python referring to a different thread
      than the current one, temporarily set INFERIOR_PTID.  */
-  cleanup = save_inferior_ptid ();
+  scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
   inferior_ptid = tp->ptid;
 
   /* We should not be called on running or exited threads.  */
   inferior_ptid = tp->ptid;
 
   /* We should not be called on running or exited threads.  */
-  gdb_assert (can_access_registers_ptid (tp->ptid));
-
-  btrace_data_init (&btrace);
-  make_cleanup_btrace_data (&btrace);
+  gdb_assert (can_access_registers_thread (tp));
 
   /* Let's first try to extend the trace we already have.  */
   if (!btinfo->functions.empty ())
 
   /* Let's first try to extend the trace we already have.  */
   if (!btinfo->functions.empty ())
@@ -1871,7 +1932,7 @@ btrace_fetch (struct thread_info *tp)
          errcode = target_read_btrace (&btrace, tinfo, BTRACE_READ_NEW);
 
          /* If we got any new trace, discard what we have.  */
          errcode = target_read_btrace (&btrace, tinfo, BTRACE_READ_NEW);
 
          /* If we got any new trace, discard what we have.  */
-         if (errcode == 0 && !btrace_data_empty (&btrace))
+         if (errcode == 0 && !btrace.empty ())
            btrace_clear (tp);
        }
 
            btrace_clear (tp);
        }
 
@@ -1890,7 +1951,7 @@ btrace_fetch (struct thread_info *tp)
     error (_("Failed to read branch trace."));
 
   /* Compute the trace, provided we have any.  */
     error (_("Failed to read branch trace."));
 
   /* Compute the trace, provided we have any.  */
-  if (!btrace_data_empty (&btrace))
+  if (!btrace.empty ())
     {
       /* Store the raw trace data.  The stored data will be cleared in
         btrace_clear, so we always append the new trace.  */
     {
       /* Store the raw trace data.  The stored data will be cleared in
         btrace_clear, so we always append the new trace.  */
@@ -1898,10 +1959,8 @@ btrace_fetch (struct thread_info *tp)
       btrace_maint_clear (btinfo);
 
       btrace_clear_history (btinfo);
       btrace_maint_clear (btinfo);
 
       btrace_clear_history (btinfo);
-      btrace_compute_ftrace (tp, &btrace);
+      btrace_compute_ftrace (tp, &btrace, cpu);
     }
     }
-
-  do_cleanups (cleanup);
 }
 
 /* See btrace.h.  */
 }
 
 /* See btrace.h.  */
@@ -1912,25 +1971,20 @@ btrace_clear (struct thread_info *tp)
   struct btrace_thread_info *btinfo;
 
   DEBUG ("clear thread %s (%s)", print_thread_id (tp),
   struct btrace_thread_info *btinfo;
 
   DEBUG ("clear thread %s (%s)", print_thread_id (tp),
-        target_pid_to_str (tp->ptid));
+        target_pid_to_str (tp->ptid).c_str ());
 
   /* Make sure btrace frames that may hold a pointer into the branch
      trace data are destroyed.  */
   reinit_frame_cache ();
 
   btinfo = &tp->btrace;
 
   /* Make sure btrace frames that may hold a pointer into the branch
      trace data are destroyed.  */
   reinit_frame_cache ();
 
   btinfo = &tp->btrace;
-  for (auto &bfun : btinfo->functions)
-    {
-      VEC_free (btrace_insn_s, bfun->insn);
-      xfree (bfun);
-    }
 
   btinfo->functions.clear ();
   btinfo->ngaps = 0;
 
   /* Must clear the maint data before - it depends on BTINFO->DATA.  */
   btrace_maint_clear (btinfo);
 
   btinfo->functions.clear ();
   btinfo->ngaps = 0;
 
   /* Must clear the maint data before - it depends on BTINFO->DATA.  */
   btrace_maint_clear (btinfo);
-  btrace_data_clear (&btinfo->data);
+  btinfo->data.clear ();
   btrace_clear_history (btinfo);
 }
 
   btrace_clear_history (btinfo);
 }
 
@@ -1939,11 +1993,9 @@ btrace_clear (struct thread_info *tp)
 void
 btrace_free_objfile (struct objfile *objfile)
 {
 void
 btrace_free_objfile (struct objfile *objfile)
 {
-  struct thread_info *tp;
-
   DEBUG ("free objfile");
 
   DEBUG ("free objfile");
 
-  ALL_NON_EXITED_THREADS (tp)
+  for (thread_info *tp : all_non_exited_threads ())
     btrace_clear (tp);
 }
 
     btrace_clear (tp);
 }
 
@@ -1954,10 +2006,11 @@ btrace_free_objfile (struct objfile *objfile)
 static void
 check_xml_btrace_version (struct gdb_xml_parser *parser,
                          const struct gdb_xml_element *element,
 static void
 check_xml_btrace_version (struct gdb_xml_parser *parser,
                          const struct gdb_xml_element *element,
-                         void *user_data, VEC (gdb_xml_value_s) *attributes)
+                         void *user_data,
+                         std::vector<gdb_xml_value> &attributes)
 {
   const char *version
 {
   const char *version
-    = (const char *) xml_find_attribute (attributes, "version")->value;
+    = (const char *) xml_find_attribute (attributes, "version")->value.get ();
 
   if (strcmp (version, "1.0") != 0)
     gdb_xml_error (parser, _("Unsupported btrace version: \"%s\""), version);
 
   if (strcmp (version, "1.0") != 0)
     gdb_xml_error (parser, _("Unsupported btrace version: \"%s\""), version);
@@ -1968,10 +2021,10 @@ check_xml_btrace_version (struct gdb_xml_parser *parser,
 static void
 parse_xml_btrace_block (struct gdb_xml_parser *parser,
                        const struct gdb_xml_element *element,
 static void
 parse_xml_btrace_block (struct gdb_xml_parser *parser,
                        const struct gdb_xml_element *element,
-                       void *user_data, VEC (gdb_xml_value_s) *attributes)
+                       void *user_data,
+                       std::vector<gdb_xml_value> &attributes)
 {
   struct btrace_data *btrace;
 {
   struct btrace_data *btrace;
-  struct btrace_block *block;
   ULONGEST *begin, *end;
 
   btrace = (struct btrace_data *) user_data;
   ULONGEST *begin, *end;
 
   btrace = (struct btrace_data *) user_data;
@@ -1983,19 +2036,16 @@ parse_xml_btrace_block (struct gdb_xml_parser *parser,
 
     case BTRACE_FORMAT_NONE:
       btrace->format = BTRACE_FORMAT_BTS;
 
     case BTRACE_FORMAT_NONE:
       btrace->format = BTRACE_FORMAT_BTS;
-      btrace->variant.bts.blocks = NULL;
+      btrace->variant.bts.blocks = new std::vector<btrace_block>;
       break;
 
     default:
       gdb_xml_error (parser, _("Btrace format error."));
     }
 
       break;
 
     default:
       gdb_xml_error (parser, _("Btrace format error."));
     }
 
-  begin = (ULONGEST *) xml_find_attribute (attributes, "begin")->value;
-  end = (ULONGEST *) xml_find_attribute (attributes, "end")->value;
-
-  block = VEC_safe_push (btrace_block_s, btrace->variant.bts.blocks, NULL);
-  block->begin = *begin;
-  block->end = *end;
+  begin = (ULONGEST *) xml_find_attribute (attributes, "begin")->value.get ();
+  end = (ULONGEST *) xml_find_attribute (attributes, "end")->value.get ();
+  btrace->variant.bts.blocks->emplace_back (*begin, *end);
 }
 
 /* Parse a "raw" xml record.  */
 }
 
 /* Parse a "raw" xml record.  */
@@ -2004,8 +2054,7 @@ static void
 parse_xml_raw (struct gdb_xml_parser *parser, const char *body_text,
               gdb_byte **pdata, size_t *psize)
 {
 parse_xml_raw (struct gdb_xml_parser *parser, const char *body_text,
               gdb_byte **pdata, size_t *psize)
 {
-  struct cleanup *cleanup;
-  gdb_byte *data, *bin;
+  gdb_byte *bin;
   size_t len, size;
 
   len = strlen (body_text);
   size_t len, size;
 
   len = strlen (body_text);
@@ -2014,10 +2063,10 @@ parse_xml_raw (struct gdb_xml_parser *parser, const char *body_text,
 
   size = len / 2;
 
 
   size = len / 2;
 
-  bin = data = (gdb_byte *) xmalloc (size);
-  cleanup = make_cleanup (xfree, data);
+  gdb::unique_xmalloc_ptr<gdb_byte> data ((gdb_byte *) xmalloc (size));
+  bin = data.get ();
 
 
-  /* We use hex encoding - see common/rsp-low.h.  */
+  /* We use hex encoding - see gdbsupport/rsp-low.h.  */
   while (len > 0)
     {
       char hi, lo;
   while (len > 0)
     {
       char hi, lo;
@@ -2032,9 +2081,7 @@ parse_xml_raw (struct gdb_xml_parser *parser, const char *body_text,
       len -= 2;
     }
 
       len -= 2;
     }
 
-  discard_cleanups (cleanup);
-
-  *pdata = data;
+  *pdata = data.release ();
   *psize = size;
 }
 
   *psize = size;
 }
 
@@ -2044,16 +2091,20 @@ static void
 parse_xml_btrace_pt_config_cpu (struct gdb_xml_parser *parser,
                                const struct gdb_xml_element *element,
                                void *user_data,
 parse_xml_btrace_pt_config_cpu (struct gdb_xml_parser *parser,
                                const struct gdb_xml_element *element,
                                void *user_data,
-                               VEC (gdb_xml_value_s) *attributes)
+                               std::vector<gdb_xml_value> &attributes)
 {
   struct btrace_data *btrace;
   const char *vendor;
   ULONGEST *family, *model, *stepping;
 
 {
   struct btrace_data *btrace;
   const char *vendor;
   ULONGEST *family, *model, *stepping;
 
-  vendor = (const char *) xml_find_attribute (attributes, "vendor")->value;
-  family = (ULONGEST *) xml_find_attribute (attributes, "family")->value;
-  model = (ULONGEST *) xml_find_attribute (attributes, "model")->value;
-  stepping = (ULONGEST *) xml_find_attribute (attributes, "stepping")->value;
+  vendor =
+    (const char *) xml_find_attribute (attributes, "vendor")->value.get ();
+  family
+    = (ULONGEST *) xml_find_attribute (attributes, "family")->value.get ();
+  model
+    = (ULONGEST *) xml_find_attribute (attributes, "model")->value.get ();
+  stepping
+    = (ULONGEST *) xml_find_attribute (attributes, "stepping")->value.get ();
 
   btrace = (struct btrace_data *) user_data;
 
 
   btrace = (struct btrace_data *) user_data;
 
@@ -2084,7 +2135,8 @@ parse_xml_btrace_pt_raw (struct gdb_xml_parser *parser,
 static void
 parse_xml_btrace_pt (struct gdb_xml_parser *parser,
                     const struct gdb_xml_element *element,
 static void
 parse_xml_btrace_pt (struct gdb_xml_parser *parser,
                     const struct gdb_xml_element *element,
-                    void *user_data, VEC (gdb_xml_value_s) *attributes)
+                    void *user_data,
+                    std::vector<gdb_xml_value> &attributes)
 {
   struct btrace_data *btrace;
 
 {
   struct btrace_data *btrace;
 
@@ -2148,25 +2200,24 @@ static const struct gdb_xml_element btrace_elements[] = {
 void
 parse_xml_btrace (struct btrace_data *btrace, const char *buffer)
 {
 void
 parse_xml_btrace (struct btrace_data *btrace, const char *buffer)
 {
-  struct cleanup *cleanup;
-  int errcode;
-
 #if defined (HAVE_LIBEXPAT)
 
 #if defined (HAVE_LIBEXPAT)
 
-  btrace->format = BTRACE_FORMAT_NONE;
+  int errcode;
+  btrace_data result;
+  result.format = BTRACE_FORMAT_NONE;
 
 
-  cleanup = make_cleanup_btrace_data (btrace);
   errcode = gdb_xml_parse_quick (_("btrace"), "btrace.dtd", btrace_elements,
   errcode = gdb_xml_parse_quick (_("btrace"), "btrace.dtd", btrace_elements,
-                                buffer, btrace);
+                                buffer, &result);
   if (errcode != 0)
     error (_("Error parsing branch trace."));
 
   /* Keep parse results.  */
   if (errcode != 0)
     error (_("Error parsing branch trace."));
 
   /* Keep parse results.  */
-  discard_cleanups (cleanup);
+  *btrace = std::move (result);
 
 #else  /* !defined (HAVE_LIBEXPAT) */
 
 
 #else  /* !defined (HAVE_LIBEXPAT) */
 
-  error (_("Cannot process branch trace.  XML parsing is not supported."));
+  error (_("Cannot process branch trace.  XML support was disabled at "
+          "compile time."));
 
 #endif  /* !defined (HAVE_LIBEXPAT) */
 }
 
 #endif  /* !defined (HAVE_LIBEXPAT) */
 }
@@ -2178,7 +2229,8 @@ parse_xml_btrace (struct btrace_data *btrace, const char *buffer)
 static void
 parse_xml_btrace_conf_bts (struct gdb_xml_parser *parser,
                          const struct gdb_xml_element *element,
 static void
 parse_xml_btrace_conf_bts (struct gdb_xml_parser *parser,
                          const struct gdb_xml_element *element,
-                         void *user_data, VEC (gdb_xml_value_s) *attributes)
+                         void *user_data,
+                         std::vector<gdb_xml_value> &attributes)
 {
   struct btrace_config *conf;
   struct gdb_xml_value *size;
 {
   struct btrace_config *conf;
   struct gdb_xml_value *size;
@@ -2189,7 +2241,7 @@ parse_xml_btrace_conf_bts (struct gdb_xml_parser *parser,
 
   size = xml_find_attribute (attributes, "size");
   if (size != NULL)
 
   size = xml_find_attribute (attributes, "size");
   if (size != NULL)
-    conf->bts.size = (unsigned int) *(ULONGEST *) size->value;
+    conf->bts.size = (unsigned int) *(ULONGEST *) size->value.get ();
 }
 
 /* Parse a btrace-conf "pt" xml record.  */
 }
 
 /* Parse a btrace-conf "pt" xml record.  */
@@ -2197,7 +2249,8 @@ parse_xml_btrace_conf_bts (struct gdb_xml_parser *parser,
 static void
 parse_xml_btrace_conf_pt (struct gdb_xml_parser *parser,
                          const struct gdb_xml_element *element,
 static void
 parse_xml_btrace_conf_pt (struct gdb_xml_parser *parser,
                          const struct gdb_xml_element *element,
-                         void *user_data, VEC (gdb_xml_value_s) *attributes)
+                         void *user_data,
+                         std::vector<gdb_xml_value> &attributes)
 {
   struct btrace_config *conf;
   struct gdb_xml_value *size;
 {
   struct btrace_config *conf;
   struct gdb_xml_value *size;
@@ -2208,7 +2261,7 @@ parse_xml_btrace_conf_pt (struct gdb_xml_parser *parser,
 
   size = xml_find_attribute (attributes, "size");
   if (size != NULL)
 
   size = xml_find_attribute (attributes, "size");
   if (size != NULL)
-    conf->pt.size = (unsigned int) *(ULONGEST *) size->value;
+    conf->pt.size = (unsigned int) *(ULONGEST *) size->value.get ();
 }
 
 static const struct gdb_xml_attribute btrace_conf_pt_attributes[] = {
 }
 
 static const struct gdb_xml_attribute btrace_conf_pt_attributes[] = {
@@ -2247,10 +2300,9 @@ static const struct gdb_xml_element btrace_conf_elements[] = {
 void
 parse_xml_btrace_conf (struct btrace_config *conf, const char *xml)
 {
 void
 parse_xml_btrace_conf (struct btrace_config *conf, const char *xml)
 {
-  int errcode;
-
 #if defined (HAVE_LIBEXPAT)
 
 #if defined (HAVE_LIBEXPAT)
 
+  int errcode;
   errcode = gdb_xml_parse_quick (_("btrace-conf"), "btrace-conf.dtd",
                                 btrace_conf_elements, xml, conf);
   if (errcode != 0)
   errcode = gdb_xml_parse_quick (_("btrace-conf"), "btrace-conf.dtd",
                                 btrace_conf_elements, xml, conf);
   if (errcode != 0)
@@ -2258,7 +2310,8 @@ parse_xml_btrace_conf (struct btrace_config *conf, const char *xml)
 
 #else  /* !defined (HAVE_LIBEXPAT) */
 
 
 #else  /* !defined (HAVE_LIBEXPAT) */
 
-  error (_("XML parsing is not supported."));
+  error (_("Cannot process the branch trace configuration.  XML support "
+          "was disabled at compile time."));
 
 #endif  /* !defined (HAVE_LIBEXPAT) */
 }
 
 #endif  /* !defined (HAVE_LIBEXPAT) */
 }
@@ -2272,18 +2325,18 @@ btrace_insn_get (const struct btrace_insn_iterator *it)
   unsigned int index, end;
 
   index = it->insn_index;
   unsigned int index, end;
 
   index = it->insn_index;
-  bfun = it->btinfo->functions[it->call_index];
+  bfun = &it->btinfo->functions[it->call_index];
 
   /* Check if the iterator points to a gap in the trace.  */
   if (bfun->errcode != 0)
     return NULL;
 
   /* The index is within the bounds of this function's instruction vector.  */
 
   /* Check if the iterator points to a gap in the trace.  */
   if (bfun->errcode != 0)
     return NULL;
 
   /* The index is within the bounds of this function's instruction vector.  */
-  end = VEC_length (btrace_insn_s, bfun->insn);
+  end = bfun->insn.size ();
   gdb_assert (0 < end);
   gdb_assert (index < end);
 
   gdb_assert (0 < end);
   gdb_assert (index < end);
 
-  return VEC_index (btrace_insn_s, bfun->insn, index);
+  return &bfun->insn[index];
 }
 
 /* See btrace.h.  */
 }
 
 /* See btrace.h.  */
@@ -2291,10 +2344,7 @@ btrace_insn_get (const struct btrace_insn_iterator *it)
 int
 btrace_insn_get_error (const struct btrace_insn_iterator *it)
 {
 int
 btrace_insn_get_error (const struct btrace_insn_iterator *it)
 {
-  const struct btrace_function *bfun;
-
-  bfun = it->btinfo->functions[it->call_index];
-  return bfun->errcode;
+  return it->btinfo->functions[it->call_index].errcode;
 }
 
 /* See btrace.h.  */
 }
 
 /* See btrace.h.  */
@@ -2302,10 +2352,7 @@ btrace_insn_get_error (const struct btrace_insn_iterator *it)
 unsigned int
 btrace_insn_number (const struct btrace_insn_iterator *it)
 {
 unsigned int
 btrace_insn_number (const struct btrace_insn_iterator *it)
 {
-  const struct btrace_function *bfun;
-
-  bfun = it->btinfo->functions[it->call_index];
-  return bfun->insn_offset + it->insn_index;
+  return it->btinfo->functions[it->call_index].insn_offset + it->insn_index;
 }
 
 /* See btrace.h.  */
 }
 
 /* See btrace.h.  */
@@ -2334,8 +2381,8 @@ btrace_insn_end (struct btrace_insn_iterator *it,
   if (btinfo->functions.empty ())
     error (_("No trace."));
 
   if (btinfo->functions.empty ())
     error (_("No trace."));
 
-  bfun = btinfo->functions.back ();
-  length = VEC_length (btrace_insn_s, bfun->insn);
+  bfun = &btinfo->functions.back ();
+  length = bfun->insn.size ();
 
   /* The last function may either be a gap or it contains the current
      instruction, which is one past the end of the execution trace; ignore
 
   /* The last function may either be a gap or it contains the current
      instruction, which is one past the end of the execution trace; ignore
@@ -2356,7 +2403,7 @@ btrace_insn_next (struct btrace_insn_iterator *it, unsigned int stride)
   const struct btrace_function *bfun;
   unsigned int index, steps;
 
   const struct btrace_function *bfun;
   unsigned int index, steps;
 
-  bfun = it->btinfo->functions[it->call_index];
+  bfun = &it->btinfo->functions[it->call_index];
   steps = 0;
   index = it->insn_index;
 
   steps = 0;
   index = it->insn_index;
 
@@ -2364,7 +2411,7 @@ btrace_insn_next (struct btrace_insn_iterator *it, unsigned int stride)
     {
       unsigned int end, space, adv;
 
     {
       unsigned int end, space, adv;
 
-      end = VEC_length (btrace_insn_s, bfun->insn);
+      end = bfun->insn.size ();
 
       /* An empty function segment represents a gap in the trace.  We count
         it as one instruction.  */
 
       /* An empty function segment represents a gap in the trace.  We count
         it as one instruction.  */
@@ -2372,7 +2419,7 @@ btrace_insn_next (struct btrace_insn_iterator *it, unsigned int stride)
        {
          const struct btrace_function *next;
 
        {
          const struct btrace_function *next;
 
-         next = bfun->flow.next;
+         next = ftrace_find_call_by_number (it->btinfo, bfun->number + 1);
          if (next == NULL)
            break;
 
          if (next == NULL)
            break;
 
@@ -2402,7 +2449,7 @@ btrace_insn_next (struct btrace_insn_iterator *it, unsigned int stride)
        {
          const struct btrace_function *next;
 
        {
          const struct btrace_function *next;
 
-         next = bfun->flow.next;
+         next = ftrace_find_call_by_number (it->btinfo, bfun->number + 1);
          if (next == NULL)
            {
              /* We stepped past the last function.
          if (next == NULL)
            {
              /* We stepped past the last function.
@@ -2438,7 +2485,7 @@ btrace_insn_prev (struct btrace_insn_iterator *it, unsigned int stride)
   const struct btrace_function *bfun;
   unsigned int index, steps;
 
   const struct btrace_function *bfun;
   unsigned int index, steps;
 
-  bfun = it->btinfo->functions[it->call_index];
+  bfun = &it->btinfo->functions[it->call_index];
   steps = 0;
   index = it->insn_index;
 
   steps = 0;
   index = it->insn_index;
 
@@ -2451,13 +2498,13 @@ btrace_insn_prev (struct btrace_insn_iterator *it, unsigned int stride)
        {
          const struct btrace_function *prev;
 
        {
          const struct btrace_function *prev;
 
-         prev = bfun->flow.prev;
+         prev = ftrace_find_call_by_number (it->btinfo, bfun->number - 1);
          if (prev == NULL)
            break;
 
          /* We point to one after the last instruction in the new function.  */
          bfun = prev;
          if (prev == NULL)
            break;
 
          /* We point to one after the last instruction in the new function.  */
          bfun = prev;
-         index = VEC_length (btrace_insn_s, bfun->insn);
+         index = bfun->insn.size ();
 
          /* An empty function segment represents a gap in the trace.  We count
             it as one instruction.  */
 
          /* An empty function segment represents a gap in the trace.  We count
             it as one instruction.  */
@@ -2516,12 +2563,12 @@ btrace_find_insn_by_number (struct btrace_insn_iterator *it,
       return 0;
 
   lower = 0;
       return 0;
 
   lower = 0;
-  bfun = btinfo->functions[lower];
+  bfun = &btinfo->functions[lower];
   if (number < bfun->insn_offset)
     return 0;
 
   upper = btinfo->functions.size () - 1;
   if (number < bfun->insn_offset)
     return 0;
 
   upper = btinfo->functions.size () - 1;
-  bfun = btinfo->functions[upper];
+  bfun = &btinfo->functions[upper];
   if (number >= bfun->insn_offset + ftrace_call_num_insn (bfun))
     return 0;
 
   if (number >= bfun->insn_offset + ftrace_call_num_insn (bfun))
     return 0;
 
@@ -2530,7 +2577,7 @@ btrace_find_insn_by_number (struct btrace_insn_iterator *it,
     {
       const unsigned int average = lower + (upper - lower) / 2;
 
     {
       const unsigned int average = lower + (upper - lower) / 2;
 
-      bfun = btinfo->functions[average];
+      bfun = &btinfo->functions[average];
 
       if (number < bfun->insn_offset)
        {
 
       if (number < bfun->insn_offset)
        {
@@ -2564,7 +2611,7 @@ btrace_ends_with_single_insn (const struct btrace_thread_info *btinfo)
   if (btinfo->functions.empty ())
     return false;
 
   if (btinfo->functions.empty ())
     return false;
 
-  bfun = btinfo->functions.back ();
+  bfun = &btinfo->functions.back ();
   if (bfun->errcode != 0)
     return false;
 
   if (bfun->errcode != 0)
     return false;
 
@@ -2579,7 +2626,7 @@ btrace_call_get (const struct btrace_call_iterator *it)
   if (it->index >= it->btinfo->functions.size ())
     return NULL;
 
   if (it->index >= it->btinfo->functions.size ())
     return NULL;
 
-  return it->btinfo->functions[it->index];
+  return &it->btinfo->functions[it->index];
 }
 
 /* See btrace.h.  */
 }
 
 /* See btrace.h.  */
@@ -2777,22 +2824,6 @@ btrace_is_empty (struct thread_info *tp)
   return btrace_insn_cmp (&begin, &end) == 0;
 }
 
   return btrace_insn_cmp (&begin, &end) == 0;
 }
 
-/* Forward the cleanup request.  */
-
-static void
-do_btrace_data_cleanup (void *arg)
-{
-  btrace_data_fini ((struct btrace_data *) arg);
-}
-
-/* See btrace.h.  */
-
-struct cleanup *
-make_cleanup_btrace_data (struct btrace_data *data)
-{
-  return make_cleanup (do_btrace_data_cleanup, data);
-}
-
 #if defined (HAVE_LIBIPT)
 
 /* Print a single packet.  */
 #if defined (HAVE_LIBIPT)
 
 /* Print a single packet.  */
@@ -2931,6 +2962,9 @@ btrace_maint_decode_pt (struct btrace_maint_info *maint,
 {
   int errcode;
 
 {
   int errcode;
 
+  if (maint->variant.pt.packets == NULL)
+    maint->variant.pt.packets = new std::vector<btrace_pt_packet>;
+
   for (;;)
     {
       struct btrace_pt_packet packet;
   for (;;)
     {
       struct btrace_pt_packet packet;
@@ -2951,8 +2985,7 @@ btrace_maint_decode_pt (struct btrace_maint_info *maint,
          if (maint_btrace_pt_skip_pad == 0 || packet.packet.type != ppt_pad)
            {
              packet.errcode = pt_errcode (errcode);
          if (maint_btrace_pt_skip_pad == 0 || packet.packet.type != ppt_pad)
            {
              packet.errcode = pt_errcode (errcode);
-             VEC_safe_push (btrace_pt_packet_s, maint->variant.pt.packets,
-                            &packet);
+             maint->variant.pt.packets->push_back (packet);
            }
        }
 
            }
        }
 
@@ -2960,8 +2993,7 @@ btrace_maint_decode_pt (struct btrace_maint_info *maint,
        break;
 
       packet.errcode = pt_errcode (errcode);
        break;
 
       packet.errcode = pt_errcode (errcode);
-      VEC_safe_push (btrace_pt_packet_s, maint->variant.pt.packets,
-                    &packet);
+      maint->variant.pt.packets->push_back (packet);
 
       warning (_("Error at trace offset 0x%" PRIx64 ": %s."),
               packet.offset, pt_errstr (packet.errcode));
 
       warning (_("Error at trace offset 0x%" PRIx64 ": %s."),
               packet.offset, pt_errstr (packet.errcode));
@@ -2977,8 +3009,8 @@ btrace_maint_decode_pt (struct btrace_maint_info *maint,
 static void
 btrace_maint_update_pt_packets (struct btrace_thread_info *btinfo)
 {
 static void
 btrace_maint_update_pt_packets (struct btrace_thread_info *btinfo)
 {
-  volatile struct gdb_exception except;
   struct pt_packet_decoder *decoder;
   struct pt_packet_decoder *decoder;
+  const struct btrace_cpu *cpu;
   struct btrace_data_pt *pt;
   struct pt_config config;
   int errcode;
   struct btrace_data_pt *pt;
   struct pt_config config;
   int errcode;
@@ -2995,32 +3027,39 @@ btrace_maint_update_pt_packets (struct btrace_thread_info *btinfo)
   config.begin = pt->data;
   config.end = pt->data + pt->size;
 
   config.begin = pt->data;
   config.end = pt->data + pt->size;
 
-  config.cpu.vendor = pt_translate_cpu_vendor (pt->config.cpu.vendor);
-  config.cpu.family = pt->config.cpu.family;
-  config.cpu.model = pt->config.cpu.model;
-  config.cpu.stepping = pt->config.cpu.stepping;
+  cpu = record_btrace_get_cpu ();
+  if (cpu == nullptr)
+    cpu = &pt->config.cpu;
+
+  /* We treat an unknown vendor as 'no errata'.  */
+  if (cpu->vendor != CV_UNKNOWN)
+    {
+      config.cpu.vendor = pt_translate_cpu_vendor (cpu->vendor);
+      config.cpu.family = cpu->family;
+      config.cpu.model = cpu->model;
+      config.cpu.stepping = cpu->stepping;
 
 
-  errcode = pt_cpu_errata (&config.errata, &config.cpu);
-  if (errcode < 0)
-    error (_("Failed to configure the Intel Processor Trace decoder: %s."),
-          pt_errstr (pt_errcode (errcode)));
+      errcode = pt_cpu_errata (&config.errata, &config.cpu);
+      if (errcode < 0)
+       error (_("Failed to configure the Intel Processor Trace "
+                "decoder: %s."), pt_errstr (pt_errcode (errcode)));
+    }
 
   decoder = pt_pkt_alloc_decoder (&config);
   if (decoder == NULL)
     error (_("Failed to allocate the Intel Processor Trace decoder."));
 
 
   decoder = pt_pkt_alloc_decoder (&config);
   if (decoder == NULL)
     error (_("Failed to allocate the Intel Processor Trace decoder."));
 
-  TRY
+  try
     {
       btrace_maint_decode_pt (&btinfo->maint, decoder);
     }
     {
       btrace_maint_decode_pt (&btinfo->maint, decoder);
     }
-  CATCH (except, RETURN_MASK_ALL)
+  catch (const gdb_exception &except)
     {
       pt_pkt_free_decoder (decoder);
 
       if (except.reason < 0)
     {
       pt_pkt_free_decoder (decoder);
 
       if (except.reason < 0)
-       throw_exception (except);
+       throw;
     }
     }
-  END_CATCH
 
   pt_pkt_free_decoder (decoder);
 }
 
   pt_pkt_free_decoder (decoder);
 }
@@ -3048,18 +3087,21 @@ btrace_maint_update_packets (struct btrace_thread_info *btinfo,
     case BTRACE_FORMAT_BTS:
       /* Nothing to do - we operate directly on BTINFO->DATA.  */
       *begin = 0;
     case BTRACE_FORMAT_BTS:
       /* Nothing to do - we operate directly on BTINFO->DATA.  */
       *begin = 0;
-      *end = VEC_length (btrace_block_s, btinfo->data.variant.bts.blocks);
+      *end = btinfo->data.variant.bts.blocks->size ();
       *from = btinfo->maint.variant.bts.packet_history.begin;
       *to = btinfo->maint.variant.bts.packet_history.end;
       break;
 
 #if defined (HAVE_LIBIPT)
     case BTRACE_FORMAT_PT:
       *from = btinfo->maint.variant.bts.packet_history.begin;
       *to = btinfo->maint.variant.bts.packet_history.end;
       break;
 
 #if defined (HAVE_LIBIPT)
     case BTRACE_FORMAT_PT:
-      if (VEC_empty (btrace_pt_packet_s, btinfo->maint.variant.pt.packets))
+      if (btinfo->maint.variant.pt.packets == nullptr)
+       btinfo->maint.variant.pt.packets = new std::vector<btrace_pt_packet>;
+
+      if (btinfo->maint.variant.pt.packets->empty ())
        btrace_maint_update_pt_packets (btinfo);
 
       *begin = 0;
        btrace_maint_update_pt_packets (btinfo);
 
       *begin = 0;
-      *end = VEC_length (btrace_pt_packet_s, btinfo->maint.variant.pt.packets);
+      *end = btinfo->maint.variant.pt.packets->size ();
       *from = btinfo->maint.variant.pt.packet_history.begin;
       *to = btinfo->maint.variant.pt.packet_history.end;
       break;
       *from = btinfo->maint.variant.pt.packet_history.begin;
       *to = btinfo->maint.variant.pt.packet_history.end;
       break;
@@ -3081,19 +3123,17 @@ btrace_maint_print_packets (struct btrace_thread_info *btinfo,
 
     case BTRACE_FORMAT_BTS:
       {
 
     case BTRACE_FORMAT_BTS:
       {
-       VEC (btrace_block_s) *blocks;
+       const std::vector<btrace_block> &blocks
+         = *btinfo->data.variant.bts.blocks;
        unsigned int blk;
 
        unsigned int blk;
 
-       blocks = btinfo->data.variant.bts.blocks;
        for (blk = begin; blk < end; ++blk)
          {
        for (blk = begin; blk < end; ++blk)
          {
-           const btrace_block_s *block;
-
-           block = VEC_index (btrace_block_s, blocks, blk);
+           const btrace_block &block = blocks.at (blk);
 
            printf_unfiltered ("%u\tbegin: %s, end: %s\n", blk,
 
            printf_unfiltered ("%u\tbegin: %s, end: %s\n", blk,
-                              core_addr_to_string_nz (block->begin),
-                              core_addr_to_string_nz (block->end));
+                              core_addr_to_string_nz (block.begin),
+                              core_addr_to_string_nz (block.end));
          }
 
        btinfo->maint.variant.bts.packet_history.begin = begin;
          }
 
        btinfo->maint.variant.bts.packet_history.begin = begin;
@@ -3104,23 +3144,21 @@ btrace_maint_print_packets (struct btrace_thread_info *btinfo,
 #if defined (HAVE_LIBIPT)
     case BTRACE_FORMAT_PT:
       {
 #if defined (HAVE_LIBIPT)
     case BTRACE_FORMAT_PT:
       {
-       VEC (btrace_pt_packet_s) *packets;
+       const std::vector<btrace_pt_packet> &packets
+         = *btinfo->maint.variant.pt.packets;
        unsigned int pkt;
 
        unsigned int pkt;
 
-       packets = btinfo->maint.variant.pt.packets;
        for (pkt = begin; pkt < end; ++pkt)
          {
        for (pkt = begin; pkt < end; ++pkt)
          {
-           const struct btrace_pt_packet *packet;
-
-           packet = VEC_index (btrace_pt_packet_s, packets, pkt);
+           const struct btrace_pt_packet &packet = packets.at (pkt);
 
            printf_unfiltered ("%u\t", pkt);
 
            printf_unfiltered ("%u\t", pkt);
-           printf_unfiltered ("0x%" PRIx64 "\t", packet->offset);
+           printf_unfiltered ("0x%" PRIx64 "\t", packet.offset);
 
 
-           if (packet->errcode == pte_ok)
-             pt_print_packet (&packet->packet);
+           if (packet.errcode == pte_ok)
+             pt_print_packet (&packet.packet);
            else
            else
-             printf_unfiltered ("[error: %s]", pt_errstr (packet->errcode));
+             printf_unfiltered ("[error: %s]", pt_errstr (packet.errcode));
 
            printf_unfiltered ("\n");
          }
 
            printf_unfiltered ("\n");
          }
@@ -3136,9 +3174,10 @@ btrace_maint_print_packets (struct btrace_thread_info *btinfo,
 /* Read a number from an argument string.  */
 
 static unsigned int
 /* Read a number from an argument string.  */
 
 static unsigned int
-get_uint (char **arg)
+get_uint (const char **arg)
 {
 {
-  char *begin, *end, *pos;
+  const char *begin, *pos;
+  char *end;
   unsigned long number;
 
   begin = *arg;
   unsigned long number;
 
   begin = *arg;
@@ -3159,23 +3198,23 @@ get_uint (char **arg)
 /* Read a context size from an argument string.  */
 
 static int
 /* Read a context size from an argument string.  */
 
 static int
-get_context_size (char **arg)
+get_context_size (const char **arg)
 {
 {
-  char *pos;
-  int number;
-
-  pos = skip_spaces (*arg);
+  const char *pos = skip_spaces (*arg);
 
   if (!isdigit (*pos))
     error (_("Expected positive number, got: %s."), pos);
 
 
   if (!isdigit (*pos))
     error (_("Expected positive number, got: %s."), pos);
 
-  return strtol (pos, arg, 10);
+  char *end;
+  long result = strtol (pos, &end, 10);
+  *arg = end;
+  return result;
 }
 
 /* Complain about junk at the end of an argument string.  */
 
 static void
 }
 
 /* Complain about junk at the end of an argument string.  */
 
 static void
-no_chunk (char *arg)
+no_chunk (const char *arg)
 {
   if (*arg != 0)
     error (_("Junk after argument: %s."), arg);
 {
   if (*arg != 0)
     error (_("Junk after argument: %s."), arg);
@@ -3184,13 +3223,12 @@ no_chunk (char *arg)
 /* The "maintenance btrace packet-history" command.  */
 
 static void
 /* The "maintenance btrace packet-history" command.  */
 
 static void
-maint_btrace_packet_history_cmd (char *arg, int from_tty)
+maint_btrace_packet_history_cmd (const char *arg, int from_tty)
 {
   struct btrace_thread_info *btinfo;
 {
   struct btrace_thread_info *btinfo;
-  struct thread_info *tp;
   unsigned int size, begin, end, from, to;
 
   unsigned int size, begin, end, from, to;
 
-  tp = find_thread_ptid (inferior_ptid);
+  thread_info *tp = find_thread_ptid (inferior_ptid);
   if (tp == NULL)
     error (_("No thread."));
 
   if (tp == NULL)
     error (_("No thread."));
 
@@ -3289,47 +3327,41 @@ maint_btrace_packet_history_cmd (char *arg, int from_tty)
 /* The "maintenance btrace clear-packet-history" command.  */
 
 static void
 /* The "maintenance btrace clear-packet-history" command.  */
 
 static void
-maint_btrace_clear_packet_history_cmd (char *args, int from_tty)
+maint_btrace_clear_packet_history_cmd (const char *args, int from_tty)
 {
 {
-  struct btrace_thread_info *btinfo;
-  struct thread_info *tp;
-
   if (args != NULL && *args != 0)
     error (_("Invalid argument."));
 
   if (args != NULL && *args != 0)
     error (_("Invalid argument."));
 
-  tp = find_thread_ptid (inferior_ptid);
-  if (tp == NULL)
+  if (inferior_ptid == null_ptid)
     error (_("No thread."));
 
     error (_("No thread."));
 
-  btinfo = &tp->btrace;
+  thread_info *tp = inferior_thread ();
+  btrace_thread_info *btinfo = &tp->btrace;
 
   /* Must clear the maint data before - it depends on BTINFO->DATA.  */
   btrace_maint_clear (btinfo);
 
   /* Must clear the maint data before - it depends on BTINFO->DATA.  */
   btrace_maint_clear (btinfo);
-  btrace_data_clear (&btinfo->data);
+  btinfo->data.clear ();
 }
 
 /* The "maintenance btrace clear" command.  */
 
 static void
 }
 
 /* The "maintenance btrace clear" command.  */
 
 static void
-maint_btrace_clear_cmd (char *args, int from_tty)
+maint_btrace_clear_cmd (const char *args, int from_tty)
 {
 {
-  struct btrace_thread_info *btinfo;
-  struct thread_info *tp;
-
   if (args != NULL && *args != 0)
     error (_("Invalid argument."));
 
   if (args != NULL && *args != 0)
     error (_("Invalid argument."));
 
-  tp = find_thread_ptid (inferior_ptid);
-  if (tp == NULL)
+  if (inferior_ptid == null_ptid)
     error (_("No thread."));
 
     error (_("No thread."));
 
+  thread_info *tp = inferior_thread ();
   btrace_clear (tp);
 }
 
 /* The "maintenance btrace" command.  */
 
 static void
   btrace_clear (tp);
 }
 
 /* The "maintenance btrace" command.  */
 
 static void
-maint_btrace_cmd (char *args, int from_tty)
+maint_btrace_cmd (const char *args, int from_tty)
 {
   help_list (maint_btrace_cmdlist, "maintenance btrace ", all_commands,
             gdb_stdout);
 {
   help_list (maint_btrace_cmdlist, "maintenance btrace ", all_commands,
             gdb_stdout);
@@ -3338,7 +3370,7 @@ maint_btrace_cmd (char *args, int from_tty)
 /* The "maintenance set btrace" command.  */
 
 static void
 /* The "maintenance set btrace" command.  */
 
 static void
-maint_btrace_set_cmd (char *args, int from_tty)
+maint_btrace_set_cmd (const char *args, int from_tty)
 {
   help_list (maint_btrace_set_cmdlist, "maintenance set btrace ", all_commands,
             gdb_stdout);
 {
   help_list (maint_btrace_set_cmdlist, "maintenance set btrace ", all_commands,
             gdb_stdout);
@@ -3347,7 +3379,7 @@ maint_btrace_set_cmd (char *args, int from_tty)
 /* The "maintenance show btrace" command.  */
 
 static void
 /* The "maintenance show btrace" command.  */
 
 static void
-maint_btrace_show_cmd (char *args, int from_tty)
+maint_btrace_show_cmd (const char *args, int from_tty)
 {
   help_list (maint_btrace_show_cmdlist, "maintenance show btrace ",
             all_commands, gdb_stdout);
 {
   help_list (maint_btrace_show_cmdlist, "maintenance show btrace ",
             all_commands, gdb_stdout);
@@ -3356,7 +3388,7 @@ maint_btrace_show_cmd (char *args, int from_tty)
 /* The "maintenance set btrace pt" command.  */
 
 static void
 /* The "maintenance set btrace pt" command.  */
 
 static void
-maint_btrace_pt_set_cmd (char *args, int from_tty)
+maint_btrace_pt_set_cmd (const char *args, int from_tty)
 {
   help_list (maint_btrace_pt_set_cmdlist, "maintenance set btrace pt ",
             all_commands, gdb_stdout);
 {
   help_list (maint_btrace_pt_set_cmdlist, "maintenance set btrace pt ",
             all_commands, gdb_stdout);
@@ -3365,7 +3397,7 @@ maint_btrace_pt_set_cmd (char *args, int from_tty)
 /* The "maintenance show btrace pt" command.  */
 
 static void
 /* The "maintenance show btrace pt" command.  */
 
 static void
-maint_btrace_pt_show_cmd (char *args, int from_tty)
+maint_btrace_pt_show_cmd (const char *args, int from_tty)
 {
   help_list (maint_btrace_pt_show_cmdlist, "maintenance show btrace pt ",
             all_commands, gdb_stdout);
 {
   help_list (maint_btrace_pt_show_cmdlist, "maintenance show btrace pt ",
             all_commands, gdb_stdout);
@@ -3374,19 +3406,19 @@ maint_btrace_pt_show_cmd (char *args, int from_tty)
 /* The "maintenance info btrace" command.  */
 
 static void
 /* The "maintenance info btrace" command.  */
 
 static void
-maint_info_btrace_cmd (char *args, int from_tty)
+maint_info_btrace_cmd (const char *args, int from_tty)
 {
   struct btrace_thread_info *btinfo;
 {
   struct btrace_thread_info *btinfo;
-  struct thread_info *tp;
   const struct btrace_config *conf;
 
   if (args != NULL && *args != 0)
     error (_("Invalid argument."));
 
   const struct btrace_config *conf;
 
   if (args != NULL && *args != 0)
     error (_("Invalid argument."));
 
-  tp = find_thread_ptid (inferior_ptid);
-  if (tp == NULL)
+  if (inferior_ptid == null_ptid)
     error (_("No thread."));
 
     error (_("No thread."));
 
+  thread_info *tp = inferior_thread ();
+
   btinfo = &tp->btrace;
 
   conf = btrace_conf (btinfo);
   btinfo = &tp->btrace;
 
   conf = btrace_conf (btinfo);
@@ -3402,9 +3434,8 @@ maint_info_btrace_cmd (char *args, int from_tty)
       break;
 
     case BTRACE_FORMAT_BTS:
       break;
 
     case BTRACE_FORMAT_BTS:
-      printf_unfiltered (_("Number of packets: %u.\n"),
-                        VEC_length (btrace_block_s,
-                                    btinfo->data.variant.bts.blocks));
+      printf_unfiltered (_("Number of packets: %zu.\n"),
+                        btinfo->data.variant.bts.blocks->size ());
       break;
 
 #if defined (HAVE_LIBIPT)
       break;
 
 #if defined (HAVE_LIBIPT)
@@ -3418,9 +3449,9 @@ maint_info_btrace_cmd (char *args, int from_tty)
                           version.ext != NULL ? version.ext : "");
 
        btrace_maint_update_pt_packets (btinfo);
                           version.ext != NULL ? version.ext : "");
 
        btrace_maint_update_pt_packets (btinfo);
-       printf_unfiltered (_("Number of packets: %u.\n"),
-                          VEC_length (btrace_pt_packet_s,
-                                      btinfo->maint.variant.pt.packets));
+       printf_unfiltered (_("Number of packets: %zu.\n"),
+                          ((btinfo->maint.variant.pt.packets == nullptr)
+                           ? 0 : btinfo->maint.variant.pt.packets->size ()));
       }
       break;
 #endif /* defined (HAVE_LIBIPT)  */
       }
       break;
 #endif /* defined (HAVE_LIBIPT)  */
@@ -3440,7 +3471,6 @@ show_maint_btrace_pt_skip_pad  (struct ui_file *file, int from_tty,
 
 /* Initialize btrace maintenance commands.  */
 
 
 /* Initialize btrace maintenance commands.  */
 
-void _initialize_btrace (void);
 void
 _initialize_btrace (void)
 {
 void
 _initialize_btrace (void)
 {
@@ -3489,21 +3519,19 @@ One argument specifies the starting packet of a ten-line print.\n\
 Two arguments with comma between specify starting and ending packets to \
 print.\n\
 Preceded with '+'/'-' the second argument specifies the distance from the \
 Two arguments with comma between specify starting and ending packets to \
 print.\n\
 Preceded with '+'/'-' the second argument specifies the distance from the \
-first.\n"),
+first."),
           &maint_btrace_cmdlist);
 
   add_cmd ("clear-packet-history", class_maintenance,
           maint_btrace_clear_packet_history_cmd,
           _("Clears the branch tracing packet history.\n\
           &maint_btrace_cmdlist);
 
   add_cmd ("clear-packet-history", class_maintenance,
           maint_btrace_clear_packet_history_cmd,
           _("Clears the branch tracing packet history.\n\
-Discards the raw branch tracing data but not the execution history data.\n\
-"),
+Discards the raw branch tracing data but not the execution history data."),
           &maint_btrace_cmdlist);
 
   add_cmd ("clear", class_maintenance, maint_btrace_clear_cmd,
           _("Clears the branch tracing data.\n\
 Discards the raw branch tracing data and the execution history data.\n\
           &maint_btrace_cmdlist);
 
   add_cmd ("clear", class_maintenance, maint_btrace_clear_cmd,
           _("Clears the branch tracing data.\n\
 Discards the raw branch tracing data and the execution history data.\n\
-The next 'record' command will fetch the branch tracing data anew.\n\
-"),
+The next 'record' command will fetch the branch tracing data anew."),
           &maint_btrace_cmdlist);
 
 }
           &maint_btrace_cmdlist);
 
 }
This page took 0.054691 seconds and 4 git commands to generate.