Handle non-ASCII identifiers in Ada
[binutils-gdb.git] / gdb / tracepoint.c
index b6e7fe5e2ea93ac01d7fb707a7aff09b050ffa0d..67b3118288006a9a949766c04ccc84a2e765a673 100644 (file)
@@ -1,6 +1,6 @@
 /* Tracing functionality for remote targets in custom GDB protocol
 
-   Copyright (C) 1997-2017 Free Software Foundation, Inc.
+   Copyright (C) 1997-2022 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -36,7 +36,7 @@
 #include "completer.h"
 #include "block.h"
 #include "dictionary.h"
-#include "observer.h"
+#include "observable.h"
 #include "user-regs.h"
 #include "valprint.h"
 #include "gdbcore.h"
 #include "memrange.h"
 #include "cli/cli-utils.h"
 #include "probe.h"
-#include "ctf.h"
-#include "filestuff.h"
-#include "rsp-low.h"
+#include "gdbsupport/filestuff.h"
+#include "gdbsupport/rsp-low.h"
 #include "tracefile.h"
 #include "location.h"
 #include <algorithm>
-
-/* readline include files */
-#include "readline/readline.h"
-#include "readline/history.h"
-
-/* readline defines this.  */
-#undef savestring
+#include "cli/cli-style.h"
+#include "expop.h"
+#include "gdbsupport/buildargv.h"
 
 #include <unistd.h>
 
@@ -114,10 +109,7 @@ void (*deprecated_trace_start_stop_hook) (int start, int from_tty);
    any of these for any reason - API is by name or number only - so it
    works to have a vector of objects.  */
 
-typedef struct trace_state_variable tsv_s;
-DEF_VEC_O(tsv_s);
-
-static VEC(tsv_s) *tvariables;
+static std::vector<trace_state_variable> tvariables;
 
 /* The next integer to assign to a variable.  */
 
@@ -133,20 +125,20 @@ static int tracepoint_number;
    yet attempted to fetch it, or if the target does not support
    fetching this object, or if we're not inspecting a traceframe
    presently.  */
-static struct traceframe_info *traceframe_info;
+static traceframe_info_up current_traceframe_info;
 
 /* Tracing command lists.  */
 static struct cmd_list_element *tfindlist;
 
 /* List of expressions to collect by default at each tracepoint hit.  */
-char *default_collect;
+std::string default_collect;
 
-static int disconnected_tracing;
+static bool disconnected_tracing;
 
 /* This variable controls whether we ask the target for a linear or
    circular trace buffer.  */
 
-static int circular_trace_buffer;
+static bool circular_trace_buffer;
 
 /* This variable is the requested trace buffer size, or -1 to indicate
    that we don't care and leave it up to the target to set a size.  */
@@ -155,23 +147,22 @@ static int trace_buffer_size = -1;
 
 /* Textual notes applying to the current and/or future trace runs.  */
 
-char *trace_user = NULL;
+static std::string trace_user;
 
 /* Textual notes applying to the current and/or future trace runs.  */
 
-char *trace_notes = NULL;
+static std::string trace_notes;
 
 /* Textual notes applying to the stopping of a trace.  */
 
-char *trace_stop_notes = NULL;
+static std::string trace_stop_notes;
 
 /* support routines */
 
 struct collection_list;
 static char *mem2hex (gdb_byte *, char *, int);
 
-static struct command_line *
-  all_tracepoint_actions_and_cleanup (struct breakpoint *t);
+static counted_command_line all_tracepoint_actions (struct breakpoint *);
 
 static struct trace_status trace_status;
 
@@ -191,28 +182,13 @@ current_trace_status (void)
   return &trace_status;
 }
 
-/* Destroy INFO.  */
-
-static void
-free_traceframe_info (struct traceframe_info *info)
-{
-  if (info != NULL)
-    {
-      VEC_free (mem_range_s, info->memory);
-      VEC_free (int, info->tvars);
-
-      xfree (info);
-    }
-}
-
 /* Free and clear the traceframe info cache of the current
    traceframe.  */
 
 static void
 clear_traceframe_info (void)
 {
-  free_traceframe_info (traceframe_info);
-  traceframe_info = NULL;
+  current_traceframe_info = NULL;
 }
 
 /* Set traceframe number to NUM.  */
@@ -262,11 +238,11 @@ set_traceframe_context (struct frame_info *trace_frame)
   /* Save func name as "$trace_func", a debugger variable visible to
      users.  */
   if (traceframe_fun == NULL
-      || SYMBOL_LINKAGE_NAME (traceframe_fun) == NULL)
+      || traceframe_fun->linkage_name () == NULL)
     clear_internalvar (lookup_internalvar ("trace_func"));
   else
     set_internalvar_string (lookup_internalvar ("trace_func"),
-                           SYMBOL_LINKAGE_NAME (traceframe_fun));
+                           traceframe_fun->linkage_name ());
 
   /* Save file name as "$trace_file", a debugger variable visible to
      users.  */
@@ -282,12 +258,8 @@ set_traceframe_context (struct frame_info *trace_frame)
 struct trace_state_variable *
 create_trace_state_variable (const char *name)
 {
-  struct trace_state_variable tsv;
-
-  memset (&tsv, 0, sizeof (tsv));
-  tsv.name = xstrdup (name);
-  tsv.number = next_tsv_number++;
-  return VEC_safe_push (tsv_s, tvariables, &tsv);
+  tvariables.emplace_back (name, next_tsv_number++);
+  return &tvariables.back ();
 }
 
 /* Look for a trace state variable of the given name.  */
@@ -295,12 +267,9 @@ create_trace_state_variable (const char *name)
 struct trace_state_variable *
 find_trace_state_variable (const char *name)
 {
-  struct trace_state_variable *tsv;
-  int ix;
-
-  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
-    if (strcmp (name, tsv->name) == 0)
-      return tsv;
+  for (trace_state_variable &tsv : tvariables)
+    if (tsv.name == name)
+      return &tsv;
 
   return NULL;
 }
@@ -311,12 +280,9 @@ find_trace_state_variable (const char *name)
 struct trace_state_variable *
 find_trace_state_variable_by_number (int number)
 {
-  struct trace_state_variable *tsv;
-  int ix;
-
-  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
-    if (tsv->number == number)
-      return tsv;
+  for (trace_state_variable &tsv : tvariables)
+    if (tsv.number == number)
+      return &tsv;
 
   return NULL;
 }
@@ -324,17 +290,11 @@ find_trace_state_variable_by_number (int number)
 static void
 delete_trace_state_variable (const char *name)
 {
-  struct trace_state_variable *tsv;
-  int ix;
-
-  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
-    if (strcmp (name, tsv->name) == 0)
+  for (auto it = tvariables.begin (); it != tvariables.end (); it++)
+    if (it->name == name)
       {
-       observer_notify_tsv_deleted (tsv);
-
-       xfree ((void *)tsv->name);
-       VEC_unordered_remove (tsv_s, tvariables, ix);
-
+       gdb::observers::tsv_deleted.notify (&*it);
+       tvariables.erase (it);
        return;
       }
 
@@ -369,12 +329,11 @@ validate_trace_state_variable_name (const char *name)
    evaluate into an initial value.  */
 
 static void
-trace_variable_command (char *args, int from_tty)
+trace_variable_command (const char *args, int from_tty)
 {
-  struct cleanup *old_chain;
   LONGEST initval = 0;
   struct trace_state_variable *tsv;
-  char *name, *p;
+  const char *name_start, *p;
 
   if (!args || !*args)
     error_no_arg (_("Syntax is $NAME [ = EXPR ]"));
@@ -385,48 +344,44 @@ trace_variable_command (char *args, int from_tty)
   if (*p++ != '$')
     error (_("Name of trace variable should start with '$'"));
 
-  name = p;
+  name_start = p;
   while (isalnum (*p) || *p == '_')
     p++;
-  name = savestring (name, p - name);
-  old_chain = make_cleanup (xfree, name);
+  std::string name (name_start, p - name_start);
 
   p = skip_spaces (p);
   if (*p != '=' && *p != '\0')
     error (_("Syntax must be $NAME [ = EXPR ]"));
 
-  validate_trace_state_variable_name (name);
+  validate_trace_state_variable_name (name.c_str ());
 
   if (*p == '=')
     initval = value_as_long (parse_and_eval (++p));
 
   /* If the variable already exists, just change its initial value.  */
-  tsv = find_trace_state_variable (name);
+  tsv = find_trace_state_variable (name.c_str ());
   if (tsv)
     {
       if (tsv->initial_value != initval)
        {
          tsv->initial_value = initval;
-         observer_notify_tsv_modified (tsv);
+         gdb::observers::tsv_modified.notify (tsv);
        }
       printf_filtered (_("Trace state variable $%s "
                         "now has initial value %s.\n"),
-                      tsv->name, plongest (tsv->initial_value));
-      do_cleanups (old_chain);
+                      tsv->name.c_str (), plongest (tsv->initial_value));
       return;
     }
 
   /* Create a new variable.  */
-  tsv = create_trace_state_variable (name);
+  tsv = create_trace_state_variable (name.c_str ());
   tsv->initial_value = initval;
 
-  observer_notify_tsv_created (tsv);
+  gdb::observers::tsv_created.notify (tsv);
 
   printf_filtered (_("Trace state variable $%s "
                     "created, with initial value %s.\n"),
-                  tsv->name, plongest (tsv->initial_value));
-
-  do_cleanups (old_chain);
+                  tsv->name.c_str (), plongest (tsv->initial_value));
 }
 
 static void
@@ -435,9 +390,9 @@ delete_trace_variable_command (const char *args, int from_tty)
   if (args == NULL)
     {
       if (query (_("Delete all trace state variables? ")))
-       VEC_free (tsv_s, tvariables);
+       tvariables.clear ();
       dont_repeat ();
-      observer_notify_tsv_deleted (NULL);
+      gdb::observers::tsv_deleted.notify (NULL);
       return;
     }
 
@@ -457,62 +412,65 @@ delete_trace_variable_command (const char *args, int from_tty)
 void
 tvariables_info_1 (void)
 {
-  struct trace_state_variable *tsv;
-  int ix;
-  int count = 0;
   struct ui_out *uiout = current_uiout;
 
-  if (VEC_length (tsv_s, tvariables) == 0 && !uiout->is_mi_like_p ())
-    {
-      printf_filtered (_("No trace state variables.\n"));
-      return;
-    }
-
   /* Try to acquire values from the target.  */
-  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix, ++count)
-    tsv->value_known = target_get_trace_state_variable_value (tsv->number,
-                                                             &(tsv->value));
+  for (trace_state_variable &tsv : tvariables)
+    tsv.value_known
+      = target_get_trace_state_variable_value (tsv.number, &tsv.value);
 
-  ui_out_emit_table table_emitter (uiout, 3, count, "trace-variables");
-  uiout->table_header (15, ui_left, "name", "Name");
-  uiout->table_header (11, ui_left, "initial", "Initial");
-  uiout->table_header (11, ui_left, "current", "Current");
+  {
+    ui_out_emit_table table_emitter (uiout, 3, tvariables.size (),
+                                    "trace-variables");
+    uiout->table_header (15, ui_left, "name", "Name");
+    uiout->table_header (11, ui_left, "initial", "Initial");
+    uiout->table_header (11, ui_left, "current", "Current");
 
-  uiout->table_body ();
+    uiout->table_body ();
 
-  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
-    {
-      const char *c;
-
-      ui_out_emit_tuple tuple_emitter (uiout, "variable");
-
-      std::string name = std::string ("$") + tsv->name;
-      uiout->field_string ("name", name.c_str ());
-      uiout->field_string ("initial", plongest (tsv->initial_value));
-
-      if (tsv->value_known)
-        c = plongest (tsv->value);
-      else if (uiout->is_mi_like_p ())
-        /* For MI, we prefer not to use magic string constants, but rather
-           omit the field completely.  The difference between unknown and
-           undefined does not seem important enough to represent.  */
-        c = NULL;
-      else if (current_trace_status ()->running || traceframe_number >= 0)
-       /* The value is/was defined, but we don't have it.  */
-        c = "<unknown>";
-      else
-       /* It is not meaningful to ask about the value.  */
-        c = "<undefined>";
-      if (c)
-        uiout->field_string ("current", c);
-      uiout->text ("\n");
-    }
+    for (const trace_state_variable &tsv : tvariables)
+      {
+       const char *c;
+
+       ui_out_emit_tuple tuple_emitter (uiout, "variable");
+
+       uiout->field_string ("name", std::string ("$") + tsv.name);
+       uiout->field_string ("initial", plongest (tsv.initial_value));
+
+       ui_file_style style;
+       if (tsv.value_known)
+         c = plongest (tsv.value);
+       else if (uiout->is_mi_like_p ())
+         /* For MI, we prefer not to use magic string constants, but rather
+            omit the field completely.  The difference between unknown and
+            undefined does not seem important enough to represent.  */
+         c = NULL;
+       else if (current_trace_status ()->running || traceframe_number >= 0)
+         {
+           /* The value is/was defined, but we don't have it.  */
+           c = "<unknown>";
+           style = metadata_style.style ();
+         }
+       else
+         {
+           /* It is not meaningful to ask about the value.  */
+           c = "<undefined>";
+           style = metadata_style.style ();
+         }
+       if (c)
+         uiout->field_string ("current", c, style);
+       uiout->text ("\n");
+      }
+  }
+
+  if (tvariables.empty ())
+    uiout->text (_("No trace state variables.\n"));
 }
 
 /* List all the trace state variables.  */
 
 static void
-info_tvariables_command (char *args, int from_tty)
+info_tvariables_command (const char *args, int from_tty)
 {
   tvariables_info_1 ();
 }
@@ -522,14 +480,11 @@ info_tvariables_command (char *args, int from_tty)
 void
 save_trace_state_variables (struct ui_file *fp)
 {
-  struct trace_state_variable *tsv;
-  int ix;
-
-  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
+  for (const trace_state_variable &tsv : tvariables)
     {
-      fprintf_unfiltered (fp, "tvariable $%s", tsv->name);
-      if (tsv->initial_value)
-       fprintf_unfiltered (fp, " = %s", plongest (tsv->initial_value));
+      fprintf_unfiltered (fp, "tvariable $%s", tsv.name.c_str ());
+      if (tsv.initial_value)
+       fprintf_unfiltered (fp, " = %s", plongest (tsv.initial_value));
       fprintf_unfiltered (fp, "\n");
     }
 }
@@ -546,25 +501,25 @@ save_trace_state_variables (struct ui_file *fp)
    which is always an error.  */
 
 static void
-end_actions_pseudocommand (char *args, int from_tty)
+end_actions_pseudocommand (const char *args, int from_tty)
 {
   error (_("This command cannot be used at the top level."));
 }
 
 static void
-while_stepping_pseudocommand (char *args, int from_tty)
+while_stepping_pseudocommand (const char *args, int from_tty)
 {
   error (_("This command can only be used in a tracepoint actions list."));
 }
 
 static void
-collect_pseudocommand (char *args, int from_tty)
+collect_pseudocommand (const char *args, int from_tty)
 {
   error (_("This command can only be used in a tracepoint actions list."));
 }
 
 static void
-teval_pseudocommand (char *args, int from_tty)
+teval_pseudocommand (const char *args, int from_tty)
 {
   error (_("This command can only be used in a tracepoint actions list."));
 }
@@ -613,7 +568,7 @@ decode_agent_options (const char *exp, int *trace_string)
 
 /* Enter a list of actions for a tracepoint.  */
 static void
-actions_command (char *args, int from_tty)
+actions_command (const char *args, int from_tty)
 {
   struct tracepoint *t;
 
@@ -624,8 +579,12 @@ actions_command (char *args, int from_tty)
        string_printf ("Enter actions for tracepoint %d, one per line.",
                       t->number);
 
-      command_line_up l = read_command_lines (&tmpbuf[0], from_tty, 1,
-                                             check_tracepoint_command, t);
+      counted_command_line l = read_command_lines (tmpbuf.c_str (),
+                                                  from_tty, 1,
+                                                  [=] (const char *line)
+                                                    {
+                                                      validate_actionline (line, t);
+                                                    });
       breakpoint_set_commands (t, std::move (l));
     }
   /* else just return */
@@ -658,15 +617,26 @@ report_agent_reqs_errors (struct agent_expr *aexpr)
     error (_("Expression is too complicated."));
 }
 
+/* Call ax_reqs on AEXPR and raise an error if something is wrong.  */
+
+static void
+finalize_tracepoint_aexpr (struct agent_expr *aexpr)
+{
+  ax_reqs (aexpr);
+
+  if (aexpr->len > MAX_AGENT_EXPR_LEN)
+    error (_("Expression is too complicated."));
+
+  report_agent_reqs_errors (aexpr);
+}
+
 /* worker function */
 void
 validate_actionline (const char *line, struct breakpoint *b)
 {
   struct cmd_list_element *c;
-  struct cleanup *old_chain = NULL;
   const char *tmp_p;
   const char *p;
-  struct bp_location *loc;
   struct tracepoint *t = (struct tracepoint *) b;
 
   /* If EOF is typed, *line is NULL.  */
@@ -682,11 +652,11 @@ validate_actionline (const char *line, struct breakpoint *b)
   if (*p == '#')               /* comment line */
     return;
 
-  c = lookup_cmd (&p, cmdlist, "", -1, 1);
+  c = lookup_cmd (&p, cmdlist, "", NULL, -1, 1);
   if (c == 0)
     error (_("`%s' is not a tracepoint action, or is ambiguous."), p);
 
-  if (cmd_cfunc_eq (c, collect_pseudocommand))
+  if (cmd_simple_func_eq (c, collect_pseudocommand))
     {
       int trace_string = 0;
 
@@ -712,27 +682,32 @@ validate_actionline (const char *line, struct breakpoint *b)
              /* else fall thru, treat p as an expression and parse it!  */
            }
          tmp_p = p;
-         for (loc = t->loc; loc; loc = loc->next)
+         for (bp_location *loc : t->locations ())
            {
              p = tmp_p;
              expression_up exp = parse_exp_1 (&p, loc->address,
                                               block_for_pc (loc->address), 1);
 
-             if (exp->elts[0].opcode == OP_VAR_VALUE)
+             if (exp->first_opcode () == OP_VAR_VALUE)
                {
-                 if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
+                 symbol *sym;
+                 expr::var_value_operation *vvop
+                   = (dynamic_cast<expr::var_value_operation *>
+                      (exp->op.get ()));
+                 sym = vvop->get_symbol ();
+
+                 if (sym->aclass () == LOC_CONST)
                    {
                      error (_("constant `%s' (value %s) "
                               "will not be collected."),
-                            SYMBOL_PRINT_NAME (exp->elts[2].symbol),
-                            plongest (SYMBOL_VALUE (exp->elts[2].symbol)));
+                            sym->print_name (),
+                            plongest (SYMBOL_VALUE (sym)));
                    }
-                 else if (SYMBOL_CLASS (exp->elts[2].symbol)
-                          == LOC_OPTIMIZED_OUT)
+                 else if (sym->aclass () == LOC_OPTIMIZED_OUT)
                    {
                      error (_("`%s' is optimized away "
                               "and cannot be collected."),
-                            SYMBOL_PRINT_NAME (exp->elts[2].symbol));
+                            sym->print_name ());
                    }
                }
 
@@ -743,18 +718,13 @@ validate_actionline (const char *line, struct breakpoint *b)
                                                        exp.get (),
                                                        trace_string);
 
-             if (aexpr->len > MAX_AGENT_EXPR_LEN)
-               error (_("Expression is too complicated."));
-
-             ax_reqs (aexpr.get ());
-
-             report_agent_reqs_errors (aexpr.get ());
+             finalize_tracepoint_aexpr (aexpr.get ());
            }
        }
       while (p && *p++ == ',');
     }
 
-  else if (cmd_cfunc_eq (c, teval_pseudocommand))
+  else if (cmd_simple_func_eq (c, teval_pseudocommand))
     {
       do
        {                       /* Repeat over a comma-separated list.  */
@@ -762,7 +732,7 @@ validate_actionline (const char *line, struct breakpoint *b)
          p = skip_spaces (p);
 
          tmp_p = p;
-         for (loc = t->loc; loc; loc = loc->next)
+         for (bp_location *loc : t->locations ())
            {
              p = tmp_p;
 
@@ -775,17 +745,13 @@ validate_actionline (const char *line, struct breakpoint *b)
                 long.  */
              agent_expr_up aexpr = gen_eval_for_expr (loc->address, exp.get ());
 
-             if (aexpr->len > MAX_AGENT_EXPR_LEN)
-               error (_("Expression is too complicated."));
-
-             ax_reqs (aexpr.get ());
-             report_agent_reqs_errors (aexpr.get ());
+             finalize_tracepoint_aexpr (aexpr.get ());
            }
        }
       while (p && *p++ == ',');
     }
 
-  else if (cmd_cfunc_eq (c, while_stepping_pseudocommand))
+  else if (cmd_simple_func_eq (c, while_stepping_pseudocommand))
     {
       char *endp;
 
@@ -796,7 +762,7 @@ validate_actionline (const char *line, struct breakpoint *b)
       p = endp;
     }
 
-  else if (cmd_cfunc_eq (c, end_actions_pseudocommand))
+  else if (cmd_simple_func_eq (c, end_actions_pseudocommand))
     ;
 
   else
@@ -855,17 +821,77 @@ memrange_sortmerge (std::vector<memrange> &memranges)
     }
 }
 
-/* Add a register to a collection list.  */
+/* Add remote register number REGNO to the collection list mask.  */
 
 void
-collection_list::add_register (unsigned int regno)
+collection_list::add_remote_register (unsigned int regno)
 {
   if (info_verbose)
     printf_filtered ("collect register %d\n", regno);
-  if (regno >= (8 * sizeof (m_regs_mask)))
-    error (_("Internal: register number %d too large for tracepoint"),
-          regno);
-  m_regs_mask[regno / 8] |= 1 << (regno % 8);
+
+  m_regs_mask.at (regno / 8) |= 1 << (regno % 8);
+}
+
+/* Add all the registers from the mask in AEXPR to the mask in the
+   collection list.  Registers in the AEXPR mask are already remote
+   register numbers.  */
+
+void
+collection_list::add_ax_registers (struct agent_expr *aexpr)
+{
+  if (aexpr->reg_mask_len > 0)
+    {
+      for (int ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
+       {
+         QUIT; /* Allow user to bail out with ^C.  */
+         if (aexpr->reg_mask[ndx1] != 0)
+           {
+             /* Assume chars have 8 bits.  */
+             for (int ndx2 = 0; ndx2 < 8; ndx2++)
+               if (aexpr->reg_mask[ndx1] & (1 << ndx2))
+                 /* It's used -- record it.  */
+                 add_remote_register (ndx1 * 8 + ndx2);
+           }
+       }
+    }
+}
+
+/* If REGNO is raw, add its corresponding remote register number to
+   the mask.  If REGNO is a pseudo-register, figure out the necessary
+   registers using a temporary agent expression, and add it to the
+   list if it needs more than just a mask.  */
+
+void
+collection_list::add_local_register (struct gdbarch *gdbarch,
+                                    unsigned int regno,
+                                    CORE_ADDR scope)
+{
+  if (regno < gdbarch_num_regs (gdbarch))
+    {
+      int remote_regno = gdbarch_remote_register_number (gdbarch, regno);
+
+      if (remote_regno < 0)
+       error (_("Can't collect register %d"), regno);
+
+      add_remote_register (remote_regno);
+    }
+  else
+    {
+      agent_expr_up aexpr (new agent_expr (gdbarch, scope));
+
+      ax_reg_mask (aexpr.get (), regno);
+
+      finalize_tracepoint_aexpr (aexpr.get ());
+
+      add_ax_registers (aexpr.get ());
+
+      /* Usually ax_reg_mask for a pseudo-regiser only sets the
+        corresponding raw registers in the ax mask, but if this isn't
+        the case add the expression that is generated to the
+        collection list.  */
+      if (aexpr->len > 0)
+       add_aexpr (std::move (aexpr));
+    }
 }
 
 /* Add a memrange to a collection list.  */
@@ -873,7 +899,7 @@ collection_list::add_register (unsigned int regno)
 void
 collection_list::add_memrange (struct gdbarch *gdbarch,
                               int type, bfd_signed_vma base,
-                              unsigned long len)
+                              unsigned long len, CORE_ADDR scope)
 {
   if (info_verbose)
     printf_filtered ("(%d,%s,%ld)\n", type, paddress (gdbarch, base), len);
@@ -884,7 +910,7 @@ collection_list::add_memrange (struct gdbarch *gdbarch,
   m_memranges.emplace_back (type, base, base + len);
 
   if (type != memrange_absolute)    /* Better collect the base register!  */
-    add_register (type);
+    add_local_register (gdbarch, type, scope);
 }
 
 /* Add a symbol to a collection list.  */
@@ -901,49 +927,46 @@ collection_list::collect_symbol (struct symbol *sym,
   bfd_signed_vma offset;
   int treat_as_expr = 0;
 
-  len = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)));
-  switch (SYMBOL_CLASS (sym))
+  len = TYPE_LENGTH (check_typedef (sym->type ()));
+  switch (sym->aclass ())
     {
     default:
       printf_filtered ("%s: don't know symbol class %d\n",
-                      SYMBOL_PRINT_NAME (sym),
-                      SYMBOL_CLASS (sym));
+                      sym->print_name (), sym->aclass ());
       break;
     case LOC_CONST:
       printf_filtered ("constant %s (value %s) will not be collected.\n",
-                      SYMBOL_PRINT_NAME (sym), plongest (SYMBOL_VALUE (sym)));
+                      sym->print_name (), plongest (SYMBOL_VALUE (sym)));
       break;
     case LOC_STATIC:
       offset = SYMBOL_VALUE_ADDRESS (sym);
       if (info_verbose)
        {
          printf_filtered ("LOC_STATIC %s: collect %ld bytes at %s.\n",
-                          SYMBOL_PRINT_NAME (sym), len,
+                          sym->print_name (), len,
                           paddress (gdbarch, offset));
        }
       /* A struct may be a C++ class with static fields, go to general
         expression handling.  */
-      if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT)
+      if (sym->type ()->code () == TYPE_CODE_STRUCT)
        treat_as_expr = 1;
       else
-       add_memrange (gdbarch, memrange_absolute, offset, len);
+       add_memrange (gdbarch, memrange_absolute, offset, len, scope);
       break;
     case LOC_REGISTER:
       reg = SYMBOL_REGISTER_OPS (sym)->register_number (sym, gdbarch);
       if (info_verbose)
-       printf_filtered ("LOC_REG[parm] %s: ", 
-                        SYMBOL_PRINT_NAME (sym));
-      add_register (reg);
+       printf_filtered ("LOC_REG[parm] %s: ", sym->print_name ());
+      add_local_register (gdbarch, reg, scope);
       /* Check for doubles stored in two registers.  */
       /* FIXME: how about larger types stored in 3 or more regs?  */
-      if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT &&
+      if (sym->type ()->code () == TYPE_CODE_FLT &&
          len > register_size (gdbarch, reg))
-       add_register (reg + 1);
+       add_local_register (gdbarch, reg + 1, scope);
       break;
     case LOC_REF_ARG:
       printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n");
-      printf_filtered ("       (will not collect %s)\n",
-                      SYMBOL_PRINT_NAME (sym));
+      printf_filtered ("       (will not collect %s)\n", sym->print_name ());
       break;
     case LOC_ARG:
       reg = frame_regno;
@@ -951,11 +974,10 @@ collection_list::collect_symbol (struct symbol *sym,
       if (info_verbose)
        {
          printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset %s"
-                          " from frame ptr reg %d\n",
-                          SYMBOL_PRINT_NAME (sym), len,
+                          " from frame ptr reg %d\n", sym->print_name (), len,
                           paddress (gdbarch, offset), reg);
        }
-      add_memrange (gdbarch, reg, offset, len);
+      add_memrange (gdbarch, reg, offset, len, scope);
       break;
     case LOC_REGPARM_ADDR:
       reg = SYMBOL_VALUE (sym);
@@ -963,11 +985,10 @@ collection_list::collect_symbol (struct symbol *sym,
       if (info_verbose)
        {
          printf_filtered ("LOC_REGPARM_ADDR %s: Collect %ld bytes at offset %s"
-                          " from reg %d\n",
-                          SYMBOL_PRINT_NAME (sym), len,
+                          " from reg %d\n", sym->print_name (), len,
                           paddress (gdbarch, offset), reg);
        }
-      add_memrange (gdbarch, reg, offset, len);
+      add_memrange (gdbarch, reg, offset, len, scope);
       break;
     case LOC_LOCAL:
       reg = frame_regno;
@@ -975,11 +996,10 @@ collection_list::collect_symbol (struct symbol *sym,
       if (info_verbose)
        {
          printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset %s"
-                          " from frame ptr reg %d\n",
-                          SYMBOL_PRINT_NAME (sym), len,
+                          " from frame ptr reg %d\n", sym->print_name (), len,
                           paddress (gdbarch, offset), reg);
        }
-      add_memrange (gdbarch, reg, offset, len);
+      add_memrange (gdbarch, reg, offset, len, scope);
       break;
 
     case LOC_UNRESOLVED:
@@ -988,7 +1008,7 @@ collection_list::collect_symbol (struct symbol *sym,
 
     case LOC_OPTIMIZED_OUT:
       printf_filtered ("%s has been optimized out of existence.\n",
-                      SYMBOL_PRINT_NAME (sym));
+                      sym->print_name ());
       break;
 
     case LOC_COMPUTED:
@@ -999,8 +1019,6 @@ collection_list::collect_symbol (struct symbol *sym,
   /* Expressions are the most general case.  */
   if (treat_as_expr)
     {
-      struct cleanup *old_chain1 = NULL;
-
       agent_expr_up aexpr = gen_trace_for_var (scope, gdbarch,
                                               sym, trace_string);
 
@@ -1010,65 +1028,19 @@ collection_list::collect_symbol (struct symbol *sym,
       if (!aexpr)
        {
          printf_filtered ("%s has been optimized out of existence.\n",
-                          SYMBOL_PRINT_NAME (sym));
+                          sym->print_name ());
          return;
        }
 
-      ax_reqs (aexpr.get ());
-
-      report_agent_reqs_errors (aexpr.get ());
+      finalize_tracepoint_aexpr (aexpr.get ());
 
       /* Take care of the registers.  */
-      if (aexpr->reg_mask_len > 0)
-       {
-         for (int ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
-           {
-             QUIT;     /* Allow user to bail out with ^C.  */
-             if (aexpr->reg_mask[ndx1] != 0)
-               {
-                 /* Assume chars have 8 bits.  */
-                 for (int ndx2 = 0; ndx2 < 8; ndx2++)
-                   if (aexpr->reg_mask[ndx1] & (1 << ndx2))
-                     /* It's used -- record it.  */
-                     add_register (ndx1 * 8 + ndx2);
-               }
-           }
-       }
+      add_ax_registers (aexpr.get ());
 
       add_aexpr (std::move (aexpr));
     }
 }
 
-/* Data to be passed around in the calls to the locals and args
-   iterators.  */
-
-struct add_local_symbols_data
-{
-  struct collection_list *collect;
-  struct gdbarch *gdbarch;
-  CORE_ADDR pc;
-  long frame_regno;
-  long frame_offset;
-  int count;
-  int trace_string;
-};
-
-/* The callback for the locals and args iterators.  */
-
-static void
-do_collect_symbol (const char *print_name,
-                  struct symbol *sym,
-                  void *cb_data)
-{
-  struct add_local_symbols_data *p = (struct add_local_symbols_data *) cb_data;
-
-  p->collect->collect_symbol (sym, p->gdbarch, p->frame_regno,
-                             p->frame_offset, p->pc, p->trace_string);
-  p->count++;
-
-  p->collect->add_wholly_collected (print_name);
-}
-
 void
 collection_list::add_wholly_collected (const char *print_name)
 {
@@ -1083,15 +1055,16 @@ collection_list::add_local_symbols (struct gdbarch *gdbarch, CORE_ADDR pc,
                                    int trace_string)
 {
   const struct block *block;
-  struct add_local_symbols_data cb_data;
+  int count = 0;
 
-  cb_data.collect = this;
-  cb_data.gdbarch = gdbarch;
-  cb_data.pc = pc;
-  cb_data.frame_regno = frame_regno;
-  cb_data.frame_offset = frame_offset;
-  cb_data.count = 0;
-  cb_data.trace_string = trace_string;
+  auto do_collect_symbol = [&] (const char *print_name,
+                               struct symbol *sym)
+    {
+      collect_symbol (sym, gdbarch, frame_regno,
+                     frame_offset, pc, trace_string);
+      count++;
+      add_wholly_collected (print_name);
+    };
 
   if (type == 'L')
     {
@@ -1103,8 +1076,8 @@ collection_list::add_local_symbols (struct gdbarch *gdbarch, CORE_ADDR pc,
          return;
        }
 
-      iterate_over_block_local_vars (block, do_collect_symbol, &cb_data);
-      if (cb_data.count == 0)
+      iterate_over_block_local_vars (block, do_collect_symbol);
+      if (count == 0)
        warning (_("No locals found in scope."));
     }
   else
@@ -1117,8 +1090,8 @@ collection_list::add_local_symbols (struct gdbarch *gdbarch, CORE_ADDR pc,
          return;
        }
 
-      iterate_over_block_arg_vars (block, do_collect_symbol, &cb_data);
-      if (cb_data.count == 0)
+      iterate_over_block_arg_vars (block, do_collect_symbol);
+      if (count == 0)
        warning (_("No args found in scope."));
     }
 }
@@ -1132,63 +1105,79 @@ collection_list::add_static_trace_data ()
 }
 
 collection_list::collection_list ()
-  : m_regs_mask (),
-    m_strace_data (false)
+  : m_strace_data (false)
 {
+  int max_remote_regno = 0;
+  for (int i = 0; i < gdbarch_num_regs (target_gdbarch ()); i++)
+    {
+      int remote_regno = (gdbarch_remote_register_number
+                         (target_gdbarch (), i));
+
+      if (remote_regno >= 0 && remote_regno > max_remote_regno)
+       max_remote_regno = remote_regno;
+    }
+
+  m_regs_mask.resize ((max_remote_regno / 8) + 1);
+
   m_memranges.reserve (128);
   m_aexprs.reserve (128);
 }
 
 /* Reduce a collection list to string form (for gdb protocol).  */
 
-char **
+std::vector<std::string>
 collection_list::stringify ()
 {
-  char temp_buf[2048];
+  gdb::char_vector temp_buf (2048);
+
   int count;
-  int ndx = 0;
-  char *(*str_list)[];
   char *end;
   long i;
-
-  count = 1 + 1 + m_memranges.size () + m_aexprs.size () + 1;
-  str_list = (char *(*)[]) xmalloc (count * sizeof (char *));
+  std::vector<std::string> str_list;
 
   if (m_strace_data)
     {
       if (info_verbose)
        printf_filtered ("\nCollecting static trace data\n");
-      end = temp_buf;
+      end = temp_buf.data ();
       *end++ = 'L';
-      (*str_list)[ndx] = savestring (temp_buf, end - temp_buf);
-      ndx++;
+      str_list.emplace_back (temp_buf.data (), end - temp_buf.data ());
     }
 
-  for (i = sizeof (m_regs_mask) - 1; i > 0; i--)
+  for (i = m_regs_mask.size () - 1; i > 0; i--)
     if (m_regs_mask[i] != 0)    /* Skip leading zeroes in regs_mask.  */
       break;
   if (m_regs_mask[i] != 0)     /* Prepare to send regs_mask to the stub.  */
     {
       if (info_verbose)
        printf_filtered ("\nCollecting registers (mask): 0x");
-      end = temp_buf;
+
+      /* One char for 'R', one for the null terminator and two per
+        mask byte.  */
+      std::size_t new_size = (i + 1) * 2 + 2;
+      if (new_size > temp_buf.size ())
+       temp_buf.resize (new_size);
+
+      end = temp_buf.data ();
       *end++ = 'R';
       for (; i >= 0; i--)
        {
          QUIT;                 /* Allow user to bail out with ^C.  */
          if (info_verbose)
            printf_filtered ("%02X", m_regs_mask[i]);
-         sprintf (end, "%02X", m_regs_mask[i]);
-         end += 2;
+
+         end = pack_hex_byte (end, m_regs_mask[i]);
        }
-      (*str_list)[ndx] = xstrdup (temp_buf);
-      ndx++;
+      *end = '\0';
+
+      str_list.emplace_back (temp_buf.data ());
     }
   if (info_verbose)
     printf_filtered ("\n");
   if (!m_memranges.empty () && info_verbose)
     printf_filtered ("Collecting memranges: \n");
-  for (i = 0, count = 0, end = temp_buf; i < m_memranges.size (); i++)
+  for (i = 0, count = 0, end = temp_buf.data ();
+       i < m_memranges.size (); i++)
     {
       QUIT;                    /* Allow user to bail out with ^C.  */
       if (info_verbose)
@@ -1202,30 +1191,29 @@ collection_list::stringify ()
        }
       if (count + 27 > MAX_AGENT_EXPR_LEN)
        {
-         (*str_list)[ndx] = savestring (temp_buf, count);
-         ndx++;
+         str_list.emplace_back (temp_buf.data (), count);
          count = 0;
-         end = temp_buf;
+         end = temp_buf.data ();
        }
 
       {
-        bfd_signed_vma length
+       bfd_signed_vma length
          = m_memranges[i].end - m_memranges[i].start;
 
-        /* The "%X" conversion specifier expects an unsigned argument,
-           so passing -1 (memrange_absolute) to it directly gives you
-           "FFFFFFFF" (or more, depending on sizeof (unsigned)).
-           Special-case it.  */
-        if (m_memranges[i].type == memrange_absolute)
-          sprintf (end, "M-1,%s,%lX", phex_nz (m_memranges[i].start, 0),
+       /* The "%X" conversion specifier expects an unsigned argument,
+          so passing -1 (memrange_absolute) to it directly gives you
+          "FFFFFFFF" (or more, depending on sizeof (unsigned)).
+          Special-case it.  */
+       if (m_memranges[i].type == memrange_absolute)
+         sprintf (end, "M-1,%s,%lX", phex_nz (m_memranges[i].start, 0),
                   (long) length);
-        else
-          sprintf (end, "M%X,%s,%lX", m_memranges[i].type,
+       else
+         sprintf (end, "M%X,%s,%lX", m_memranges[i].type,
                   phex_nz (m_memranges[i].start, 0), (long) length);
       }
 
       count += strlen (end);
-      end = temp_buf + count;
+      end = temp_buf.data () + count;
     }
 
   for (i = 0; i < m_aexprs.size (); i++)
@@ -1233,10 +1221,9 @@ collection_list::stringify ()
       QUIT;                    /* Allow user to bail out with ^C.  */
       if ((count + 10 + 2 * m_aexprs[i]->len) > MAX_AGENT_EXPR_LEN)
        {
-         (*str_list)[ndx] = savestring (temp_buf, count);
-         ndx++;
+         str_list.emplace_back (temp_buf.data (), count);
          count = 0;
-         end = temp_buf;
+         end = temp_buf.data ();
        }
       sprintf (end, "X%08X,", m_aexprs[i]->len);
       end += 10;               /* 'X' + 8 hex digits + ',' */
@@ -1248,32 +1235,20 @@ collection_list::stringify ()
 
   if (count != 0)
     {
-      (*str_list)[ndx] = savestring (temp_buf, count);
-      ndx++;
+      str_list.emplace_back (temp_buf.data (), count);
       count = 0;
-      end = temp_buf;
+      end = temp_buf.data ();
     }
-  (*str_list)[ndx] = NULL;
 
-  if (ndx == 0)
-    {
-      xfree (str_list);
-      return NULL;
-    }
-  else
-    return *str_list;
+  return str_list;
 }
 
-/* Add the printed expression EXP to *LIST.  */
+/* Add the expression STR to M_COMPUTED.  */
 
 void
-collection_list::append_exp (struct expression *exp)
+collection_list::append_exp (std::string &&str)
 {
-  string_file tmp_stream;
-
-  print_expression (exp, &tmp_stream);
-
-  m_computed.push_back (std::move (tmp_stream.string ()));
+  m_computed.push_back (std::move (str));
 }
 
 void
@@ -1301,11 +1276,11 @@ encode_actions_1 (struct command_line *action,
       action_exp = action->line;
       action_exp = skip_spaces (action_exp);
 
-      cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
+      cmd = lookup_cmd (&action_exp, cmdlist, "", NULL, -1, 1);
       if (cmd == 0)
        error (_("Bad action list item: %s"), action_exp);
 
-      if (cmd_cfunc_eq (cmd, collect_pseudocommand))
+      if (cmd_simple_func_eq (cmd, collect_pseudocommand))
        {
          int trace_string = 0;
 
@@ -1319,8 +1294,18 @@ encode_actions_1 (struct command_line *action,
 
              if (0 == strncasecmp ("$reg", action_exp, 4))
                {
-                 for (i = 0; i < gdbarch_num_regs (target_gdbarch ()); i++)
-                   collect->add_register (i);
+                 for (i = 0; i < gdbarch_num_regs (target_gdbarch ());
+                      i++)
+                   {
+                     int remote_regno = (gdbarch_remote_register_number
+                                         (target_gdbarch (), i));
+
+                     /* Ignore arch regnos without a corresponding
+                        remote regno.  This can happen for regnos not
+                        in the tdesc.  */
+                     if (remote_regno >= 0)
+                       collect->add_remote_register (remote_regno);
+                   }
                  action_exp = strchr (action_exp, ',');        /* more? */
                }
              else if (0 == strncasecmp ("$arg", action_exp, 4))
@@ -1350,27 +1335,10 @@ encode_actions_1 (struct command_line *action,
                                                    target_gdbarch (),
                                                    trace_string);
 
-                 ax_reqs (aexpr.get ());
-                 report_agent_reqs_errors (aexpr.get ());
+                 finalize_tracepoint_aexpr (aexpr.get ());
 
                  /* take care of the registers */
-                 if (aexpr->reg_mask_len > 0)
-                   {
-                     for (int ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
-                       {
-                         QUIT; /* allow user to bail out with ^C */
-                         if (aexpr->reg_mask[ndx1] != 0)
-                           {
-                             /* assume chars have 8 bits */
-                             for (int ndx2 = 0; ndx2 < 8; ndx2++)
-                               if (aexpr->reg_mask[ndx1] & (1 << ndx2))
-                                 {
-                                   /* It's used -- record it.  */
-                                   collect->add_register (ndx1 * 8 + ndx2);
-                                 }
-                           }
-                       }
-                   }
+                 collect->add_ax_registers (aexpr.get ());
 
                  collect->add_aexpr (std::move (aexpr));
                  action_exp = strchr (action_exp, ',');        /* more? */
@@ -1383,17 +1351,20 @@ encode_actions_1 (struct command_line *action,
              else
                {
                  unsigned long addr;
-                 struct cleanup *old_chain1 = NULL;
 
+                 const char *exp_start = action_exp;
                  expression_up exp = parse_exp_1 (&action_exp, tloc->address,
                                                   block_for_pc (tloc->address),
                                                   1);
 
-                 switch (exp->elts[0].opcode)
+                 switch (exp->first_opcode ())
                    {
                    case OP_REGISTER:
                      {
-                       const char *name = &exp->elts[2].string;
+                       expr::register_operation *regop
+                         = (dynamic_cast<expr::register_operation *>
+                            (exp->op.get ()));
+                       const char *name = regop->get_name ();
 
                        i = user_reg_map_name_to_regnum (target_gdbarch (),
                                                         name, strlen (name));
@@ -1403,28 +1374,40 @@ encode_actions_1 (struct command_line *action,
                                          name);
                        if (info_verbose)
                          printf_filtered ("OP_REGISTER: ");
-                       collect->add_register (i);
+                       collect->add_local_register (target_gdbarch (),
+                                                    i, tloc->address);
                        break;
                      }
 
                    case UNOP_MEMVAL:
-                     /* Safe because we know it's a simple expression.  */
-                     tempval = evaluate_expression (exp.get ());
-                     addr = value_address (tempval);
-                     /* Initialize the TYPE_LENGTH if it is a typedef.  */
-                     check_typedef (exp->elts[1].type);
-                     collect->add_memrange (target_gdbarch (),
-                                            memrange_absolute, addr,
-                                            TYPE_LENGTH (exp->elts[1].type));
-                     collect->append_exp (exp.get ());
+                     {
+                       /* Safe because we know it's a simple expression.  */
+                       tempval = evaluate_expression (exp.get ());
+                       addr = value_address (tempval);
+                       expr::unop_memval_operation *memop
+                         = (dynamic_cast<expr::unop_memval_operation *>
+                            (exp->op.get ()));
+                       struct type *type = memop->get_type ();
+                       /* Initialize the TYPE_LENGTH if it is a typedef.  */
+                       check_typedef (type);
+                       collect->add_memrange (target_gdbarch (),
+                                              memrange_absolute, addr,
+                                              TYPE_LENGTH (type),
+                                              tloc->address);
+                       collect->append_exp (std::string (exp_start,
+                                                         action_exp));
+                     }
                      break;
 
                    case OP_VAR_VALUE:
                      {
-                       struct symbol *sym = exp->elts[2].symbol;
-                       char_ptr name = (char_ptr) SYMBOL_NATURAL_NAME (sym);
+                       expr::var_value_operation *vvo
+                         = (dynamic_cast<expr::var_value_operation *>
+                            (exp->op.get ()));
+                       struct symbol *sym = vvo->get_symbol ();
+                       const char *name = sym->natural_name ();
 
-                       collect->collect_symbol (exp->elts[2].symbol,
+                       collect->collect_symbol (sym,
                                                 target_gdbarch (),
                                                 frame_reg,
                                                 frame_offset,
@@ -1439,38 +1422,21 @@ encode_actions_1 (struct command_line *action,
                                                                exp.get (),
                                                                trace_string);
 
-                     ax_reqs (aexpr.get ());
-
-                     report_agent_reqs_errors (aexpr.get ());
+                     finalize_tracepoint_aexpr (aexpr.get ());
 
                      /* Take care of the registers.  */
-                     if (aexpr->reg_mask_len > 0)
-                       {
-                         for (int ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
-                           {
-                             QUIT;     /* Allow user to bail out with ^C.  */
-                             if (aexpr->reg_mask[ndx1] != 0)
-                               {
-                                 /* Assume chars have 8 bits.  */
-                                 for (int ndx2 = 0; ndx2 < 8; ndx2++)
-                                   if (aexpr->reg_mask[ndx1] & (1 << ndx2))
-                                     {
-                                       /* It's used -- record it.  */
-                                       collect->add_register (ndx1 * 8 + ndx2);
-                                     }
-                               }
-                           }
-                       }
+                     collect->add_ax_registers (aexpr.get ());
 
                      collect->add_aexpr (std::move (aexpr));
-                     collect->append_exp (exp.get ());
+                     collect->append_exp (std::string (exp_start,
+                                                       action_exp));
                      break;
                    }           /* switch */
                }               /* do */
            }
          while (action_exp && *action_exp++ == ',');
        }                       /* if */
-      else if (cmd_cfunc_eq (cmd, teval_pseudocommand))
+      else if (cmd_simple_func_eq (cmd, teval_pseudocommand))
        {
          do
            {                   /* Repeat over a comma-separated list.  */
@@ -1478,8 +1444,6 @@ encode_actions_1 (struct command_line *action,
              action_exp = skip_spaces (action_exp);
 
                {
-                 struct cleanup *old_chain1 = NULL;
-
                  expression_up exp = parse_exp_1 (&action_exp, tloc->address,
                                                   block_for_pc (tloc->address),
                                                   1);
@@ -1487,8 +1451,7 @@ encode_actions_1 (struct command_line *action,
                  agent_expr_up aexpr = gen_eval_for_expr (tloc->address,
                                                           exp.get ());
 
-                 ax_reqs (aexpr.get ());
-                 report_agent_reqs_errors (aexpr.get ());
+                 finalize_tracepoint_aexpr (aexpr.get ());
 
                  /* Even though we're not officially collecting, add
                     to the collect list anyway.  */
@@ -1497,14 +1460,14 @@ encode_actions_1 (struct command_line *action,
            }
          while (action_exp && *action_exp++ == ',');
        }                       /* if */
-      else if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand))
+      else if (cmd_simple_func_eq (cmd, while_stepping_pseudocommand))
        {
          /* We check against nested while-stepping when setting
             breakpoint action, so no way to run into nested
             here.  */
          gdb_assert (stepping_list);
 
-         encode_actions_1 (action->body_list[0], tloc, frame_reg,
+         encode_actions_1 (action->body_list_0.get (), tloc, frame_reg,
                            frame_offset, stepping_list, NULL);
        }
       else
@@ -1520,17 +1483,17 @@ encode_actions (struct bp_location *tloc,
                struct collection_list *tracepoint_list,
                struct collection_list *stepping_list)
 {
-  struct command_line *actions;
   int frame_reg;
   LONGEST frame_offset;
 
   gdbarch_virtual_frame_pointer (tloc->gdbarch,
                                 tloc->address, &frame_reg, &frame_offset);
 
-  actions = all_tracepoint_actions_and_cleanup (tloc->owner);
-
-  encode_actions_1 (actions, tloc, frame_reg, frame_offset,
+  counted_command_line actions = all_tracepoint_actions (tloc->owner);
+  encode_actions_1 (actions.get (), tloc, frame_reg, frame_offset,
                    tracepoint_list, stepping_list);
+  encode_actions_1 (breakpoint_commands (tloc->owner), tloc,
+                   frame_reg, frame_offset, tracepoint_list, stepping_list);
 
   tracepoint_list->finish ();
   stepping_list->finish ();
@@ -1539,14 +1502,12 @@ encode_actions (struct bp_location *tloc,
 /* Render all actions into gdb protocol.  */
 
 void
-encode_actions_rsp (struct bp_location *tloc, char ***tdp_actions,
-                   char ***stepping_actions)
+encode_actions_rsp (struct bp_location *tloc,
+                   std::vector<std::string> *tdp_actions,
+                   std::vector<std::string> *stepping_actions)
 {
   struct collection_list tracepoint_list, stepping_list;
 
-  *tdp_actions = NULL;
-  *stepping_actions = NULL;
-
   encode_actions (tloc, &tracepoint_list, &stepping_list);
 
   *tdp_actions = tracepoint_list.stringify ();
@@ -1562,15 +1523,11 @@ collection_list::add_aexpr (agent_expr_up aexpr)
 static void
 process_tracepoint_on_disconnect (void)
 {
-  VEC(breakpoint_p) *tp_vec = NULL;
-  int ix;
-  struct breakpoint *b;
   int has_pending_p = 0;
 
   /* Check whether we still have pending tracepoint.  If we have, warn the
      user that pending tracepoint will no longer work.  */
-  tp_vec = all_tracepoints ();
-  for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++)
+  for (breakpoint *b : all_tracepoints ())
     {
       if (b->loc == NULL)
        {
@@ -1579,9 +1536,7 @@ process_tracepoint_on_disconnect (void)
        }
       else
        {
-         struct bp_location *loc1;
-
-         for (loc1 = b->loc; loc1; loc1 = loc1->next)
+         for (bp_location *loc1 : b->locations ())
            {
              if (loc1->shlib_disabled)
                {
@@ -1594,7 +1549,6 @@ process_tracepoint_on_disconnect (void)
            break;
        }
     }
-  VEC_free (breakpoint_p, tp_vec);
 
   if (has_pending_p)
     warning (_("Pending tracepoints will not be resolved while"
@@ -1613,25 +1567,18 @@ trace_reset_local_state (void)
 }
 
 void
-start_tracing (char *notes)
+start_tracing (const char *notes)
 {
-  VEC(breakpoint_p) *tp_vec = NULL;
-  int ix;
-  struct breakpoint *b;
-  struct trace_state_variable *tsv;
   int any_enabled = 0, num_to_download = 0;
   int ret;
 
-  tp_vec = all_tracepoints ();
+  auto tracepoint_range = all_tracepoints ();
 
   /* No point in tracing without any tracepoints...  */
-  if (VEC_length (breakpoint_p, tp_vec) == 0)
-    {
-      VEC_free (breakpoint_p, tp_vec);
-      error (_("No tracepoints defined, not starting trace"));
-    }
+  if (tracepoint_range.begin () == tracepoint_range.end ())
+    error (_("No tracepoints defined, not starting trace"));
 
-  for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++)
+  for (breakpoint *b : tracepoint_range)
     {
       if (b->enable_state == bp_enabled)
        any_enabled = 1;
@@ -1653,27 +1600,22 @@ start_tracing (char *notes)
        {
          /* No point in tracing with only disabled tracepoints that
             cannot be re-enabled.  */
-         VEC_free (breakpoint_p, tp_vec);
          error (_("No tracepoints enabled, not starting trace"));
        }
     }
 
   if (num_to_download <= 0)
-    {
-      VEC_free (breakpoint_p, tp_vec);
-      error (_("No tracepoints that may be downloaded, not starting trace"));
-    }
+    error (_("No tracepoints that may be downloaded, not starting trace"));
 
   target_trace_init ();
 
-  for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++)
+  for (breakpoint *b : tracepoint_range)
     {
       struct tracepoint *t = (struct tracepoint *) b;
-      struct bp_location *loc;
       int bp_location_downloaded = 0;
 
       /* Clear `inserted' flag.  */
-      for (loc = b->loc; loc; loc = loc->next)
+      for (bp_location *loc : b->locations ())
        loc->inserted = 0;
 
       if ((b->type == bp_fast_tracepoint
@@ -1683,7 +1625,7 @@ start_tracing (char *notes)
 
       t->number_on_target = 0;
 
-      for (loc = b->loc; loc; loc = loc->next)
+      for (bp_location *loc : b->locations ())
        {
          /* Since tracepoint locations are never duplicated, `inserted'
             flag should be zero.  */
@@ -1697,23 +1639,18 @@ start_tracing (char *notes)
 
       t->number_on_target = b->number;
 
-      for (loc = b->loc; loc; loc = loc->next)
-       if (loc->probe.probe != NULL
-           && loc->probe.probe->pops->set_semaphore != NULL)
-         loc->probe.probe->pops->set_semaphore (loc->probe.probe,
-                                                loc->probe.objfile,
-                                                loc->gdbarch);
+      for (bp_location *loc : b->locations ())
+       if (loc->probe.prob != NULL)
+         loc->probe.prob->set_semaphore (loc->probe.objfile,
+                                         loc->gdbarch);
 
       if (bp_location_downloaded)
-       observer_notify_breakpoint_modified (b);
+       gdb::observers::breakpoint_modified.notify (b);
     }
-  VEC_free (breakpoint_p, tp_vec);
 
   /* Send down all the trace state variables too.  */
-  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
-    {
-      target_download_trace_state_variable (tsv);
-    }
+  for (const trace_state_variable &tsv : tvariables)
+    target_download_trace_state_variable (tsv);
   
   /* Tell target to treat text-like sections as transparent.  */
   target_trace_set_readonly_regions ();
@@ -1723,10 +1660,11 @@ start_tracing (char *notes)
   target_set_trace_buffer_size (trace_buffer_size);
 
   if (!notes)
-    notes = trace_notes;
-  ret = target_set_trace_notes (trace_user, notes, NULL);
+    notes = trace_notes.c_str ();
+
+  ret = target_set_trace_notes (trace_user.c_str (), notes, NULL);
 
-  if (!ret && (trace_user || notes))
+  if (!ret && (!trace_user.empty () || notes))
     warning (_("Target does not support trace user/notes, info ignored"));
 
   /* Now insert traps and begin collecting data.  */
@@ -1744,7 +1682,7 @@ start_tracing (char *notes)
    anybody else messing with the target.  */
 
 static void
-tstart_command (char *args, int from_tty)
+tstart_command (const char *args, int from_tty)
 {
   dont_repeat ();      /* Like "run", dangerous to repeat accidentally.  */
 
@@ -1764,7 +1702,7 @@ tstart_command (char *args, int from_tty)
    of the trace run's status.  */
 
 static void
-tstop_command (char *args, int from_tty)
+tstop_command (const char *args, int from_tty)
 {
   if (!current_trace_status ()->running)
     error (_("Trace is not running."));
@@ -1773,43 +1711,34 @@ tstop_command (char *args, int from_tty)
 }
 
 void
-stop_tracing (char *note)
+stop_tracing (const char *note)
 {
   int ret;
-  VEC(breakpoint_p) *tp_vec = NULL;
-  int ix;
-  struct breakpoint *t;
 
   target_trace_stop ();
 
-  tp_vec = all_tracepoints ();
-  for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
+  for (breakpoint *t : all_tracepoints ())
     {
-      struct bp_location *loc;
-
       if ((t->type == bp_fast_tracepoint
           ? !may_insert_fast_tracepoints
           : !may_insert_tracepoints))
        continue;
 
-      for (loc = t->loc; loc; loc = loc->next)
+      for (bp_location *loc : t->locations ())
        {
          /* GDB can be totally absent in some disconnected trace scenarios,
             but we don't really care if this semaphore goes out of sync.
             That's why we are decrementing it here, but not taking care
             in other places.  */
-         if (loc->probe.probe != NULL
-             && loc->probe.probe->pops->clear_semaphore != NULL)
-           loc->probe.probe->pops->clear_semaphore (loc->probe.probe,
-                                                    loc->probe.objfile,
-                                                    loc->gdbarch);
+         if (loc->probe.prob != NULL)
+           loc->probe.prob->clear_semaphore (loc->probe.objfile,
+                                             loc->gdbarch);
        }
     }
 
-  VEC_free (breakpoint_p, tp_vec);
-
   if (!note)
-    note = trace_stop_notes;
+    note = trace_stop_notes.c_str ();
+
   ret = target_set_trace_notes (NULL, NULL, note);
 
   if (!ret && note)
@@ -1821,12 +1750,10 @@ stop_tracing (char *note)
 
 /* tstatus command */
 static void
-tstatus_command (char *args, int from_tty)
+tstatus_command (const char *args, int from_tty)
 {
   struct trace_status *ts = current_trace_status ();
-  int status, ix;
-  VEC(breakpoint_p) *tp_vec = NULL;
-  struct breakpoint *t;
+  int status;
   
   status = target_get_trace_status (ts);
 
@@ -1969,12 +1896,8 @@ tstatus_command (char *args, int from_tty)
                     (long int) (ts->stop_time % 1000000));
 
   /* Now report any per-tracepoint status available.  */
-  tp_vec = all_tracepoints ();
-
-  for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
+  for (breakpoint *t : all_tracepoints ())
     target_get_tracepoint_status (t, NULL);
-
-  VEC_free (breakpoint_p, tp_vec);
 }
 
 /* Report the trace status to uiout, in a way suitable for MI, and not
@@ -2056,8 +1979,8 @@ trace_status_mi (int on_stop)
            {
              uiout->field_string ("stop-reason", stop_reason);
              if (stopping_tracepoint != -1)
-               uiout->field_int ("stopping-tracepoint",
-                                 stopping_tracepoint);
+               uiout->field_signed ("stopping-tracepoint",
+                                    stopping_tracepoint);
              if (ts->stop_reason == tracepoint_error)
                uiout->field_string ("error-description",
                                     ts->stop_desc);
@@ -2066,16 +1989,16 @@ trace_status_mi (int on_stop)
     }
 
   if (ts->traceframe_count != -1)
-    uiout->field_int ("frames", ts->traceframe_count);
+    uiout->field_signed ("frames", ts->traceframe_count);
   if (ts->traceframes_created != -1)
-    uiout->field_int ("frames-created", ts->traceframes_created);
+    uiout->field_signed ("frames-created", ts->traceframes_created);
   if (ts->buffer_size != -1)
-    uiout->field_int ("buffer-size", ts->buffer_size);
+    uiout->field_signed ("buffer-size", ts->buffer_size);
   if (ts->buffer_free != -1)
-    uiout->field_int ("buffer-free", ts->buffer_free);
+    uiout->field_signed ("buffer-free", ts->buffer_free);
 
-  uiout->field_int ("disconnected",  ts->disconnected_tracing);
-  uiout->field_int ("circular",  ts->circular_buffer);
+  uiout->field_signed ("disconnected",  ts->disconnected_tracing);
+  uiout->field_signed ("circular",  ts->circular_buffer);
 
   uiout->field_string ("user-name", ts->user_name);
   uiout->field_string ("notes", ts->notes);
@@ -2192,7 +2115,7 @@ tfind_1 (enum trace_find_type type, int num,
         DON'T give an error, but DO change the state of
         traceframe_number etc. to invalid.
 
-        The rationalle is that if you typed the command, you
+        The rationale is that if you typed the command, you
         might just have committed a typo or something, and you'd
         like to NOT lose your current debugging state.  However
         if you're in a user-defined command or especially in a
@@ -2223,7 +2146,7 @@ tfind_1 (enum trace_find_type type, int num,
   set_tracepoint_num (tp ? tp->number : target_tracept);
 
   if (target_frameno != get_traceframe_number ())
-    observer_notify_traceframe_changed (target_frameno, tracepoint_number);
+    gdb::observers::traceframe_changed.notify (target_frameno, tracepoint_number);
 
   set_current_traceframe (target_frameno);
 
@@ -2239,13 +2162,13 @@ tfind_1 (enum trace_find_type type, int num,
       if (uiout->is_mi_like_p ())
        {
          uiout->field_string ("found", "1");
-         uiout->field_int ("tracepoint", tracepoint_number);
-         uiout->field_int ("traceframe", traceframe_number);
+         uiout->field_signed ("tracepoint", tracepoint_number);
+         uiout->field_signed ("traceframe", traceframe_number);
        }
       else
        {
-         printf_unfiltered (_("Found trace frame %d, tracepoint %d\n"),
-                            traceframe_number, tracepoint_number);
+         printf_filtered (_("Found trace frame %d, tracepoint %d\n"),
+                          traceframe_number, tracepoint_number);
        }
     }
   else
@@ -2253,9 +2176,9 @@ tfind_1 (enum trace_find_type type, int num,
       if (uiout->is_mi_like_p ())
        uiout->field_string ("found", "0");
       else if (type == tfind_number && num == -1)
-       printf_unfiltered (_("No longer looking at any trace frame\n"));
+       printf_filtered (_("No longer looking at any trace frame\n"));
       else /* This case may never occur, check.  */
-       printf_unfiltered (_("No trace frame found\n"));
+       printf_filtered (_("No trace frame found\n"));
     }
 
   /* If we're in nonstop mode and getting out of looking at trace
@@ -2267,10 +2190,10 @@ tfind_1 (enum trace_find_type type, int num,
       enum print_what print_what;
 
       /* NOTE: in imitation of the step command, try to determine
-         whether we have made a transition from one function to
-         another.  If so, we'll print the "stack frame" (ie. the new
-         function and it's arguments) -- otherwise we'll just show the
-         new source line.  */
+        whether we have made a transition from one function to
+        another.  If so, we'll print the "stack frame" (ie. the new
+        function and it's arguments) -- otherwise we'll just show the
+        new source line.  */
 
       if (frame_id_eq (old_frame_id,
                       get_frame_id (get_current_frame ())))
@@ -2318,7 +2241,7 @@ tfind_command_1 (const char *args, int from_tty)
     { /* TFIND with no args means find NEXT trace frame.  */
       if (traceframe_number == -1)
        frameno = 0;    /* "next" is first one.  */
-        else
+      else
        frameno = traceframe_number + 1;
     }
   else if (0 == strcmp (args, "-"))
@@ -2343,9 +2266,9 @@ tfind_command_1 (const char *args, int from_tty)
 }
 
 static void
-tfind_command (char *args, int from_tty)
+tfind_command (const char *args, int from_tty)
 {
-  tfind_command_1 (const_cast<char *> (args), from_tty);
+  tfind_command_1 (args, from_tty);
 }
 
 /* tfind end */
@@ -2439,14 +2362,14 @@ tfind_line_command (const char *args, int from_tty)
   if (sal.line > 0 && find_line_pc_range (sal, &start_pc, &end_pc))
     {
       if (start_pc == end_pc)
-       {
+       {
          printf_filtered ("Line %d of \"%s\"",
                           sal.line,
                           symtab_to_filename_for_display (sal.symtab));
-         wrap_here ("  ");
+         gdb_stdout->wrap_here (2);
          printf_filtered (" is at address ");
          print_address (get_current_arch (), start_pc, gdb_stdout);
-         wrap_here ("  ");
+         gdb_stdout->wrap_here (2);
          printf_filtered (" but contains no code.\n");
          sal = find_pc_line (start_pc, 0);
          if (sal.line > 0
@@ -2454,16 +2377,18 @@ tfind_line_command (const char *args, int from_tty)
              && start_pc != end_pc)
            printf_filtered ("Attempting to find line %d instead.\n",
                             sal.line);
-         else
+         else
            error (_("Cannot find a good line."));
-       }
+       }
       }
-    else
-    /* Is there any case in which we get here, and have an address
-       which the user would want to see?  If we have debugging
-       symbols and no line numbers?  */
-    error (_("Line number %d is out of range for \"%s\"."),
-          sal.line, symtab_to_filename_for_display (sal.symtab));
+  else
+    {
+      /* Is there any case in which we get here, and have an address
+        which the user would want to see?  If we have debugging
+        symbols and no line numbers?  */
+      error (_("Line number %d is out of range for \"%s\"."),
+            sal.line, symtab_to_filename_for_display (sal.symtab));
+    }
 
   /* Find within range of stated line.  */
   if (args && *args)
@@ -2483,7 +2408,7 @@ tfind_range_command (const char *args, int from_tty)
 
   if (args == 0 || *args == 0)
     { /* XXX FIXME: what should default behavior be?  */
-      printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
+      printf_filtered ("Usage: tfind range STARTADDR, ENDADDR\n");
       return;
     }
 
@@ -2517,7 +2442,7 @@ tfind_outside_command (const char *args, int from_tty)
 
   if (args == 0 || *args == 0)
     { /* XXX FIXME: what should default behavior be?  */
-      printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
+      printf_filtered ("Usage: tfind outside STARTADDR, ENDADDR\n");
       return;
     }
 
@@ -2540,7 +2465,7 @@ tfind_outside_command (const char *args, int from_tty)
 
 /* info scope command: list the locals for a scope.  */
 static void
-info_scope_command (char *args_in, int from_tty)
+info_scope_command (const char *args_in, int from_tty)
 {
   struct symbol *sym;
   struct bound_minimal_symbol msym;
@@ -2582,7 +2507,7 @@ info_scope_command (char *args_in, int from_tty)
            printf_filtered ("Scope for %s:\n", save_args);
          count++;
 
-         symname = SYMBOL_PRINT_NAME (sym);
+         symname = sym->print_name ();
          if (symname == NULL || *symname == '\0')
            continue;           /* Probably botched, certainly useless.  */
 
@@ -2592,16 +2517,16 @@ info_scope_command (char *args_in, int from_tty)
 
          if (SYMBOL_COMPUTED_OPS (sym) != NULL)
            SYMBOL_COMPUTED_OPS (sym)->describe_location (sym,
-                                                         BLOCK_START (block),
+                                                         BLOCK_ENTRY_PC (block),
                                                          gdb_stdout);
          else
            {
-             switch (SYMBOL_CLASS (sym))
+             switch (sym->aclass ())
                {
                default:
                case LOC_UNDEF: /* Messed up symbol?  */
                  printf_filtered ("a bogus symbol, class %d.\n",
-                                  SYMBOL_CLASS (sym));
+                                  sym->aclass ());
                  count--;              /* Don't count this one.  */
                  continue;
                case LOC_CONST:
@@ -2611,10 +2536,10 @@ info_scope_command (char *args_in, int from_tty)
                  break;
                case LOC_CONST_BYTES:
                  printf_filtered ("constant bytes: ");
-                 if (SYMBOL_TYPE (sym))
-                   for (j = 0; j < TYPE_LENGTH (SYMBOL_TYPE (sym)); j++)
-                     fprintf_filtered (gdb_stdout, " %02x",
-                                       (unsigned) SYMBOL_VALUE_BYTES (sym)[j]);
+                 if (sym->type ())
+                   for (j = 0; j < TYPE_LENGTH (sym->type ()); j++)
+                     printf_filtered (" %02x",
+                                      (unsigned) SYMBOL_VALUE_BYTES (sym)[j]);
                  break;
                case LOC_STATIC:
                  printf_filtered ("in static storage at address ");
@@ -2632,7 +2557,7 @@ info_scope_command (char *args_in, int from_tty)
                  regno = SYMBOL_REGISTER_OPS (sym)->register_number (sym,
                                                                      gdbarch);
 
-                 if (SYMBOL_IS_ARGUMENT (sym))
+                 if (sym->is_argument ())
                    printf_filtered ("an argument in register $%s",
                                     gdbarch_register_name (gdbarch, regno));
                  else
@@ -2669,10 +2594,10 @@ info_scope_command (char *args_in, int from_tty)
                case LOC_BLOCK:
                  printf_filtered ("a function at address ");
                  printf_filtered ("%s",
-                                  paddress (gdbarch, BLOCK_START (SYMBOL_BLOCK_VALUE (sym))));
+                                  paddress (gdbarch, BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym))));
                  break;
                case LOC_UNRESOLVED:
-                 msym = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (sym),
+                 msym = lookup_minimal_symbol (sym->linkage_name (),
                                                NULL, NULL);
                  if (msym.minsym == NULL)
                    printf_filtered ("Unresolved Static");
@@ -2688,12 +2613,15 @@ info_scope_command (char *args_in, int from_tty)
                  printf_filtered ("optimized out.\n");
                  continue;
                case LOC_COMPUTED:
-                 gdb_assert_not_reached (_("LOC_COMPUTED variable missing a method"));
+                 gdb_assert_not_reached ("LOC_COMPUTED variable missing a method");
                }
            }
-         if (SYMBOL_TYPE (sym))
-           printf_filtered (", length %d.\n",
-                            TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym))));
+         if (sym->type ())
+           {
+             struct type *t = check_typedef (sym->type ());
+
+             printf_filtered (", length %s.\n", pulongest (TYPE_LENGTH (t)));
+           }
        }
       if (BLOCK_FUNCTION (block))
        break;
@@ -2727,24 +2655,22 @@ trace_dump_actions (struct command_line *action,
       action_exp = skip_spaces (action_exp);
 
       /* The collection actions to be done while stepping are
-         bracketed by the commands "while-stepping" and "end".  */
+        bracketed by the commands "while-stepping" and "end".  */
 
       if (*action_exp == '#')  /* comment line */
        continue;
 
-      cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
+      cmd = lookup_cmd (&action_exp, cmdlist, "", NULL, -1, 1);
       if (cmd == 0)
        error (_("Bad action list item: %s"), action_exp);
 
-      if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand))
+      if (cmd_simple_func_eq (cmd, while_stepping_pseudocommand))
        {
-         int i;
-
-         for (i = 0; i < action->body_count; ++i)
-           trace_dump_actions (action->body_list[i],
-                               1, stepping_frame, from_tty);
+         gdb_assert (action->body_list_1 == nullptr);
+         trace_dump_actions (action->body_list_0.get (),
+                             1, stepping_frame, from_tty);
        }
-      else if (cmd_cfunc_eq (cmd, collect_pseudocommand))
+      else if (cmd_simple_func_eq (cmd, collect_pseudocommand))
        {
          /* Display the collected data.
             For the trap frame, display only what was collected at
@@ -2754,9 +2680,6 @@ trace_dump_actions (struct command_line *action,
             STEPPING_ACTIONS should be equal.  */
          if (stepping_frame == stepping_actions)
            {
-             char *cmd = NULL;
-             struct cleanup *old_chain
-               = make_cleanup (free_current_contents, &cmd);
              int trace_string = 0;
 
              if (*action_exp == '/')
@@ -2781,31 +2704,22 @@ trace_dump_actions (struct command_line *action,
                    info_args_command (NULL, from_tty);
                  else
                    {           /* variable */
+                     std::string contents;
+                     const char *exp = action_exp;
                      if (next_comma != NULL)
                        {
                          size_t len = next_comma - action_exp;
-
-                         cmd = (char *) xrealloc (cmd, len + 1);
-                         memcpy (cmd, action_exp, len);
-                         cmd[len] = 0;
-                       }
-                     else
-                       {
-                         size_t len = strlen (action_exp);
-
-                         cmd = (char *) xrealloc (cmd, len + 1);
-                         memcpy (cmd, action_exp, len + 1);
+                         contents = std::string (action_exp, len);
+                         exp = contents.c_str ();
                        }
 
-                     printf_filtered ("%s = ", cmd);
-                     output_command_const (cmd, from_tty);
+                     printf_filtered ("%s = ", exp);
+                     output_command (exp, from_tty);
                      printf_filtered ("\n");
                    }
                  action_exp = next_comma;
                }
              while (action_exp && *action_exp == ',');
-
-             do_cleanups (old_chain);
            }
        }
     }
@@ -2819,7 +2733,6 @@ struct bp_location *
 get_traceframe_location (int *stepping_frame_p)
 {
   struct tracepoint *t;
-  struct bp_location *tloc;
   struct regcache *regcache;
 
   if (tracepoint_number == -1)
@@ -2840,7 +2753,7 @@ get_traceframe_location (int *stepping_frame_p)
      locations, assume it is a direct hit rather than a while-stepping
      frame.  (FIXME this is not reliable, should record each frame's
      type.)  */
-  for (tloc = t->loc; tloc; tloc = tloc->next)
+  for (bp_location *tloc : t->locations ())
     if (tloc->address == regcache_read_pc (regcache))
       {
        *stepping_frame_p = 0;
@@ -2853,36 +2766,27 @@ get_traceframe_location (int *stepping_frame_p)
   return t->loc;
 }
 
-/* Return all the actions, including default collect, of a tracepoint
-   T.  It constructs cleanups into the chain, and leaves the caller to
-   handle them (call do_cleanups).  */
+/* Return the default collect actions of a tracepoint T.  */
 
-static struct command_line *
-all_tracepoint_actions_and_cleanup (struct breakpoint *t)
+static counted_command_line
+all_tracepoint_actions (struct breakpoint *t)
 {
-  struct command_line *actions;
-
-  actions = breakpoint_commands (t);
+  counted_command_line actions (nullptr, command_lines_deleter ());
 
   /* If there are default expressions to collect, make up a collect
      action and prepend to the action list to encode.  Note that since
      validation is per-tracepoint (local var "xyz" might be valid for
      one tracepoint and not another, etc), we make up the action on
      the fly, and don't cache it.  */
-  if (*default_collect)
+  if (!default_collect.empty ())
     {
-      struct command_line *default_collect_action;
-      char *default_collect_line;
-
-      default_collect_line = xstrprintf ("collect %s", default_collect);
-      make_cleanup (xfree, default_collect_line);
-
-      validate_actionline (default_collect_line, t);
-      default_collect_action = XNEW (struct command_line);
-      make_cleanup (xfree, default_collect_action);
-      default_collect_action->next = actions;
-      default_collect_action->line = default_collect_line;
-      actions = default_collect_action;
+      gdb::unique_xmalloc_ptr<char> default_collect_line
+       = xstrprintf ("collect %s", default_collect.c_str ());
+
+      validate_actionline (default_collect_line.get (), t);
+      actions.reset (new struct command_line (simple_control,
+                                             default_collect_line.release ()),
+                    command_lines_deleter ());
     }
 
   return actions;
@@ -2891,11 +2795,10 @@ all_tracepoint_actions_and_cleanup (struct breakpoint *t)
 /* The tdump command.  */
 
 static void
-tdump_command (char *args, int from_tty)
+tdump_command (const char *args, int from_tty)
 {
   int stepping_frame = 0;
   struct bp_location *loc;
-  struct command_line *actions;
 
   /* This throws an error is not inspecting a trace frame.  */
   loc = get_traceframe_location (&stepping_frame);
@@ -2909,9 +2812,11 @@ tdump_command (char *args, int from_tty)
 
   select_frame (get_current_frame ());
 
-  actions = all_tracepoint_actions_and_cleanup (loc->owner);
+  counted_command_line actions = all_tracepoint_actions (loc->owner);
 
-  trace_dump_actions (actions, 0, stepping_frame, from_tty);
+  trace_dump_actions (actions.get (), 0, stepping_frame, from_tty);
+  trace_dump_actions (breakpoint_commands (loc->owner), 0, stepping_frame,
+                     from_tty);
 }
 
 /* Encode a piece of a tracepoint's source-level definition in a form
@@ -2939,57 +2844,57 @@ encode_source_string (int tpnum, ULONGEST addr,
    disconnects for some reason.  */
 
 static void
-set_disconnected_tracing (char *args, int from_tty,
+set_disconnected_tracing (const char *args, int from_tty,
                          struct cmd_list_element *c)
 {
   target_set_disconnected_tracing (disconnected_tracing);
 }
 
 static void
-set_circular_trace_buffer (char *args, int from_tty,
+set_circular_trace_buffer (const char *args, int from_tty,
                           struct cmd_list_element *c)
 {
   target_set_circular_trace_buffer (circular_trace_buffer);
 }
 
 static void
-set_trace_buffer_size (char *args, int from_tty,
+set_trace_buffer_size (const char *args, int from_tty,
                           struct cmd_list_element *c)
 {
   target_set_trace_buffer_size (trace_buffer_size);
 }
 
 static void
-set_trace_user (char *args, int from_tty,
+set_trace_user (const char *args, int from_tty,
                struct cmd_list_element *c)
 {
   int ret;
 
-  ret = target_set_trace_notes (trace_user, NULL, NULL);
+  ret = target_set_trace_notes (trace_user.c_str (), NULL, NULL);
 
   if (!ret)
     warning (_("Target does not support trace notes, user ignored"));
 }
 
 static void
-set_trace_notes (char *args, int from_tty,
+set_trace_notes (const char *args, int from_tty,
                 struct cmd_list_element *c)
 {
   int ret;
 
-  ret = target_set_trace_notes (NULL, trace_notes, NULL);
+  ret = target_set_trace_notes (NULL, trace_notes.c_str (), NULL);
 
   if (!ret)
     warning (_("Target does not support trace notes, note ignored"));
 }
 
 static void
-set_trace_stop_notes (char *args, int from_tty,
+set_trace_stop_notes (const char *args, int from_tty,
                      struct cmd_list_element *c)
 {
   int ret;
 
-  ret = target_set_trace_notes (NULL, NULL, trace_stop_notes);
+  ret = target_set_trace_notes (NULL, NULL, trace_stop_notes.c_str ());
 
   if (!ret)
     warning (_("Target does not support trace notes, stop note ignored"));
@@ -3060,43 +2965,9 @@ set_current_traceframe (int num)
   clear_traceframe_info ();
 }
 
-/* A cleanup used when switching away and back from tfind mode.  */
-
-struct current_traceframe_cleanup
-{
-  /* The traceframe we were inspecting.  */
-  int traceframe_number;
-};
-
-static void
-do_restore_current_traceframe_cleanup (void *arg)
-{
-  struct current_traceframe_cleanup *old
-    = (struct current_traceframe_cleanup *) arg;
-
-  set_current_traceframe (old->traceframe_number);
-}
-
-static void
-restore_current_traceframe_cleanup_dtor (void *arg)
-{
-  struct current_traceframe_cleanup *old
-    = (struct current_traceframe_cleanup *) arg;
-
-  xfree (old);
-}
-
-struct cleanup *
-make_cleanup_restore_current_traceframe (void)
-{
-  struct current_traceframe_cleanup *old =
-    XNEW (struct current_traceframe_cleanup);
-
-  old->traceframe_number = traceframe_number;
-
-  return make_cleanup_dtor (do_restore_current_traceframe_cleanup, old,
-                           restore_current_traceframe_cleanup_dtor);
-}
+scoped_restore_current_traceframe::scoped_restore_current_traceframe ()
+: m_traceframe_number (traceframe_number)
+{}
 
 /* Given a number and address, return an uploaded tracepoint with that
    number, creating if necessary.  */
@@ -3110,12 +2981,9 @@ get_uploaded_tp (int num, ULONGEST addr, struct uploaded_tp **utpp)
     if (utp->number == num && utp->addr == addr)
       return utp;
 
-  utp = XCNEW (struct uploaded_tp);
+  utp = new uploaded_tp;
   utp->number = num;
   utp->addr = addr;
-  utp->actions = NULL;
-  utp->step_actions = NULL;
-  utp->cmd_strings = NULL;
   utp->next = *utpp;
   *utpp = utp;
 
@@ -3130,7 +2998,7 @@ free_uploaded_tps (struct uploaded_tp **utpp)
   while (*utpp)
     {
       next_one = (*utpp)->next;
-      xfree (*utpp);
+      delete *utpp;
       *utpp = next_one;
     }
 }
@@ -3189,19 +3057,17 @@ cond_string_is_same (char *str1, char *str2)
 static struct bp_location *
 find_matching_tracepoint_location (struct uploaded_tp *utp)
 {
-  VEC(breakpoint_p) *tp_vec = all_tracepoints ();
-  int ix;
-  struct breakpoint *b;
   struct bp_location *loc;
 
-  for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++)
+  for (breakpoint *b : all_tracepoints ())
     {
       struct tracepoint *t = (struct tracepoint *) b;
 
       if (b->type == utp->type
          && t->step_count == utp->step
          && t->pass_count == utp->pass
-         && cond_string_is_same (t->cond_string, utp->cond_string)
+         && cond_string_is_same (t->cond_string.get (),
+                                 utp->cond_string.get ())
          /* FIXME also test actions.  */
          )
        {
@@ -3225,9 +3091,7 @@ merge_uploaded_tracepoints (struct uploaded_tp **uploaded_tps)
 {
   struct uploaded_tp *utp;
   /* A set of tracepoints which are modified.  */
-  VEC(breakpoint_p) *modified_tp = NULL;
-  int ix;
-  struct breakpoint *b;
+  std::vector<breakpoint *> modified_tp;
 
   /* Look for GDB tracepoints that match up with our uploaded versions.  */
   for (utp = *uploaded_tps; utp; utp = utp->next)
@@ -3253,16 +3117,14 @@ merge_uploaded_tracepoints (struct uploaded_tp **uploaded_tps)
             MODIFIED_TP if not there yet.  The 'breakpoint-modified'
             observers will be notified later once for each tracepoint
             saved in MODIFIED_TP.  */
-         for (ix = 0;
-              VEC_iterate (breakpoint_p, modified_tp, ix, b);
-              ix++)
+         for (breakpoint *b : modified_tp)
            if (b == loc->owner)
              {
                found = 1;
                break;
              }
          if (!found)
-           VEC_safe_push (breakpoint_p, modified_tp, loc->owner);
+           modified_tp.push_back (loc->owner);
        }
       else
        {
@@ -3287,10 +3149,9 @@ merge_uploaded_tracepoints (struct uploaded_tp **uploaded_tps)
 
   /* Notify 'breakpoint-modified' observer that at least one of B's
      locations was changed.  */
-  for (ix = 0; VEC_iterate (breakpoint_p, modified_tp, ix, b); ix++)
-    observer_notify_breakpoint_modified (b);
+  for (breakpoint *b : modified_tp)
+    gdb::observers::breakpoint_modified.notify (b);
 
-  VEC_free (breakpoint_p, modified_tp);
   free_uploaded_tps (uploaded_tps);
 }
 
@@ -3310,40 +3171,32 @@ static struct trace_state_variable *
 create_tsv_from_upload (struct uploaded_tsv *utsv)
 {
   const char *namebase;
-  char *buf;
+  std::string buf;
   int try_num = 0;
   struct trace_state_variable *tsv;
-  struct cleanup *old_chain;
 
   if (utsv->name)
     {
       namebase = utsv->name;
-      buf = xstrprintf ("%s", namebase);
+      buf = namebase;
     }
   else
     {
       namebase = "__tsv";
-      buf = xstrprintf ("%s_%d", namebase, try_num++);
+      buf = string_printf ("%s_%d", namebase, try_num++);
     }
 
   /* Fish for a name that is not in use.  */
   /* (should check against all internal vars?)  */
-  while (find_trace_state_variable (buf))
-    {
-      xfree (buf);
-      buf = xstrprintf ("%s_%d", namebase, try_num++);
-    }
-
-  old_chain = make_cleanup (xfree, buf);
+  while (find_trace_state_variable (buf.c_str ()))
+    buf = string_printf ("%s_%d", namebase, try_num++);
 
   /* We have an available name, create the variable.  */
-  tsv = create_trace_state_variable (buf);
+  tsv = create_trace_state_variable (buf.c_str ());
   tsv->initial_value = utsv->initial_value;
   tsv->builtin = utsv->builtin;
 
-  observer_notify_tsv_created (tsv);
-
-  do_cleanups (old_chain);
+  gdb::observers::tsv_created.notify (tsv);
 
   return tsv;
 }
@@ -3354,25 +3207,23 @@ create_tsv_from_upload (struct uploaded_tsv *utsv)
 void
 merge_uploaded_trace_state_variables (struct uploaded_tsv **uploaded_tsvs)
 {
-  int ix;
   struct uploaded_tsv *utsv;
-  struct trace_state_variable *tsv;
   int highest;
 
   /* Most likely some numbers will have to be reassigned as part of
      the merge, so clear them all in anticipation.  */
-  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
-    tsv->number = 0;
+  for (trace_state_variable &tsv : tvariables)
+    tsv.number = 0;
 
   for (utsv = *uploaded_tsvs; utsv; utsv = utsv->next)
     {
-      tsv = find_matching_tsv (utsv);
+      struct trace_state_variable *tsv = find_matching_tsv (utsv);
       if (tsv)
        {
          if (info_verbose)
            printf_filtered (_("Assuming trace state variable $%s "
                               "is same as target's variable %d.\n"),
-                            tsv->name, utsv->number);
+                            tsv->name.c_str (), utsv->number);
        }
       else
        {
@@ -3380,7 +3231,7 @@ merge_uploaded_trace_state_variables (struct uploaded_tsv **uploaded_tsvs)
          if (info_verbose)
            printf_filtered (_("Created trace state variable "
                               "$%s for target's variable %d.\n"),
-                            tsv->name, utsv->number);
+                            tsv->name.c_str (), utsv->number);
        }
       /* Give precedence to numberings that come from the target.  */
       if (tsv)
@@ -3389,14 +3240,13 @@ merge_uploaded_trace_state_variables (struct uploaded_tsv **uploaded_tsvs)
 
   /* Renumber everything that didn't get a target-assigned number.  */
   highest = 0;
-  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
-    if (tsv->number > highest)
-      highest = tsv->number;
+  for (const trace_state_variable &tsv : tvariables)
+    highest = std::max (tsv.number, highest);
 
   ++highest;
-  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
-    if (tsv->number == 0)
-      tsv->number = highest++;
+  for (trace_state_variable &tsv : tvariables)
+    if (tsv.number == 0)
+      tsv.number = highest++;
 
   free_uploaded_tsvs (uploaded_tsvs);
 }
@@ -3596,7 +3446,7 @@ parse_tracepoint_definition (const char *line, struct uploaded_tp **utpp)
   int enabled, end;
   enum bptype type;
   const char *srctype;
-  char *cond, *buf;
+  char *buf;
   struct uploaded_tp *utp = NULL;
 
   p = line;
@@ -3609,13 +3459,14 @@ parse_tracepoint_definition (const char *line, struct uploaded_tp **utpp)
   p++;  /* skip a colon */
   if (piece == 'T')
     {
+      gdb::unique_xmalloc_ptr<char[]> cond;
+
       enabled = (*p++ == 'E');
       p++;  /* skip a colon */
       p = unpack_varlen_hex (p, &step);
       p++;  /* skip a colon */
       p = unpack_varlen_hex (p, &pass);
       type = bp_tracepoint;
-      cond = NULL;
       /* Thumb through optional fields.  */
       while (*p == ':')
        {
@@ -3636,8 +3487,8 @@ parse_tracepoint_definition (const char *line, struct uploaded_tp **utpp)
              p++;
              p = unpack_varlen_hex (p, &xlen);
              p++;  /* skip a comma */
-             cond = (char *) xmalloc (2 * xlen + 1);
-             strncpy (cond, p, 2 * xlen);
+             cond.reset ((char *) xmalloc (2 * xlen + 1));
+             strncpy (&cond[0], p, 2 * xlen);
              cond[2 * xlen] = '\0';
              p += 2 * xlen;
            }
@@ -3650,17 +3501,17 @@ parse_tracepoint_definition (const char *line, struct uploaded_tp **utpp)
       utp->enabled = enabled;
       utp->step = step;
       utp->pass = pass;
-      utp->cond = cond;
+      utp->cond = std::move (cond);
     }
   else if (piece == 'A')
     {
       utp = get_uploaded_tp (num, addr, utpp);
-      VEC_safe_push (char_ptr, utp->actions, xstrdup (p));
+      utp->actions.emplace_back (xstrdup (p));
     }
   else if (piece == 'S')
     {
       utp = get_uploaded_tp (num, addr, utpp);
-      VEC_safe_push (char_ptr, utp->step_actions, xstrdup (p));
+      utp->step_actions.emplace_back (xstrdup (p));
     }
   else if (piece == 'Z')
     {
@@ -3680,11 +3531,11 @@ parse_tracepoint_definition (const char *line, struct uploaded_tp **utpp)
       buf[end] = '\0';
 
       if (startswith (srctype, "at:"))
-       utp->at_string = xstrdup (buf);
+       utp->at_string.reset (xstrdup (buf));
       else if (startswith (srctype, "cond:"))
-       utp->cond_string = xstrdup (buf);
+       utp->cond_string.reset (xstrdup (buf));
       else if (startswith (srctype, "cmd:"))
-       VEC_safe_push (char_ptr, utp->cmd_strings, xstrdup (buf));
+       utp->cmd_strings.emplace_back (xstrdup (buf));
     }
   else if (piece == 'V')
     {
@@ -3730,21 +3581,6 @@ parse_tsv_definition (const char *line, struct uploaded_tsv **utsvp)
   utsv->name = xstrdup (buf);
 }
 
-void
-free_current_marker (void *arg)
-{
-  struct static_tracepoint_marker **marker_p
-    = (struct static_tracepoint_marker **) arg;
-
-  if (*marker_p != NULL)
-    {
-      release_static_tracepoint_marker (*marker_p);
-      xfree (*marker_p);
-    }
-  else
-    *marker_p = NULL;
-}
-
 /* Given a line of text defining a static tracepoint marker, parse it
    into a "static tracepoint marker" object.  Throws an error is
    parsing fails.  If PP is non-null, it points to one past the end of
@@ -3752,11 +3588,10 @@ free_current_marker (void *arg)
 
 void
 parse_static_tracepoint_marker_definition (const char *line, const char **pp,
-                                          struct static_tracepoint_marker *marker)
+                                          static_tracepoint_marker *marker)
 {
   const char *p, *endp;
   ULONGEST addr;
-  int end;
 
   p = line;
   p = unpack_varlen_hex (p, &addr);
@@ -3769,80 +3604,70 @@ parse_static_tracepoint_marker_definition (const char *line, const char **pp,
   if (endp == NULL)
     error (_("bad marker definition: %s"), line);
 
-  marker->str_id = (char *) xmalloc (endp - p + 1);
-  end = hex2bin (p, (gdb_byte *) marker->str_id, (endp - p + 1) / 2);
-  marker->str_id[end] = '\0';
+  marker->str_id = hex2str (p, (endp - p) / 2);
 
-  p += 2 * end;
-  p++;  /* skip a colon */
-
-  marker->extra = (char *) xmalloc (strlen (p) + 1);
-  end = hex2bin (p, (gdb_byte *) marker->extra, strlen (p) / 2);
-  marker->extra[end] = '\0';
+  p = endp;
+  p++; /* skip a colon */
 
-  if (pp)
-    *pp = p;
-}
+  /* This definition may be followed by another one, separated by a comma.  */
+  int hex_len;
+  endp = strchr (p, ',');
+  if (endp != nullptr)
+    hex_len = endp - p;
+  else
+    hex_len = strlen (p);
 
-/* Release a static tracepoint marker's contents.  Note that the
-   object itself isn't released here.  There objects are usually on
-   the stack.  */
+  marker->extra = hex2str (p, hex_len / 2);
 
-void
-release_static_tracepoint_marker (struct static_tracepoint_marker *marker)
-{
-  xfree (marker->str_id);
-  marker->str_id = NULL;
+  if (pp != nullptr)
+    *pp = p + hex_len;
 }
 
 /* Print MARKER to gdb_stdout.  */
 
 static void
 print_one_static_tracepoint_marker (int count,
-                                   struct static_tracepoint_marker *marker)
+                                   const static_tracepoint_marker &marker)
 {
   struct symbol *sym;
 
-  char wrap_indent[80];
-  char extra_field_indent[80];
   struct ui_out *uiout = current_uiout;
-  VEC(breakpoint_p) *tracepoints;
 
   symtab_and_line sal;
-  sal.pc = marker->address;
+  sal.pc = marker.address;
 
-  tracepoints = static_tracepoints_here (marker->address);
+  std::vector<breakpoint *> tracepoints
+    = static_tracepoints_here (marker.address);
 
   ui_out_emit_tuple tuple_emitter (uiout, "marker");
 
   /* A counter field to help readability.  This is not a stable
      identifier!  */
-  uiout->field_int ("count", count);
+  uiout->field_signed ("count", count);
 
-  uiout->field_string ("marker-id", marker->str_id);
+  uiout->field_string ("marker-id", marker.str_id);
 
   uiout->field_fmt ("enabled", "%c",
-                   !VEC_empty (breakpoint_p, tracepoints) ? 'y' : 'n');
+                   !tracepoints.empty () ? 'y' : 'n');
   uiout->spaces (2);
 
-  strcpy (wrap_indent, "                                   ");
-
-  if (gdbarch_addr_bit (marker->gdbarch) <= 32)
-    strcat (wrap_indent, "           ");
+  int wrap_indent = 35;
+  if (gdbarch_addr_bit (marker.gdbarch) <= 32)
+    wrap_indent += 11;
   else
-    strcat (wrap_indent, "                   ");
+    wrap_indent += 19;
 
-  strcpy (extra_field_indent, "         ");
+  const char *extra_field_indent = "         ";
 
-  uiout->field_core_addr ("addr", marker->gdbarch, marker->address);
+  uiout->field_core_addr ("addr", marker.gdbarch, marker.address);
 
-  sal = find_pc_line (marker->address, 0);
-  sym = find_pc_sect_function (marker->address, NULL);
+  sal = find_pc_line (marker.address, 0);
+  sym = find_pc_sect_function (marker.address, NULL);
   if (sym)
     {
       uiout->text ("in ");
-      uiout->field_string ("func",
-                          SYMBOL_PRINT_NAME (sym));
+      uiout->field_string ("func", sym->print_name (),
+                          function_name_style.style ());
       uiout->wrap_hint (wrap_indent);
       uiout->text (" at ");
     }
@@ -3852,7 +3677,8 @@ print_one_static_tracepoint_marker (int count,
   if (sal.symtab != NULL)
     {
       uiout->field_string ("file",
-                          symtab_to_filename_for_display (sal.symtab));
+                          symtab_to_filename_for_display (sal.symtab),
+                          file_name_style.style ());
       uiout->text (":");
 
       if (uiout->is_mi_like_p ())
@@ -3864,7 +3690,7 @@ print_one_static_tracepoint_marker (int count,
       else
        uiout->field_skip ("fullname");
 
-      uiout->field_int ("line", sal.line);
+      uiout->field_signed ("line", sal.line);
     }
   else
     {
@@ -3875,45 +3701,40 @@ print_one_static_tracepoint_marker (int count,
   uiout->text ("\n");
   uiout->text (extra_field_indent);
   uiout->text (_("Data: \""));
-  uiout->field_string ("extra-data", marker->extra);
+  uiout->field_string ("extra-data", marker.extra);
   uiout->text ("\"\n");
 
-  if (!VEC_empty (breakpoint_p, tracepoints))
+  if (!tracepoints.empty ())
     {
       int ix;
-      struct breakpoint *b;
 
       {
-       ui_out_emit_tuple tuple_emitter (uiout, "tracepoints-at");
+       ui_out_emit_tuple inner_tuple_emitter (uiout, "tracepoints-at");
 
        uiout->text (extra_field_indent);
        uiout->text (_("Probed by static tracepoints: "));
-       for (ix = 0; VEC_iterate(breakpoint_p, tracepoints, ix, b); ix++)
+       for (ix = 0; ix < tracepoints.size (); ix++)
          {
            if (ix > 0)
              uiout->text (", ");
            uiout->text ("#");
-           uiout->field_int ("tracepoint-id", b->number);
+           uiout->field_signed ("tracepoint-id", tracepoints[ix]->number);
          }
       }
 
       if (uiout->is_mi_like_p ())
-       uiout->field_int ("number-of-tracepoints",
-                         VEC_length(breakpoint_p, tracepoints));
+       uiout->field_signed ("number-of-tracepoints", tracepoints.size ());
       else
        uiout->text ("\n");
     }
-  VEC_free (breakpoint_p, tracepoints);
 }
 
 static void
-info_static_tracepoint_markers_command (char *arg, int from_tty)
+info_static_tracepoint_markers_command (const char *arg, int from_tty)
 {
-  VEC(static_tracepoint_marker_p) *markers;
-  struct cleanup *old_chain;
-  struct static_tracepoint_marker *marker;
   struct ui_out *uiout = current_uiout;
-  int i;
+  std::vector<static_tracepoint_marker> markers
+    = target_static_tracepoint_markers_by_strid (NULL);
 
   /* We don't have to check target_can_use_agent and agent's capability on
      static tracepoint here, in order to be compatible with older GDBserver.
@@ -3937,19 +3758,8 @@ info_static_tracepoint_markers_command (char *arg, int from_tty)
 
   uiout->table_body ();
 
-  markers = target_static_tracepoint_markers_by_strid (NULL);
-  old_chain = make_cleanup (VEC_cleanup (static_tracepoint_marker_p), &markers);
-
-  for (i = 0;
-       VEC_iterate (static_tracepoint_marker_p,
-                   markers, i, marker);
-       i++)
-    {
-      print_one_static_tracepoint_marker (i + 1, marker);
-      release_static_tracepoint_marker (marker);
-    }
-
-  do_cleanups (old_chain);
+  for (int i = 0; i < markers.size (); i++)
+    print_one_static_tracepoint_marker (i + 1, markers[i]);
 }
 
 /* The $_sdata convenience variable is a bit special.  We don't know
@@ -3966,23 +3776,20 @@ static struct value *
 sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var,
                  void *ignore)
 {
-  LONGEST size;
-  gdb_byte *buf;
-
   /* We need to read the whole object before we know its size.  */
-  size = target_read_alloc (&current_target,
-                           TARGET_OBJECT_STATIC_TRACE_DATA,
-                           NULL, &buf);
-  if (size >= 0)
+  gdb::optional<gdb::byte_vector> buf
+    = target_read_alloc (current_inferior ()->top_target (),
+                        TARGET_OBJECT_STATIC_TRACE_DATA,
+                        NULL);
+  if (buf)
     {
       struct value *v;
       struct type *type;
 
       type = init_vector_type (builtin_type (gdbarch)->builtin_true_char,
-                              size);
+                              buf->size ());
       v = allocate_value (type);
-      memcpy (value_contents_raw (v), buf, size);
-      xfree (buf);
+      memcpy (value_contents_raw (v).data (), buf->data (), buf->size ());
       return v;
     }
   else
@@ -3991,7 +3798,7 @@ sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var,
 
 #if !defined(HAVE_LIBEXPAT)
 
-struct traceframe_info *
+struct std::unique_ptr<traceframe_info>
 parse_traceframe_info (const char *tframe_info)
 {
   static int have_warned;
@@ -4015,19 +3822,18 @@ parse_traceframe_info (const char *tframe_info)
 static void
 traceframe_info_start_memory (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 traceframe_info *info = (struct traceframe_info *) user_data;
-  struct mem_range *r = VEC_safe_push (mem_range_s, info->memory, NULL);
   ULONGEST *start_p, *length_p;
 
   start_p
-    = (ULONGEST *) xml_find_attribute (attributes, "start")->value;
+    = (ULONGEST *) xml_find_attribute (attributes, "start")->value.get ();
   length_p
-    = (ULONGEST *) xml_find_attribute (attributes, "length")->value;
+    = (ULONGEST *) xml_find_attribute (attributes, "length")->value.get ();
 
-  r->start = *start_p;
-  r->length = *length_p;
+  info->memory.emplace_back (*start_p, *length_p);
 }
 
 /* Handle the start of a <tvar> element.  */
@@ -4036,24 +3842,14 @@ static void
 traceframe_info_start_tvar (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 traceframe_info *info = (struct traceframe_info *) user_data;
   const char *id_attrib
-    = (const char *) xml_find_attribute (attributes, "id")->value;
+    = (const char *) xml_find_attribute (attributes, "id")->value.get ();
   int id = gdb_xml_parse_ulongest (parser, id_attrib);
 
-  VEC_safe_push (int, info->tvars, id);
-}
-
-/* Discard the constructed trace frame info (if an error occurs).  */
-
-static void
-free_result (void *p)
-{
-  struct traceframe_info *result = (struct traceframe_info *) p;
-
-  free_traceframe_info (result);
+  info->tvars.push_back (id);
 }
 
 /* The allowed elements and attributes for an XML memory map.  */
@@ -4087,26 +3883,16 @@ static const struct gdb_xml_element traceframe_info_elements[] = {
 
 /* Parse a traceframe-info XML document.  */
 
-struct traceframe_info *
+traceframe_info_up
 parse_traceframe_info (const char *tframe_info)
 {
-  struct traceframe_info *result;
-  struct cleanup *back_to;
-
-  result = XCNEW (struct traceframe_info);
-  back_to = make_cleanup (free_result, result);
+  traceframe_info_up result (new traceframe_info);
 
   if (gdb_xml_parse_quick (_("trace frame info"),
                           "traceframe-info.dtd", traceframe_info_elements,
-                          tframe_info, result) == 0)
-    {
-      /* Parsed successfully, keep the result.  */
-      discard_cleanups (back_to);
-
-      return result;
-    }
+                          tframe_info, result.get ()) == 0)
+    return result;
 
-  do_cleanups (back_to);
   return NULL;
 }
 
@@ -4119,10 +3905,10 @@ parse_traceframe_info (const char *tframe_info)
 struct traceframe_info *
 get_traceframe_info (void)
 {
-  if (traceframe_info == NULL)
-    traceframe_info = target_traceframe_info ();
+  if (current_traceframe_info == NULL)
+    current_traceframe_info = target_traceframe_info ();
 
-  return traceframe_info;
+  return current_traceframe_info.get ();
 }
 
 /* If the target supports the query, return in RESULT the set of
@@ -4132,37 +3918,33 @@ get_traceframe_info (void)
    undefined.  */
 
 int
-traceframe_available_memory (VEC(mem_range_s) **result,
+traceframe_available_memory (std::vector<mem_range> *result,
                             CORE_ADDR memaddr, ULONGEST len)
 {
   struct traceframe_info *info = get_traceframe_info ();
 
   if (info != NULL)
     {
-      struct mem_range *r;
-      int i;
+      result->clear ();
 
-      *result = NULL;
-
-      for (i = 0; VEC_iterate (mem_range_s, info->memory, i, r); i++)
-       if (mem_ranges_overlap (r->start, r->length, memaddr, len))
+      for (mem_range &r : info->memory)
+       if (mem_ranges_overlap (r.start, r.length, memaddr, len))
          {
            ULONGEST lo1, hi1, lo2, hi2;
-           struct mem_range *nr;
 
            lo1 = memaddr;
            hi1 = memaddr + len;
 
-           lo2 = r->start;
-           hi2 = r->start + r->length;
+           lo2 = r.start;
+           hi2 = r.start + r.length;
 
-           nr = VEC_safe_push (mem_range_s, *result, NULL);
+           CORE_ADDR start = std::max (lo1, lo2);
+           int length = std::min (hi1, hi2) - start;
 
-           nr->start = std::max (lo1, lo2);
-           nr->length = std::min (hi1, hi2) - nr->start;
+           result->emplace_back (start, length);
          }
 
-      normalize_mem_ranges (*result);
+      normalize_mem_ranges (result);
       return 1;
     }
 
@@ -4174,13 +3956,16 @@ traceframe_available_memory (VEC(mem_range_s) **result,
 static const struct internalvar_funcs sdata_funcs =
 {
   sdata_make_value,
-  NULL,
   NULL
 };
 
+/* See tracepoint.h.  */
+cmd_list_element *while_stepping_cmd_element = nullptr;
+
 /* module initialization */
+void _initialize_tracepoint ();
 void
-_initialize_tracepoint (void)
+_initialize_tracepoint ()
 {
   struct cmd_list_element *c;
 
@@ -4194,7 +3979,7 @@ _initialize_tracepoint (void)
   tracepoint_number = -1;
 
   add_info ("scope", info_scope_command,
-           _("List the variables local to a scope"));
+           _("List the variables local to a scope."));
 
   add_cmd ("tracepoints", class_trace,
           _("Tracing of program execution without stopping the program."),
@@ -4217,27 +4002,25 @@ If no arguments are supplied, delete all variables."), &deletelist);
   /* FIXME add a trace variable completer.  */
 
   add_info ("tvariables", info_tvariables_command, _("\
-Status of trace state variables and their values.\n\
-"));
+Status of trace state variables and their values."));
 
   add_info ("static-tracepoint-markers",
            info_static_tracepoint_markers_command, _("\
-List target static tracepoints markers.\n\
-"));
+List target static tracepoints markers."));
 
   add_prefix_cmd ("tfind", class_trace, tfind_command, _("\
-Select a trace frame;\n\
+Select a trace frame.\n\
 No argument means forward by one frame; '-' means backward by one frame."),
-                 &tfindlist, "tfind ", 1, &cmdlist);
+                 &tfindlist, 1, &cmdlist);
 
   add_cmd ("outside", class_trace, tfind_outside_command, _("\
 Select a trace frame whose PC is outside the given range (exclusive).\n\
-Usage: tfind outside addr1, addr2"),
+Usage: tfind outside ADDR1, ADDR2"),
           &tfindlist);
 
   add_cmd ("range", class_trace, tfind_range_command, _("\
 Select a trace frame whose PC is in the given range (inclusive).\n\
-Usage: tfind range addr1,addr2"),
+Usage: tfind range ADDR1, ADDR2"),
           &tfindlist);
 
   add_cmd ("line", class_trace, tfind_line_command, _("\
@@ -4257,11 +4040,11 @@ Select a trace frame by PC.\n\
 Default is the current PC, or the PC of the current trace frame."),
           &tfindlist);
 
-  add_cmd ("end", class_trace, tfind_end_command, _("\
-De-select any trace frame and resume 'live' debugging."),
-          &tfindlist);
+  cmd_list_element *tfind_end_cmd
+    = add_cmd ("end", class_trace, tfind_end_command, _("\
+De-select any trace frame and resume 'live' debugging."), &tfindlist);
 
-  add_alias_cmd ("none", "end", class_trace, 0, &tfindlist);
+  add_alias_cmd ("none", tfind_end_cmd, class_trace, 0, &tfindlist);
 
   add_cmd ("start", class_trace, tfind_start_command,
           _("Select the first trace frame in the trace buffer."),
@@ -4272,13 +4055,13 @@ De-select any trace frame and resume 'live' debugging."),
 
   add_com ("tstop", class_trace, tstop_command, _("\
 Stop trace data collection.\n\
-Usage: tstop [ <notes> ... ]\n\
+Usage: tstop [NOTES]...\n\
 Any arguments supplied are recorded with the trace as a stop reason and\n\
 reported by tstatus (if the target supports trace notes)."));
 
   add_com ("tstart", class_trace, tstart_command, _("\
 Start trace data collection.\n\
-Usage: tstart [ <notes> ... ]\n\
+Usage: tstart [NOTES]...\n\
 Any arguments supplied are recorded with the trace as a note and\n\
 reported by tstatus (if the target supports trace notes)."));
 
@@ -4289,7 +4072,8 @@ Entering \"end\" on a line by itself is the normal way to terminate\n\
 such a list.\n\n\
 Note: the \"end\" command cannot be used at the gdb prompt."));
 
-  add_com ("while-stepping", class_trace, while_stepping_pseudocommand, _("\
+  while_stepping_cmd_element = add_com ("while-stepping", class_trace,
+                                       while_stepping_pseudocommand, _("\
 Specify single-stepping behavior at a tracepoint.\n\
 Argument is number of instructions to trace in single-step mode\n\
 following the tracepoint.  This command is normally followed by\n\
@@ -4297,8 +4081,8 @@ one or more \"collect\" commands, to specify what to collect\n\
 while single-stepping.\n\n\
 Note: this command can only be used in a tracepoint \"actions\" list."));
 
-  add_com_alias ("ws", "while-stepping", class_alias, 0);
-  add_com_alias ("stepping", "while-stepping", class_alias, 0);
+  add_com_alias ("ws", while_stepping_cmd_element, class_trace, 0);
+  add_com_alias ("stepping", while_stepping_cmd_element, class_trace, 0);
 
   add_com ("collect", class_trace, collect_pseudocommand, _("\
 Specify one or more data items to be collected at a tracepoint.\n\
@@ -4323,11 +4107,10 @@ Tracepoint actions may include collecting of specified data,\n\
 single-stepping, or enabling/disabling other tracepoints,\n\
 depending on target's capabilities."));
 
-  default_collect = xstrdup ("");
   add_setshow_string_cmd ("default-collect", class_trace,
                          &default_collect, _("\
-Set the list of expressions to collect by default"), _("\
-Show the list of expressions to collect by default"), NULL,
+Set the list of expressions to collect by default."), _("\
+Show the list of expressions to collect by default."), NULL,
                          NULL, NULL,
                          &setlist, &showlist);
 
@@ -4367,22 +4150,22 @@ disables any attempt to set the buffer size and lets the target choose."),
 
   add_setshow_string_cmd ("trace-user", class_trace,
                          &trace_user, _("\
-Set the user name to use for current and future trace runs"), _("\
-Show the user name to use for current and future trace runs"), NULL,
+Set the user name to use for current and future trace runs."), _("\
+Show the user name to use for current and future trace runs."), NULL,
                          set_trace_user, NULL,
                          &setlist, &showlist);
 
   add_setshow_string_cmd ("trace-notes", class_trace,
                          &trace_notes, _("\
-Set notes string to use for current and future trace runs"), _("\
-Show the notes string to use for current and future trace runs"), NULL,
+Set notes string to use for current and future trace runs."), _("\
+Show the notes string to use for current and future trace runs."), NULL,
                          set_trace_notes, NULL,
                          &setlist, &showlist);
 
   add_setshow_string_cmd ("trace-stop-notes", class_trace,
                          &trace_stop_notes, _("\
-Set notes string to use for future tstop commands"), _("\
-Show the notes string to use for future tstop commands"), NULL,
+Set notes string to use for future tstop commands."), _("\
+Show the notes string to use for future tstop commands."), NULL,
                          set_trace_stop_notes, NULL,
                          &setlist, &showlist);
 }