gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / tracepoint.c
index 6ca66e7c8d1849992d03c604d4a2e6b68b164d14..f4a208f616926bb6728fb15442e8495e96f39787 100644 (file)
@@ -1,6 +1,6 @@
 /* Tracing functionality for remote targets in custom GDB protocol
 
-   Copyright (C) 1997-2015 Free Software Foundation, Inc.
+   Copyright (C) 1997-2020 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"
-
-/* readline include files */
-#include "readline/readline.h"
-#include "readline/history.h"
-
-/* readline defines this.  */
-#undef savestring
+#include <algorithm>
+#include "cli/cli-style.h"
 
 #include <unistd.h>
 
@@ -113,10 +107,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.  */
 
@@ -132,20 +123,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 = "";
+char *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.  */
@@ -164,31 +155,12 @@ char *trace_notes = NULL;
 
 char *trace_stop_notes = NULL;
 
-/* ======= Important command functions: ======= */
-static void trace_actions_command (char *, int);
-static void trace_start_command (char *, int);
-static void trace_stop_command (char *, int);
-static void trace_status_command (char *, int);
-static void trace_find_command (char *, int);
-static void trace_find_pc_command (char *, int);
-static void trace_find_tracepoint_command (char *, int);
-static void trace_find_line_command (char *, int);
-static void trace_find_range_command (char *, int);
-static void trace_find_outside_command (char *, int);
-static void trace_dump_command (char *, int);
-
 /* support routines */
 
 struct collection_list;
-static void add_aexpr (struct collection_list *, struct agent_expr *);
 static char *mem2hex (gdb_byte *, char *, int);
-static void add_register (struct collection_list *collection,
-                         unsigned int regno);
-
-static struct command_line *
-  all_tracepoint_actions_and_cleanup (struct breakpoint *t);
 
-extern void _initialize_tracepoint (void);
+static counted_command_line all_tracepoint_actions (struct breakpoint *);
 
 static struct trace_status trace_status;
 
@@ -208,28 +180,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.  */
@@ -256,7 +213,7 @@ set_traceframe_context (struct frame_info *trace_frame)
 {
   CORE_ADDR trace_pc;
   struct symbol *traceframe_fun;
-  struct symtab_and_line traceframe_sal;
+  symtab_and_line traceframe_sal;
 
   /* Save as globals for internal use.  */
   if (trace_frame != NULL
@@ -272,7 +229,6 @@ set_traceframe_context (struct frame_info *trace_frame)
     }
   else
     {
-      init_sal (&traceframe_sal);
       traceframe_fun = NULL;
       set_internalvar_integer (lookup_internalvar ("trace_line"), -1);
     }
@@ -280,11 +236,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.  */
@@ -300,12 +256,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.  */
@@ -313,12 +265,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;
 }
@@ -329,12 +278,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;
 }
@@ -342,17 +288,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;
       }
 
@@ -387,12 +327,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 ]"));
@@ -403,150 +342,133 @@ 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
-delete_trace_variable_command (char *args, int from_tty)
+delete_trace_variable_command (const char *args, int from_tty)
 {
-  int ix;
-  char **argv;
-  struct cleanup *back_to;
-
   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;
     }
 
-  argv = gdb_buildargv (args);
-  back_to = make_cleanup_freeargv (argv);
+  gdb_argv argv (args);
 
-  for (ix = 0; argv[ix] != NULL; ix++)
+  for (char *arg : argv)
     {
-      if (*argv[ix] == '$')
-       delete_trace_state_variable (argv[ix] + 1);
+      if (*arg == '$')
+       delete_trace_state_variable (arg + 1);
       else
-       warning (_("Name \"%s\" not prefixed with '$', ignoring"), argv[ix]);
+       warning (_("Name \"%s\" not prefixed with '$', ignoring"), arg);
     }
 
-  do_cleanups (back_to);
-
   dont_repeat ();
 }
 
 void
 tvariables_info_1 (void)
 {
-  struct trace_state_variable *tsv;
-  int ix;
-  int count = 0;
-  struct cleanup *back_to;
   struct ui_out *uiout = current_uiout;
 
-  if (VEC_length (tsv_s, tvariables) == 0 && !ui_out_is_mi_like_p (uiout))
-    {
-      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);
 
-  back_to = make_cleanup_ui_out_table_begin_end (uiout, 3,
-                                                 count, "trace-variables");
-  ui_out_table_header (uiout, 15, ui_left, "name", "Name");
-  ui_out_table_header (uiout, 11, ui_left, "initial", "Initial");
-  ui_out_table_header (uiout, 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");
 
-  ui_out_table_body (uiout);
+    uiout->table_body ();
 
-  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
-    {
-      struct cleanup *back_to2;
-      char *c;
-      char *name;
-
-      back_to2 = make_cleanup_ui_out_tuple_begin_end (uiout, "variable");
-
-      name = concat ("$", tsv->name, (char *) NULL);
-      make_cleanup (xfree, name);
-      ui_out_field_string (uiout, "name", name);
-      ui_out_field_string (uiout, "initial", plongest (tsv->initial_value));
-
-      if (tsv->value_known)
-        c = plongest (tsv->value);
-      else if (ui_out_is_mi_like_p (uiout))
-        /* 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)
-        ui_out_field_string (uiout, "current", c);
-      ui_out_text (uiout, "\n");
-
-      do_cleanups (back_to2);
-    }
+    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");
+      }
+  }
 
-  do_cleanups (back_to);
+  if (tvariables.empty ())
+    uiout->text (_("No trace state variables.\n"));
 }
 
 /* List all the trace state variables.  */
 
 static void
-tvariables_info (char *args, int from_tty)
+info_tvariables_command (const char *args, int from_tty)
 {
   tvariables_info_1 ();
 }
@@ -556,14 +478,11 @@ tvariables_info (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");
     }
 }
@@ -580,25 +499,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."));
 }
@@ -640,30 +559,31 @@ decode_agent_options (const char *exp, int *trace_string)
   else
     error (_("Undefined collection format \"%c\"."), *exp);
 
-  exp = skip_spaces_const (exp);
+  exp = skip_spaces (exp);
 
   return exp;
 }
 
 /* Enter a list of actions for a tracepoint.  */
 static void
-trace_actions_command (char *args, int from_tty)
+actions_command (const char *args, int from_tty)
 {
   struct tracepoint *t;
-  struct command_line *l;
 
   t = get_tracepoint_by_number (&args, NULL);
   if (t)
     {
-      char *tmpbuf =
-       xstrprintf ("Enter actions for tracepoint %d, one per line.",
-                   t->base.number);
-      struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
-
-      l = read_command_lines (tmpbuf, from_tty, 1,
-                             check_tracepoint_command, t);
-      do_cleanups (cleanups);
-      breakpoint_set_commands (&t->base, l);
+      std::string tmpbuf =
+       string_printf ("Enter actions for tracepoint %d, one per line.",
+                      t->number);
+
+      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 */
 }
@@ -695,24 +615,34 @@ 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 expression *exp = NULL;
-  struct cleanup *old_chain = NULL;
   const char *tmp_p;
   const char *p;
   struct bp_location *loc;
-  struct agent_expr *aexpr;
   struct tracepoint *t = (struct tracepoint *) b;
 
   /* If EOF is typed, *line is NULL.  */
   if (line == NULL)
     return;
 
-  p = skip_spaces_const (line);
+  p = skip_spaces (line);
 
   /* Symbol lookup etc.  */
   if (*p == '\0')      /* empty line: just prompt for another line.  */
@@ -735,7 +665,7 @@ validate_actionline (const char *line, struct breakpoint *b)
       do
        {                       /* Repeat over a comma-separated list.  */
          QUIT;                 /* Allow user to bail out with ^C.  */
-         p = skip_spaces_const (p);
+         p = skip_spaces (p);
 
          if (*p == '$')        /* Look for special pseudo-symbols.  */
            {
@@ -751,12 +681,11 @@ 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->base.loc; loc; loc = loc->next)
+         for (loc = t->loc; loc; loc = loc->next)
            {
              p = tmp_p;
-             exp = parse_exp_1 (&p, loc->address,
-                                block_for_pc (loc->address), 1);
-             old_chain = make_cleanup (free_current_contents, &exp);
+             expression_up exp = parse_exp_1 (&p, loc->address,
+                                              block_for_pc (loc->address), 1);
 
              if (exp->elts[0].opcode == OP_VAR_VALUE)
                {
@@ -764,7 +693,7 @@ validate_actionline (const char *line, struct breakpoint *b)
                    {
                      error (_("constant `%s' (value %s) "
                               "will not be collected."),
-                            SYMBOL_PRINT_NAME (exp->elts[2].symbol),
+                            exp->elts[2].symbol->print_name (),
                             plongest (SYMBOL_VALUE (exp->elts[2].symbol)));
                    }
                  else if (SYMBOL_CLASS (exp->elts[2].symbol)
@@ -772,24 +701,18 @@ validate_actionline (const char *line, struct breakpoint *b)
                    {
                      error (_("`%s' is optimized away "
                               "and cannot be collected."),
-                            SYMBOL_PRINT_NAME (exp->elts[2].symbol));
+                            exp->elts[2].symbol->print_name ());
                    }
                }
 
              /* We have something to collect, make sure that the expr to
                 bytecode translator can handle it and that it's not too
                 long.  */
-             aexpr = gen_trace_for_expr (loc->address, exp, trace_string);
-             make_cleanup_free_agent_expr (aexpr);
-
-             if (aexpr->len > MAX_AGENT_EXPR_LEN)
-               error (_("Expression is too complicated."));
-
-             ax_reqs (aexpr);
-
-             report_agent_reqs_errors (aexpr);
+             agent_expr_up aexpr = gen_trace_for_expr (loc->address,
+                                                       exp.get (),
+                                                       trace_string);
 
-             do_cleanups (old_chain);
+             finalize_tracepoint_aexpr (aexpr.get ());
            }
        }
       while (p && *p++ == ',');
@@ -800,31 +723,23 @@ validate_actionline (const char *line, struct breakpoint *b)
       do
        {                       /* Repeat over a comma-separated list.  */
          QUIT;                 /* Allow user to bail out with ^C.  */
-         p = skip_spaces_const (p);
+         p = skip_spaces (p);
 
          tmp_p = p;
-         for (loc = t->base.loc; loc; loc = loc->next)
+         for (loc = t->loc; loc; loc = loc->next)
            {
              p = tmp_p;
 
              /* Only expressions are allowed for this action.  */
-             exp = parse_exp_1 (&p, loc->address,
-                                block_for_pc (loc->address), 1);
-             old_chain = make_cleanup (free_current_contents, &exp);
+             expression_up exp = parse_exp_1 (&p, loc->address,
+                                              block_for_pc (loc->address), 1);
 
              /* We have something to evaluate, make sure that the expr to
                 bytecode translator can handle it and that it's not too
                 long.  */
-             aexpr = gen_eval_for_expr (loc->address, exp);
-             make_cleanup_free_agent_expr (aexpr);
+             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);
-             report_agent_reqs_errors (aexpr);
-
-             do_cleanups (old_chain);
+             finalize_tracepoint_aexpr (aexpr.get ());
            }
        }
       while (p && *p++ == ',');
@@ -834,7 +749,7 @@ validate_actionline (const char *line, struct breakpoint *b)
     {
       char *endp;
 
-      p = skip_spaces_const (p);
+      p = skip_spaces (p);
       t->step_count = strtol (p, &endp, 0);
       if (endp == p || t->step_count == 0)
        error (_("while-stepping step count `%s' is malformed."), line);
@@ -854,117 +769,152 @@ enum {
 
 /* MEMRANGE functions: */
 
-static int memrange_cmp (const void *, const void *);
+/* Compare memranges for std::sort.  */
 
-/* Compare memranges for qsort.  */
-static int
-memrange_cmp (const void *va, const void *vb)
+static bool
+memrange_comp (const memrange &a, const memrange &b)
 {
-  const struct memrange *a = (const struct memrange *) va;
-  const struct memrange *b = (const struct memrange *) vb;
-
-  if (a->type < b->type)
-    return -1;
-  if (a->type > b->type)
-    return 1;
-  if (a->type == memrange_absolute)
-    {
-      if ((bfd_vma) a->start < (bfd_vma) b->start)
-       return -1;
-      if ((bfd_vma) a->start > (bfd_vma) b->start)
-       return 1;
-    }
-  else
+  if (a.type == b.type)
     {
-      if (a->start < b->start)
-       return -1;
-      if (a->start > b->start)
-       return 1;
+      if (a.type == memrange_absolute)
+       return (bfd_vma) a.start < (bfd_vma) b.start;
+      else
+       return a.start < b.start;
     }
-  return 0;
+
+  return a.type < b.type;
 }
 
-/* Sort the memrange list using qsort, and merge adjacent memranges.  */
+/* Sort the memrange list using std::sort, and merge adjacent memranges.  */
+
 static void
-memrange_sortmerge (struct collection_list *memranges)
+memrange_sortmerge (std::vector<memrange> &memranges)
 {
-  int a, b;
-
-  qsort (memranges->list, memranges->next_memrange,
-        sizeof (struct memrange), memrange_cmp);
-  if (memranges->next_memrange > 0)
+  if (!memranges.empty ())
     {
-      for (a = 0, b = 1; b < memranges->next_memrange; b++)
+      int a, b;
+
+      std::sort (memranges.begin (), memranges.end (), memrange_comp);
+
+      for (a = 0, b = 1; b < memranges.size (); b++)
        {
          /* If memrange b overlaps or is adjacent to memrange a,
             merge them.  */
-         if (memranges->list[a].type == memranges->list[b].type
-             && memranges->list[b].start <= memranges->list[a].end)
+         if (memranges[a].type == memranges[b].type
+             && memranges[b].start <= memranges[a].end)
            {
-             if (memranges->list[b].end > memranges->list[a].end)
-               memranges->list[a].end = memranges->list[b].end;
+             if (memranges[b].end > memranges[a].end)
+               memranges[a].end = memranges[b].end;
              continue;         /* next b, same a */
            }
          a++;                  /* next a */
          if (a != b)
-           memcpy (&memranges->list[a], &memranges->list[b],
-                   sizeof (struct memrange));
+           memranges[a] = memranges[b];
        }
-      memranges->next_memrange = a + 1;
+      memranges.resize (a + 1);
     }
 }
 
-/* Add a register to a collection list.  */
-static void
-add_register (struct collection_list *collection, unsigned int regno)
+/* Add remote register number REGNO to the collection list mask.  */
+
+void
+collection_list::add_remote_register (unsigned int regno)
 {
   if (info_verbose)
     printf_filtered ("collect register %d\n", regno);
-  if (regno >= (8 * sizeof (collection->regs_mask)))
-    error (_("Internal: register number %d too large for tracepoint"),
-          regno);
-  collection->regs_mask[regno / 8] |= 1 << (regno % 8);
+
+  m_regs_mask.at (regno / 8) |= 1 << (regno % 8);
 }
 
-/* Add a memrange to a collection list.  */
-static void
-add_memrange (struct collection_list *memranges, 
-             int type, bfd_signed_vma base,
-             unsigned long len)
+/* 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 (info_verbose)
+  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
     {
-      printf_filtered ("(%d,", type);
-      printf_vma (base);
-      printf_filtered (",%ld)\n", len);
+      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.  */
+
+void
+collection_list::add_memrange (struct gdbarch *gdbarch,
+                              int type, bfd_signed_vma base,
+                              unsigned long len, CORE_ADDR scope)
+{
+  if (info_verbose)
+    printf_filtered ("(%d,%s,%ld)\n", type, paddress (gdbarch, base), len);
 
   /* type: memrange_absolute == memory, other n == basereg */
-  memranges->list[memranges->next_memrange].type = type;
   /* base: addr if memory, offset if reg relative.  */
-  memranges->list[memranges->next_memrange].start = base;
   /* len: we actually save end (base + len) for convenience */
-  memranges->list[memranges->next_memrange].end = base + len;
-  memranges->next_memrange++;
-  if (memranges->next_memrange >= memranges->listsize)
-    {
-      memranges->listsize *= 2;
-      memranges->list = (struct memrange *) xrealloc (memranges->list,
-                                                     memranges->listsize);
-    }
+  m_memranges.emplace_back (type, base, base + len);
 
   if (type != memrange_absolute)    /* Better collect the base register!  */
-    add_register (memranges, type);
+    add_local_register (gdbarch, type, scope);
 }
 
 /* Add a symbol to a collection list.  */
-static void
-collect_symbol (struct collection_list *collect, 
-               struct symbol *sym,
-               struct gdbarch *gdbarch,
-               long frame_regno, long frame_offset,
-               CORE_ADDR scope,
-               int trace_string)
+
+void
+collection_list::collect_symbol (struct symbol *sym,
+                                struct gdbarch *gdbarch,
+                                long frame_regno, long frame_offset,
+                                CORE_ADDR scope,
+                                int trace_string)
 {
   unsigned long len;
   unsigned int reg;
@@ -976,83 +926,74 @@ collect_symbol (struct collection_list *collect,
     {
     default:
       printf_filtered ("%s: don't know symbol class %d\n",
-                      SYMBOL_PRINT_NAME (sym),
-                      SYMBOL_CLASS (sym));
+                      sym->print_name (), SYMBOL_CLASS (sym));
       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)
        {
-         char tmp[40];
-
-         sprintf_vma (tmp, offset);
          printf_filtered ("LOC_STATIC %s: collect %ld bytes at %s.\n",
-                          SYMBOL_PRINT_NAME (sym), len,
-                          tmp /* address */);
+                          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 (SYMBOL_TYPE (sym)->code () == TYPE_CODE_STRUCT)
        treat_as_expr = 1;
       else
-       add_memrange (collect, 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 (collect, 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 (SYMBOL_TYPE (sym)->code () == TYPE_CODE_FLT &&
          len > register_size (gdbarch, reg))
-       add_register (collect, 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;
       offset = frame_offset + SYMBOL_VALUE (sym);
       if (info_verbose)
        {
-         printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset ",
-                          SYMBOL_PRINT_NAME (sym), len);
-         printf_vma (offset);
-         printf_filtered (" from frame ptr reg %d\n", reg);
+         printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset %s"
+                          " from frame ptr reg %d\n", sym->print_name (), len,
+                          paddress (gdbarch, offset), reg);
        }
-      add_memrange (collect, reg, offset, len);
+      add_memrange (gdbarch, reg, offset, len, scope);
       break;
     case LOC_REGPARM_ADDR:
       reg = SYMBOL_VALUE (sym);
       offset = 0;
       if (info_verbose)
        {
-         printf_filtered ("LOC_REGPARM_ADDR %s: Collect %ld bytes at offset ",
-                          SYMBOL_PRINT_NAME (sym), len);
-         printf_vma (offset);
-         printf_filtered (" from reg %d\n", reg);
+         printf_filtered ("LOC_REGPARM_ADDR %s: Collect %ld bytes at offset %s"
+                          " from reg %d\n", sym->print_name (), len,
+                          paddress (gdbarch, offset), reg);
        }
-      add_memrange (collect, reg, offset, len);
+      add_memrange (gdbarch, reg, offset, len, scope);
       break;
     case LOC_LOCAL:
       reg = frame_regno;
       offset = frame_offset + SYMBOL_VALUE (sym);
       if (info_verbose)
        {
-         printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset ",
-                          SYMBOL_PRINT_NAME (sym), len);
-         printf_vma (offset);
-         printf_filtered (" from frame ptr reg %d\n", reg);
+         printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset %s"
+                          " from frame ptr reg %d\n", sym->print_name (), len,
+                          paddress (gdbarch, offset), reg);
        }
-      add_memrange (collect, reg, offset, len);
+      add_memrange (gdbarch, reg, offset, len, scope);
       break;
 
     case LOC_UNRESOLVED:
@@ -1061,7 +1002,7 @@ collect_symbol (struct collection_list *collect,
 
     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:
@@ -1072,10 +1013,8 @@ collect_symbol (struct collection_list *collect,
   /* Expressions are the most general case.  */
   if (treat_as_expr)
     {
-      struct agent_expr *aexpr;
-      struct cleanup *old_chain1 = NULL;
-
-      aexpr = gen_trace_for_var (scope, gdbarch, sym, trace_string);
+      agent_expr_up aexpr = gen_trace_for_var (scope, gdbarch,
+                                              sym, trace_string);
 
       /* It can happen that the symbol is recorded as a computed
         location, but it's been optimized away and doesn't actually
@@ -1083,37 +1022,16 @@ collect_symbol (struct collection_list *collect,
       if (!aexpr)
        {
          printf_filtered ("%s has been optimized out of existence.\n",
-                          SYMBOL_PRINT_NAME (sym));
+                          sym->print_name ());
          return;
        }
 
-      old_chain1 = make_cleanup_free_agent_expr (aexpr);
-
-      ax_reqs (aexpr);
-
-      report_agent_reqs_errors (aexpr);
-
-      discard_cleanups (old_chain1);
-      add_aexpr (collect, aexpr);
+      finalize_tracepoint_aexpr (aexpr.get ());
 
       /* Take care of the registers.  */
-      if (aexpr->reg_mask_len > 0)
-       {
-         int ndx1, ndx2;
+      add_ax_registers (aexpr.get ());
 
-         for (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 (ndx2 = 0; ndx2 < 8; ndx2++)
-                   if (aexpr->reg_mask[ndx1] & (1 << ndx2))
-                     /* It's used -- record it.  */
-                     add_register (collect, ndx1 * 8 + ndx2);
-               }
-           }
-       }
+      add_aexpr (std::move (aexpr));
     }
 }
 
@@ -1140,25 +1058,30 @@ do_collect_symbol (const char *print_name,
 {
   struct add_local_symbols_data *p = (struct add_local_symbols_data *) cb_data;
 
-  collect_symbol (p->collect, sym, p->gdbarch, p->frame_regno,
-                 p->frame_offset, p->pc, p->trace_string);
+  p->collect->collect_symbol (sym, p->gdbarch, p->frame_regno,
+                             p->frame_offset, p->pc, p->trace_string);
   p->count++;
 
-  VEC_safe_push (char_ptr, p->collect->wholly_collected,
-                xstrdup (print_name));
+  p->collect->add_wholly_collected (print_name);
+}
+
+void
+collection_list::add_wholly_collected (const char *print_name)
+{
+  m_wholly_collected.push_back (print_name);
 }
 
 /* Add all locals (or args) symbols to collection list.  */
-static void
-add_local_symbols (struct collection_list *collect,
-                  struct gdbarch *gdbarch, CORE_ADDR pc,
-                  long frame_regno, long frame_offset, int type,
-                  int trace_string)
+
+void
+collection_list::add_local_symbols (struct gdbarch *gdbarch, CORE_ADDR pc,
+                                   long frame_regno, long frame_offset, int type,
+                                   int trace_string)
 {
   const struct block *block;
   struct add_local_symbols_data cb_data;
 
-  cb_data.collect = collect;
+  cb_data.collect = this;
   cb_data.gdbarch = gdbarch;
   cb_data.pc = pc;
   cb_data.frame_regno = frame_regno;
@@ -1196,197 +1119,169 @@ add_local_symbols (struct collection_list *collect,
     }
 }
 
-static void
-add_static_trace_data (struct collection_list *collection)
+void
+collection_list::add_static_trace_data ()
 {
   if (info_verbose)
     printf_filtered ("collect static trace data\n");
-  collection->strace_data = 1;
+  m_strace_data = true;
 }
 
-/* worker function */
-static void
-clear_collection_list (struct collection_list *list)
+collection_list::collection_list ()
+  : m_strace_data (false)
 {
-  int ndx;
-
-  list->next_memrange = 0;
-  for (ndx = 0; ndx < list->next_aexpr_elt; ndx++)
+  int max_remote_regno = 0;
+  for (int i = 0; i < gdbarch_num_regs (target_gdbarch ()); i++)
     {
-      free_agent_expr (list->aexpr_list[ndx]);
-      list->aexpr_list[ndx] = NULL;
-    }
-  list->next_aexpr_elt = 0;
-  memset (list->regs_mask, 0, sizeof (list->regs_mask));
-  list->strace_data = 0;
-
-  xfree (list->aexpr_list);
-  xfree (list->list);
-
-  VEC_free (char_ptr, list->wholly_collected);
-  VEC_free (char_ptr, list->computed);
-}
+      int remote_regno = (gdbarch_remote_register_number
+                         (target_gdbarch (), i));
 
-/* A cleanup wrapper for function clear_collection_list.  */
+      if (remote_regno >= 0 && remote_regno > max_remote_regno)
+       max_remote_regno = remote_regno;
+    }
 
-static void
-do_clear_collection_list (void *list)
-{
-  struct collection_list *l = (struct collection_list *) list;
+  m_regs_mask.resize ((max_remote_regno / 8) + 1);
 
-  clear_collection_list (l);
+  m_memranges.reserve (128);
+  m_aexprs.reserve (128);
 }
 
-/* Initialize collection_list CLIST.  */
+/* Reduce a collection list to string form (for gdb protocol).  */
 
-static void
-init_collection_list (struct collection_list *clist)
+std::vector<std::string>
+collection_list::stringify ()
 {
-  memset (clist, 0, sizeof *clist);
+  gdb::char_vector temp_buf (2048);
 
-  clist->listsize = 128;
-  clist->list = XCNEWVEC (struct memrange, clist->listsize);
-
-  clist->aexpr_listsize = 128;
-  clist->aexpr_list = XCNEWVEC (struct agent_expr *, clist->aexpr_listsize);
-}
-
-/* Reduce a collection list to string form (for gdb protocol).  */
-static char **
-stringify_collection_list (struct collection_list *list)
-{
-  char temp_buf[2048];
-  char tmp2[40];
   int count;
-  int ndx = 0;
-  char *(*str_list)[];
   char *end;
   long i;
+  std::vector<std::string> str_list;
 
-  count = 1 + 1 + list->next_memrange + list->next_aexpr_elt + 1;
-  str_list = (char *(*)[]) xmalloc (count * sizeof (char *));
-
-  if (list->strace_data)
+  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 (list->regs_mask) - 1; i > 0; i--)
-    if (list->regs_mask[i] != 0)    /* Skip leading zeroes in regs_mask.  */
+  for (i = m_regs_mask.size () - 1; i > 0; i--)
+    if (m_regs_mask[i] != 0)    /* Skip leading zeroes in regs_mask.  */
       break;
-  if (list->regs_mask[i] != 0) /* Prepare to send regs_mask to the stub.  */
+  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", list->regs_mask[i]);
-         sprintf (end, "%02X", list->regs_mask[i]);
-         end += 2;
+           printf_filtered ("%02X", m_regs_mask[i]);
+
+         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 (list->next_memrange > 0 && info_verbose)
+  if (!m_memranges.empty () && info_verbose)
     printf_filtered ("Collecting memranges: \n");
-  for (i = 0, count = 0, end = temp_buf; i < list->next_memrange; i++)
+  for (i = 0, count = 0, end = temp_buf.data ();
+       i < m_memranges.size (); i++)
     {
       QUIT;                    /* Allow user to bail out with ^C.  */
-      sprintf_vma (tmp2, list->list[i].start);
       if (info_verbose)
        {
          printf_filtered ("(%d, %s, %ld)\n", 
-                          list->list[i].type, 
-                          tmp2, 
-                          (long) (list->list[i].end - list->list[i].start));
+                          m_memranges[i].type,
+                          paddress (target_gdbarch (),
+                                    m_memranges[i].start),
+                          (long) (m_memranges[i].end
+                                  - m_memranges[i].start));
        }
       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 = list->list[i].end - list->list[i].start;
+        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 (list->list[i].type == memrange_absolute)
-          sprintf (end, "M-1,%s,%lX", tmp2, (long) length);
+        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", list->list[i].type, tmp2, (long) length);
+          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 < list->next_aexpr_elt; i++)
+  for (i = 0; i < m_aexprs.size (); i++)
     {
       QUIT;                    /* Allow user to bail out with ^C.  */
-      if ((count + 10 + 2 * list->aexpr_list[i]->len) > MAX_AGENT_EXPR_LEN)
+      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,", list->aexpr_list[i]->len);
+      sprintf (end, "X%08X,", m_aexprs[i]->len);
       end += 10;               /* 'X' + 8 hex digits + ',' */
       count += 10;
 
-      end = mem2hex (list->aexpr_list[i]->buf, 
-                    end, list->aexpr_list[i]->len);
-      count += 2 * list->aexpr_list[i]->len;
+      end = mem2hex (m_aexprs[i]->buf, end, m_aexprs[i]->len);
+      count += 2 * m_aexprs[i]->len;
     }
 
   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.  */
 
-static void
-append_exp (struct expression *exp, VEC(char_ptr) **list)
+void
+collection_list::append_exp (struct expression *exp)
 {
-  struct ui_file *tmp_stream = mem_fileopen ();
-  char *text;
+  string_file tmp_stream;
 
-  print_expression (exp, tmp_stream);
+  print_expression (exp, &tmp_stream);
 
-  text = ui_file_xstrdup (tmp_stream, NULL);
+  m_computed.push_back (std::move (tmp_stream.string ()));
+}
 
-  VEC_safe_push (char_ptr, *list, text);
-  ui_file_delete (tmp_stream);
+void
+collection_list::finish ()
+{
+  memrange_sortmerge (m_memranges);
 }
 
 static void
@@ -1398,17 +1293,15 @@ encode_actions_1 (struct command_line *action,
                  struct collection_list *stepping_list)
 {
   const char *action_exp;
-  struct expression *exp = NULL;
   int i;
   struct value *tempval;
   struct cmd_list_element *cmd;
-  struct agent_expr *aexpr;
 
   for (; action; action = action->next)
     {
       QUIT;                    /* Allow user to bail out with ^C.  */
       action_exp = action->line;
-      action_exp = skip_spaces_const (action_exp);
+      action_exp = skip_spaces (action_exp);
 
       cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
       if (cmd == 0)
@@ -1424,88 +1317,71 @@ encode_actions_1 (struct command_line *action,
          do
            {                   /* Repeat over a comma-separated list.  */
              QUIT;             /* Allow user to bail out with ^C.  */
-             action_exp = skip_spaces_const (action_exp);
+             action_exp = skip_spaces (action_exp);
 
              if (0 == strncasecmp ("$reg", action_exp, 4))
                {
-                 for (i = 0; i < gdbarch_num_regs (tloc->gdbarch); i++)
-                   add_register (collect, 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))
                {
-                 add_local_symbols (collect,
-                                    tloc->gdbarch,
-                                    tloc->address,
-                                    frame_reg,
-                                    frame_offset,
-                                    'A',
-                                    trace_string);
+                 collect->add_local_symbols (target_gdbarch (),
+                                             tloc->address,
+                                             frame_reg,
+                                             frame_offset,
+                                             'A',
+                                             trace_string);
                  action_exp = strchr (action_exp, ',');        /* more? */
                }
              else if (0 == strncasecmp ("$loc", action_exp, 4))
                {
-                 add_local_symbols (collect,
-                                    tloc->gdbarch,
-                                    tloc->address,
-                                    frame_reg,
-                                    frame_offset,
-                                    'L',
-                                    trace_string);
+                 collect->add_local_symbols (target_gdbarch (),
+                                             tloc->address,
+                                             frame_reg,
+                                             frame_offset,
+                                             'L',
+                                             trace_string);
                  action_exp = strchr (action_exp, ',');        /* more? */
                }
              else if (0 == strncasecmp ("$_ret", action_exp, 5))
                {
-                 struct cleanup *old_chain1 = NULL;
-
-                 aexpr = gen_trace_for_return_address (tloc->address,
-                                                       tloc->gdbarch,
-                                                       trace_string);
-
-                 old_chain1 = make_cleanup_free_agent_expr (aexpr);
-
-                 ax_reqs (aexpr);
-                 report_agent_reqs_errors (aexpr);
+                 agent_expr_up aexpr
+                   = gen_trace_for_return_address (tloc->address,
+                                                   target_gdbarch (),
+                                                   trace_string);
 
-                 discard_cleanups (old_chain1);
-                 add_aexpr (collect, aexpr);
+                 finalize_tracepoint_aexpr (aexpr.get ());
 
                  /* take care of the registers */
-                 if (aexpr->reg_mask_len > 0)
-                   {
-                     int ndx1, ndx2;
-
-                     for (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 (ndx2 = 0; ndx2 < 8; ndx2++)
-                               if (aexpr->reg_mask[ndx1] & (1 << ndx2))
-                                 /* it's used -- record it */
-                                 add_register (collect, 
-                                               ndx1 * 8 + ndx2);
-                           }
-                       }
-                   }
+                 collect->add_ax_registers (aexpr.get ());
 
+                 collect->add_aexpr (std::move (aexpr));
                  action_exp = strchr (action_exp, ',');        /* more? */
                }
              else if (0 == strncasecmp ("$_sdata", action_exp, 7))
                {
-                 add_static_trace_data (collect);
+                 collect->add_static_trace_data ();
                  action_exp = strchr (action_exp, ',');        /* more? */
                }
              else
                {
                  unsigned long addr;
-                 struct cleanup *old_chain = NULL;
-                 struct cleanup *old_chain1 = NULL;
 
-                 exp = parse_exp_1 (&action_exp, tloc->address,
-                                    block_for_pc (tloc->address), 1);
-                 old_chain = make_cleanup (free_current_contents, &exp);
+                 expression_up exp = parse_exp_1 (&action_exp, tloc->address,
+                                                  block_for_pc (tloc->address),
+                                                  1);
 
                  switch (exp->elts[0].opcode)
                    {
@@ -1513,7 +1389,7 @@ encode_actions_1 (struct command_line *action,
                      {
                        const char *name = &exp->elts[2].string;
 
-                       i = user_reg_map_name_to_regnum (tloc->gdbarch,
+                       i = user_reg_map_name_to_regnum (target_gdbarch (),
                                                         name, strlen (name));
                        if (i == -1)
                          internal_error (__FILE__, __LINE__,
@@ -1521,77 +1397,53 @@ encode_actions_1 (struct command_line *action,
                                          name);
                        if (info_verbose)
                          printf_filtered ("OP_REGISTER: ");
-                       add_register (collect, 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);
+                     tempval = evaluate_expression (exp.get ());
                      addr = value_address (tempval);
                      /* Initialize the TYPE_LENGTH if it is a typedef.  */
                      check_typedef (exp->elts[1].type);
-                     add_memrange (collect, memrange_absolute, addr,
-                                   TYPE_LENGTH (exp->elts[1].type));
-                     append_exp (exp, &collect->computed);
+                     collect->add_memrange (target_gdbarch (),
+                                            memrange_absolute, addr,
+                                            TYPE_LENGTH (exp->elts[1].type),
+                                            tloc->address);
+                     collect->append_exp (exp.get ());
                      break;
 
                    case OP_VAR_VALUE:
                      {
                        struct symbol *sym = exp->elts[2].symbol;
-                       char_ptr name = (char_ptr) SYMBOL_NATURAL_NAME (sym);
-
-                       collect_symbol (collect,
-                                       exp->elts[2].symbol,
-                                       tloc->gdbarch,
-                                       frame_reg,
-                                       frame_offset,
-                                       tloc->address,
-                                       trace_string);
-                       VEC_safe_push (char_ptr,
-                                      collect->wholly_collected,
-                                      name);
+                       const char *name = sym->natural_name ();
+
+                       collect->collect_symbol (exp->elts[2].symbol,
+                                                target_gdbarch (),
+                                                frame_reg,
+                                                frame_offset,
+                                                tloc->address,
+                                                trace_string);
+                       collect->add_wholly_collected (name);
                      }
                      break;
 
                    default:    /* Full-fledged expression.  */
-                     aexpr = gen_trace_for_expr (tloc->address, exp,
-                                                 trace_string);
-
-                     old_chain1 = make_cleanup_free_agent_expr (aexpr);
-
-                     ax_reqs (aexpr);
+                     agent_expr_up aexpr = gen_trace_for_expr (tloc->address,
+                                                               exp.get (),
+                                                               trace_string);
 
-                     report_agent_reqs_errors (aexpr);
-
-                     discard_cleanups (old_chain1);
-                     add_aexpr (collect, aexpr);
+                     finalize_tracepoint_aexpr (aexpr.get ());
 
                      /* Take care of the registers.  */
-                     if (aexpr->reg_mask_len > 0)
-                       {
-                         int ndx1;
-                         int ndx2;
-
-                         for (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 (ndx2 = 0; ndx2 < 8; ndx2++)
-                                   if (aexpr->reg_mask[ndx1] & (1 << ndx2))
-                                     /* It's used -- record it.  */
-                                     add_register (collect, 
-                                                   ndx1 * 8 + ndx2);
-                               }
-                           }
-                       }
+                     collect->add_ax_registers (aexpr.get ());
 
-                     append_exp (exp, &collect->computed);
+                     collect->add_aexpr (std::move (aexpr));
+                     collect->append_exp (exp.get ());
                      break;
                    }           /* switch */
-                 do_cleanups (old_chain);
                }               /* do */
            }
          while (action_exp && *action_exp++ == ',');
@@ -1601,28 +1453,21 @@ encode_actions_1 (struct command_line *action,
          do
            {                   /* Repeat over a comma-separated list.  */
              QUIT;             /* Allow user to bail out with ^C.  */
-             action_exp = skip_spaces_const (action_exp);
+             action_exp = skip_spaces (action_exp);
 
                {
-                 struct cleanup *old_chain = NULL;
-                 struct cleanup *old_chain1 = NULL;
-
-                 exp = parse_exp_1 (&action_exp, tloc->address,
-                                    block_for_pc (tloc->address), 1);
-                 old_chain = make_cleanup (free_current_contents, &exp);
+                 expression_up exp = parse_exp_1 (&action_exp, tloc->address,
+                                                  block_for_pc (tloc->address),
+                                                  1);
 
-                 aexpr = gen_eval_for_expr (tloc->address, exp);
-                 old_chain1 = make_cleanup_free_agent_expr (aexpr);
+                 agent_expr_up aexpr = gen_eval_for_expr (tloc->address,
+                                                          exp.get ());
 
-                 ax_reqs (aexpr);
-                 report_agent_reqs_errors (aexpr);
+                 finalize_tracepoint_aexpr (aexpr.get ());
 
-                 discard_cleanups (old_chain1);
                  /* Even though we're not officially collecting, add
                     to the collect list anyway.  */
-                 add_aexpr (collect, aexpr);
-
-                 do_cleanups (old_chain);
+                 collect->add_aexpr (std::move (aexpr));
                }               /* do */
            }
          while (action_exp && *action_exp++ == ',');
@@ -1634,7 +1479,7 @@ encode_actions_1 (struct command_line *action,
             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
@@ -1643,91 +1488,58 @@ encode_actions_1 (struct command_line *action,
 }
 
 /* Encode actions of tracepoint TLOC->owner and fill TRACEPOINT_LIST
-   and STEPPING_LIST.  Return a cleanup pointer to clean up both
-   TRACEPOINT_LIST and STEPPING_LIST.  */
+   and STEPPING_LIST.  */
 
-struct cleanup *
-encode_actions_and_make_cleanup (struct bp_location *tloc,
-                                struct collection_list *tracepoint_list,
-                                struct collection_list *stepping_list)
+void
+encode_actions (struct bp_location *tloc,
+               struct collection_list *tracepoint_list,
+               struct collection_list *stepping_list)
 {
-  char *default_collect_line = NULL;
-  struct command_line *actions;
-  struct command_line *default_collect_action = NULL;
   int frame_reg;
   LONGEST frame_offset;
-  struct cleanup *back_to, *return_chain;
-
-  return_chain = make_cleanup (null_cleanup, NULL);
-  init_collection_list (tracepoint_list);
-  init_collection_list (stepping_list);
 
-  make_cleanup (do_clear_collection_list, tracepoint_list);
-  make_cleanup (do_clear_collection_list, stepping_list);
-
-  back_to = make_cleanup (null_cleanup, NULL);
   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);
 
-  memrange_sortmerge (tracepoint_list);
-  memrange_sortmerge (stepping_list);
-
-  do_cleanups (back_to);
-  return return_chain;
+  tracepoint_list->finish ();
+  stepping_list->finish ();
 }
 
 /* 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;
-  struct cleanup *cleanup;
-
-  *tdp_actions = NULL;
-  *stepping_actions = NULL;
-
-  cleanup = encode_actions_and_make_cleanup (tloc, &tracepoint_list,
-                                            &stepping_list);
 
-  *tdp_actions = stringify_collection_list (&tracepoint_list);
-  *stepping_actions = stringify_collection_list (&stepping_list);
+  encode_actions (tloc, &tracepoint_list, &stepping_list);
 
-  do_cleanups (cleanup);
+  *tdp_actions = tracepoint_list.stringify ();
+  *stepping_actions = stepping_list.stringify ();
 }
 
-static void
-add_aexpr (struct collection_list *collect, struct agent_expr *aexpr)
+void
+collection_list::add_aexpr (agent_expr_up aexpr)
 {
-  if (collect->next_aexpr_elt >= collect->aexpr_listsize)
-    {
-      collect->aexpr_list = XRESIZEVEC (struct agent_expr *,
-                                       collect->aexpr_list,
-                                       2 * collect->aexpr_listsize);
-      collect->aexpr_listsize *= 2;
-    }
-  collect->aexpr_list[collect->next_aexpr_elt] = aexpr;
-  collect->next_aexpr_elt++;
+  m_aexprs.push_back (std::move (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)
        {
@@ -1751,7 +1563,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"
@@ -1770,29 +1581,19 @@ 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 ();
+  std::vector<breakpoint *> tp_vec = 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 (tp_vec.empty ())
+    error (_("No tracepoints defined, not starting trace"));
 
-  for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++)
+  for (breakpoint *b : tp_vec)
     {
-      struct tracepoint *t = (struct tracepoint *) b;
-      struct bp_location *loc;
-
       if (b->enable_state == bp_enabled)
        any_enabled = 1;
 
@@ -1813,20 +1614,16 @@ 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 : tp_vec)
     {
       struct tracepoint *t = (struct tracepoint *) b;
       struct bp_location *loc;
@@ -1858,22 +1655,17 @@ 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);
+       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 ();
@@ -1904,7 +1696,7 @@ start_tracing (char *notes)
    anybody else messing with the target.  */
 
 static void
-trace_start_command (char *args, int from_tty)
+tstart_command (const char *args, int from_tty)
 {
   dont_repeat ();      /* Like "run", dangerous to repeat accidentally.  */
 
@@ -1924,7 +1716,7 @@ trace_start_command (char *args, int from_tty)
    of the trace run's status.  */
 
 static void
-trace_stop_command (char *args, int from_tty)
+tstop_command (const char *args, int from_tty)
 {
   if (!current_trace_status ()->running)
     error (_("Trace is not running."));
@@ -1933,17 +1725,13 @@ trace_stop_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;
 
@@ -1958,16 +1746,12 @@ stop_tracing (char *note)
             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;
   ret = target_set_trace_notes (NULL, NULL, note);
@@ -1981,12 +1765,10 @@ stop_tracing (char *note)
 
 /* tstatus command */
 static void
-trace_status_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);
 
@@ -2016,7 +1798,7 @@ trace_status_command (char *args, int from_tty)
        case trace_never_run:
          printf_filtered (_("No trace has been run on the target.\n"));
          break;
-       case tstop_command:
+       case trace_stop_command:
          if (ts->stop_desc)
            printf_filtered (_("Trace stopped by a tstop command (%s).\n"),
                             ts->stop_desc);
@@ -2129,12 +1911,8 @@ trace_status_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
@@ -2154,23 +1932,23 @@ trace_status_mi (int on_stop)
 
   if (status == -1 && ts->filename == NULL)
     {
-      ui_out_field_string (uiout, "supported", "0");
+      uiout->field_string ("supported", "0");
       return;
     }
 
   if (ts->filename != NULL)
-    ui_out_field_string (uiout, "supported", "file");
+    uiout->field_string ("supported", "file");
   else if (!on_stop)
-    ui_out_field_string (uiout, "supported", "1");
+    uiout->field_string ("supported", "1");
 
   if (ts->filename != NULL)
-    ui_out_field_string (uiout, "trace-file", ts->filename);
+    uiout->field_string ("trace-file", ts->filename);
 
   gdb_assert (ts->running_known);
 
   if (ts->running)
     {
-      ui_out_field_string (uiout, "running", "1");
+      uiout->field_string ("running", "1");
 
       /* Unlike CLI, do not show the state of 'disconnected-tracing' variable.
         Given that the frontend gets the status either on -trace-stop, or from
@@ -2183,17 +1961,17 @@ trace_status_mi (int on_stop)
     }
   else
     {
-      char *stop_reason = NULL;
+      const char *stop_reason = NULL;
       int stopping_tracepoint = -1;
 
       if (!on_stop)
-       ui_out_field_string (uiout, "running", "0");
+       uiout->field_string ("running", "0");
 
       if (ts->stop_reason != trace_stop_reason_unknown)
        {
          switch (ts->stop_reason)
            {
-           case tstop_command:
+           case trace_stop_command:
              stop_reason = "request";
              break;
            case trace_buffer_full:
@@ -2214,31 +1992,31 @@ trace_status_mi (int on_stop)
          
          if (stop_reason)
            {
-             ui_out_field_string (uiout, "stop-reason", stop_reason);
+             uiout->field_string ("stop-reason", stop_reason);
              if (stopping_tracepoint != -1)
-               ui_out_field_int (uiout, "stopping-tracepoint",
-                                 stopping_tracepoint);
+               uiout->field_signed ("stopping-tracepoint",
+                                    stopping_tracepoint);
              if (ts->stop_reason == tracepoint_error)
-               ui_out_field_string (uiout, "error-description",
+               uiout->field_string ("error-description",
                                     ts->stop_desc);
            }
        }
     }
 
   if (ts->traceframe_count != -1)
-    ui_out_field_int (uiout, "frames", ts->traceframe_count);
+    uiout->field_signed ("frames", ts->traceframe_count);
   if (ts->traceframes_created != -1)
-    ui_out_field_int (uiout, "frames-created", ts->traceframes_created);
+    uiout->field_signed ("frames-created", ts->traceframes_created);
   if (ts->buffer_size != -1)
-    ui_out_field_int (uiout, "buffer-size", ts->buffer_size);
+    uiout->field_signed ("buffer-size", ts->buffer_size);
   if (ts->buffer_free != -1)
-    ui_out_field_int (uiout, "buffer-free", ts->buffer_free);
+    uiout->field_signed ("buffer-free", ts->buffer_free);
 
-  ui_out_field_int (uiout, "disconnected",  ts->disconnected_tracing);
-  ui_out_field_int (uiout, "circular",  ts->circular_buffer);
+  uiout->field_signed ("disconnected",  ts->disconnected_tracing);
+  uiout->field_signed ("circular",  ts->circular_buffer);
 
-  ui_out_field_string (uiout, "user-name", ts->user_name);
-  ui_out_field_string (uiout, "notes", ts->notes);
+  uiout->field_string ("user-name", ts->user_name);
+  uiout->field_string ("notes", ts->notes);
 
   {
     char buf[100];
@@ -2246,11 +2024,11 @@ trace_status_mi (int on_stop)
     xsnprintf (buf, sizeof buf, "%ld.%06ld",
               (long int) (ts->start_time / 1000000),
               (long int) (ts->start_time % 1000000));
-    ui_out_field_string (uiout, "start-time", buf);
+    uiout->field_string ("start-time", buf);
     xsnprintf (buf, sizeof buf, "%ld.%06ld",
               (long int) (ts->stop_time / 1000000),
               (long int) (ts->stop_time % 1000000));
-    ui_out_field_string (uiout, "stop-time", buf);
+    uiout->field_string ("stop-time", buf);
   }
 }
 
@@ -2352,7 +2130,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
@@ -2370,7 +2148,7 @@ tfind_1 (enum trace_find_type type, int num,
 #if 0 /* dubious now?  */
          /* The following will not recurse, since it's
             special-cased.  */
-         trace_find_command ("-1", from_tty);
+         tfind_command ("-1", from_tty);
 #endif
        }
     }
@@ -2380,10 +2158,10 @@ tfind_1 (enum trace_find_type type, int num,
   reinit_frame_cache ();
   target_dcache_invalidate ();
 
-  set_tracepoint_num (tp ? tp->base.number : target_tracept);
+  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);
 
@@ -2396,11 +2174,11 @@ tfind_1 (enum trace_find_type type, int num,
     {
       /* Use different branches for MI and CLI to make CLI messages
         i18n-eable.  */
-      if (ui_out_is_mi_like_p (uiout))
+      if (uiout->is_mi_like_p ())
        {
-         ui_out_field_string (uiout, "found", "1");
-         ui_out_field_int (uiout, "tracepoint", tracepoint_number);
-         ui_out_field_int (uiout, "traceframe", traceframe_number);
+         uiout->field_string ("found", "1");
+         uiout->field_signed ("tracepoint", tracepoint_number);
+         uiout->field_signed ("traceframe", traceframe_number);
        }
       else
        {
@@ -2410,8 +2188,8 @@ tfind_1 (enum trace_find_type type, int num,
     }
   else
     {
-      if (ui_out_is_mi_like_p (uiout))
-       ui_out_field_string (uiout, "found", "0");
+      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"));
       else /* This case may never occur, check.  */
@@ -2468,7 +2246,7 @@ check_trace_running (struct trace_status *status)
 
 /* tfind command */
 static void
-trace_find_command (char *args, int from_tty)
+tfind_command_1 (const char *args, int from_tty)
 { /* This should only be called with a numeric argument.  */
   int frameno = -1;
 
@@ -2502,23 +2280,29 @@ trace_find_command (char *args, int from_tty)
   tfind_1 (tfind_number, frameno, 0, 0, from_tty);
 }
 
+static void
+tfind_command (const char *args, int from_tty)
+{
+  tfind_command_1 (args, from_tty);
+}
+
 /* tfind end */
 static void
-trace_find_end_command (char *args, int from_tty)
+tfind_end_command (const char *args, int from_tty)
 {
-  trace_find_command ("-1", from_tty);
+  tfind_command_1 ("-1", from_tty);
 }
 
 /* tfind start */
 static void
-trace_find_start_command (char *args, int from_tty)
+tfind_start_command (const char *args, int from_tty)
 {
-  trace_find_command ("0", from_tty);
+  tfind_command_1 ("0", from_tty);
 }
 
 /* tfind pc command */
 static void
-trace_find_pc_command (char *args, int from_tty)
+tfind_pc_command (const char *args, int from_tty)
 {
   CORE_ADDR pc;
 
@@ -2534,7 +2318,7 @@ trace_find_pc_command (char *args, int from_tty)
 
 /* tfind tracepoint command */
 static void
-trace_find_tracepoint_command (char *args, int from_tty)
+tfind_tracepoint_command (const char *args, int from_tty)
 {
   int tdp;
   struct tracepoint *tp;
@@ -2570,32 +2354,26 @@ trace_find_tracepoint_command (char *args, int from_tty)
    corresponding to a source line OTHER THAN THE CURRENT ONE.  */
 
 static void
-trace_find_line_command (char *args, int from_tty)
+tfind_line_command (const char *args, int from_tty)
 {
-  static CORE_ADDR start_pc, end_pc;
-  struct symtabs_and_lines sals;
-  struct symtab_and_line sal;
-  struct cleanup *old_chain;
-
   check_trace_running (current_trace_status ());
 
+  symtab_and_line sal;
   if (args == 0 || *args == 0)
     {
       sal = find_pc_line (get_frame_pc (get_current_frame ()), 0);
-      sals.nelts = 1;
-      sals.sals = XNEW (struct symtab_and_line);
-      sals.sals[0] = sal;
     }
   else
     {
-      sals = decode_line_with_current_source (args, DECODE_LINE_FUNFIRSTLINE);
-      sal = sals.sals[0];
+      std::vector<symtab_and_line> sals
+       = decode_line_with_current_source (args, DECODE_LINE_FUNFIRSTLINE);
+      sal = sals[0];
     }
-  
-  old_chain = make_cleanup (xfree, sals.sals);
+
   if (sal.symtab == 0)
     error (_("No line number information available."));
 
+  CORE_ADDR start_pc, end_pc;
   if (sal.line > 0 && find_line_pc_range (sal, &start_pc, &end_pc))
     {
       if (start_pc == end_pc)
@@ -2630,29 +2408,29 @@ trace_find_line_command (char *args, int from_tty)
     tfind_1 (tfind_range, 0, start_pc, end_pc - 1, from_tty);
   else
     tfind_1 (tfind_outside, 0, start_pc, end_pc - 1, from_tty);
-  do_cleanups (old_chain);
 }
 
 /* tfind range command */
 static void
-trace_find_range_command (char *args, int from_tty)
+tfind_range_command (const char *args, int from_tty)
 {
   static CORE_ADDR start, stop;
-  char *tmp;
+  const char *tmp;
 
   check_trace_running (current_trace_status ());
 
   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;
     }
 
   if (0 != (tmp = strchr (args, ',')))
     {
-      *tmp++ = '\0';   /* Terminate start address.  */
+      std::string start_addr (args, tmp);
+      ++tmp;
       tmp = skip_spaces (tmp);
-      start = parse_and_eval_address (args);
+      start = parse_and_eval_address (start_addr.c_str ());
       stop = parse_and_eval_address (tmp);
     }
   else
@@ -2666,10 +2444,10 @@ trace_find_range_command (char *args, int from_tty)
 
 /* tfind outside command */
 static void
-trace_find_outside_command (char *args, int from_tty)
+tfind_outside_command (const char *args, int from_tty)
 {
   CORE_ADDR start, stop;
-  char *tmp;
+  const char *tmp;
 
   if (current_trace_status ()->running
       && current_trace_status ()->filename == NULL)
@@ -2677,15 +2455,16 @@ trace_find_outside_command (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;
     }
 
   if (0 != (tmp = strchr (args, ',')))
     {
-      *tmp++ = '\0';   /* Terminate start address.  */
+      std::string start_addr (args, tmp);
+      ++tmp;
       tmp = skip_spaces (tmp);
-      start = parse_and_eval_address (args);
+      start = parse_and_eval_address (start_addr.c_str ());
       stop = parse_and_eval_address (tmp);
     }
   else
@@ -2699,38 +2478,37 @@ trace_find_outside_command (char *args, int from_tty)
 
 /* info scope command: list the locals for a scope.  */
 static void
-scope_info (char *args, int from_tty)
+info_scope_command (const char *args_in, int from_tty)
 {
-  struct symtabs_and_lines sals;
   struct symbol *sym;
   struct bound_minimal_symbol msym;
   const struct block *block;
   const char *symname;
-  char *save_args = args;
+  const char *save_args = args_in;
   struct block_iterator iter;
   int j, count = 0;
   struct gdbarch *gdbarch;
   int regno;
-  struct event_location *location;
-  struct cleanup *back_to;
+  const char *args = args_in;
 
   if (args == 0 || *args == 0)
     error (_("requires an argument (function, "
             "line or *addr) to define a scope"));
 
-  location = string_to_event_location (&args, current_language);
-  back_to = make_cleanup_delete_event_location (location);
-  sals = decode_line_1 (location, DECODE_LINE_FUNFIRSTLINE, NULL, 0);
-  if (sals.nelts == 0)
+  event_location_up location = string_to_event_location (&args,
+                                                        current_language);
+  std::vector<symtab_and_line> sals
+    = decode_line_1 (location.get (), DECODE_LINE_FUNFIRSTLINE,
+                    NULL, NULL, 0);
+  if (sals.empty ())
     {
       /* Presumably decode_line_1 has already warned.  */
-      do_cleanups (back_to);
       return;
     }
 
   /* Resolve line numbers to PC.  */
-  resolve_sal_pc (&sals.sals[0]);
-  block = block_for_pc (sals.sals[0].pc);
+  resolve_sal_pc (&sals[0]);
+  block = block_for_pc (sals[0].pc);
 
   while (block != 0)
     {
@@ -2742,7 +2520,7 @@ scope_info (char *args, 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.  */
 
@@ -2752,7 +2530,7 @@ scope_info (char *args, 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
            {
@@ -2829,10 +2607,10 @@ scope_info (char *args, 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");
@@ -2852,8 +2630,11 @@ scope_info (char *args, int from_tty)
                }
            }
          if (SYMBOL_TYPE (sym))
-           printf_filtered (", length %d.\n",
-                            TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym))));
+           {
+             struct type *t = check_typedef (SYMBOL_TYPE (sym));
+
+             printf_filtered (", length %s.\n", pulongest (TYPE_LENGTH (t)));
+           }
        }
       if (BLOCK_FUNCTION (block))
        break;
@@ -2863,7 +2644,6 @@ scope_info (char *args, int from_tty)
   if (count <= 0)
     printf_filtered ("Scope for %s contains no locals or arguments.\n",
                     save_args);
-  do_cleanups (back_to);
 }
 
 /* Helper for trace_dump_command.  Dump the action list starting at
@@ -2885,7 +2665,7 @@ trace_dump_actions (struct command_line *action,
 
       QUIT;                    /* Allow user to bail out with ^C.  */
       action_exp = action->line;
-      action_exp = skip_spaces_const (action_exp);
+      action_exp = skip_spaces (action_exp);
 
       /* The collection actions to be done while stepping are
          bracketed by the commands "while-stepping" and "end".  */
@@ -2899,11 +2679,9 @@ trace_dump_actions (struct command_line *action,
 
       if (cmd_cfunc_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))
        {
@@ -2915,9 +2693,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 == '/')
@@ -2928,7 +2703,7 @@ trace_dump_actions (struct command_line *action,
                  QUIT;         /* Allow user to bail out with ^C.  */
                  if (*action_exp == ',')
                    action_exp++;
-                 action_exp = skip_spaces_const (action_exp);
+                 action_exp = skip_spaces (action_exp);
 
                  next_comma = strchr (action_exp, ',');
 
@@ -2937,36 +2712,27 @@ trace_dump_actions (struct command_line *action,
                  else if (0 == strncasecmp (action_exp, "$_ret", 5))
                    ;
                  else if (0 == strncasecmp (action_exp, "$loc", 4))
-                   locals_info (NULL, from_tty);
+                   info_locals_command (NULL, from_tty);
                  else if (0 == strncasecmp (action_exp, "$arg", 4))
-                   args_info (NULL, from_tty);
+                   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;
+                         contents = std::string (action_exp, len);
+                         exp = contents.c_str ();
                        }
-                     else
-                       {
-                         size_t len = strlen (action_exp);
 
-                         cmd = (char *) xrealloc (cmd, len + 1);
-                         memcpy (cmd, action_exp, len + 1);
-                       }
-
-                     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);
            }
        }
     }
@@ -3001,7 +2767,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->base.loc; tloc; tloc = tloc->next)
+  for (tloc = t->loc; tloc; tloc = tloc->next)
     if (tloc->address == regcache_read_pc (regcache))
       {
        *stepping_frame_p = 0;
@@ -3011,19 +2777,15 @@ get_traceframe_location (int *stepping_frame_p)
   /* If this is a stepping frame, we don't know which location
      triggered.  The first is as good (or bad) a guess as any...  */
   *stepping_frame_p = 1;
-  return t->base.loc;
+  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
@@ -3032,18 +2794,13 @@ all_tracepoint_actions_and_cleanup (struct breakpoint *t)
      the fly, and don't cache it.  */
   if (*default_collect)
     {
-      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));
+
+      validate_actionline (default_collect_line.get (), t);
+      actions.reset (new struct command_line (simple_control,
+                                             default_collect_line.release ()),
+                    command_lines_deleter ());
     }
 
   return actions;
@@ -3052,12 +2809,10 @@ all_tracepoint_actions_and_cleanup (struct breakpoint *t)
 /* The tdump command.  */
 
 static void
-trace_dump_command (char *args, int from_tty)
+tdump_command (const char *args, int from_tty)
 {
   int stepping_frame = 0;
   struct bp_location *loc;
-  struct cleanup *old_chain;
-  struct command_line *actions;
 
   /* This throws an error is not inspecting a trace frame.  */
   loc = get_traceframe_location (&stepping_frame);
@@ -3065,18 +2820,17 @@ trace_dump_command (char *args, int from_tty)
   printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n",
                   tracepoint_number, traceframe_number);
 
-  old_chain = make_cleanup (null_cleanup, NULL);
-
   /* This command only makes sense for the current frame, not the
      selected frame.  */
-  make_cleanup_restore_current_thread ();
-  select_frame (get_current_frame ());
+  scoped_restore_current_thread restore_thread;
 
-  actions = all_tracepoint_actions_and_cleanup (loc->owner);
+  select_frame (get_current_frame ());
 
-  trace_dump_actions (actions, 0, stepping_frame, from_tty);
+  counted_command_line actions = all_tracepoint_actions (loc->owner);
 
-  do_cleanups (old_chain);
+  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
@@ -3084,9 +2838,10 @@ trace_dump_command (char *args, int from_tty)
 /* This version does not do multiple encodes for long strings; it should
    return an offset to the next piece to encode.  FIXME  */
 
-extern int
+int
 encode_source_string (int tpnum, ULONGEST addr,
-                     char *srctype, const char *src, char *buf, int buf_size)
+                     const char *srctype, const char *src,
+                     char *buf, int buf_size)
 {
   if (80 + strlen (srctype) > buf_size)
     error (_("Buffer too small for source encoding"));
@@ -3103,28 +2858,28 @@ 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;
@@ -3136,7 +2891,7 @@ set_trace_user (char *args, int from_tty,
 }
 
 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;
@@ -3148,7 +2903,7 @@ set_trace_notes (char *args, int from_tty,
 }
 
 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;
@@ -3224,43 +2979,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.  */
@@ -3274,12 +2995,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;
 
@@ -3294,7 +3012,7 @@ free_uploaded_tps (struct uploaded_tp **utpp)
   while (*utpp)
     {
       next_one = (*utpp)->next;
-      xfree (*utpp);
+      delete *utpp;
       *utpp = next_one;
     }
 }
@@ -3353,19 +3071,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->base.cond_string, utp->cond_string)
+         && cond_string_is_same (t->cond_string,
+                                 utp->cond_string.get ())
          /* FIXME also test actions.  */
          )
        {
@@ -3389,9 +3105,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)
@@ -3417,16 +3131,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
        {
@@ -3434,7 +3146,7 @@ merge_uploaded_tracepoints (struct uploaded_tp **uploaded_tps)
          if (t)
            printf_filtered (_("Created tracepoint %d for "
                               "target's tracepoint %d at %s.\n"),
-                            t->base.number, utp->number,
+                            t->number, utp->number,
                             paddress (get_current_arch (), utp->addr));
          else
            printf_filtered (_("Failed to create tracepoint for target's "
@@ -3451,10 +3163,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);
 }
 
@@ -3474,40 +3185,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;
 }
@@ -3518,25 +3221,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
        {
@@ -3544,7 +3245,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)
@@ -3553,14 +3254,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);
 }
@@ -3569,9 +3269,9 @@ merge_uploaded_trace_state_variables (struct uploaded_tsv **uploaded_tsvs)
    the remote protocol and the trace file reader.  */
 
 void
-parse_trace_status (char *line, struct trace_status *ts)
+parse_trace_status (const char *line, struct trace_status *ts)
 {
-  char *p = line, *p1, *p2, *p3, *p_temp;
+  const char *p = line, *p1, *p2, *p3, *p_temp;
   int end;
   ULONGEST val;
 
@@ -3618,7 +3318,7 @@ Status line: '%s'\n"), p, line);
          ts->stop_reason = tracepoint_passcount;
          ts->stopping_tracepoint = val;
        }
-      else if (strncmp (p, stop_reason_names[tstop_command], p1 - p) == 0)
+      else if (strncmp (p, stop_reason_names[trace_stop_command], p1 - p) == 0)
        {
          p2 = strchr (++p1, ':');
          if (!p2 || p2 > p3)
@@ -3636,7 +3336,7 @@ Status line: '%s'\n"), p, line);
            ts->stop_desc = xstrdup ("");
 
          p = unpack_varlen_hex (++p2, &val);
-         ts->stop_reason = tstop_command;
+         ts->stop_reason = trace_stop_command;
        }
       else if (strncmp (p, stop_reason_names[trace_disconnected], p1 - p) == 0)
        {
@@ -3729,7 +3429,7 @@ Status line: '%s'\n"), p, line);
 }
 
 void
-parse_tracepoint_status (char *p, struct breakpoint *bp,
+parse_tracepoint_status (const char *p, struct breakpoint *bp,
                         struct uploaded_tp *utp)
 {
   ULONGEST uval;
@@ -3737,7 +3437,7 @@ parse_tracepoint_status (char *p, struct breakpoint *bp,
 
   p = unpack_varlen_hex (p, &uval);
   if (tp)
-    tp->base.hit_count += uval;
+    tp->hit_count += uval;
   else
     utp->hit_count += uval;
   p = unpack_varlen_hex (p + 1, &uval);
@@ -3752,14 +3452,15 @@ parse_tracepoint_status (char *p, struct breakpoint *bp,
    an "uploaded tracepoint".  */
 
 void
-parse_tracepoint_definition (char *line, struct uploaded_tp **utpp)
+parse_tracepoint_definition (const char *line, struct uploaded_tp **utpp)
 {
-  char *p;
+  const char *p;
   char piece;
   ULONGEST num, addr, step, pass, orig_size, xlen, start;
   int enabled, end;
   enum bptype type;
-  char *cond, *srctype, *buf;
+  const char *srctype;
+  char *buf;
   struct uploaded_tp *utp = NULL;
 
   p = line;
@@ -3772,13 +3473,14 @@ parse_tracepoint_definition (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 == ':')
        {
@@ -3799,8 +3501,8 @@ parse_tracepoint_definition (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;
            }
@@ -3813,17 +3515,17 @@ parse_tracepoint_definition (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')
     {
@@ -3843,11 +3545,11 @@ parse_tracepoint_definition (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')
     {
@@ -3867,9 +3569,10 @@ parse_tracepoint_definition (char *line, struct uploaded_tp **utpp)
    uploaded object.  */
 
 void
-parse_tsv_definition (char *line, struct uploaded_tsv **utsvp)
+parse_tsv_definition (const char *line, struct uploaded_tsv **utsvp)
 {
-  char *p, *buf;
+  const char *p;
+  char *buf;
   ULONGEST num, initval, builtin;
   int end;
   struct uploaded_tsv *utsv = NULL;
@@ -3892,33 +3595,17 @@ parse_tsv_definition (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
    the parsed marker definition.  */
 
 void
-parse_static_tracepoint_marker_definition (char *line, char **pp,
-                                          struct static_tracepoint_marker *marker)
+parse_static_tracepoint_marker_definition (const char *line, const char **pp,
+                                          static_tracepoint_marker *marker)
 {
-  char *p, *endp;
+  const char *p, *endp;
   ULONGEST addr;
-  int end;
 
   p = line;
   p = unpack_varlen_hex (p, &addr);
@@ -3931,160 +3618,140 @@ parse_static_tracepoint_marker_definition (char *line, 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 command_line *l;
   struct symbol *sym;
 
   char wrap_indent[80];
   char extra_field_indent[80];
   struct ui_out *uiout = current_uiout;
-  struct cleanup *bkpt_chain;
-  VEC(breakpoint_p) *tracepoints;
-
-  struct symtab_and_line sal;
 
-  init_sal (&sal);
+  symtab_and_line sal;
+  sal.pc = marker.address;
 
-  sal.pc = marker->address;
+  std::vector<breakpoint *> tracepoints
+    = static_tracepoints_here (marker.address);
 
-  tracepoints = static_tracepoints_here (marker->address);
-
-  bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "marker");
+  ui_out_emit_tuple tuple_emitter (uiout, "marker");
 
   /* A counter field to help readability.  This is not a stable
      identifier!  */
-  ui_out_field_int (uiout, "count", count);
+  uiout->field_signed ("count", count);
 
-  ui_out_field_string (uiout, "marker-id", marker->str_id);
+  uiout->field_string ("marker-id", marker.str_id.c_str ());
 
-  ui_out_field_fmt (uiout, "enabled", "%c",
-                   !VEC_empty (breakpoint_p, tracepoints) ? 'y' : 'n');
-  ui_out_spaces (uiout, 2);
+  uiout->field_fmt ("enabled", "%c",
+                   !tracepoints.empty () ? 'y' : 'n');
+  uiout->spaces (2);
 
   strcpy (wrap_indent, "                                   ");
 
-  if (gdbarch_addr_bit (marker->gdbarch) <= 32)
+  if (gdbarch_addr_bit (marker.gdbarch) <= 32)
     strcat (wrap_indent, "           ");
   else
     strcat (wrap_indent, "                   ");
 
   strcpy (extra_field_indent, "         ");
 
-  ui_out_field_core_addr (uiout, "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)
     {
-      ui_out_text (uiout, "in ");
-      ui_out_field_string (uiout, "func",
-                          SYMBOL_PRINT_NAME (sym));
-      ui_out_wrap_hint (uiout, wrap_indent);
-      ui_out_text (uiout, " at ");
+      uiout->text ("in ");
+      uiout->field_string ("func", sym->print_name (),
+                          function_name_style.style ());
+      uiout->wrap_hint (wrap_indent);
+      uiout->text (" at ");
     }
   else
-    ui_out_field_skip (uiout, "func");
+    uiout->field_skip ("func");
 
   if (sal.symtab != NULL)
     {
-      ui_out_field_string (uiout, "file",
-                          symtab_to_filename_for_display (sal.symtab));
-      ui_out_text (uiout, ":");
+      uiout->field_string ("file",
+                          symtab_to_filename_for_display (sal.symtab),
+                          file_name_style.style ());
+      uiout->text (":");
 
-      if (ui_out_is_mi_like_p (uiout))
+      if (uiout->is_mi_like_p ())
        {
          const char *fullname = symtab_to_fullname (sal.symtab);
 
-         ui_out_field_string (uiout, "fullname", fullname);
+         uiout->field_string ("fullname", fullname);
        }
       else
-       ui_out_field_skip (uiout, "fullname");
+       uiout->field_skip ("fullname");
 
-      ui_out_field_int (uiout, "line", sal.line);
+      uiout->field_signed ("line", sal.line);
     }
   else
     {
-      ui_out_field_skip (uiout, "fullname");
-      ui_out_field_skip (uiout, "line");
+      uiout->field_skip ("fullname");
+      uiout->field_skip ("line");
     }
 
-  ui_out_text (uiout, "\n");
-  ui_out_text (uiout, extra_field_indent);
-  ui_out_text (uiout, _("Data: \""));
-  ui_out_field_string (uiout, "extra-data", marker->extra);
-  ui_out_text (uiout, "\"\n");
+  uiout->text ("\n");
+  uiout->text (extra_field_indent);
+  uiout->text (_("Data: \""));
+  uiout->field_string ("extra-data", marker.extra.c_str ());
+  uiout->text ("\"\n");
 
-  if (!VEC_empty (breakpoint_p, tracepoints))
+  if (!tracepoints.empty ())
     {
-      struct cleanup *cleanup_chain;
       int ix;
-      struct breakpoint *b;
 
-      cleanup_chain = make_cleanup_ui_out_tuple_begin_end (uiout,
-                                                          "tracepoints-at");
-
-      ui_out_text (uiout, extra_field_indent);
-      ui_out_text (uiout, _("Probed by static tracepoints: "));
-      for (ix = 0; VEC_iterate(breakpoint_p, tracepoints, ix, b); ix++)
-       {
-         if (ix > 0)
-           ui_out_text (uiout, ", ");
-         ui_out_text (uiout, "#");
-         ui_out_field_int (uiout, "tracepoint-id", b->number);
-       }
+      {
+       ui_out_emit_tuple inner_tuple_emitter (uiout, "tracepoints-at");
 
-      do_cleanups (cleanup_chain);
+       uiout->text (extra_field_indent);
+       uiout->text (_("Probed by static tracepoints: "));
+       for (ix = 0; ix < tracepoints.size (); ix++)
+         {
+           if (ix > 0)
+             uiout->text (", ");
+           uiout->text ("#");
+           uiout->field_signed ("tracepoint-id", tracepoints[ix]->number);
+         }
+      }
 
-      if (ui_out_is_mi_like_p (uiout))
-       ui_out_field_int (uiout, "number-of-tracepoints",
-                         VEC_length(breakpoint_p, tracepoints));
+      if (uiout->is_mi_like_p ())
+       uiout->field_signed ("number-of-tracepoints", tracepoints.size ());
       else
-       ui_out_text (uiout, "\n");
+       uiout->text ("\n");
     }
-  VEC_free (breakpoint_p, tracepoints);
-
-  do_cleanups (bkpt_chain);
 }
 
 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.
@@ -4092,36 +3759,24 @@ info_static_tracepoint_markers_command (char *arg, int from_tty)
      don't work without in-process agent, so we don't bother users to type
      `set agent on' when to use static tracepoint.  */
 
-  old_chain
-    = make_cleanup_ui_out_table_begin_end (uiout, 5, -1,
-                                          "StaticTracepointMarkersTable");
+  ui_out_emit_table table_emitter (uiout, 5, -1,
+                                  "StaticTracepointMarkersTable");
 
-  ui_out_table_header (uiout, 7, ui_left, "counter", "Cnt");
+  uiout->table_header (7, ui_left, "counter", "Cnt");
 
-  ui_out_table_header (uiout, 40, ui_left, "marker-id", "ID");
+  uiout->table_header (40, ui_left, "marker-id", "ID");
 
-  ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb");
+  uiout->table_header (3, ui_left, "enabled", "Enb");
   if (gdbarch_addr_bit (target_gdbarch ()) <= 32)
-    ui_out_table_header (uiout, 10, ui_left, "addr", "Address");
+    uiout->table_header (10, ui_left, "addr", "Address");
   else
-    ui_out_table_header (uiout, 18, ui_left, "addr", "Address");
-  ui_out_table_header (uiout, 40, ui_noalign, "what", "What");
+    uiout->table_header (18, ui_left, "addr", "Address");
+  uiout->table_header (40, ui_noalign, "what", "What");
 
-  ui_out_table_body (uiout);
+  uiout->table_body ();
 
-  markers = target_static_tracepoint_markers_by_strid (NULL);
-  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
@@ -4138,23 +3793,19 @@ 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_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), buf->data (), buf->size ());
       return v;
     }
   else
@@ -4163,7 +3814,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;
@@ -4187,19 +3838,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.  */
@@ -4208,24 +3858,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.  */
@@ -4259,26 +3899,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);
+                          tframe_info, result.get ()) == 0)
+    return result;
 
-      return result;
-    }
-
-  do_cleanups (back_to);
   return NULL;
 }
 
@@ -4291,10 +3921,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
@@ -4304,37 +3934,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 = max (lo1, lo2);
-           nr->length = min (hi1, hi2) - nr->start;
+           result->emplace_back (start, length);
          }
 
-      normalize_mem_ranges (*result);
+      normalize_mem_ranges (result);
       return 1;
     }
 
@@ -4350,9 +3976,13 @@ static const struct internalvar_funcs sdata_funcs =
   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;
 
@@ -4365,14 +3995,14 @@ _initialize_tracepoint (void)
   traceframe_number = -1;
   tracepoint_number = -1;
 
-  add_info ("scope", scope_info,
-           _("List the variables local to a scope"));
+  add_info ("scope", info_scope_command,
+           _("List the variables local to a scope."));
 
-  add_cmd ("tracepoints", class_trace, NULL,
+  add_cmd ("tracepoints", class_trace,
           _("Tracing of program execution without stopping the program."),
           &cmdlist);
 
-  add_com ("tdump", class_trace, trace_dump_command,
+  add_com ("tdump", class_trace, tdump_command,
           _("Print everything collected at the current tracepoint."));
 
   c = add_com ("tvariable", class_trace, trace_variable_command,_("\
@@ -4388,69 +4018,67 @@ Arguments are the names of the variables to delete.\n\
 If no arguments are supplied, delete all variables."), &deletelist);
   /* FIXME add a trace variable completer.  */
 
-  add_info ("tvariables", tvariables_info, _("\
-Status of trace state variables and their values.\n\
-"));
+  add_info ("tvariables", info_tvariables_command, _("\
+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, trace_find_command, _("\
-Select a trace frame;\n\
+  add_prefix_cmd ("tfind", class_trace, tfind_command, _("\
+Select a trace frame.\n\
 No argument means forward by one frame; '-' means backward by one frame."),
                  &tfindlist, "tfind ", 1, &cmdlist);
 
-  add_cmd ("outside", class_trace, trace_find_outside_command, _("\
+  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, trace_find_range_command, _("\
+  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, trace_find_line_command, _("\
+  add_cmd ("line", class_trace, tfind_line_command, _("\
 Select a trace frame by source line.\n\
 Argument can be a line number (with optional source file),\n\
 a function name, or '*' followed by an address.\n\
 Default argument is 'the next source line that was traced'."),
           &tfindlist);
 
-  add_cmd ("tracepoint", class_trace, trace_find_tracepoint_command, _("\
+  add_cmd ("tracepoint", class_trace, tfind_tracepoint_command, _("\
 Select a trace frame by tracepoint number.\n\
 Default is the tracepoint for the current trace frame."),
           &tfindlist);
 
-  add_cmd ("pc", class_trace, trace_find_pc_command, _("\
+  add_cmd ("pc", class_trace, tfind_pc_command, _("\
 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, trace_find_end_command, _("\
+  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_cmd ("start", class_trace, trace_find_start_command,
+  add_cmd ("start", class_trace, tfind_start_command,
           _("Select the first trace frame in the trace buffer."),
           &tfindlist);
 
-  add_com ("tstatus", class_trace, trace_status_command,
+  add_com ("tstatus", class_trace, tstatus_command,
           _("Display the status of the current trace data collection."));
 
-  add_com ("tstop", class_trace, trace_stop_command, _("\
+  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, trace_start_command, _("\
+  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)."));
 
@@ -4461,7 +4089,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\
@@ -4469,8 +4098,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", class_trace, 0);
+  add_com_alias ("stepping", "while-stepping", class_trace, 0);
 
   add_com ("collect", class_trace, collect_pseudocommand, _("\
 Specify one or more data items to be collected at a tracepoint.\n\
@@ -4489,7 +4118,7 @@ Accepts a comma-separated list of (one or more) expressions.\n\
 The result of each evaluation will be discarded.\n\
 Note: this command can only be used in a tracepoint \"actions\" list."));
 
-  add_com ("actions", class_trace, trace_actions_command, _("\
+  add_com ("actions", class_trace, actions_command, _("\
 Specify the actions to be taken at a tracepoint.\n\
 Tracepoint actions may include collecting of specified data,\n\
 single-stepping, or enabling/disabling other tracepoints,\n\
@@ -4498,8 +4127,8 @@ 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);
 
@@ -4539,22 +4168,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);
 }
This page took 0.073342 seconds and 4 git commands to generate.