public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Andrew Burgess <aburgess@redhat.com>
To: gdb-patches@sourceware.org
Cc: Pedro Alves <pedro@palves.net>, Simon Marchi <simark@simark.ca>,
	Andrew Burgess <aburgess@redhat.com>
Subject: [PATCHv2 1/2] gdb: more debug output for displaced stepping
Date: Wed, 22 Mar 2023 21:17:37 +0000	[thread overview]
Message-ID: <b16248406a3026c8081733764f4e76e2ea66f0ad.1679519312.git.aburgess@redhat.com> (raw)
In-Reply-To: <cover.1679519312.git.aburgess@redhat.com>

While investigating a displaced stepping issue I wanted an easy way to
see what GDB thought the original instruction was, and what
instruction GDB replaced that with when performing the displaced step.

We do print out the address that is being stepped, so I can track down
the original instruction, I just need to go find the information
myself.

And we do print out the bytes of the new instruction, so I can figure
out what the replacement instruction was, but it's not really easy.

Also, the code that prints the bytes of the replacement instruction
only prints 4 bytes, which clearly isn't always going to be correct.

In this commit I remove the existing code that prints the bytes of the
replacement instruction, and add two new blocks of code to
displaced_step_prepare_throw.  This new code prints the original
instruction, and the replacement instruction.  In each case we print
both the bytes that make up the instruction and the completely
disassembled instruction.

Here's an example of what the output looks like on x86-64 (this is
with 'set debug displaced on').  The two interesting lines contain the
strings 'original insn' and 'replacement insn':

  (gdb) step
  [displaced] displaced_step_prepare_throw: displaced-stepping 2892655.2892655.0 now
  [displaced] displaced_step_prepare_throw: original insn 0x401030: ff 25 e2 2f 00 00	jmp    *0x2fe2(%rip)        # 0x404018 <puts@got.plt>
  [displaced] prepare: selected buffer at 0x401052
  [displaced] prepare: saved 0x401052: 1e fa 31 ed 49 89 d1 5e 48 89 e2 48 83 e4 f0 50
  [displaced] fixup_riprel: %rip-relative addressing used.
  [displaced] fixup_riprel: using temp reg 2, old value 0x7ffff7f8a578, new value 0x401036
  [displaced] amd64_displaced_step_copy_insn: copy 0x401030->0x401052: ff a1 e2 2f 00 00 68 00 00 00 00 e9 e0 ff ff ff
  [displaced] displaced_step_prepare_throw: prepared successfully thread=2892655.2892655.0, original_pc=0x401030, displaced_pc=0x401052
  [displaced] displaced_step_prepare_throw: replacement insn 0x401052: ff a1 e2 2f 00 00	jmp    *0x2fe2(%rcx)
  [displaced] finish: restored 2892655.2892655.0 0x401052
  [displaced] amd64_displaced_step_fixup: fixup (0x401030, 0x401052), insn = 0xff 0xa1 ...
  [displaced] amd64_displaced_step_fixup: restoring reg 2 to 0x7ffff7f8a578
  0x00007ffff7e402c0 in puts () from /lib64/libc.so.6
  (gdb)

One final note.  For many targets that support displaced stepping (in
fact all targets except ARM) the replacement instruction is always a
single instruction.  But on ARM the replacement could actually be a
series of instructions.

The debug code tries to handle this by disassembling the entire
displaced stepping buffer.  Obviously this might actually print more
than is necessary, but there's (currently) no easy way to know how
many instructions to disassemble; that knowledge is all locked in the
architecture specific code.  Still I don't think it really hurts, if
someone is looking at this debug then hopefully they known what to
expect.

Obviously we can imagine schemes where the architecture specific
displaced stepping code could communicate back how many bytes its
replacement sequence was, and then our debug print code could use this
to limit the disassembly.  But this seems like a lot of effort just to
save printing a few additional instructions in some debug output.

I'm not proposing to do anything about this issue for now.
---
 gdb/infrun.c | 85 +++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 68 insertions(+), 17 deletions(-)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 5c9babb9104..8c56a9a4dfb 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -74,6 +74,7 @@
 #include "gdbsupport/common-debug.h"
 #include "gdbsupport/buildargv.h"
 #include "extension.h"
+#include "disasm.h"
 
 /* Prototypes for local functions */
 
@@ -1807,6 +1808,31 @@ displaced_step_prepare_throw (thread_info *tp)
   CORE_ADDR original_pc = regcache_read_pc (regcache);
   CORE_ADDR displaced_pc;
 
+  /* Display the instruction we are going to displaced step.  */
+  if (debug_displaced)
+    {
+      string_file tmp_stream;
+      int dislen = gdb_print_insn (gdbarch, original_pc, &tmp_stream,
+				   nullptr);
+
+      if (dislen > 0)
+	{
+	  gdb::byte_vector insn_buf (dislen);
+	  read_memory (original_pc, insn_buf.data (), insn_buf.size ());
+
+	  std::string insn_bytes
+	    = displaced_step_dump_bytes (insn_buf.data (), insn_buf.size ());
+
+	  displaced_debug_printf ("original insn %s: %s \t %s",
+				  paddress (gdbarch, original_pc),
+				  insn_bytes.c_str (),
+				  tmp_stream.string ().c_str ());
+	}
+      else
+	displaced_debug_printf ("replacement insn %s: invalid length: %d",
+				paddress (gdbarch, original_pc), dislen);
+    }
+
   displaced_step_prepare_status status
     = gdbarch_displaced_step_prepare (gdbarch, tp, displaced_pc);
 
@@ -1845,6 +1871,48 @@ displaced_step_prepare_throw (thread_info *tp)
 			  paddress (gdbarch, original_pc),
 			  paddress (gdbarch, displaced_pc));
 
+  /* Display the new displaced instruction(s).  */
+  if (debug_displaced)
+    {
+      string_file tmp_stream;
+      CORE_ADDR addr = displaced_pc;
+
+      /* If displaced stepping is going to use h/w single step then we know
+	 that the replacement instruction can only be a single instruction,
+	 in that case set the end address at the next byte.
+
+	 Otherwise the displaced stepping copy instruction routine could
+	 have generated multiple instructions, and all we know is that they
+	 must fit within the LEN bytes of the buffer.  */
+      CORE_ADDR end
+	= addr + (gdbarch_displaced_step_hw_singlestep (gdbarch)
+		  ? 1 : gdbarch_displaced_step_buffer_length (gdbarch));
+
+      while (addr < end)
+	{
+	  int dislen = gdb_print_insn (gdbarch, addr, &tmp_stream, nullptr);
+	  if (dislen <= 0)
+	    {
+	      displaced_debug_printf
+		("replacement insn %s: invalid length: %d",
+		 paddress (gdbarch, addr), dislen);
+	      break;
+	    }
+
+	  gdb::byte_vector insn_buf (dislen);
+	  read_memory (addr, insn_buf.data (), insn_buf.size ());
+
+	  std::string insn_bytes
+	    = displaced_step_dump_bytes (insn_buf.data (), insn_buf.size ());
+	  std::string insn_str = tmp_stream.release ();
+	  displaced_debug_printf ("replacement insn %s: %s \t %s",
+				  paddress (gdbarch, addr),
+				  insn_bytes.c_str (),
+				  insn_str.c_str ());
+	  addr += dislen;
+	}
+    }
+
   return DISPLACED_STEP_PREPARE_STATUS_OK;
 }
 
@@ -2711,23 +2779,6 @@ resume_1 (enum gdb_signal sig)
 	step = false;
     }
 
-  if (debug_displaced
-      && tp->control.trap_expected
-      && use_displaced_stepping (tp)
-      && !step_over_info_valid_p ())
-    {
-      struct regcache *resume_regcache = get_thread_regcache (tp);
-      struct gdbarch *resume_gdbarch = resume_regcache->arch ();
-      CORE_ADDR actual_pc = regcache_read_pc (resume_regcache);
-      gdb_byte buf[4];
-
-      read_memory (actual_pc, buf, sizeof (buf));
-      displaced_debug_printf ("run %s: %s",
-			      paddress (resume_gdbarch, actual_pc),
-			      displaced_step_dump_bytes
-				(buf, sizeof (buf)).c_str ());
-    }
-
   if (tp->control.may_range_step)
     {
       /* If we're resuming a thread with the PC out of the step
-- 
2.25.4


  reply	other threads:[~2023-03-22 21:17 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-23 15:46 [PATCH 0/3] AMD64 Displaced Stepping Fix Andrew Burgess
2023-02-23 15:46 ` [PATCH 1/3] gdb: more debug output for displaced stepping Andrew Burgess
2023-02-23 15:46 ` [PATCH 2/3] gdb: remove gdbarch_displaced_step_fixup_p Andrew Burgess
2023-02-23 15:46 ` [PATCH 3/3] gdb: fix reg corruption from displaced stepping on amd64 Andrew Burgess
2023-03-16 16:39 ` [PATCHv2 0/4] AMD64 Displaced Stepping Fix Andrew Burgess
2023-03-16 16:39   ` [PATCHv2 1/4] gdb: more debug output for displaced stepping Andrew Burgess
2023-03-21 12:29     ` Pedro Alves
2023-03-21 14:41       ` Simon Marchi
2023-03-22 21:17         ` [PATCHv2 0/2] displaced stepping debug improvements Andrew Burgess
2023-03-22 21:17           ` Andrew Burgess [this message]
2023-03-22 21:17           ` [PATCHv2 2/2] gdb: move displaced_step_dump_bytes into gdbsupport (and rename) Andrew Burgess
2023-03-27 12:35           ` [PATCHv2 0/2] displaced stepping debug improvements Andrew Burgess
2023-03-21 14:45     ` [PATCHv2 1/4] gdb: more debug output for displaced stepping Simon Marchi
2023-03-16 16:39   ` [PATCHv2 2/4] gdb: remove gdbarch_displaced_step_fixup_p Andrew Burgess
2023-03-21 13:10     ` Pedro Alves
2023-03-22 21:22       ` Andrew Burgess
2023-03-16 16:39   ` [PATCHv2 3/4] gdb: fix reg corruption from displaced stepping on amd64 Andrew Burgess
2023-03-21 13:23     ` Pedro Alves
2023-03-16 16:39   ` [PATCHv2 4/4] gdb: remove redundant signal passing Andrew Burgess
2023-03-27 12:32   ` [PATCHv3 0/3] AMD64 Displaced Stepping Fix Andrew Burgess
2023-03-27 12:32     ` [PATCHv3 1/3] gdb: more debug output for displaced stepping Andrew Burgess
2023-03-28 13:05       ` Simon Marchi
2023-03-28 15:08         ` Andrew Burgess
2023-03-28 15:11           ` Simon Marchi
2023-03-29  9:42             ` Andrew Burgess
2023-03-27 12:32     ` [PATCHv3 2/3] gdb: move displaced_step_dump_bytes into gdbsupport (and rename) Andrew Burgess
2023-03-28 13:10       ` Simon Marchi
2023-03-29  9:43         ` Andrew Burgess
2023-03-27 12:32     ` [PATCHv3 3/3] gdb: fix reg corruption from displaced stepping on amd64 Andrew Burgess
2023-03-29  9:43       ` Pedro Alves
2023-03-28 12:33     ` [PATCHv3 0/3] AMD64 Displaced Stepping Fix Simon Marchi
2023-03-28 15:29       ` Andrew Burgess
2023-03-29 13:46     ` [PATCHv4] gdb: fix reg corruption from displaced stepping on amd64 Andrew Burgess
2023-04-04 13:03       ` Pedro Alves
2023-04-06 13:29         ` Andrew Burgess
2023-04-06 15:38           ` Andrew Burgess

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=b16248406a3026c8081733764f4e76e2ea66f0ad.1679519312.git.aburgess@redhat.com \
    --to=aburgess@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=pedro@palves.net \
    --cc=simark@simark.ca \
    /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).