From patchwork Fri Apr 1 18:18:05 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leonardo Boquillon X-Patchwork-Id: 11594 Received: (qmail 118753 invoked by alias); 1 Apr 2016 18:18:27 -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 118734 invoked by uid 89); 1 Apr 2016 18:18:26 -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=coworker, Prints, 2406 X-HELO: mail-qg0-f48.google.com Received: from mail-qg0-f48.google.com (HELO mail-qg0-f48.google.com) (209.85.192.48) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Fri, 01 Apr 2016 18:18:15 +0000 Received: by mail-qg0-f48.google.com with SMTP id y89so103176914qge.2 for ; Fri, 01 Apr 2016 11:18:15 -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=Q4d+ZIaNd2SUFu6gJvH7R9/9GDvau6pbP3AfoduwHVc=; b=dWh7BrZqnVWzafyMvyuMlrjE4GWAFgzgI63b/06X7Q88sh4OrV156iCmObFFdDyJmq v08yWTaKrvZaJtRkvVzflpq8l0wG0Y9FRDjCMXrI9ceLm1CmqFADb0OKt9Rp6xg/ebNt EcXtGljAcJZr0IW/jyIpVJliT+OXlaefo/EH9f64Gi6lp5U24PwWYWCb2U8yfum3DfnN kFBbhOradpgf6bCdE0CJNp4OcK3OhMDS0E3/y+8ICykWIfeAsadAa9gzf3yLz17Ze+nB JrfoVU7dSE6COkMK10LRKOOO5iYSliB80X47B3fqqnb+Zr8VvLeM+seojD7XLl5tCuqh F9Yg== X-Gm-Message-State: AD7BkJIHQCAC5FTW8URMu74o5Yu6a9jwL7YZwf5AJzDAqW+nIMAZxgX4F5zTXUQDL8ooHuYG X-Received: by 10.140.233.135 with SMTP id e129mr26743170qhc.86.1459534693734; Fri, 01 Apr 2016 11:18:13 -0700 (PDT) Received: from leonardo.dominio.tallertechnologies.com ([200.69.202.173]) by smtp.gmail.com with ESMTPSA id n48sm6638121qgd.38.2016.04.01.11.18.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 01 Apr 2016 11:18:12 -0700 (PDT) From: Leonardo Boquillon To: gdb-patches@sourceware.org, dje@google.com, daniel.gutson@tallertechnologies.com Subject: [PATCH v2] Fix alignment of disassemble /r Date: Fri, 1 Apr 2016 15:18:05 -0300 Message-Id: <1459534685-10835-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 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 * 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); } }