From: Markus Metzger <markus.t.metzger@intel.com>
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 [thread overview]
Message-ID: <1439552272-6256-1-git-send-email-markus.t.metzger@intel.com> (raw)
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 <markus.t.metzger@intel.com>
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
next reply other threads:[~2015-08-14 11:37 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-14 11:37 Markus Metzger [this message]
2015-08-14 13:45 ` Eli Zaretskii
2015-08-14 17:06 ` Doug Evans
2015-08-14 20:32 ` Eli Zaretskii
2015-08-17 7:16 ` Metzger, Markus T
2015-08-17 15:10 ` Eli Zaretskii
2015-08-18 6:30 ` Metzger, Markus T
2015-08-18 14:22 ` Eli Zaretskii
2015-08-14 17:02 ` Doug Evans
2015-08-14 17:44 ` Doug Evans
2015-08-17 7:23 ` Metzger, Markus T
2015-08-18 14:57 ` Pedro Alves
2015-08-19 14:45 ` Marc Khouzam
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1439552272-6256-1-git-send-email-markus.t.metzger@intel.com \
--to=markus.t.metzger@intel.com \
--cc=dje@google.com \
--cc=gdb-patches@sourceware.org \
--cc=palves@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox