public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Bruno Larsen <blarsen@redhat.com>
To: gdb-patches@sourceware.org
Cc: Bruno Larsen <blarsen@redhat.com>
Subject: [PATCH v2] gdb: add 'maintenance print record-instruction' command
Date: Mon, 12 Dec 2022 11:44:17 +0100	[thread overview]
Message-ID: <20221212104417.136536-1-blarsen@redhat.com> (raw)

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..25e1fd22c6f 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 != nullptr && offset > 0)
+	    {
+	      to_print = to_print->next;
+	      if (to_print->type == record_full_end)
+		offset--;
+	    }
+	  if (offset != 0)
+	    error (_("Not enough recorded history"));
+	}
+      else
+	{
+	  while (to_print->prev != nullptr && offset < 0)
+	    {
+	      to_print = to_print->prev;
+	      if (to_print->type == record_full_end)
+		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 != nullptr && to_print->prev->type != record_full_end)
+    to_print = to_print->prev;
+
+  while (to_print->type != record_full_end)
+    {
+      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


             reply	other threads:[~2022-12-12 10:44 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-12 10:44 Bruno Larsen [this message]
2022-12-12 13:54 ` Eli Zaretskii
2022-12-14  0:46 ` Lancelot SIX
2022-12-14 10:04   ` Lancelot SIX
2022-12-14 16:30     ` Tom Tromey
2022-12-16 10:03   ` Bruno Larsen
2022-12-16 13:25 ` Pedro Alves

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221212104417.136536-1-blarsen@redhat.com \
    --to=blarsen@redhat.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).