public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] gdb: add 'maintenance print record-instruction' command
@ 2022-12-07 13:50 Bruno Larsen
  2022-12-07 14:37 ` Lancelot SIX
  2022-12-15 21:29 ` Tom Tromey
  0 siblings, 2 replies; 6+ messages in thread
From: Bruno Larsen @ 2022-12-07 13:50 UTC (permalink / raw)
  To: gdb-patches; +Cc: Bruno Larsen

While chasing some reverse debugging bugs, I found myself wondering what
was recorded by GDB to undo and redo a certain instruction. This commit
implements a simple way of printing that information.
---
 gdb/NEWS            |  6 ++++
 gdb/doc/gdb.texinfo |  8 +++++
 gdb/record-full.c   | 81 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 95 insertions(+)

diff --git a/gdb/NEWS b/gdb/NEWS
index c4ccfcc9e32..d6ce6bf86a0 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -103,6 +103,12 @@
 
 * New commands
 
+maintenance print record-instruction [ N ]
+  Print the recorded information for a given instruction. If N is not given
+  prints how GDB would undo the last instruction executed. If N is negative,
+  prints how GDB would undo the N-th previous instruction, and if N is
+  positive, it prints how GDB will redo the N-th following instruction.
+
 maintenance set ignore-prologue-end-flag on|off
 maintenance show ignore-prologue-end-flag
   This setting, which is off by default, controls whether GDB ignores the
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 5b566669975..807af351e79 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -40531,6 +40531,14 @@ that symbol is described.  The type chain produced by this command is
 a recursive definition of the data type as stored in @value{GDBN}'s
 data structures, including its flags and contained types.
 
+@kindex maint print record-instruction
+@item maint print record-instruction
+@itemx maint print record-instruction @var{N}
+@cindex print how GDB recorded a given instruction.  If N is not positive
+number, it prints the values stored by the inferior before the N-th previous
+instruction was exectued.  If N is positive, print the values after the N-th
+following instruction is executed.  If N is not given, 0 is assumed.
+
 @kindex maint selftest
 @cindex self tests
 @item maint selftest @r{[}-verbose@r{]} @r{[}@var{filter}@r{]}
diff --git a/gdb/record-full.c b/gdb/record-full.c
index 48b92281fe6..47cdf75eea4 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -2764,6 +2764,79 @@ set_record_full_insn_max_num (const char *args, int from_tty,
     }
 }
 
+/* Implement the 'maintenance print record-instruction' command.  */
+
+static void
+maintenance_print_record_instruction (const char *args, int from_tty)
+{
+  struct record_full_entry* to_print = record_full_list;
+
+  if (args != nullptr)
+    {
+      int offset = value_as_long (parse_and_eval (args));
+      if (offset > 0)
+	{
+	  /* Move forward OFFSET instructions.  We know we found the
+	     end of an instruction when to_print->type is 0.  */
+	  while (to_print->next && offset > 0)
+	    {
+	      to_print = to_print->next;
+	      if (!to_print->type)
+		offset --;
+	    }
+	  if (offset != 0)
+	    error (_("Not enough recorded history"));
+	}
+      else
+	{
+	  while (to_print->prev && offset < 0)
+	    {
+	      to_print = to_print->prev;
+	      if (!to_print->type)
+		offset++;
+	    }
+	  if (offset != 0)
+	    error (_("Not enough recorded history"));
+	}
+    }
+  gdb_assert (to_print != nullptr);
+
+  /* Go back to the start of the instruction.  */
+  while (to_print->prev && to_print->prev->type)
+    to_print = to_print->prev;
+
+  while (to_print->type)
+    {
+      switch (to_print->type)
+	{
+	  case record_full_reg:
+	    {
+	      gdb_byte* b = record_full_get_loc (to_print);
+	      gdb_printf ("Register %%%s changed:",
+			  gdbarch_register_name (target_gdbarch (),
+						 to_print->u.reg.num));
+	      for (int i = 0; i < to_print->u.reg.len; i++)
+		gdb_printf (" %02x",b[i]);
+	      gdb_printf ("\n");
+	      break;
+	    }
+	  case record_full_mem:
+	    {
+	      gdb_byte* b = record_full_get_loc (to_print);
+	      gdb_printf ("%d bytes of memory at address %s changed from:",
+			  to_print->u.mem.len,
+			  print_core_address (target_gdbarch (),
+					      to_print->u.mem.addr));
+	      for (int i = 0; i < to_print->u.mem.len; i++)
+		gdb_printf (" %02x",b[i]);
+	      gdb_printf ("\n");
+	      break;
+	    }
+	}
+      to_print = to_print->next;
+    }
+}
+
 void _initialize_record_full ();
 void
 _initialize_record_full ()
@@ -2868,4 +2941,12 @@ When ON, query if PREC cannot record memory change of next instruction."),
   c = add_alias_cmd ("memory-query", record_full_memory_query_cmds.show,
 		     no_class, 1,&show_record_cmdlist);
   deprecate_cmd (c, "show record full memory-query");
+
+  add_cmd ("record-instruction", class_maintenance,
+	   maintenance_print_record_instruction,
+	   _("\
+Print a recorded instruction.\nIf no argument is provided, print the last \
+instruction recorded.\nIf a negative argument is given, prints how the nth \
+previous instruction will be undone.\nIf a positive argument is given, prints \
+how the nth following instruction will be redone."), &maintenanceprintlist);
 }
-- 
2.38.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-12-15 21:29 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-07 13:50 [PATCH] gdb: add 'maintenance print record-instruction' command Bruno Larsen
2022-12-07 14:37 ` Lancelot SIX
2022-12-08  8:45   ` Bruno Larsen
2022-12-08  9:32     ` Lancelot SIX
2022-12-15 21:27   ` Tom Tromey
2022-12-15 21:29 ` Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).