From patchwork Thu Apr 7 21:58:42 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leonardo Boquillon X-Patchwork-Id: 11666 Received: (qmail 81988 invoked by alias); 7 Apr 2016 21:58:59 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 81948 invoked by uid 89); 7 Apr 2016 21:58:58 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=Taller, Technologies, Hx-spam-relays-external:sk:leonard, 6977 X-HELO: mail-qg0-f54.google.com Received: from mail-qg0-f54.google.com (HELO mail-qg0-f54.google.com) (209.85.192.54) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Thu, 07 Apr 2016 21:58:47 +0000 Received: by mail-qg0-f54.google.com with SMTP id j35so75901683qge.0 for ; Thu, 07 Apr 2016 14:58:46 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id; bh=0hDJd7iRIBPmIdYWt+fLk03WxG6I5O6dtIGhb96g+HQ=; b=j1oq/BPldi5hWxchr17lGKwJWQ8LXGlrpmJQHAgucUyYa0MgJl5zm2n3StRP1aDxSw JETTHWTD45J5EASGDTBoUiJ0mbNvwAHPJGTMlELbhIEJF+8VrFoNIQ9/MI+ba8S3Xj7Q 5FxcPZCKPGZF/X3rx46wDLf6Wfw/HDh7fZooxSdAQGXWqM4yaT/CnZcT8pZ/LDMBvNad 7yEzWXMG2c7qkP2ajBdeASyG6dc8jKBh2Y84oTTLraXzS3OGrbhPP+vCyp8B5gKhZIRL eXrHZWt82ZXewciakfe+FYxxCHhVDu//4UeQLE4F/4J2pX9RJuzRgeWOLDZTcIubXgR/ GBsw== X-Gm-Message-State: AD7BkJK/EJzQ2+myWfE/oNnEcCYL0GfPNGc9192hLg6XhwTjZC7DxzGqToOu44LqUaCAzGbW X-Received: by 10.140.89.103 with SMTP id u94mr7021787qgd.3.1460066325005; Thu, 07 Apr 2016 14:58:45 -0700 (PDT) Received: from leonardo.dominio.tallertechnologies.com ([200.69.202.173]) by smtp.gmail.com with ESMTPSA id z65sm4212511qhb.36.2016.04.07.14.58.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 07 Apr 2016 14:58:44 -0700 (PDT) From: Leonardo Boquillon To: gdb-patches@sourceware.org, daniel.gutson@tallertechnologies.com, dje@google.com, markus.t.metzger@intel.com Subject: [PATCH v3] Fix alignment of disassemble /r Date: Thu, 7 Apr 2016 18:58:42 -0300 Message-Id: <1460066322-21732-1-git-send-email-leonardo.boquillon@tallertechnologies.com> 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 * 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 * 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 +# +# 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 . + +# 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