This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH v2] Fix alignment of disassemble /r
- From: Leonardo Boquillon <leonardo dot boquillon at tallertechnologies dot com>
- To: gdb-patches at sourceware dot org, dje at google dot com, daniel dot gutson at tallertechnologies dot com
- Date: Fri, 1 Apr 2016 15:18:05 -0300
- Subject: [PATCH v2] Fix alignment of disassemble /r
- Authentication-results: sourceware.org; auth=none
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