@@ -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;
@@ -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. */
@@ -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);
}
}
new file mode 100644
@@ -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
new file mode 100644
@@ -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