]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/record-btrace.c
gdb: allow specifying multiple filters when running selftests
[thirdparty/binutils-gdb.git] / gdb / record-btrace.c
index 3b6709649399a4ec8c2486cebb6fefe7c34b3fac..a1a3efc3d681404c5ed2f7edd9f95e379e291915 100644 (file)
@@ -1,6 +1,6 @@
 /* Branch trace support for GDB, the GNU debugger.
 
-   Copyright (C) 2013-2018 Free Software Foundation, Inc.
+   Copyright (C) 2013-2020 Free Software Foundation, Inc.
 
    Contributed by Intel Corp. <markus.t.metzger@intel.com>
 
 #include "frame-unwind.h"
 #include "hashtab.h"
 #include "infrun.h"
-#include "event-loop.h"
+#include "gdbsupport/event-loop.h"
 #include "inf-loop.h"
-#include "vec.h"
 #include "inferior.h"
 #include <algorithm>
+#include "gdbarch.h"
+#include "cli/cli-style.h"
+#include "async-event.h"
+#include <forward_list>
 
 static const target_info record_btrace_target_info = {
   "record-btrace",
@@ -282,15 +285,19 @@ require_btrace (void)
 static void
 record_btrace_enable_warn (struct thread_info *tp)
 {
-  TRY
+  /* Ignore this thread if its inferior is not recorded by us.  */
+  target_ops *rec = tp->inf->target_at (record_stratum);
+  if (rec != &record_btrace_ops)
+    return;
+
+  try
     {
       btrace_enable (tp, &record_btrace_conf);
     }
-  CATCH (error, RETURN_MASK_ERROR)
+  catch (const gdb_exception_error &error)
     {
-      warning ("%s", error.message);
+      warning ("%s", error.what ());
     }
-  END_CATCH
 }
 
 /* Enable automatic tracing of new threads.  */
@@ -319,7 +326,7 @@ record_btrace_auto_disable (void)
 static void
 record_btrace_handle_async_inferior_event (gdb_client_data data)
 {
-  inferior_event_handler (INF_REG_EVENT, NULL);
+  inferior_event_handler (INF_REG_EVENT);
 }
 
 /* See record-btrace.h.  */
@@ -386,7 +393,7 @@ record_btrace_target_open (const char *args, int from_tty)
   if (!target_has_execution)
     error (_("The program is not being run."));
 
-  for (thread_info *tp : all_non_exited_threads ())
+  for (thread_info *tp : current_inferior ()->non_exited_threads ())
     if (args == NULL || *args == 0 || number_is_in_list (args, tp->global_num))
       {
        btrace_enable (tp, &record_btrace_conf);
@@ -408,7 +415,7 @@ record_btrace_target::stop_recording ()
 
   record_btrace_auto_disable ();
 
-  for (thread_info *tp : all_non_exited_threads ())
+  for (thread_info *tp : current_inferior ()->non_exited_threads ())
     if (tp->btrace.target != NULL)
       btrace_disable (tp);
 }
@@ -442,7 +449,7 @@ record_btrace_target::close ()
 
   /* We should have already stopped recording.
      Tear down btrace in case we have not.  */
-  for (thread_info *tp : all_non_exited_threads ())
+  for (thread_info *tp : current_inferior ()->non_exited_threads ())
     btrace_teardown (tp);
 }
 
@@ -541,7 +548,7 @@ record_btrace_print_conf (const struct btrace_config *conf)
       return;
     }
 
-  internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
+  internal_error (__FILE__, __LINE__, _("Unknown branch trace format."));
 }
 
 /* The info_record method of target record-btrace.  */
@@ -556,10 +563,11 @@ record_btrace_target::info_record ()
 
   DEBUG ("info");
 
-  tp = find_thread_ptid (inferior_ptid);
-  if (tp == NULL)
+  if (inferior_ptid == null_ptid)
     error (_("No thread."));
 
+  tp = inferior_thread ();
+
   validate_registers_access ();
 
   btinfo = &tp->btrace;
@@ -596,7 +604,8 @@ record_btrace_target::info_record ()
 
   printf_unfiltered (_("Recorded %u instructions in %u functions (%u gaps) "
                       "for thread %s (%s).\n"), insns, calls, gaps,
-                    print_thread_id (tp), target_pid_to_str (tp->ptid));
+                    print_thread_id (tp),
+                    target_pid_to_str (tp->ptid).c_str ());
 
   if (btrace_is_replaying (tp))
     printf_unfiltered (_("Replay in progress.  At instruction %u.\n"),
@@ -616,21 +625,13 @@ btrace_ui_out_decode_error (struct ui_out *uiout, int errcode,
   if (!(format == BTRACE_FORMAT_PT && errcode > 0))
     {
       uiout->text (_("decode error ("));
-      uiout->field_int ("errcode", errcode);
+      uiout->field_signed ("errcode", errcode);
       uiout->text (_("): "));
     }
   uiout->text (errstr);
   uiout->text (_("]\n"));
 }
 
-/* Print an unsigned int.  */
-
-static void
-ui_out_field_uint (struct ui_out *uiout, const char *fld, unsigned int val)
-{
-  uiout->field_fmt (fld, "%u", val);
-}
-
 /* A range of source lines.  */
 
 struct btrace_line_range
@@ -724,7 +725,16 @@ btrace_find_line_range (CORE_ADDR pc)
   range = btrace_mk_line_range (symtab, 0, 0);
   for (i = 0; i < nlines - 1; i++)
     {
-      if ((lines[i].pc == pc) && (lines[i].line != 0))
+      /* The test of is_stmt here was added when the is_stmt field was
+        introduced to the 'struct linetable_entry' structure.  This
+        ensured that this loop maintained the same behaviour as before we
+        introduced is_stmt.  That said, it might be that we would be
+        better off not checking is_stmt here, this would lead to us
+        possibly adding more line numbers to the range.  At the time this
+        change was made I was unsure how to test this so chose to go with
+        maintaining the existing experience.  */
+      if ((lines[i].pc == pc) && (lines[i].line != 0)
+         && (lines[i].is_stmt == 1))
        range = btrace_line_range_add (range, lines[i].line);
     }
 
@@ -785,7 +795,7 @@ btrace_insn_history (struct ui_out *uiout,
   gdb::optional<ui_out_emit_tuple> src_and_asm_tuple;
   gdb::optional<ui_out_emit_list> asm_list;
 
-  gdb_pretty_print_disassembler disasm (gdbarch);
+  gdb_pretty_print_disassembler disasm (gdbarch, uiout);
 
   for (btrace_insn_iterator it = *begin; btrace_insn_cmp (&it, end) != 0;
          btrace_insn_next (&it, 1))
@@ -848,7 +858,7 @@ btrace_insn_history (struct ui_out *uiout,
          if ((insn->flags & BTRACE_INSN_FLAG_SPECULATIVE) != 0)
            dinsn.is_speculative = 1;
 
-         disasm.pretty_print_insn (uiout, &dinsn, flags);
+         disasm.pretty_print_insn (&dinsn, flags);
        }
     }
 }
@@ -1032,9 +1042,9 @@ btrace_call_history_insn_range (struct ui_out *uiout,
   begin = bfun->insn_offset;
   end = begin + size - 1;
 
-  ui_out_field_uint (uiout, "insn begin", begin);
+  uiout->field_unsigned ("insn begin", begin);
   uiout->text (",");
-  ui_out_field_uint (uiout, "insn end", end);
+  uiout->field_unsigned ("insn end", end);
 }
 
 /* Compute the lowest and highest source line for the instructions in BFUN
@@ -1091,20 +1101,20 @@ btrace_call_history_src_line (struct ui_out *uiout,
 
   uiout->field_string ("file",
                       symtab_to_filename_for_display (symbol_symtab (sym)),
-                      ui_out_style_kind::FILE);
+                      file_name_style.style ());
 
   btrace_compute_src_line_range (bfun, &begin, &end);
   if (end < begin)
     return;
 
   uiout->text (":");
-  uiout->field_int ("min line", begin);
+  uiout->field_signed ("min line", begin);
 
   if (end == begin)
     return;
 
   uiout->text (",");
-  uiout->field_int ("max line", end);
+  uiout->field_signed ("max line", end);
 }
 
 /* Get the name of a branch trace function.  */
@@ -1122,9 +1132,9 @@ btrace_get_bfun_name (const struct btrace_function *bfun)
   sym = bfun->sym;
 
   if (sym != NULL)
-    return SYMBOL_PRINT_NAME (sym);
+    return sym->print_name ();
   else if (msym != NULL)
-    return MSYMBOL_PRINT_NAME (msym);
+    return msym->print_name ();
   else
     return "??";
 }
@@ -1155,7 +1165,7 @@ btrace_call_history (struct ui_out *uiout,
       msym = bfun->msym;
 
       /* Print the function index.  */
-      ui_out_field_uint (uiout, "index", bfun->number);
+      uiout->field_unsigned ("index", bfun->number);
       uiout->text ("\t");
 
       /* Indicate gaps in the trace.  */
@@ -1182,14 +1192,14 @@ btrace_call_history (struct ui_out *uiout,
        }
 
       if (sym != NULL)
-       uiout->field_string ("function", SYMBOL_PRINT_NAME (sym),
-                            ui_out_style_kind::FUNCTION);
+       uiout->field_string ("function", sym->print_name (),
+                            function_name_style.style ());
       else if (msym != NULL)
-       uiout->field_string ("function", MSYMBOL_PRINT_NAME (msym),
-                            ui_out_style_kind::FUNCTION);
+       uiout->field_string ("function", msym->print_name (),
+                            function_name_style.style ());
       else if (!uiout->is_mi_like_p ())
        uiout->field_string ("function", "??",
-                            ui_out_style_kind::FUNCTION);
+                            function_name_style.style ());
 
       if ((flags & RECORD_PRINT_INSN_RANGE) != 0)
        {
@@ -1380,7 +1390,8 @@ record_btrace_target::call_history_from (ULONGEST from, int size,
 enum record_method
 record_btrace_target::record_method (ptid_t ptid)
 {
-  struct thread_info * const tp = find_thread_ptid (ptid);
+  process_stratum_target *proc_target = current_inferior ()->process_target ();
+  thread_info *const tp = find_thread_ptid (proc_target, ptid);
 
   if (tp == NULL)
     error (_("No thread."));
@@ -1396,7 +1407,8 @@ record_btrace_target::record_method (ptid_t ptid)
 bool
 record_btrace_target::record_is_replaying (ptid_t ptid)
 {
-  for (thread_info *tp : all_non_exited_threads (ptid))
+  process_stratum_target *proc_target = current_inferior ()->process_target ();
+  for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
     if (btrace_is_replaying (tp))
       return true;
 
@@ -1442,8 +1454,7 @@ record_btrace_target::xfer_partial (enum target_object object,
            if (section != NULL)
              {
                /* Check if the section we found is readonly.  */
-               if ((bfd_get_section_flags (section->the_bfd_section->owner,
-                                           section->the_bfd_section)
+               if ((bfd_section_flags (section->the_bfd_section)
                     & SEC_READONLY) != 0)
                  {
                    /* Truncate the request to fit into this section.  */
@@ -1478,16 +1489,15 @@ record_btrace_target::insert_breakpoint (struct gdbarch *gdbarch,
   replay_memory_access = replay_memory_access_read_write;
 
   ret = 0;
-  TRY
+  try
     {
       ret = this->beneath ()->insert_breakpoint (gdbarch, bp_tgt);
     }
-  CATCH (except, RETURN_MASK_ALL)
+  catch (const gdb_exception &except)
     {
       replay_memory_access = old;
-      throw_exception (except);
+      throw;
     }
-  END_CATCH
   replay_memory_access = old;
 
   return ret;
@@ -1509,16 +1519,15 @@ record_btrace_target::remove_breakpoint (struct gdbarch *gdbarch,
   replay_memory_access = replay_memory_access_read_write;
 
   ret = 0;
-  TRY
+  try
     {
       ret = this->beneath ()->remove_breakpoint (gdbarch, bp_tgt, reason);
     }
-  CATCH (except, RETURN_MASK_ALL)
+  catch (const gdb_exception &except)
     {
       replay_memory_access = old;
-      throw_exception (except);
+      throw;
     }
-  END_CATCH
   replay_memory_access = old;
 
   return ret;
@@ -1529,14 +1538,16 @@ record_btrace_target::remove_breakpoint (struct gdbarch *gdbarch,
 void
 record_btrace_target::fetch_registers (struct regcache *regcache, int regno)
 {
-  struct btrace_insn_iterator *replay;
-  struct thread_info *tp;
+  btrace_insn_iterator *replay = nullptr;
 
-  tp = find_thread_ptid (regcache->ptid ());
-  gdb_assert (tp != NULL);
+  /* Thread-db may ask for a thread's registers before GDB knows about the
+     thread.  We forward the request to the target beneath in this
+     case.  */
+  thread_info *tp = find_thread_ptid (regcache->target (), regcache->ptid ());
+  if (tp != nullptr)
+    replay =  tp->btrace.replay;
 
-  replay = tp->btrace.replay;
-  if (replay != NULL && !record_btrace_generating_corefile)
+  if (replay != nullptr && !record_btrace_generating_corefile)
     {
       const struct btrace_insn *insn;
       struct gdbarch *gdbarch;
@@ -1569,7 +1580,7 @@ record_btrace_target::store_registers (struct regcache *regcache, int regno)
       && record_is_replaying (regcache->ptid ()))
     error (_("Cannot write registers while replaying."));
 
-  gdb_assert (may_write_registers != 0);
+  gdb_assert (may_write_registers);
 
   this->beneath ()->store_registers (regcache, regno);
 }
@@ -1871,7 +1882,7 @@ record_btrace_frame_dealloc_cache (struct frame_info *self, void *this_cache)
 }
 
 /* btrace recording does not store previous memory content, neither the stack
-   frames content.  Any unwinding would return errorneous results as the stack
+   frames content.  Any unwinding would return erroneous results as the stack
    contents no longer matches the changed PC value restored from history.
    Therefore this unwinder reports any possibly unwound registers as
    <unavailable>.  */
@@ -1949,7 +1960,8 @@ record_btrace_resume_thread (struct thread_info *tp,
   struct btrace_thread_info *btinfo;
 
   DEBUG ("resuming thread %s (%s): %x (%s)", print_thread_id (tp),
-        target_pid_to_str (tp->ptid), flag, btrace_thread_flag_to_str (flag));
+        target_pid_to_str (tp->ptid).c_str (), flag,
+        btrace_thread_flag_to_str (flag));
 
   btinfo = &tp->btrace;
 
@@ -1967,7 +1979,7 @@ static struct frame_id
 get_thread_current_frame_id (struct thread_info *tp)
 {
   struct frame_id id;
-  int executing;
+  bool executing;
 
   /* Set current thread, which is implicitly used by
      get_current_frame.  */
@@ -1975,32 +1987,33 @@ get_thread_current_frame_id (struct thread_info *tp)
 
   switch_to_thread (tp);
 
+  process_stratum_target *proc_target = tp->inf->process_target ();
+
   /* Clear the executing flag to allow changes to the current frame.
      We are not actually running, yet.  We just started a reverse execution
      command or a record goto command.
      For the latter, EXECUTING is false and this has no effect.
      For the former, EXECUTING is true and we're in wait, about to
      move the thread.  Since we need to recompute the stack, we temporarily
-     set EXECUTING to flase.  */
+     set EXECUTING to false.  */
   executing = tp->executing;
-  set_executing (inferior_ptid, false);
+  set_executing (proc_target, inferior_ptid, false);
 
   id = null_frame_id;
-  TRY
+  try
     {
       id = get_frame_id (get_current_frame ());
     }
-  CATCH (except, RETURN_MASK_ALL)
+  catch (const gdb_exception &except)
     {
       /* Restore the previous execution state.  */
-      set_executing (inferior_ptid, executing);
+      set_executing (proc_target, inferior_ptid, executing);
 
-      throw_exception (except);
+      throw;
     }
-  END_CATCH
 
   /* Restore the previous execution state.  */
-  set_executing (inferior_ptid, executing);
+  set_executing (proc_target, inferior_ptid, executing);
 
   return id;
 }
@@ -2025,7 +2038,7 @@ record_btrace_start_replaying (struct thread_info *tp)
      Since frames are computed differently when we're replaying, we need to
      recompute those stored frames and fix them up so we can still detect
      subroutines after we started replaying.  */
-  TRY
+  try
     {
       struct frame_id frame_id;
       int upd_step_frame_id, upd_step_stack_frame_id;
@@ -2070,16 +2083,15 @@ record_btrace_start_replaying (struct thread_info *tp)
       if (upd_step_stack_frame_id)
        tp->control.step_stack_frame_id = frame_id;
     }
-  CATCH (except, RETURN_MASK_ALL)
+  catch (const gdb_exception &except)
     {
       xfree (btinfo->replay);
       btinfo->replay = NULL;
 
       registers_changed_thread (tp);
 
-      throw_exception (except);
+      throw;
     }
-  END_CATCH
 
   return replay;
 }
@@ -2127,7 +2139,7 @@ record_btrace_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
 {
   enum btrace_thread_flag flag, cflag;
 
-  DEBUG ("resume %s: %s%s", target_pid_to_str (ptid),
+  DEBUG ("resume %s: %s%s", target_pid_to_str (ptid).c_str (),
         ::execution_direction == EXEC_REVERSE ? "reverse-" : "",
         step ? "step" : "cont");
 
@@ -2165,11 +2177,14 @@ record_btrace_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
      record_btrace_wait below.
 
      For all-stop targets, we only step INFERIOR_PTID and continue others.  */
+
+  process_stratum_target *proc_target = current_inferior ()->process_target ();
+
   if (!target_is_non_stop_p ())
     {
       gdb_assert (inferior_ptid.matches (ptid));
 
-      for (thread_info *tp : all_non_exited_threads (ptid))
+      for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
        {
          if (tp->ptid.matches (inferior_ptid))
            record_btrace_resume_thread (tp, flag);
@@ -2179,7 +2194,7 @@ record_btrace_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
     }
   else
     {
-      for (thread_info *tp : all_non_exited_threads (ptid))
+      for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
        record_btrace_resume_thread (tp, flag);
     }
 
@@ -2214,7 +2229,7 @@ record_btrace_cancel_resume (struct thread_info *tp)
 
   DEBUG ("cancel resume thread %s (%s): %x (%s)",
         print_thread_id (tp),
-        target_pid_to_str (tp->ptid), flags,
+        target_pid_to_str (tp->ptid).c_str (), flags,
         btrace_thread_flag_to_str (flags));
 
   tp->btrace.flags &= ~(BTHR_MOVE | BTHR_STOP);
@@ -2442,7 +2457,7 @@ record_btrace_step_thread (struct thread_info *tp)
   btinfo->flags &= ~(BTHR_MOVE | BTHR_STOP);
 
   DEBUG ("stepping thread %s (%s): %x (%s)", print_thread_id (tp),
-        target_pid_to_str (tp->ptid), flags,
+        target_pid_to_str (tp->ptid).c_str (), flags,
         btrace_thread_flag_to_str (flags));
 
   /* We can't step without an execution history.  */
@@ -2527,7 +2542,7 @@ record_btrace_target::wait (ptid_t ptid, struct target_waitstatus *status,
   std::vector<thread_info *> moving;
   std::vector<thread_info *> no_history;
 
-  DEBUG ("wait %s (0x%x)", target_pid_to_str (ptid), options);
+  DEBUG ("wait %s (0x%x)", target_pid_to_str (ptid).c_str (), options);
 
   /* As long as we're not replaying, just forward the request.  */
   if ((::execution_direction != EXEC_REVERSE)
@@ -2537,7 +2552,8 @@ record_btrace_target::wait (ptid_t ptid, struct target_waitstatus *status,
     }
 
   /* Keep a work list of moving threads.  */
-  for (thread_info *tp : all_non_exited_threads (ptid))
+  process_stratum_target *proc_target = current_inferior ()->process_target ();
+  for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
     if ((tp->btrace.flags & (BTHR_MOVE | BTHR_STOP)) != 0)
       moving.push_back (tp);
 
@@ -2545,7 +2561,7 @@ record_btrace_target::wait (ptid_t ptid, struct target_waitstatus *status,
     {
       *status = btrace_step_no_resumed ();
 
-      DEBUG ("wait ended by %s: %s", target_pid_to_str (null_ptid),
+      DEBUG ("wait ended by %s: %s", target_pid_to_str (null_ptid).c_str (),
             target_waitstatus_to_string (status).c_str ());
 
       return null_ptid;
@@ -2620,7 +2636,7 @@ record_btrace_target::wait (ptid_t ptid, struct target_waitstatus *status,
   /* Stop all other threads. */
   if (!target_is_non_stop_p ())
     {
-      for (thread_info *tp : all_non_exited_threads ())
+      for (thread_info *tp : current_inferior ()->non_exited_threads ())
        record_btrace_cancel_resume (tp);
     }
 
@@ -2636,7 +2652,7 @@ record_btrace_target::wait (ptid_t ptid, struct target_waitstatus *status,
 
   DEBUG ("wait ended by thread %s (%s): %s",
         print_thread_id (eventing),
-        target_pid_to_str (eventing->ptid),
+        target_pid_to_str (eventing->ptid).c_str (),
         target_waitstatus_to_string (status).c_str ());
 
   return eventing->ptid;
@@ -2647,7 +2663,7 @@ record_btrace_target::wait (ptid_t ptid, struct target_waitstatus *status,
 void
 record_btrace_target::stop (ptid_t ptid)
 {
-  DEBUG ("stop %s", target_pid_to_str (ptid));
+  DEBUG ("stop %s", target_pid_to_str (ptid).c_str ());
 
   /* As long as we're not replaying, just forward the request.  */
   if ((::execution_direction != EXEC_REVERSE)
@@ -2657,7 +2673,10 @@ record_btrace_target::stop (ptid_t ptid)
     }
   else
     {
-      for (thread_info *tp : all_non_exited_threads (ptid))
+      process_stratum_target *proc_target
+       = current_inferior ()->process_target ();
+
+      for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
        {
          tp->btrace.flags &= ~BTHR_MOVE;
          tp->btrace.flags |= BTHR_STOP;
@@ -2854,7 +2873,7 @@ record_btrace_target::goto_record (ULONGEST insn)
 void
 record_btrace_target::record_stop_replaying ()
 {
-  for (thread_info *tp : all_non_exited_threads ())
+  for (thread_info *tp : current_inferior ()->non_exited_threads ())
     record_btrace_stop_replaying (tp);
 }
 
@@ -2892,16 +2911,15 @@ cmd_record_btrace_bts_start (const char *args, int from_tty)
 
   record_btrace_conf.format = BTRACE_FORMAT_BTS;
 
-  TRY
+  try
     {
       execute_command ("target record-btrace", from_tty);
     }
-  CATCH (exception, RETURN_MASK_ALL)
+  catch (const gdb_exception &exception)
     {
       record_btrace_conf.format = BTRACE_FORMAT_NONE;
-      throw_exception (exception);
+      throw;
     }
-  END_CATCH
 }
 
 /* Start recording in Intel Processor Trace format.  */
@@ -2914,16 +2932,15 @@ cmd_record_btrace_pt_start (const char *args, int from_tty)
 
   record_btrace_conf.format = BTRACE_FORMAT_PT;
 
-  TRY
+  try
     {
       execute_command ("target record-btrace", from_tty);
     }
-  CATCH (exception, RETURN_MASK_ALL)
+  catch (const gdb_exception &exception)
     {
       record_btrace_conf.format = BTRACE_FORMAT_NONE;
-      throw_exception (exception);
+      throw;
     }
-  END_CATCH
 }
 
 /* Alias for "target record".  */
@@ -2936,45 +2953,24 @@ cmd_record_btrace_start (const char *args, int from_tty)
 
   record_btrace_conf.format = BTRACE_FORMAT_PT;
 
-  TRY
+  try
     {
       execute_command ("target record-btrace", from_tty);
     }
-  CATCH (exception, RETURN_MASK_ALL)
+  catch (const gdb_exception &exception)
     {
       record_btrace_conf.format = BTRACE_FORMAT_BTS;
 
-      TRY
+      try
        {
          execute_command ("target record-btrace", from_tty);
        }
-      CATCH (ex, RETURN_MASK_ALL)
+      catch (const gdb_exception &ex)
        {
          record_btrace_conf.format = BTRACE_FORMAT_NONE;
-         throw_exception (ex);
+         throw;
        }
-      END_CATCH
     }
-  END_CATCH
-}
-
-/* The "set record btrace" command.  */
-
-static void
-cmd_set_record_btrace (const char *args, int from_tty)
-{
-  printf_unfiltered (_("\"set record btrace\" must be followed "
-                      "by an appropriate subcommand.\n"));
-  help_list (set_record_btrace_cmdlist, "set record btrace ",
-            all_commands, gdb_stdout);
-}
-
-/* The "show record btrace" command.  */
-
-static void
-cmd_show_record_btrace (const char *args, int from_tty)
-{
-  cmd_show_list (show_record_btrace_cmdlist, from_tty, "");
 }
 
 /* The "show record btrace replay-memory-access" command.  */
@@ -3091,44 +3087,6 @@ cmd_show_record_btrace_cpu (const char *args, int from_tty)
   error (_("Internal error: bad cpu state."));
 }
 
-/* The "s record btrace bts" command.  */
-
-static void
-cmd_set_record_btrace_bts (const char *args, int from_tty)
-{
-  printf_unfiltered (_("\"set record btrace bts\" must be followed "
-                      "by an appropriate subcommand.\n"));
-  help_list (set_record_btrace_bts_cmdlist, "set record btrace bts ",
-            all_commands, gdb_stdout);
-}
-
-/* The "show record btrace bts" command.  */
-
-static void
-cmd_show_record_btrace_bts (const char *args, int from_tty)
-{
-  cmd_show_list (show_record_btrace_bts_cmdlist, from_tty, "");
-}
-
-/* The "set record btrace pt" command.  */
-
-static void
-cmd_set_record_btrace_pt (const char *args, int from_tty)
-{
-  printf_unfiltered (_("\"set record btrace pt\" must be followed "
-                      "by an appropriate subcommand.\n"));
-  help_list (set_record_btrace_pt_cmdlist, "set record btrace pt ",
-            all_commands, gdb_stdout);
-}
-
-/* The "show record btrace pt" command.  */
-
-static void
-cmd_show_record_btrace_pt (const char *args, int from_tty)
-{
-  cmd_show_list (show_record_btrace_pt_cmdlist, from_tty, "");
-}
-
 /* The "record bts buffer-size" show value function.  */
 
 static void
@@ -3153,8 +3111,9 @@ show_record_pt_buffer_size_value (struct ui_file *file, int from_tty,
 
 /* Initialize btrace commands.  */
 
+void _initialize_record_btrace ();
 void
-_initialize_record_btrace (void)
+_initialize_record_btrace ()
 {
   add_prefix_cmd ("btrace", class_obscure, cmd_record_btrace_start,
                  _("Start branch trace recording."), &record_btrace_cmdlist,
@@ -3176,13 +3135,13 @@ This format may not be available on all processors."),
           &record_btrace_cmdlist);
   add_alias_cmd ("pt", "btrace pt", class_obscure, 1, &record_cmdlist);
 
-  add_prefix_cmd ("btrace", class_support, cmd_set_record_btrace,
-                 _("Set record options"), &set_record_btrace_cmdlist,
-                 "set record btrace ", 0, &set_record_cmdlist);
+  add_basic_prefix_cmd ("btrace", class_support,
+                       _("Set record options."), &set_record_btrace_cmdlist,
+                       "set record btrace ", 0, &set_record_cmdlist);
 
-  add_prefix_cmd ("btrace", class_support, cmd_show_record_btrace,
-                 _("Show record options"), &show_record_btrace_cmdlist,
-                 "show record btrace ", 0, &show_record_cmdlist);
+  add_show_prefix_cmd ("btrace", class_support,
+                      _("Show record options."), &show_record_btrace_cmdlist,
+                      "show record btrace ", 0, &show_record_cmdlist);
 
   add_setshow_enum_cmd ("replay-memory-access", no_class,
                        replay_memory_access_types, &replay_memory_access, _("\
@@ -3210,7 +3169,7 @@ When GDB does not support that cpu, this option can be used to enable\n\
 workarounds for a similar cpu that GDB supports.\n\n\
 When set to \"none\", errata workarounds are disabled."),
                  &set_record_btrace_cpu_cmdlist,
-                 _("set record btrace cpu "), 1,
+                 "set record btrace cpu ", 1,
                  &set_record_btrace_cmdlist);
 
   add_cmd ("auto", class_support, cmd_set_record_btrace_cpu_auto, _("\
@@ -3225,15 +3184,17 @@ Do not enable errata workarounds for trace decode."),
 Show the cpu to be used for trace decode."),
           &show_record_btrace_cmdlist);
 
-  add_prefix_cmd ("bts", class_support, cmd_set_record_btrace_bts,
-                 _("Set record btrace bts options"),
-                 &set_record_btrace_bts_cmdlist,
-                 "set record btrace bts ", 0, &set_record_btrace_cmdlist);
+  add_basic_prefix_cmd ("bts", class_support,
+                       _("Set record btrace bts options."),
+                       &set_record_btrace_bts_cmdlist,
+                       "set record btrace bts ", 0,
+                       &set_record_btrace_cmdlist);
 
-  add_prefix_cmd ("bts", class_support, cmd_show_record_btrace_bts,
-                 _("Show record btrace bts options"),
-                 &show_record_btrace_bts_cmdlist,
-                 "show record btrace bts ", 0, &show_record_btrace_cmdlist);
+  add_show_prefix_cmd ("bts", class_support,
+                      _("Show record btrace bts options."),
+                      &show_record_btrace_bts_cmdlist,
+                      "show record btrace bts ", 0,
+                      &show_record_btrace_cmdlist);
 
   add_setshow_uinteger_cmd ("buffer-size", no_class,
                            &record_btrace_conf.bts.size,
@@ -3249,15 +3210,17 @@ The trace buffer size may not be changed while recording."), NULL,
                            &set_record_btrace_bts_cmdlist,
                            &show_record_btrace_bts_cmdlist);
 
-  add_prefix_cmd ("pt", class_support, cmd_set_record_btrace_pt,
-                 _("Set record btrace pt options"),
-                 &set_record_btrace_pt_cmdlist,
-                 "set record btrace pt ", 0, &set_record_btrace_cmdlist);
-
-  add_prefix_cmd ("pt", class_support, cmd_show_record_btrace_pt,
-                 _("Show record btrace pt options"),
-                 &show_record_btrace_pt_cmdlist,
-                 "show record btrace pt ", 0, &show_record_btrace_cmdlist);
+  add_basic_prefix_cmd ("pt", class_support,
+                       _("Set record btrace pt options."),
+                       &set_record_btrace_pt_cmdlist,
+                       "set record btrace pt ", 0,
+                       &set_record_btrace_cmdlist);
+
+  add_show_prefix_cmd ("pt", class_support,
+                      _("Show record btrace pt options."),
+                      &show_record_btrace_pt_cmdlist,
+                      "show record btrace pt ", 0,
+                      &show_record_btrace_cmdlist);
 
   add_setshow_uinteger_cmd ("buffer-size", no_class,
                            &record_btrace_conf.pt.size,