]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/record.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / record.c
index 34ebd1bd7c6009f52e09ac366d0e313a03c90e09..f7c95153537448f2267e9a6882806b3633318767 100644 (file)
@@ -1,6 +1,6 @@
 /* Process record and replay target for GDB, the GNU debugger.
 
-   Copyright (C) 2008-2016 Free Software Foundation, Inc.
+   Copyright (C) 2008-2023 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -21,9 +21,9 @@
 #include "gdbcmd.h"
 #include "completer.h"
 #include "record.h"
-#include "observer.h"
+#include "observable.h"
 #include "inferior.h"
-#include "common/common-utils.h"
+#include "gdbsupport/common-utils.h"
 #include "cli/cli-utils.h"
 #include "disasm.h"
 
@@ -48,14 +48,14 @@ static unsigned int record_call_history_size = 10;
 static unsigned int record_call_history_size_setshow_var;
 
 struct cmd_list_element *record_cmdlist = NULL;
-struct cmd_list_element *record_goto_cmdlist = NULL;
+static struct cmd_list_element *record_goto_cmdlist = NULL;
 struct cmd_list_element *set_record_cmdlist = NULL;
 struct cmd_list_element *show_record_cmdlist = NULL;
 struct cmd_list_element *info_record_cmdlist = NULL;
 
 #define DEBUG(msg, args...)                                            \
   if (record_debug)                                                    \
-    fprintf_unfiltered (gdb_stdlog, "record: " msg "\n", ##args)
+    gdb_printf (gdb_stdlog, "record: " msg "\n", ##args)
 
 /* See record.h.  */
 
@@ -74,8 +74,8 @@ require_record_target (void)
 
   t = find_record_target ();
   if (t == NULL)
-    error (_("No record target is currently active.\n"
-            "Use one of the \"target record-<tab><tab>\" commands first."));
+    error (_("No recording is currently active.\n"
+            "Use the \"record full\" or \"record btrace\" command first."));
 
   return t;
 }
@@ -93,6 +93,48 @@ record_preopen (void)
 
 /* See record.h.  */
 
+void
+record_start (const char *method, const char *format, int from_tty)
+{
+  if (method == NULL)
+    {
+      if (format == NULL)
+       execute_command_to_string ("record", from_tty, false);
+      else
+       error (_("Invalid format."));
+    }
+  else if (strcmp (method, "full") == 0)
+    {
+      if (format == NULL)
+       execute_command_to_string ("record full", from_tty, false);
+      else
+       error (_("Invalid format."));
+    }
+  else if (strcmp (method, "btrace") == 0)
+    {
+      if (format == NULL)
+       execute_command_to_string ("record btrace", from_tty, false);
+      else if (strcmp (format, "bts") == 0)
+       execute_command_to_string ("record btrace bts", from_tty, false);
+      else if (strcmp (format, "pt") == 0)
+       execute_command_to_string ("record btrace pt", from_tty, false);
+      else
+       error (_("Invalid format."));
+    }
+  else
+    error (_("Invalid method."));
+}
+
+/* See record.h.  */
+
+void
+record_stop (int from_tty)
+{
+  execute_command_to_string ("record stop", from_tty, false);
+}
+
+/* See record.h.  */
+
 int
 record_read_memory (struct gdbarch *gdbarch,
                    CORE_ADDR memaddr, gdb_byte *myaddr,
@@ -112,9 +154,9 @@ record_read_memory (struct gdbarch *gdbarch,
 static void
 record_stop (struct target_ops *t)
 {
-  DEBUG ("stop %s", t->to_shortname);
+  DEBUG ("stop %s", t->shortname ());
 
-  t->to_stop_recording (t);
+  t->stop_recording ();
 }
 
 /* Unpush the record target.  */
@@ -122,9 +164,9 @@ record_stop (struct target_ops *t)
 static void
 record_unpush (struct target_ops *t)
 {
-  DEBUG ("unpush %s", t->to_shortname);
+  DEBUG ("unpush %s", t->shortname ());
 
-  unpush_target (t);
+  current_inferior ()->unpush_target (t);
 }
 
 /* See record.h.  */
@@ -132,9 +174,9 @@ record_unpush (struct target_ops *t)
 void
 record_disconnect (struct target_ops *t, const char *args, int from_tty)
 {
-  gdb_assert (t->to_stratum == record_stratum);
+  gdb_assert (t->stratum () == record_stratum);
 
-  DEBUG ("disconnect %s", t->to_shortname);
+  DEBUG ("disconnect %s", t->shortname ());
 
   record_stop (t);
   record_unpush (t);
@@ -145,16 +187,16 @@ record_disconnect (struct target_ops *t, const char *args, int from_tty)
 /* See record.h.  */
 
 void
-record_detach (struct target_ops *t, const char *args, int from_tty)
+record_detach (struct target_ops *t, inferior *inf, int from_tty)
 {
-  gdb_assert (t->to_stratum == record_stratum);
+  gdb_assert (t->stratum () == record_stratum);
 
-  DEBUG ("detach %s", t->to_shortname);
+  DEBUG ("detach %s", t->shortname ());
 
   record_stop (t);
   record_unpush (t);
 
-  target_detach (args, from_tty);
+  target_detach (inf, from_tty);
 }
 
 /* See record.h.  */
@@ -162,9 +204,9 @@ record_detach (struct target_ops *t, const char *args, int from_tty)
 void
 record_mourn_inferior (struct target_ops *t)
 {
-  gdb_assert (t->to_stratum == record_stratum);
+  gdb_assert (t->stratum () == record_stratum);
 
-  DEBUG ("mourn inferior %s", t->to_shortname);
+  DEBUG ("mourn inferior %s", t->shortname ());
 
   /* It is safer to not stop recording.  Resources will be freed when
      threads are discarded.  */
@@ -178,9 +220,9 @@ record_mourn_inferior (struct target_ops *t)
 void
 record_kill (struct target_ops *t)
 {
-  gdb_assert (t->to_stratum == record_stratum);
+  gdb_assert (t->stratum () == record_stratum);
 
-  DEBUG ("kill %s", t->to_shortname);
+  DEBUG ("kill %s", t->shortname ());
 
   /* It is safer to not stop recording.  Resources will be freed when
      threads are discarded.  */
@@ -192,7 +234,8 @@ record_kill (struct target_ops *t)
 /* See record.h.  */
 
 int
-record_check_stopped_by_breakpoint (struct address_space *aspace, CORE_ADDR pc,
+record_check_stopped_by_breakpoint (const address_space *aspace,
+                                   CORE_ADDR pc,
                                    enum target_stop_reason *reason)
 {
   if (breakpoint_inserted_here_p (aspace, pc))
@@ -214,14 +257,14 @@ static void
 show_record_debug (struct ui_file *file, int from_tty,
                   struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("Debugging of process record target is %s.\n"),
-                   value);
+  gdb_printf (file, _("Debugging of process record target is %s.\n"),
+             value);
 }
 
 /* Alias for "target record".  */
 
 static void
-cmd_record_start (char *args, int from_tty)
+cmd_record_start (const char *args, int from_tty)
 {
   execute_command ("target record-full", from_tty);
 }
@@ -230,20 +273,20 @@ cmd_record_start (char *args, int from_tty)
    of replay until the end.  */
 
 static void
-cmd_record_delete (char *args, int from_tty)
+cmd_record_delete (const char *args, int from_tty)
 {
   require_record_target ();
 
   if (!target_record_is_replaying (inferior_ptid))
     {
-      printf_unfiltered (_("Already at end of record list.\n"));
+      gdb_printf (_("Already at end of record list.\n"));
       return;
     }
 
   if (!target_supports_delete_record ())
     {
-      printf_unfiltered (_("The current record target does not support "
-                          "this operation.\n"));
+      gdb_printf (_("The current record target does not support "
+                   "this operation.\n"));
       return;
     }
 
@@ -256,7 +299,7 @@ cmd_record_delete (char *args, int from_tty)
 /* Implement the "stoprecord" or "record stop" command.  */
 
 static void
-cmd_record_stop (char *args, int from_tty)
+cmd_record_stop (const char *args, int from_tty)
 {
   struct target_ops *t;
 
@@ -265,54 +308,38 @@ cmd_record_stop (char *args, int from_tty)
   record_stop (t);
   record_unpush (t);
 
-  printf_unfiltered (_("Process record is stopped and all execution "
-                      "logs are deleted.\n"));
-
-  observer_notify_record_changed (current_inferior (), 0, NULL, NULL);
-}
-
-/* The "set record" command.  */
+  gdb_printf (_("Process record is stopped and all execution "
+               "logs are deleted.\n"));
 
-static void
-set_record_command (char *args, int from_tty)
-{
-  printf_unfiltered (_("\"set record\" must be followed "
-                      "by an apporpriate subcommand.\n"));
-  help_list (set_record_cmdlist, "set record ", all_commands, gdb_stdout);
+  gdb::observers::record_changed.notify (current_inferior (), 0, NULL, NULL);
 }
 
-/* The "show record" command.  */
-
-static void
-show_record_command (char *args, int from_tty)
-{
-  cmd_show_list (show_record_cmdlist, from_tty, "");
-}
 
 /* The "info record" command.  */
 
 static void
-info_record_command (char *args, int from_tty)
+info_record_command (const char *args, int from_tty)
 {
   struct target_ops *t;
 
   t = find_record_target ();
   if (t == NULL)
     {
-      printf_filtered (_("No record target is currently active.\n"));
+      gdb_printf (_("No recording is currently active.\n"));
       return;
     }
 
-  printf_filtered (_("Active record target: %s\n"), t->to_shortname);
-  t->to_info_record (t);
+  gdb_printf (_("Active record target: %s\n"), t->shortname ());
+  t->info_record ();
 }
 
 /* The "record save" command.  */
 
 static void
-cmd_record_save (char *args, int from_tty)
+cmd_record_save (const char *args, int from_tty)
 {
-  char *recfilename, recfilename_buffer[40];
+  const char *recfilename;
+  char recfilename_buffer[40];
 
   require_record_target ();
 
@@ -322,7 +349,7 @@ cmd_record_save (char *args, int from_tty)
     {
       /* Default recfile name is "gdb_record.PID".  */
       xsnprintf (recfilename_buffer, sizeof (recfilename_buffer),
-                "gdb_record.%d", ptid_get_pid (inferior_ptid));
+               "gdb_record.%d", inferior_ptid.pid ());
       recfilename = recfilename_buffer;
     }
 
@@ -351,7 +378,7 @@ record_goto (const char *arg)
    Rewinds the recording (forward or backward) to the given instruction.  */
 
 static void
-cmd_record_goto (char *arg, int from_tty)
+cmd_record_goto (const char *arg, int from_tty)
 {
   record_goto (arg);
 }
@@ -359,7 +386,7 @@ cmd_record_goto (char *arg, int from_tty)
 /* The "record goto begin" command.  */
 
 static void
-cmd_record_goto_begin (char *arg, int from_tty)
+cmd_record_goto_begin (const char *arg, int from_tty)
 {
   if (arg != NULL && *arg != '\0')
     error (_("Junk after argument: %s."), arg);
@@ -371,7 +398,7 @@ cmd_record_goto_begin (char *arg, int from_tty)
 /* The "record goto end" command.  */
 
 static void
-cmd_record_goto_end (char *arg, int from_tty)
+cmd_record_goto_end (const char *arg, int from_tty)
 {
   if (arg != NULL && *arg != '\0')
     error (_("Junk after argument: %s."), arg);
@@ -383,13 +410,13 @@ cmd_record_goto_end (char *arg, int from_tty)
 /* Read an instruction number from an argument string.  */
 
 static ULONGEST
-get_insn_number (char **arg)
+get_insn_number (const char **arg)
 {
   ULONGEST number;
   const char *begin, *end, *pos;
 
   begin = *arg;
-  pos = skip_spaces_const (begin);
+  pos = skip_spaces (begin);
 
   if (!isdigit (*pos))
     error (_("Expected positive number, got: %s."), pos);
@@ -404,23 +431,25 @@ get_insn_number (char **arg)
 /* Read a context size from an argument string.  */
 
 static int
-get_context_size (char **arg)
+get_context_size (const char **arg)
 {
-  char *pos;
-  int number;
+  const char *pos;
+  char *end;
 
   pos = skip_spaces (*arg);
 
   if (!isdigit (*pos))
     error (_("Expected positive number, got: %s."), pos);
 
-  return strtol (pos, arg, 10);
+  long result = strtol (pos, &end, 10);
+  *arg = end;
+  return result;
 }
 
 /* Complain about junk at the end of an argument string.  */
 
 static void
-no_chunk (char *arg)
+no_chunk (const char *arg)
 {
   if (*arg != 0)
     error (_("Junk after argument: %s."), arg);
@@ -428,11 +457,11 @@ no_chunk (char *arg)
 
 /* Read instruction-history modifiers from an argument string.  */
 
-static int
-get_insn_history_modifiers (char **arg)
+static gdb_disassembly_flags
+get_insn_history_modifiers (const char **arg)
 {
-  int modifiers;
-  char *args;
+  gdb_disassembly_flags modifiers;
+  const char *args;
 
   modifiers = 0;
   args = *arg;
@@ -465,6 +494,9 @@ get_insn_history_modifiers (char **arg)
            case 'r':
              modifiers |= DISASSEMBLY_RAW_INSN;
              break;
+           case 'b':
+             modifiers |= DISASSEMBLY_RAW_BYTES;
+             break;
            case 'f':
              modifiers |= DISASSEMBLY_OMIT_FNAME;
              break;
@@ -507,15 +539,13 @@ command_size_to_target_size (unsigned int size)
 /* The "record instruction-history" command.  */
 
 static void
-cmd_record_insn_history (char *arg, int from_tty)
+cmd_record_insn_history (const char *arg, int from_tty)
 {
-  int flags, size;
-
   require_record_target ();
 
-  flags = get_insn_history_modifiers (&arg);
+  gdb_disassembly_flags flags = get_insn_history_modifiers (&arg);
 
-  size = command_size_to_target_size (record_insn_history_size);
+  int size = command_size_to_target_size (record_insn_history_size);
 
   if (arg == NULL || *arg == 0 || strcmp (arg, "+") == 0)
     target_insn_history (size, flags);
@@ -571,14 +601,11 @@ cmd_record_insn_history (char *arg, int from_tty)
 
 /* Read function-call-history modifiers from an argument string.  */
 
-static int
-get_call_history_modifiers (char **arg)
+static record_print_flags
+get_call_history_modifiers (const char **arg)
 {
-  int modifiers;
-  char *args;
-
-  modifiers = 0;
-  args = *arg;
+  record_print_flags modifiers = 0;
+  const char *args = *arg;
 
   if (args == NULL)
     return modifiers;
@@ -626,15 +653,13 @@ get_call_history_modifiers (char **arg)
 /* The "record function-call-history" command.  */
 
 static void
-cmd_record_call_history (char *arg, int from_tty)
+cmd_record_call_history (const char *arg, int from_tty)
 {
-  int flags, size;
-
   require_record_target ();
 
-  flags = get_call_history_modifiers (&arg);
+  record_print_flags flags = get_call_history_modifiers (&arg);
 
-  size = command_size_to_target_size (record_call_history_size);
+  int size = command_size_to_target_size (record_call_history_size);
 
   if (arg == NULL || *arg == 0 || strcmp (arg, "+") == 0)
     target_call_history (size, flags);
@@ -714,7 +739,7 @@ validate_history_size (unsigned int *command_var, unsigned int *setting)
    [0..UINT_MAX].  See command_size_to_target_size.  */
 
 static void
-set_record_insn_history_size (char *args, int from_tty,
+set_record_insn_history_size (const char *args, int from_tty,
                              struct cmd_list_element *c)
 {
   validate_history_size (&record_insn_history_size_setshow_var,
@@ -726,18 +751,16 @@ set_record_insn_history_size (char *args, int from_tty,
    [0..UINT_MAX].  See command_size_to_target_size.  */
 
 static void
-set_record_call_history_size (char *args, int from_tty,
+set_record_call_history_size (const char *args, int from_tty,
                              struct cmd_list_element *c)
 {
   validate_history_size (&record_call_history_size_setshow_var,
                         &record_call_history_size);
 }
 
-/* Provide a prototype to silence -Wmissing-prototypes.  */
-extern initialize_file_ftype _initialize_record;
-
+void _initialize_record ();
 void
-_initialize_record (void)
+_initialize_record ()
 {
   struct cmd_list_element *c;
 
@@ -765,52 +788,63 @@ A size of \"unlimited\" means unlimited lines.  The default is 10."),
                            set_record_call_history_size, NULL,
                            &set_record_cmdlist, &show_record_cmdlist);
 
-  c = add_prefix_cmd ("record", class_obscure, cmd_record_start,
+  cmd_list_element *record_cmd
+    = add_prefix_cmd ("record", class_obscure, cmd_record_start,
                      _("Start recording."),
-                     &record_cmdlist, "record ", 0, &cmdlist);
-  set_cmd_completer (c, filename_completer);
+                     &record_cmdlist, 0, &cmdlist);
+  set_cmd_completer (record_cmd, filename_completer);
+
+  add_com_alias ("rec", record_cmd, class_obscure, 1);
 
-  add_com_alias ("rec", "record", class_obscure, 1);
-  add_prefix_cmd ("record", class_support, set_record_command,
-                 _("Set record options"), &set_record_cmdlist,
-                 "set record ", 0, &setlist);
-  add_alias_cmd ("rec", "record", class_obscure, 1, &setlist);
-  add_prefix_cmd ("record", class_support, show_record_command,
-                 _("Show record options"), &show_record_cmdlist,
-                 "show record ", 0, &showlist);
-  add_alias_cmd ("rec", "record", class_obscure, 1, &showlist);
-  add_prefix_cmd ("record", class_support, info_record_command,
-                 _("Info record options"), &info_record_cmdlist,
-                 "info record ", 0, &infolist);
-  add_alias_cmd ("rec", "record", class_obscure, 1, &infolist);
+  set_show_commands setshow_record_cmds
+    = add_setshow_prefix_cmd ("record", class_support,
+                             _("Set record options."),
+                             _("Show record options."),
+                             &set_record_cmdlist, &show_record_cmdlist,
+                             &setlist, &showlist);
+
+
+  add_alias_cmd ("rec", setshow_record_cmds.set, class_obscure, 1, &setlist);
+  add_alias_cmd ("rec", setshow_record_cmds.show, class_obscure, 1, &showlist);
+
+  cmd_list_element *info_record_cmd
+    = add_prefix_cmd ("record", class_support, info_record_command,
+                     _("Info record options."), &info_record_cmdlist,
+                     0, &infolist);
+  add_alias_cmd ("rec", info_record_cmd, class_obscure, 1, &infolist);
 
   c = add_cmd ("save", class_obscure, cmd_record_save,
               _("Save the execution log to a file.\n\
-Argument is optional filename.\n\
-Default filename is 'gdb_record.<process_id>'."),
+Usage: record save [FILENAME]\n\
+Default filename is 'gdb_record.PROCESS_ID'."),
               &record_cmdlist);
   set_cmd_completer (c, filename_completer);
 
-  add_cmd ("delete", class_obscure, cmd_record_delete,
-          _("Delete the rest of execution log and start recording it anew."),
-           &record_cmdlist);
-  add_alias_cmd ("d", "delete", class_obscure, 1, &record_cmdlist);
-  add_alias_cmd ("del", "delete", class_obscure, 1, &record_cmdlist);
-
-  add_cmd ("stop", class_obscure, cmd_record_stop,
-          _("Stop the record/replay target."),
-           &record_cmdlist);
-  add_alias_cmd ("s", "stop", class_obscure, 1, &record_cmdlist);
+  cmd_list_element *record_delete_cmd
+    =  add_cmd ("delete", class_obscure, cmd_record_delete,
+               _("Delete the rest of execution log and start recording it \
+anew."),
+           &record_cmdlist);
+  add_alias_cmd ("d", record_delete_cmd, class_obscure, 1, &record_cmdlist);
+  add_alias_cmd ("del", record_delete_cmd, class_obscure, 1, &record_cmdlist);
+
+  cmd_list_element *record_stop_cmd
+    = add_cmd ("stop", class_obscure, cmd_record_stop,
+              _("Stop the record/replay target."),
+              &record_cmdlist);
+  add_alias_cmd ("s", record_stop_cmd, class_obscure, 1, &record_cmdlist);
 
   add_prefix_cmd ("goto", class_obscure, cmd_record_goto, _("\
 Restore the program to its state at instruction number N.\n\
 Argument is instruction number, as shown by 'info record'."),
-                 &record_goto_cmdlist, "record goto ", 1, &record_cmdlist);
+                 &record_goto_cmdlist, 1, &record_cmdlist);
 
-  add_cmd ("begin", class_obscure, cmd_record_goto_begin,
-          _("Go to the beginning of the execution log."),
-          &record_goto_cmdlist);
-  add_alias_cmd ("start", "begin", class_obscure, 1, &record_goto_cmdlist);
+  cmd_list_element *record_goto_begin_cmd
+    = add_cmd ("begin", class_obscure, cmd_record_goto_begin,
+              _("Go to the beginning of the execution log."),
+              &record_goto_cmdlist);
+  add_alias_cmd ("start", record_goto_begin_cmd, class_obscure, 1,
+                &record_goto_cmdlist);
 
   add_cmd ("end", class_obscure, cmd_record_goto_end,
           _("Go to the end of the execution log."),
@@ -834,7 +868,7 @@ If the second argument is preceded by '+' or '-', it specifies the distance \
 from the first argument.\n\
 The number of instructions to disassemble can be defined with \"set record \
 instruction-history-size\"."),
-           &record_cmdlist);
+          &record_cmdlist);
 
   add_cmd ("function-call-history", class_obscure, cmd_record_call_history, _("\
 Prints the execution history at function granularity.\n\
@@ -854,7 +888,7 @@ If the second argument is preceded by '+' or '-', it specifies the distance \
 from the first argument.\n\
 The number of functions to print can be defined with \"set record \
 function-call-history-size\"."),
-           &record_cmdlist);
+          &record_cmdlist);
 
   /* Sync command control variables.  */
   record_insn_history_size_setshow_var = record_insn_history_size;