This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH v3] Fix alignment of disassemble /r
- From: Leonardo Boquillon <leonardo dot boquillon at tallertechnologies dot com>
- To: gdb-patches at sourceware dot org, daniel dot gutson at tallertechnologies dot com, dje at google dot com, markus dot t dot metzger at intel dot com
- Date: Thu, 7 Apr 2016 18:58:42 -0300
- Subject: [PATCH v3] 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
In this version have been added the capability to compute longest opcode for
btrace.
If this is ok for commit I have a company-wide copyright access, and a coworker
of mine has write access.
gdb/ChangeLog
2016-04-07 Leonardo Boquillon <leonardo.boquillon@tallertechnologies.com>
* disasm.c (gdb_pretty_print_insn): Refactored to use longest opcode.
(dump_insns): Add calls to calculate longest opcode, then pass it to the
print function.
(dis_get_longest_opcode): New function.
* disasm.h (gdb_pretty_print_insn): Refactored to use longest opcode.
* record-btrace.c (btrace_get_longest_opcode): New function.
(btrace_insn_history): Add calls to calculate longest opcode,
then pass it to the print function.
gdb/testsuite/ChangeLog
2016-04-07 Leonardo Boquillon <leonardo.boquillon@tallertechnologies.com>
* disas_raw.exp: New file.
* main.S: New file.
---
gdb/disasm.c | 32 +++++++++++++++++++++++++---
gdb/disasm.h | 2 +-
gdb/record-btrace.c | 28 +++++++++++++++++++++++-
gdb/testsuite/gdb.disasm/disas_raw.exp | 39 ++++++++++++++++++++++++++++++++++
gdb/testsuite/gdb.disasm/main.S | 10 +++++++++
5 files changed, 106 insertions(+), 5 deletions(-)
create mode 100644 gdb/testsuite/gdb.disasm/disas_raw.exp
create mode 100644 gdb/testsuite/gdb.disasm/main.S
diff --git a/gdb/disasm.c b/gdb/disasm.c
index 1cf0901..5027317 100644
--- a/gdb/disasm.c
+++ b/gdb/disasm.c
@@ -169,19 +169,39 @@ compare_lines (const void *mle1p, const void *mle2p)
return val;
}
+static unsigned int
+dis_get_longest_opcode(struct gdbarch *gdbarch, CORE_ADDR addr, CORE_ADDR high,
+ int how_many)
+{
+ unsigned int longest_opcode = 0;
+ unsigned int insn_checked = 0;
+
+ while (addr < high && (how_many < 0 || insn_checked++ < how_many))
+ {
+ const unsigned int current_length = gdb_insn_length(gdbarch, addr);
+ longest_opcode =
+ (current_length > longest_opcode) ? current_length : longest_opcode;
+ addr += current_length;
+ }
+
+ return longest_opcode;
+}
+
/* See disasm.h. */
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 ui_file *stb, unsigned int longest_opcode)
{
/* parts of the symbolic representation of the address */
int unmapped;
int offset;
int line;
int size;
+ unsigned int i;
+ unsigned int max_print_space;
struct cleanup *ui_out_chain;
char *filename = NULL;
char *name = NULL;
@@ -267,7 +287,10 @@ gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout,
}
ui_out_field_stream (uiout, "opcodes", opcode_stream);
- ui_out_text (uiout, "\t");
+ gdb_assert(longest_opcode >= size);
+ max_print_space = 3u * (1u + longest_opcode - size);
+ for (i = 0; i < max_print_space; i++)
+ ui_out_text(uiout, " ");
do_cleanups (cleanups);
}
@@ -291,15 +314,18 @@ dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout,
{
struct disasm_insn insn;
int num_displayed = 0;
+ unsigned int longest_opcode;
memset (&insn, 0, sizeof (insn));
insn.addr = low;
+ longest_opcode = dis_get_longest_opcode(gdbarch, 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 (gdbarch, uiout, di, &insn, flags, stb,
+ longest_opcode);
if (size <= 0)
break;
diff --git a/gdb/disasm.h b/gdb/disasm.h
index a2b72b9..06f2f5e 100644
--- a/gdb/disasm.h
+++ b/gdb/disasm.h
@@ -53,7 +53,7 @@ struct disasm_insn
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);
+ struct ui_file *stb, unsigned int 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..84d9d57 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -660,6 +660,29 @@ btrace_print_lines (struct btrace_line_range lines, struct ui_out *uiout,
}
}
+static unsigned int
+btrace_get_longest_opcode(struct gdbarch *gdbarch,
+ const struct btrace_insn_iterator *begin,
+ const struct btrace_insn_iterator *end)
+{
+ unsigned int longest_opcode = 0;
+ struct btrace_insn_iterator it;
+
+ for (it = *begin; btrace_insn_cmp (&it, end) != 0; btrace_insn_next (&it, 1))
+ {
+ const struct btrace_insn *insn = btrace_insn_get (&it);
+
+ if (insn != NULL)
+ {
+ const unsigned int current_length =
+ gdb_insn_length(gdbarch, insn->pc);
+ longest_opcode =
+ (current_length > longest_opcode) ? current_length : longest_opcode;
+ }
+ }
+
+ return longest_opcode;
+}
/* Disassemble a section of the recorded instruction trace. */
static void
@@ -674,6 +697,7 @@ btrace_insn_history (struct ui_out *uiout,
struct gdbarch *gdbarch;
struct btrace_insn_iterator it;
struct btrace_line_range last_lines;
+ unsigned int longest_opcode;
DEBUG ("itrace (0x%x): [%u; %u)", flags, btrace_insn_number (begin),
btrace_insn_number (end));
@@ -692,6 +716,7 @@ btrace_insn_history (struct ui_out *uiout,
instructions corresponding to that line. */
ui_item_chain = NULL;
+ longest_opcode = btrace_get_longest_opcode(gdbarch, begin, end);
for (it = *begin; btrace_insn_cmp (&it, end) != 0; btrace_insn_next (&it, 1))
{
const struct btrace_insn *insn;
@@ -745,7 +770,8 @@ 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 (gdbarch, uiout, &di, &dinsn, flags, stb,
+ longest_opcode);
}
}
diff --git a/gdb/testsuite/gdb.disasm/disas_raw.exp b/gdb/testsuite/gdb.disasm/disas_raw.exp
new file mode 100644
index 0000000..a233bad
--- /dev/null
+++ b/gdb/testsuite/gdb.disasm/disas_raw.exp
@@ -0,0 +1,39 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2016 Free Software Foundation, Inc.
+#
+# Contributed by Taller Technologies <leonardo.boquillon@tallertechnologies.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test alignment of raw disassemble dump (Bugzilla #19768).
+
+if { ![istarget "x86_64-*-*"] } { return -1 }
+
+set asm_file "main.S"
+
+standard_testfile ${asm_file}
+
+if [prepare_for_testing ${testfile}.exp ${testfile} ${asm_file} {}] {
+ return -1
+}
+
+set asm_line ".*55 push %rbp"
+append asm_line ".*48 89 e5 mov %rsp,%rbp"
+append asm_line ".*b8 00 00 00 00 mov \\\$0x0,%eax"
+append asm_line ".*5d pop %rbp"
+append asm_line ".*c3 retq "
+append asm_line ".*0f 1f 84 00 00 00 00 00 nopl 0x0\\(%rax,%rax,1\\).*"
+
+gdb_test "disass /r main" ${asm_line} "disass /r main"
\ No newline at end of file
diff --git a/gdb/testsuite/gdb.disasm/main.S b/gdb/testsuite/gdb.disasm/main.S
new file mode 100644
index 0000000..0178938
--- /dev/null
+++ b/gdb/testsuite/gdb.disasm/main.S
@@ -0,0 +1,10 @@
+ .file "main.c"
+ .text
+ .globl main
+ .type main, @function
+main:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ popq %rbp
+ ret
--
1.9.1