From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21055 invoked by alias); 14 Aug 2015 11:37:58 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 21046 invoked by uid 89); 14 Aug 2015 11:37:57 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=AWL,BAYES_00,KAM_LAZY_DOMAIN_SECURITY,RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mga01.intel.com Received: from mga01.intel.com (HELO mga01.intel.com) (192.55.52.88) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 14 Aug 2015 11:37:56 +0000 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga101.fm.intel.com with ESMTP; 14 Aug 2015 04:37:55 -0700 X-ExtLoop1: 1 Received: from irvmail001.ir.intel.com ([163.33.26.43]) by orsmga001.jf.intel.com with ESMTP; 14 Aug 2015 04:37:53 -0700 Received: from ulvlx001.iul.intel.com (ulvlx001.iul.intel.com [172.28.207.17]) by irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id t7EBbqhg017300; Fri, 14 Aug 2015 12:37:52 +0100 Received: from ulvlx001.iul.intel.com (localhost [127.0.0.1]) by ulvlx001.iul.intel.com with ESMTP id t7EBbql8006527; Fri, 14 Aug 2015 13:37:52 +0200 Received: (from mmetzger@localhost) by ulvlx001.iul.intel.com with œ id t7EBbqIs006523; Fri, 14 Aug 2015 13:37:52 +0200 From: Markus Metzger To: palves@redhat.com Cc: gdb-patches@sourceware.org, dje@google.com Subject: [rfc] btrace: change record instruction-history /m Date: Fri, 14 Aug 2015 11:37:00 -0000 Message-Id: <1439552272-6256-1-git-send-email-markus.t.metzger@intel.com> X-IsSubscribed: yes X-SW-Source: 2015-08/txt/msg00380.txt.bz2 The /m modifier interleaves source lines with the disassembly of recorded instructions. This calls disasm.c's do_mixed_source_and_assembly once for each recorded instruction to be printed. The latter really does a source print with intermixed disassembly. To that purpose, it may reorder instructions to better match the source. This is nice for disassembling an entire function, but it doesn't work for printing a single instruction. Change record instruction-history /m to use its own simple source interleaving algorithm. The most important part is that instructions are printed in the order in which they were executed. Before each instruction, we print a range of source lines that are attributed to the instruction's PC. If the source line range has already been printed (or skipped) for the previous instruction, we skip it. The algorithm would fill in the missing lines if a PC is attributed to more than one source line. I have not seen this. There always seems to be at most one source line per PC. I don't think that there is an MI consumer of "record instruction-history" and I have no idea if and how this might affect MI. Alternatively, we could extend Doug Evan's new algorithm https://sourceware.org/ml/gdb-patches/2015-08/msg00335.html to take a vector of PCs. 2015-08-14 Markus Metzger gdb/ * record-btrace.c (struct btrace_line_range): New. (btrace_mk_line_range, btrace_line_range_add) (btrace_line_range_is_empty, btrace_line_range_contains_range) (btrace_find_line_range, btrace_print_lines): New. (btrace_insn_history): Add source interleaving algorithm. --- gdb/record-btrace.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 152 insertions(+), 2 deletions(-) diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index 2f43171..df03e50 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -530,6 +530,137 @@ ui_out_field_uint (struct ui_out *uiout, const char *fld, unsigned int val) ui_out_field_fmt (uiout, fld, "%u", val); } +/* A range of source lines. */ + +struct btrace_line_range +{ + /* The symtab this line is from. */ + struct symtab *symtab; + + /* The first line (inclusive). */ + int begin; + + /* The last line (exclusive). */ + int end; +}; + +/* Construct a line range. */ + +static struct btrace_line_range +btrace_mk_line_range (struct symtab *symtab, int begin, int end) +{ + struct btrace_line_range range; + + range.symtab = symtab; + range.begin = begin; + range.end = end; + + return range; +} + +/* Add a line to a line range. */ + +static struct btrace_line_range +btrace_line_range_add (struct btrace_line_range range, int line) +{ + if (range.end <= range.begin) + { + /* This is the first entry. */ + range.begin = line; + range.end = line + 1; + } + else if (line < range.begin) + range.begin = line; + else if (range.end < line) + range.end = line; + + return range; +} + +/* Return non-zero if RANGE is empty, zero otherwise. */ + +static int +btrace_line_range_is_empty (struct btrace_line_range range) +{ + return (range.end <= range.begin); +} + +/* Return non-zero if LHS contains RHS, zero otherwise. */ + +static int +btrace_line_range_contains_range (struct btrace_line_range lhs, + struct btrace_line_range rhs) +{ + return ((lhs.symtab == rhs.symtab) + && (lhs.begin <= rhs.begin) + && (rhs.end <= lhs.end)); +} + +/* Find the lange range associated with PC. */ + +static struct btrace_line_range +btrace_find_line_range (CORE_ADDR pc) +{ + struct btrace_line_range range; + struct linetable_entry *lines; + struct linetable *ltable; + struct symtab *symtab; + int nlines, i; + + symtab = find_pc_line_symtab (pc); + if (symtab == NULL) + return btrace_mk_line_range (NULL, 0, 0); + + ltable = SYMTAB_LINETABLE (symtab); + if (ltable == NULL) + return btrace_mk_line_range (symtab, 0, 0); + + nlines = ltable->nitems; + lines = ltable->item; + if (nlines <= 0) + return btrace_mk_line_range (symtab, 0, 0); + + range = btrace_mk_line_range (symtab, 0, 0); + for (i = 0; i < nlines - 1; i++) + { + if ((lines[i].pc == pc) && (lines[i].line != 0)) + range = btrace_line_range_add (range, lines[i].line); + } + + return range; +} + +/* Print source lines in LINES. */ + +static void +btrace_print_lines (struct btrace_line_range lines, struct ui_out *uiout, + int flags) +{ + enum print_source_lines_flags psl_flags; + int line; + + psl_flags = 0; + if (flags & DISASSEMBLY_FILENAME) + psl_flags |= PRINT_SOURCE_LINES_FILENAME; + + for (line = lines.begin; line < lines.end; ++line) + { + struct cleanup *ui_out_list_chain_line; + struct cleanup *ui_out_tuple_chain_line; + + ui_out_tuple_chain_line + = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line"); + + print_source_lines (lines.symtab, line, line + 1, psl_flags); + + ui_out_list_chain_line + = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn"); + + do_cleanups (ui_out_list_chain_line); + do_cleanups (ui_out_tuple_chain_line); + } +} + /* Disassemble a section of the recorded instruction trace. */ static void @@ -540,11 +671,17 @@ btrace_insn_history (struct ui_out *uiout, { struct gdbarch *gdbarch; struct btrace_insn_iterator it; + struct btrace_line_range last_lines; + int disas_flags; DEBUG ("itrace (0x%x): [%u; %u)", flags, btrace_insn_number (begin), btrace_insn_number (end)); gdbarch = target_gdbarch (); + disas_flags = ((flags + & ~(DISASSEMBLY_SOURCE | DISASSEMBLY_FILENAME)) + | DISASSEMBLY_OMIT_PC); + last_lines = btrace_mk_line_range (NULL, 0, 0); for (it = *begin; btrace_insn_cmp (&it, end) != 0; btrace_insn_next (&it, 1)) { @@ -569,6 +706,19 @@ btrace_insn_history (struct ui_out *uiout, { char prefix[4]; + if ((flags & DISASSEMBLY_SOURCE) != 0) + { + struct btrace_line_range lines; + + lines = btrace_find_line_range (insn->pc); + if (!btrace_line_range_is_empty (lines) + && !btrace_line_range_contains_range (last_lines, lines)) + { + btrace_print_lines (lines, uiout, flags); + last_lines = lines; + } + } + /* We may add a speculation prefix later. We use the same space that is used for the pc prefix. */ if ((flags & DISASSEMBLY_OMIT_PC) == 0) @@ -594,8 +744,8 @@ btrace_insn_history (struct ui_out *uiout, /* Disassembly with '/m' flag may not produce the expected result. See PR gdb/11833. */ - gdb_disassembly (gdbarch, uiout, NULL, flags | DISASSEMBLY_OMIT_PC, - 1, insn->pc, insn->pc + 1); + gdb_disassembly (gdbarch, uiout, NULL, disas_flags, 1, insn->pc, + insn->pc + 1); } } } -- 1.8.3.1