This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH v2] Fix alignment of disassemble /r


When disassembling in raw mode (/r) in a variable-length insn architecture (i.e. x86),
the output can be messed since no alignment takes place.

The first version of this was sent on this mail thread
https://sourceware.org/ml/gdb-patches/2014-04/msg00226.html and this patch is
the same placed previously here https://sourceware.org/bugzilla/show_bug.cgi?id=19768

This patch performs the two passes: the first is at get_insn_set_longest_opcode
at line 136 in the patch, and the second is the while loop that follows like was
agreed here https://sourceware.org/ml/gdb-patches/2014-04/msg00427.html

If this is ok for commit I have a company-wide copyright access, and a coworker 
of mine has write access.

2016-04-01  Leonrado Boquillon  <leonardo.boquillon@tallertechnologies.com>

	* gdb/disasm.c (gdb_pretty_print_insn): Made it static and refactored.
	(dump_insns): Add calls to calculate longest opcode, then pass it to the
	print function.
	(get_insn_set_longest_opcode): New function.
	(gdb_print_clean): New function.
	(gdb_pretty_print_insn_tab): New function.
	(gdb_pretty_print_insn_padding): New function.
	* gdb/disasm.h (gdb_pretty_print_insn_tab): Declare.
	(gdb_pretty_print_insn_padding): Declare.
	* gdb/record-btrace.c (btrace_insn_history): Use
	gdb_pretty_print_insn_tab for printing.

---
 gdb/disasm.c        | 82 ++++++++++++++++++++++++++++++++++++++++++++---------
 gdb/disasm.h        | 20 ++++++++++---
 gdb/record-btrace.c |  2 +-
 3 files changed, 85 insertions(+), 19 deletions(-)

diff --git a/gdb/disasm.c b/gdb/disasm.c
index 1cf0901..6e06b5f 100644
--- a/gdb/disasm.c
+++ b/gdb/disasm.c
@@ -169,25 +169,22 @@ compare_lines (const void *mle1p, const void *mle2p)
   return val;
 }
 
-/* See disasm.h.  */
-
-int
+static int
 gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout,
-		       struct disassemble_info * di,
-		       const struct disasm_insn *insn, int flags,
-		       struct ui_file *stb)
+                       struct disassemble_info * di,
+                       const struct disasm_insn *insn, int flags,
+                       struct ui_file *stb, struct cleanup **ui_out_chain)
 {
   /* parts of the symbolic representation of the address */
   int unmapped;
   int offset;
   int line;
   int size;
-  struct cleanup *ui_out_chain;
   char *filename = NULL;
   char *name = NULL;
   CORE_ADDR pc;
 
-  ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
+  *ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
   pc = insn->addr;
 
   if (insn->number != 0)
@@ -240,6 +237,7 @@ gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout,
     xfree (name);
 
   ui_file_rewind (stb);
+  size = gdbarch_print_insn (gdbarch, pc, di);
   if (flags & DISASSEMBLY_RAW_INSN)
     {
       CORE_ADDR end_pc;
@@ -253,7 +251,6 @@ gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout,
       struct cleanup *cleanups =
 	make_cleanup_ui_file_delete (opcode_stream);
 
-      size = gdbarch_print_insn (gdbarch, pc, di);
       end_pc = pc + size;
 
       for (;pc < end_pc; ++pc)
@@ -267,18 +264,72 @@ gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout,
 	}
 
       ui_out_field_stream (uiout, "opcodes", opcode_stream);
-      ui_out_text (uiout, "\t");
+    }
+  return size;
+}
+
+static size_t
+get_insn_set_longest_opcode(struct gdbarch *gdbarch, struct disassemble_info *di,
+                            CORE_ADDR addr, CORE_ADDR high, int how_many)
+{
+  size_t longest_opcode = 0;
+  size_t num_displayed = 0;
 
-      do_cleanups (cleanups);
+  while (addr < high && (how_many < 0 || num_displayed < how_many))
+    {
+      const int current_length = gdbarch_print_insn(gdbarch, addr, di);
+      longest_opcode = 
+        (current_length > longest_opcode) ? current_length : longest_opcode;
+      addr += current_length;
+      ++num_displayed;
     }
-  else
-    size = gdbarch_print_insn (gdbarch, pc, di);
 
+  return longest_opcode;
+}
+
+static void
+gdb_print_clean (struct ui_out *uiout, struct ui_file *stb, 
+                 struct cleanup *ui_out_chain)
+{
+  do_cleanups (ui_out_chain);
   ui_out_field_stream (uiout, "inst", stb);
   ui_file_rewind (stb);
   do_cleanups (ui_out_chain);
   ui_out_text (uiout, "\n");
+}
 
+/* See disasm.h.  */
+
+int gdb_pretty_print_insn_tab (struct gdbarch *gdbarch, struct ui_out *uiout,
+                                  struct disassemble_info *di,
+                                  const struct disasm_insn *insn, int flags,
+                                  struct ui_file *stb)
+{
+  struct cleanup *ui_out_chain = NULL;
+  const int size = gdb_pretty_print_insn(gdbarch, uiout, di, insn, flags, stb, 
+                                         &ui_out_chain);
+  ui_out_text (uiout, "\t");
+  gdb_print_clean(uiout, stb, ui_out_chain);
+  return size;
+}
+
+int gdb_pretty_print_insn_padding (struct gdbarch *gdbarch,
+                                   struct ui_out *uiout,
+                                   struct disassemble_info *di,
+                                   const struct disasm_insn *insn, int flags,
+                                   struct ui_file *stb, size_t longest_opcode)
+{
+  struct cleanup *ui_out_chain = NULL;
+  const int size = gdb_pretty_print_insn(gdbarch, uiout, di, insn, flags, stb, 
+                                         &ui_out_chain);
+  size_t i;
+  size_t max_print_space;
+  gdb_assert(longest_opcode >= size);
+  max_print_space = 3u * (1 + longest_opcode - size);
+  for (i = 0; i < max_print_space; ++i)
+    ui_out_text (uiout, " ");
+
+  gdb_print_clean(uiout, stb, ui_out_chain);
   return size;
 }
 
@@ -291,15 +342,18 @@ dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout,
 {
   struct disasm_insn insn;
   int num_displayed = 0;
+  size_t longest_opcode;
 
   memset (&insn, 0, sizeof (insn));
   insn.addr = low;
 
+  longest_opcode = get_insn_set_longest_opcode(gdbarch, di, low, high, how_many);
   while (insn.addr < high && (how_many < 0 || num_displayed < how_many))
     {
       int size;
 
-      size = gdb_pretty_print_insn (gdbarch, uiout, di, &insn, flags, stb);
+      size = gdb_pretty_print_insn_padding (gdbarch, uiout, di, &insn, flags, 
+                                            stb, longest_opcode);
       if (size <= 0)
 	break;
 
diff --git a/gdb/disasm.h b/gdb/disasm.h
index a2b72b9..370036a 100644
--- a/gdb/disasm.h
+++ b/gdb/disasm.h
@@ -50,10 +50,22 @@ struct disasm_insn
 /* Prints the instruction INSN into UIOUT and returns the length of the
    printed instruction in bytes.  */
 
-extern int gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout,
-				  struct disassemble_info * di,
-				  const struct disasm_insn *insn, int flags,
-				  struct ui_file *stb);
+extern int gdb_pretty_print_insn_tab (struct gdbarch *gdbarch,
+                                      struct ui_out *uiout,
+				      struct disassemble_info *di,
+				      const struct disasm_insn *insn, int flags,
+                                      struct ui_file *stb);
+
+/* Prints the instruction INSN aligned according opcode length into UIOUT and
+   returns the length of the printed instruction in bytes.  */
+
+
+extern int gdb_pretty_print_insn_padding (struct gdbarch *gdbarch,
+                                          struct ui_out *uiout,
+                                          struct disassemble_info *di,
+                                          const struct disasm_insn *insn, 
+                                          int flags, struct ui_file *stb,
+                                          size_t longest_opcode);
 
 /* Return a filled in disassemble_info object for use by gdb.  */
 
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 77b5180..72a0b77 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -745,7 +745,7 @@ btrace_insn_history (struct ui_out *uiout,
 	  if ((insn->flags & BTRACE_INSN_FLAG_SPECULATIVE) != 0)
 	    dinsn.is_speculative = 1;
 
-	  gdb_pretty_print_insn (gdbarch, uiout, &di, &dinsn, flags, stb);
+	  gdb_pretty_print_insn_tab (gdbarch, uiout, &di, &dinsn, flags, stb);
 	}
     }
 
-- 
1.9.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]