X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Frecord-btrace.c;h=77b51801e6c4b7b21ce12931b6d75193f8339066;hb=11cf4ffb5e256d268a8f4cea0fc88a0a46bf824c;hp=a9eb7fe098b369003bfecc54a3ea0b809994b398;hpb=19ba03f49581e407097a3e4821a957c422551ae5;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index a9eb7fe098..77b51801e6 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -1,6 +1,6 @@ /* Branch trace support for GDB, the GNU debugger. - Copyright (C) 2013-2015 Free Software Foundation, Inc. + Copyright (C) 2013-2016 Free Software Foundation, Inc. Contributed by Intel Corp. @@ -218,7 +218,7 @@ record_btrace_open (const char *args, int from_tty) disable_chain = make_cleanup (null_cleanup, NULL); ALL_NON_EXITED_THREADS (tp) - if (args == NULL || *args == 0 || number_is_in_list (args, tp->num)) + if (args == NULL || *args == 0 || number_is_in_list (args, tp->global_num)) { btrace_enable (tp, &record_btrace_conf); @@ -332,7 +332,7 @@ record_btrace_print_bts_conf (const struct btrace_config_bts *conf) } } -/* Print an Intel(R) Processor Trace configuration. */ +/* Print an Intel Processor Trace configuration. */ static void record_btrace_print_pt_conf (const struct btrace_config_pt *conf) @@ -438,8 +438,8 @@ record_btrace_info (struct target_ops *self) } printf_unfiltered (_("Recorded %u instructions in %u functions (%u gaps) " - "for thread %d (%s).\n"), insns, calls, gaps, - tp->num, target_pid_to_str (tp->ptid)); + "for thread %s (%s).\n"), insns, calls, gaps, + print_thread_id (tp), target_pid_to_str (tp->ptid)); if (btrace_is_replaying (tp)) printf_unfiltered (_("Replay in progress. At instruction %u.\n"), @@ -526,6 +526,140 @@ 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 line 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 to UIOUT. + + UI_ITEM_CHAIN is a cleanup chain for the last source line and the + instructions corresponding to that source line. When printing a new source + line, we do the cleanups for the open chain and open a new cleanup chain for + the new source line. If the source line range in LINES is not empty, this + function will leave the cleanup chain for the last printed source line open + so instructions can be added to it. */ + +static void +btrace_print_lines (struct btrace_line_range lines, struct ui_out *uiout, + struct cleanup **ui_item_chain, int flags) +{ + 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) + { + if (*ui_item_chain != NULL) + do_cleanups (*ui_item_chain); + + *ui_item_chain + = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line"); + + print_source_lines (lines.symtab, line, line + 1, psl_flags); + + make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn"); + } +} + /* Disassemble a section of the recorded instruction trace. */ static void @@ -534,13 +668,29 @@ btrace_insn_history (struct ui_out *uiout, const struct btrace_insn_iterator *begin, const struct btrace_insn_iterator *end, int flags) { + struct ui_file *stb; + struct cleanup *cleanups, *ui_item_chain; + struct disassemble_info di; struct gdbarch *gdbarch; struct btrace_insn_iterator it; + struct btrace_line_range last_lines; DEBUG ("itrace (0x%x): [%u; %u)", flags, btrace_insn_number (begin), btrace_insn_number (end)); + flags |= DISASSEMBLY_SPECULATIVE; + gdbarch = target_gdbarch (); + stb = mem_fileopen (); + cleanups = make_cleanup_ui_file_delete (stb); + di = gdb_disassemble_info (gdbarch, stb); + last_lines = btrace_mk_line_range (NULL, 0, 0); + + make_cleanup_ui_out_list_begin_end (uiout, "asm_insns"); + + /* UI_ITEM_CHAIN is a cleanup chain for the last source line and the + instructions corresponding to that line. */ + ui_item_chain = NULL; for (it = *begin; btrace_insn_cmp (&it, end) != 0; btrace_insn_next (&it, 1)) { @@ -563,37 +713,43 @@ btrace_insn_history (struct ui_out *uiout, } else { - char prefix[4]; + struct disasm_insn dinsn; - /* 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) - strncpy (prefix, pc_prefix (insn->pc), 3); - else + if ((flags & DISASSEMBLY_SOURCE) != 0) { - prefix[0] = ' '; - prefix[1] = ' '; - prefix[2] = ' '; + 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, &ui_item_chain, flags); + last_lines = lines; + } + else if (ui_item_chain == NULL) + { + ui_item_chain + = make_cleanup_ui_out_tuple_begin_end (uiout, + "src_and_asm_line"); + /* No source information. */ + make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn"); + } + + gdb_assert (ui_item_chain != NULL); } - prefix[3] = 0; - /* Print the instruction index. */ - ui_out_field_uint (uiout, "index", btrace_insn_number (&it)); - ui_out_text (uiout, "\t"); + memset (&dinsn, 0, sizeof (dinsn)); + dinsn.number = btrace_insn_number (&it); + dinsn.addr = insn->pc; - /* Indicate speculative execution by a leading '?'. */ if ((insn->flags & BTRACE_INSN_FLAG_SPECULATIVE) != 0) - prefix[0] = '?'; + dinsn.is_speculative = 1; - /* Print the prefix; we tell gdb_disassembly below to omit it. */ - ui_out_field_fmt (uiout, "prefix", "%s", prefix); - - /* 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_pretty_print_insn (gdbarch, uiout, &di, &dinsn, flags, stb); } } + + do_cleanups (cleanups); } /* The to_insn_history method of target record-btrace. */ @@ -888,11 +1044,12 @@ btrace_call_history (struct ui_out *uiout, const struct btrace_thread_info *btinfo, const struct btrace_call_iterator *begin, const struct btrace_call_iterator *end, - enum record_print_flag flags) + int int_flags) { struct btrace_call_iterator it; + record_print_flags flags = (enum record_print_flag) int_flags; - DEBUG ("ftrace (0x%x): [%u; %u)", flags, btrace_call_number (begin), + DEBUG ("ftrace (0x%x): [%u; %u)", int_flags, btrace_call_number (begin), btrace_call_number (end)); for (it = *begin; btrace_call_cmp (&it, end) < 0; btrace_call_next (&it, 1)) @@ -958,7 +1115,7 @@ btrace_call_history (struct ui_out *uiout, /* The to_call_history method of target record-btrace. */ static void -record_btrace_call_history (struct target_ops *self, int size, int flags) +record_btrace_call_history (struct target_ops *self, int size, int int_flags) { struct btrace_thread_info *btinfo; struct btrace_call_history *history; @@ -966,6 +1123,7 @@ record_btrace_call_history (struct target_ops *self, int size, int flags) struct cleanup *uiout_cleanup; struct ui_out *uiout; unsigned int context, covered; + record_print_flags flags = (enum record_print_flag) int_flags; uiout = current_uiout; uiout_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, @@ -980,7 +1138,7 @@ record_btrace_call_history (struct target_ops *self, int size, int flags) { struct btrace_insn_iterator *replay; - DEBUG ("call-history (0x%x): %d", flags, size); + DEBUG ("call-history (0x%x): %d", int_flags, size); /* If we're replaying, we start at the replay position. Otherwise, we start at the tail of the trace. */ @@ -1015,7 +1173,7 @@ record_btrace_call_history (struct target_ops *self, int size, int flags) begin = history->begin; end = history->end; - DEBUG ("call-history (0x%x): %d, prev: [%u; %u)", flags, size, + DEBUG ("call-history (0x%x): %d, prev: [%u; %u)", int_flags, size, btrace_call_number (&begin), btrace_call_number (&end)); if (size < 0) @@ -1048,7 +1206,8 @@ record_btrace_call_history (struct target_ops *self, int size, int flags) static void record_btrace_call_history_range (struct target_ops *self, - ULONGEST from, ULONGEST to, int flags) + ULONGEST from, ULONGEST to, + int int_flags) { struct btrace_thread_info *btinfo; struct btrace_call_history *history; @@ -1057,6 +1216,7 @@ record_btrace_call_history_range (struct target_ops *self, struct ui_out *uiout; unsigned int low, high; int found; + record_print_flags flags = (enum record_print_flag) int_flags; uiout = current_uiout; uiout_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, @@ -1064,7 +1224,7 @@ record_btrace_call_history_range (struct target_ops *self, low = from; high = to; - DEBUG ("call-history (0x%x): [%u; %u)", flags, low, high); + DEBUG ("call-history (0x%x): [%u; %u)", int_flags, low, high); /* Check for wrap-arounds. */ if (low != from || high != to) @@ -1101,9 +1261,11 @@ record_btrace_call_history_range (struct target_ops *self, static void record_btrace_call_history_from (struct target_ops *self, - ULONGEST from, int size, int flags) + ULONGEST from, int size, + int int_flags) { ULONGEST begin, end, context; + record_print_flags flags = (enum record_print_flag) int_flags; context = abs (size); if (context == 0) @@ -1702,7 +1864,7 @@ record_btrace_resume_thread (struct thread_info *tp, { struct btrace_thread_info *btinfo; - DEBUG ("resuming thread %d (%s): %x (%s)", tp->num, + DEBUG ("resuming thread %s (%s): %x (%s)", print_thread_id (tp), target_pid_to_str (tp->ptid), flag, btrace_thread_flag_to_str (flag)); btinfo = &tp->btrace; @@ -1910,7 +2072,8 @@ record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step, && !record_btrace_is_replaying (ops, minus_one_ptid)) { ops = ops->beneath; - return ops->to_resume (ops, ptid, step, signal); + ops->to_resume (ops, ptid, step, signal); + return; } /* Compute the btrace thread flag for the requested move. */ @@ -1968,7 +2131,8 @@ record_btrace_cancel_resume (struct thread_info *tp) if (flags == 0) return; - DEBUG ("cancel resume thread %d (%s): %x (%s)", tp->num, + DEBUG ("cancel resume thread %s (%s): %x (%s)", + print_thread_id (tp), target_pid_to_str (tp->ptid), flags, btrace_thread_flag_to_str (flags)); @@ -2191,7 +2355,7 @@ record_btrace_step_thread (struct thread_info *tp) flags = btinfo->flags & (BTHR_MOVE | BTHR_STOP); btinfo->flags &= ~(BTHR_MOVE | BTHR_STOP); - DEBUG ("stepping thread %d (%s): %x (%s)", tp->num, + DEBUG ("stepping thread %s (%s): %x (%s)", print_thread_id (tp), target_pid_to_str (tp->ptid), flags, btrace_thread_flag_to_str (flags)); @@ -2400,7 +2564,8 @@ record_btrace_wait (struct target_ops *ops, ptid_t ptid, /* We moved the replay position but did not update registers. */ registers_changed_ptid (eventing->ptid); - DEBUG ("wait ended by thread %d (%s): %s", eventing->num, + DEBUG ("wait ended by thread %s (%s): %s", + print_thread_id (eventing), target_pid_to_str (eventing->ptid), target_waitstatus_to_string (status)); @@ -2723,7 +2888,7 @@ cmd_record_btrace_bts_start (char *args, int from_tty) END_CATCH } -/* Start recording Intel(R) Processor Trace. */ +/* Start recording in Intel Processor Trace format. */ static void cmd_record_btrace_pt_start (char *args, int from_tty) @@ -2885,7 +3050,7 @@ This format may not be available on all processors."), add_cmd ("pt", class_obscure, cmd_record_btrace_pt_start, _("\ -Start branch trace recording in Intel(R) Processor Trace format.\n\n\ +Start branch trace recording in Intel Processor Trace format.\n\n\ This format may not be available on all processors."), &record_btrace_cmdlist); add_alias_cmd ("pt", "btrace pt", class_obscure, 1, &record_cmdlist);