X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fbtrace.c;h=d41e3c4f8f91ac102a76207437a80b1545590f1b;hb=cee00f171520eb85867230d4cbed34480c64e71e;hp=8338ebfb0a2edf674897cc88a808a517c19eb367;hpb=981a3fb3594dddae266b7a5014c3001727200d7b;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/btrace.c b/gdb/btrace.c index 8338ebfb0a..d41e3c4f8f 100644 --- a/gdb/btrace.c +++ b/gdb/btrace.c @@ -1,6 +1,6 @@ /* Branch trace support for GDB, the GNU debugger. - Copyright (C) 2013-2017 Free Software Foundation, Inc. + Copyright (C) 2013-2020 Free Software Foundation, Inc. Contributed by Intel Corp. @@ -31,9 +31,13 @@ #include "filenames.h" #include "xml-support.h" #include "regcache.h" -#include "rsp-low.h" +#include "gdbsupport/rsp-low.h" #include "gdbcmd.h" #include "cli/cli-utils.h" +#include "gdbarch.h" + +/* For maintenance commands. */ +#include "record-btrace.h" #include #include @@ -47,7 +51,7 @@ static struct cmd_list_element *maint_btrace_pt_set_cmdlist; static struct cmd_list_element *maint_btrace_pt_show_cmdlist; /* Control whether to skip PAD packets when computing the packet history. */ -static int maint_btrace_pt_skip_pad = 1; +static bool maint_btrace_pt_skip_pad = true; static void btrace_add_pc (struct thread_info *tp); @@ -78,10 +82,10 @@ ftrace_print_function_name (const struct btrace_function *bfun) sym = bfun->sym; if (sym != NULL) - return SYMBOL_PRINT_NAME (sym); + return sym->print_name (); if (msym != NULL) - return MSYMBOL_PRINT_NAME (msym); + return msym->print_name (); return ""; } @@ -193,7 +197,7 @@ ftrace_function_switched (const struct btrace_function *bfun, /* If the minimal symbol changed, we certainly switched functions. */ if (mfun != NULL && msym != NULL - && strcmp (MSYMBOL_LINKAGE_NAME (mfun), MSYMBOL_LINKAGE_NAME (msym)) != 0) + && strcmp (mfun->linkage_name (), msym->linkage_name ()) != 0) return 1; /* If the symbol changed, we certainly switched functions. */ @@ -202,7 +206,7 @@ ftrace_function_switched (const struct btrace_function *bfun, const char *bfname, *fname; /* Check the function name. */ - if (strcmp (SYMBOL_LINKAGE_NAME (fun), SYMBOL_LINKAGE_NAME (sym)) != 0) + if (strcmp (fun->linkage_name (), sym->linkage_name ()) != 0) return 1; /* Check the location of those functions, as well. */ @@ -617,6 +621,20 @@ ftrace_update_function (struct btrace_thread_info *btinfo, CORE_ADDR pc) if (start == pc) return ftrace_new_tailcall (btinfo, mfun, fun); + /* Some versions of _Unwind_RaiseException use an indirect + jump to 'return' to the exception handler of the caller + handling the exception instead of a return. Let's restrict + this heuristic to that and related functions. */ + const char *fname = ftrace_print_function_name (bfun); + if (strncmp (fname, "_Unwind_", strlen ("_Unwind_")) == 0) + { + struct btrace_function *caller + = ftrace_find_call_by_number (btinfo, bfun->up); + caller = ftrace_find_caller (btinfo, caller, mfun, fun); + if (caller != NULL) + return ftrace_new_return (btinfo, mfun, fun); + } + /* If we can't determine the function for PC, we treat a jump at the end of the block as tail call if we're switching functions and as an intra-function branch if we don't. */ @@ -661,7 +679,7 @@ ftrace_classify_insn (struct gdbarch *gdbarch, CORE_ADDR pc) enum btrace_insn_class iclass; iclass = BTRACE_INSN_OTHER; - TRY + try { if (gdbarch_insn_is_call (gdbarch, pc)) iclass = BTRACE_INSN_CALL; @@ -670,10 +688,9 @@ ftrace_classify_insn (struct gdbarch *gdbarch, CORE_ADDR pc) else if (gdbarch_insn_is_jump (gdbarch, pc)) iclass = BTRACE_INSN_JUMP; } - CATCH (error, RETURN_MASK_ERROR) + catch (const gdb_exception_error &error) { } - END_CATCH return iclass; } @@ -909,7 +926,7 @@ ftrace_bridge_gap (struct btrace_thread_info *btinfo, best_r = NULL; /* We search the back traces of LHS and RHS for valid connections and connect - the two functon segments that give the longest combined back trace. */ + the two function segments that give the longest combined back trace. */ for (cand_l = lhs; cand_l != NULL; cand_l = ftrace_get_caller (btinfo, cand_l)) @@ -1042,7 +1059,7 @@ btrace_compute_ftrace_bts (struct thread_info *tp, gdbarch = target_gdbarch (); btinfo = &tp->btrace; - blk = VEC_length (btrace_block_s, btrace->blocks); + blk = btrace->blocks->size (); if (btinfo->functions.empty ()) level = INT_MAX; @@ -1051,13 +1068,12 @@ btrace_compute_ftrace_bts (struct thread_info *tp, while (blk != 0) { - btrace_block_s *block; CORE_ADDR pc; blk -= 1; - block = VEC_index (btrace_block_s, btrace->blocks, blk); - pc = block->begin; + const btrace_block &block = btrace->blocks->at (blk); + pc = block.begin; for (;;) { @@ -1066,7 +1082,7 @@ btrace_compute_ftrace_bts (struct thread_info *tp, int size; /* We should hit the end of the block. Warn if we went too far. */ - if (block->end < pc) + if (block.end < pc) { /* Indicate the gap in the trace. */ bfun = ftrace_new_gap (btinfo, BDE_BTS_OVERFLOW, gaps); @@ -1086,14 +1102,13 @@ btrace_compute_ftrace_bts (struct thread_info *tp, level = std::min (level, bfun->level); size = 0; - TRY + try { size = gdb_insn_length (gdbarch, pc); } - CATCH (error, RETURN_MASK_ERROR) + catch (const gdb_exception_error &error) { } - END_CATCH insn.pc = pc; insn.size = size; @@ -1103,7 +1118,7 @@ btrace_compute_ftrace_bts (struct thread_info *tp, ftrace_update_insns (bfun, insn); /* We're done once we pushed the instruction at the end. */ - if (block->end == pc) + if (block.end == pc) break; /* We can't continue if we fail to compute the size. */ @@ -1353,17 +1368,16 @@ btrace_pt_readmem_callback (gdb_byte *buffer, size_t size, int result, errcode; result = (int) size; - TRY + try { errcode = target_read_code ((CORE_ADDR) pc, buffer, size); if (errcode != 0) result = -pte_nomap; } - CATCH (error, RETURN_MASK_ERROR) + catch (const gdb_exception_error &error) { result = -pte_nomap; } - END_CATCH return result; } @@ -1428,21 +1442,26 @@ btrace_compute_ftrace_pt (struct thread_info *tp, config.begin = btrace->data; config.end = btrace->data + btrace->size; - config.cpu.vendor = pt_translate_cpu_vendor (btrace->config.cpu.vendor); - config.cpu.family = btrace->config.cpu.family; - config.cpu.model = btrace->config.cpu.model; - config.cpu.stepping = btrace->config.cpu.stepping; + /* We treat an unknown vendor as 'no errata'. */ + if (btrace->config.cpu.vendor != CV_UNKNOWN) + { + config.cpu.vendor + = pt_translate_cpu_vendor (btrace->config.cpu.vendor); + config.cpu.family = btrace->config.cpu.family; + config.cpu.model = btrace->config.cpu.model; + config.cpu.stepping = btrace->config.cpu.stepping; - errcode = pt_cpu_errata (&config.errata, &config.cpu); - if (errcode < 0) - error (_("Failed to configure the Intel Processor Trace decoder: %s."), - pt_errstr (pt_errcode (errcode))); + errcode = pt_cpu_errata (&config.errata, &config.cpu); + if (errcode < 0) + error (_("Failed to configure the Intel Processor Trace " + "decoder: %s."), pt_errstr (pt_errcode (errcode))); + } decoder = pt_insn_alloc_decoder (&config); if (decoder == NULL) error (_("Failed to allocate the Intel Processor Trace decoder.")); - TRY + try { struct pt_image *image; @@ -1457,7 +1476,7 @@ btrace_compute_ftrace_pt (struct thread_info *tp, ftrace_add_pt (btinfo, decoder, &level, gaps); } - CATCH (error, RETURN_MASK_ALL) + catch (const gdb_exception &error) { /* Indicate a gap in the trace if we quit trace processing. */ if (error.reason == RETURN_QUIT && !btinfo->functions.empty ()) @@ -1465,9 +1484,8 @@ btrace_compute_ftrace_pt (struct thread_info *tp, btrace_finalize_ftrace_pt (decoder, tp, level); - throw_exception (error); + throw; } - END_CATCH btrace_finalize_ftrace_pt (decoder, tp, level); } @@ -1485,10 +1503,14 @@ btrace_compute_ftrace_pt (struct thread_info *tp, #endif /* defined (HAVE_LIBIPT) */ /* Compute the function branch trace from a block branch trace BTRACE for - a thread given by BTINFO. */ + a thread given by BTINFO. If CPU is not NULL, overwrite the cpu in the + branch trace configuration. This is currently only used for the PT + format. */ static void -btrace_compute_ftrace_1 (struct thread_info *tp, struct btrace_data *btrace, +btrace_compute_ftrace_1 (struct thread_info *tp, + struct btrace_data *btrace, + const struct btrace_cpu *cpu, std::vector &gaps) { DEBUG ("compute ftrace"); @@ -1503,11 +1525,15 @@ btrace_compute_ftrace_1 (struct thread_info *tp, struct btrace_data *btrace, return; case BTRACE_FORMAT_PT: + /* Overwrite the cpu we use for enabling errata workarounds. */ + if (cpu != nullptr) + btrace->variant.pt.config.cpu = *cpu; + btrace_compute_ftrace_pt (tp, &btrace->variant.pt, gaps); return; } - internal_error (__FILE__, __LINE__, _("Unkown branch trace format.")); + internal_error (__FILE__, __LINE__, _("Unknown branch trace format.")); } static void @@ -1521,21 +1547,21 @@ btrace_finalize_ftrace (struct thread_info *tp, std::vector &gaps) } static void -btrace_compute_ftrace (struct thread_info *tp, struct btrace_data *btrace) +btrace_compute_ftrace (struct thread_info *tp, struct btrace_data *btrace, + const struct btrace_cpu *cpu) { std::vector gaps; - TRY + try { - btrace_compute_ftrace_1 (tp, btrace, gaps); + btrace_compute_ftrace_1 (tp, btrace, cpu, gaps); } - CATCH (error, RETURN_MASK_ALL) + catch (const gdb_exception &error) { btrace_finalize_ftrace (tp, gaps); - throw_exception (error); + throw; } - END_CATCH btrace_finalize_ftrace (tp, gaps); } @@ -1546,27 +1572,18 @@ static void btrace_add_pc (struct thread_info *tp) { struct btrace_data btrace; - struct btrace_block *block; struct regcache *regcache; - struct cleanup *cleanup; CORE_ADDR pc; - regcache = get_thread_regcache (tp->ptid); + regcache = get_thread_regcache (tp); pc = regcache_read_pc (regcache); - btrace_data_init (&btrace); btrace.format = BTRACE_FORMAT_BTS; - btrace.variant.bts.blocks = NULL; - - cleanup = make_cleanup_btrace_data (&btrace); + btrace.variant.bts.blocks = new std::vector; - block = VEC_safe_push (btrace_block_s, btrace.variant.bts.blocks, NULL); - block->begin = pc; - block->end = pc; + btrace.variant.bts.blocks->emplace_back (pc, pc); - btrace_compute_ftrace (tp, &btrace); - - do_cleanups (cleanup); + btrace_compute_ftrace (tp, &btrace, NULL); } /* See btrace.h. */ @@ -1575,27 +1592,25 @@ void btrace_enable (struct thread_info *tp, const struct btrace_config *conf) { if (tp->btrace.target != NULL) - return; + error (_("Recording already enabled on thread %s (%s)."), + print_thread_id (tp), target_pid_to_str (tp->ptid).c_str ()); #if !defined (HAVE_LIBIPT) if (conf->format == BTRACE_FORMAT_PT) - error (_("GDB does not support Intel Processor Trace.")); + error (_("Intel Processor Trace support was disabled at compile time.")); #endif /* !defined (HAVE_LIBIPT) */ - if (!target_supports_btrace (conf->format)) - error (_("Target does not support branch tracing.")); - DEBUG ("enable thread %s (%s)", print_thread_id (tp), - target_pid_to_str (tp->ptid)); + target_pid_to_str (tp->ptid).c_str ()); tp->btrace.target = target_enable_btrace (tp->ptid, conf); - /* We're done if we failed to enable tracing. */ if (tp->btrace.target == NULL) - return; + error (_("Failed to enable recording on thread %s (%s)."), + print_thread_id (tp), target_pid_to_str (tp->ptid).c_str ()); /* We need to undo the enable in case of errors. */ - TRY + try { /* Add an entry for the current PC so we start tracing from where we enabled it. @@ -1607,16 +1622,15 @@ btrace_enable (struct thread_info *tp, const struct btrace_config *conf) This is not relevant for BTRACE_FORMAT_PT since the trace will already start at the PC at which tracing was enabled. */ if (conf->format != BTRACE_FORMAT_PT - && can_access_registers_ptid (tp->ptid)) + && can_access_registers_thread (tp)) btrace_add_pc (tp); } - CATCH (exception, RETURN_MASK_ALL) + catch (const gdb_exception &exception) { btrace_disable (tp); - throw_exception (exception); + throw; } - END_CATCH } /* See btrace.h. */ @@ -1636,13 +1650,13 @@ void btrace_disable (struct thread_info *tp) { struct btrace_thread_info *btp = &tp->btrace; - int errcode = 0; if (btp->target == NULL) - return; + error (_("Recording not enabled on thread %s (%s)."), + print_thread_id (tp), target_pid_to_str (tp->ptid).c_str ()); DEBUG ("disable thread %s (%s)", print_thread_id (tp), - target_pid_to_str (tp->ptid)); + target_pid_to_str (tp->ptid).c_str ()); target_disable_btrace (btp->target); btp->target = NULL; @@ -1656,13 +1670,12 @@ void btrace_teardown (struct thread_info *tp) { struct btrace_thread_info *btp = &tp->btrace; - int errcode = 0; if (btp->target == NULL) return; DEBUG ("teardown thread %s (%s)", print_thread_id (tp), - target_pid_to_str (tp->ptid)); + target_pid_to_str (tp->ptid).c_str ()); target_teardown_btrace (btp->target); btp->target = NULL; @@ -1677,11 +1690,11 @@ btrace_stitch_bts (struct btrace_data_bts *btrace, struct thread_info *tp) { struct btrace_thread_info *btinfo; struct btrace_function *last_bfun; - btrace_block_s *first_new_block; + btrace_block *first_new_block; btinfo = &tp->btrace; gdb_assert (!btinfo->functions.empty ()); - gdb_assert (!VEC_empty (btrace_block_s, btrace->blocks)); + gdb_assert (!btrace->blocks->empty ()); last_bfun = &btinfo->functions.back (); @@ -1690,14 +1703,14 @@ btrace_stitch_bts (struct btrace_data_bts *btrace, struct thread_info *tp) of the new trace, though, since we can't fill in the start address.*/ if (last_bfun->insn.empty ()) { - VEC_pop (btrace_block_s, btrace->blocks); + btrace->blocks->pop_back (); return 0; } /* Beware that block trace starts with the most recent block, so the chronologically first block in the new trace is the last block in the new trace's block vector. */ - first_new_block = VEC_last (btrace_block_s, btrace->blocks); + first_new_block = &btrace->blocks->back (); const btrace_insn &last_insn = last_bfun->insn.back (); /* If the current PC at the end of the block is the same as in our current @@ -1708,10 +1721,9 @@ btrace_stitch_bts (struct btrace_data_bts *btrace, struct thread_info *tp) entries. In the second case, the delta trace vector should contain exactly one entry for the partial block containing the current PC. Remove it. */ - if (first_new_block->end == last_insn.pc - && VEC_length (btrace_block_s, btrace->blocks) == 1) + if (first_new_block->end == last_insn.pc && btrace->blocks->size () == 1) { - VEC_pop (btrace_block_s, btrace->blocks); + btrace->blocks->pop_back (); return 0; } @@ -1765,7 +1777,7 @@ static int btrace_stitch_trace (struct btrace_data *btrace, struct thread_info *tp) { /* If we don't have trace, there's nothing to do. */ - if (btrace_data_empty (btrace)) + if (btrace->empty ()) return 0; switch (btrace->format) @@ -1781,7 +1793,7 @@ btrace_stitch_trace (struct btrace_data *btrace, struct thread_info *tp) return -1; } - internal_error (__FILE__, __LINE__, _("Unkown branch trace format.")); + internal_error (__FILE__, __LINE__, _("Unknown branch trace format.")); } /* Clear the branch trace histories in BTINFO. */ @@ -1815,7 +1827,7 @@ btrace_maint_clear (struct btrace_thread_info *btinfo) #if defined (HAVE_LIBIPT) case BTRACE_FORMAT_PT: - xfree (btinfo->maint.variant.pt.packets); + delete btinfo->maint.variant.pt.packets; btinfo->maint.variant.pt.packets = NULL; btinfo->maint.variant.pt.packet_history.begin = 0; @@ -1877,16 +1889,15 @@ btrace_decode_error (enum btrace_format format, int errcode) /* See btrace.h. */ void -btrace_fetch (struct thread_info *tp) +btrace_fetch (struct thread_info *tp, const struct btrace_cpu *cpu) { struct btrace_thread_info *btinfo; struct btrace_target_info *tinfo; struct btrace_data btrace; - struct cleanup *cleanup; int errcode; DEBUG ("fetch thread %s (%s)", print_thread_id (tp), - target_pid_to_str (tp->ptid)); + target_pid_to_str (tp->ptid).c_str ()); btinfo = &tp->btrace; tinfo = btinfo->target; @@ -1906,10 +1917,7 @@ btrace_fetch (struct thread_info *tp) inferior_ptid = tp->ptid; /* We should not be called on running or exited threads. */ - gdb_assert (can_access_registers_ptid (tp->ptid)); - - btrace_data_init (&btrace); - cleanup = make_cleanup_btrace_data (&btrace); + gdb_assert (can_access_registers_thread (tp)); /* Let's first try to extend the trace we already have. */ if (!btinfo->functions.empty ()) @@ -1926,7 +1934,7 @@ btrace_fetch (struct thread_info *tp) errcode = target_read_btrace (&btrace, tinfo, BTRACE_READ_NEW); /* If we got any new trace, discard what we have. */ - if (errcode == 0 && !btrace_data_empty (&btrace)) + if (errcode == 0 && !btrace.empty ()) btrace_clear (tp); } @@ -1945,7 +1953,7 @@ btrace_fetch (struct thread_info *tp) error (_("Failed to read branch trace.")); /* Compute the trace, provided we have any. */ - if (!btrace_data_empty (&btrace)) + if (!btrace.empty ()) { /* Store the raw trace data. The stored data will be cleared in btrace_clear, so we always append the new trace. */ @@ -1953,10 +1961,8 @@ btrace_fetch (struct thread_info *tp) btrace_maint_clear (btinfo); btrace_clear_history (btinfo); - btrace_compute_ftrace (tp, &btrace); + btrace_compute_ftrace (tp, &btrace, cpu); } - - do_cleanups (cleanup); } /* See btrace.h. */ @@ -1967,7 +1973,7 @@ btrace_clear (struct thread_info *tp) struct btrace_thread_info *btinfo; DEBUG ("clear thread %s (%s)", print_thread_id (tp), - target_pid_to_str (tp->ptid)); + target_pid_to_str (tp->ptid).c_str ()); /* Make sure btrace frames that may hold a pointer into the branch trace data are destroyed. */ @@ -1980,7 +1986,7 @@ btrace_clear (struct thread_info *tp) /* Must clear the maint data before - it depends on BTINFO->DATA. */ btrace_maint_clear (btinfo); - btrace_data_clear (&btinfo->data); + btinfo->data.clear (); btrace_clear_history (btinfo); } @@ -1989,11 +1995,9 @@ btrace_clear (struct thread_info *tp) void btrace_free_objfile (struct objfile *objfile) { - struct thread_info *tp; - DEBUG ("free objfile"); - ALL_NON_EXITED_THREADS (tp) + for (thread_info *tp : all_non_exited_threads ()) btrace_clear (tp); } @@ -2004,10 +2008,11 @@ btrace_free_objfile (struct objfile *objfile) static void check_xml_btrace_version (struct gdb_xml_parser *parser, const struct gdb_xml_element *element, - void *user_data, VEC (gdb_xml_value_s) *attributes) + void *user_data, + std::vector &attributes) { const char *version - = (const char *) xml_find_attribute (attributes, "version")->value; + = (const char *) xml_find_attribute (attributes, "version")->value.get (); if (strcmp (version, "1.0") != 0) gdb_xml_error (parser, _("Unsupported btrace version: \"%s\""), version); @@ -2018,10 +2023,10 @@ check_xml_btrace_version (struct gdb_xml_parser *parser, static void parse_xml_btrace_block (struct gdb_xml_parser *parser, const struct gdb_xml_element *element, - void *user_data, VEC (gdb_xml_value_s) *attributes) + void *user_data, + std::vector &attributes) { struct btrace_data *btrace; - struct btrace_block *block; ULONGEST *begin, *end; btrace = (struct btrace_data *) user_data; @@ -2033,19 +2038,16 @@ parse_xml_btrace_block (struct gdb_xml_parser *parser, case BTRACE_FORMAT_NONE: btrace->format = BTRACE_FORMAT_BTS; - btrace->variant.bts.blocks = NULL; + btrace->variant.bts.blocks = new std::vector; break; default: gdb_xml_error (parser, _("Btrace format error.")); } - begin = (ULONGEST *) xml_find_attribute (attributes, "begin")->value; - end = (ULONGEST *) xml_find_attribute (attributes, "end")->value; - - block = VEC_safe_push (btrace_block_s, btrace->variant.bts.blocks, NULL); - block->begin = *begin; - block->end = *end; + begin = (ULONGEST *) xml_find_attribute (attributes, "begin")->value.get (); + end = (ULONGEST *) xml_find_attribute (attributes, "end")->value.get (); + btrace->variant.bts.blocks->emplace_back (*begin, *end); } /* Parse a "raw" xml record. */ @@ -2054,8 +2056,7 @@ static void parse_xml_raw (struct gdb_xml_parser *parser, const char *body_text, gdb_byte **pdata, size_t *psize) { - struct cleanup *cleanup; - gdb_byte *data, *bin; + gdb_byte *bin; size_t len, size; len = strlen (body_text); @@ -2064,10 +2065,10 @@ parse_xml_raw (struct gdb_xml_parser *parser, const char *body_text, size = len / 2; - bin = data = (gdb_byte *) xmalloc (size); - cleanup = make_cleanup (xfree, data); + gdb::unique_xmalloc_ptr data ((gdb_byte *) xmalloc (size)); + bin = data.get (); - /* We use hex encoding - see common/rsp-low.h. */ + /* We use hex encoding - see gdbsupport/rsp-low.h. */ while (len > 0) { char hi, lo; @@ -2082,9 +2083,7 @@ parse_xml_raw (struct gdb_xml_parser *parser, const char *body_text, len -= 2; } - discard_cleanups (cleanup); - - *pdata = data; + *pdata = data.release (); *psize = size; } @@ -2094,16 +2093,20 @@ static void parse_xml_btrace_pt_config_cpu (struct gdb_xml_parser *parser, const struct gdb_xml_element *element, void *user_data, - VEC (gdb_xml_value_s) *attributes) + std::vector &attributes) { struct btrace_data *btrace; const char *vendor; ULONGEST *family, *model, *stepping; - vendor = (const char *) xml_find_attribute (attributes, "vendor")->value; - family = (ULONGEST *) xml_find_attribute (attributes, "family")->value; - model = (ULONGEST *) xml_find_attribute (attributes, "model")->value; - stepping = (ULONGEST *) xml_find_attribute (attributes, "stepping")->value; + vendor = + (const char *) xml_find_attribute (attributes, "vendor")->value.get (); + family + = (ULONGEST *) xml_find_attribute (attributes, "family")->value.get (); + model + = (ULONGEST *) xml_find_attribute (attributes, "model")->value.get (); + stepping + = (ULONGEST *) xml_find_attribute (attributes, "stepping")->value.get (); btrace = (struct btrace_data *) user_data; @@ -2134,7 +2137,8 @@ parse_xml_btrace_pt_raw (struct gdb_xml_parser *parser, static void parse_xml_btrace_pt (struct gdb_xml_parser *parser, const struct gdb_xml_element *element, - void *user_data, VEC (gdb_xml_value_s) *attributes) + void *user_data, + std::vector &attributes) { struct btrace_data *btrace; @@ -2198,25 +2202,24 @@ static const struct gdb_xml_element btrace_elements[] = { void parse_xml_btrace (struct btrace_data *btrace, const char *buffer) { - struct cleanup *cleanup; - int errcode; - #if defined (HAVE_LIBEXPAT) - btrace->format = BTRACE_FORMAT_NONE; + int errcode; + btrace_data result; + result.format = BTRACE_FORMAT_NONE; - cleanup = make_cleanup_btrace_data (btrace); errcode = gdb_xml_parse_quick (_("btrace"), "btrace.dtd", btrace_elements, - buffer, btrace); + buffer, &result); if (errcode != 0) error (_("Error parsing branch trace.")); /* Keep parse results. */ - discard_cleanups (cleanup); + *btrace = std::move (result); #else /* !defined (HAVE_LIBEXPAT) */ - error (_("Cannot process branch trace. XML parsing is not supported.")); + error (_("Cannot process branch trace. XML support was disabled at " + "compile time.")); #endif /* !defined (HAVE_LIBEXPAT) */ } @@ -2228,7 +2231,8 @@ parse_xml_btrace (struct btrace_data *btrace, const char *buffer) static void parse_xml_btrace_conf_bts (struct gdb_xml_parser *parser, const struct gdb_xml_element *element, - void *user_data, VEC (gdb_xml_value_s) *attributes) + void *user_data, + std::vector &attributes) { struct btrace_config *conf; struct gdb_xml_value *size; @@ -2239,7 +2243,7 @@ parse_xml_btrace_conf_bts (struct gdb_xml_parser *parser, size = xml_find_attribute (attributes, "size"); if (size != NULL) - conf->bts.size = (unsigned int) *(ULONGEST *) size->value; + conf->bts.size = (unsigned int) *(ULONGEST *) size->value.get (); } /* Parse a btrace-conf "pt" xml record. */ @@ -2247,7 +2251,8 @@ parse_xml_btrace_conf_bts (struct gdb_xml_parser *parser, static void parse_xml_btrace_conf_pt (struct gdb_xml_parser *parser, const struct gdb_xml_element *element, - void *user_data, VEC (gdb_xml_value_s) *attributes) + void *user_data, + std::vector &attributes) { struct btrace_config *conf; struct gdb_xml_value *size; @@ -2258,7 +2263,7 @@ parse_xml_btrace_conf_pt (struct gdb_xml_parser *parser, size = xml_find_attribute (attributes, "size"); if (size != NULL) - conf->pt.size = (unsigned int) *(ULONGEST *) size->value; + conf->pt.size = (unsigned int) *(ULONGEST *) size->value.get (); } static const struct gdb_xml_attribute btrace_conf_pt_attributes[] = { @@ -2297,10 +2302,9 @@ static const struct gdb_xml_element btrace_conf_elements[] = { void parse_xml_btrace_conf (struct btrace_config *conf, const char *xml) { - int errcode; - #if defined (HAVE_LIBEXPAT) + int errcode; errcode = gdb_xml_parse_quick (_("btrace-conf"), "btrace-conf.dtd", btrace_conf_elements, xml, conf); if (errcode != 0) @@ -2308,7 +2312,8 @@ parse_xml_btrace_conf (struct btrace_config *conf, const char *xml) #else /* !defined (HAVE_LIBEXPAT) */ - error (_("XML parsing is not supported.")); + error (_("Cannot process the branch trace configuration. XML support " + "was disabled at compile time.")); #endif /* !defined (HAVE_LIBEXPAT) */ } @@ -2821,22 +2826,6 @@ btrace_is_empty (struct thread_info *tp) return btrace_insn_cmp (&begin, &end) == 0; } -/* Forward the cleanup request. */ - -static void -do_btrace_data_cleanup (void *arg) -{ - btrace_data_fini ((struct btrace_data *) arg); -} - -/* See btrace.h. */ - -struct cleanup * -make_cleanup_btrace_data (struct btrace_data *data) -{ - return make_cleanup (do_btrace_data_cleanup, data); -} - #if defined (HAVE_LIBIPT) /* Print a single packet. */ @@ -2975,6 +2964,9 @@ btrace_maint_decode_pt (struct btrace_maint_info *maint, { int errcode; + if (maint->variant.pt.packets == NULL) + maint->variant.pt.packets = new std::vector; + for (;;) { struct btrace_pt_packet packet; @@ -2995,8 +2987,7 @@ btrace_maint_decode_pt (struct btrace_maint_info *maint, if (maint_btrace_pt_skip_pad == 0 || packet.packet.type != ppt_pad) { packet.errcode = pt_errcode (errcode); - VEC_safe_push (btrace_pt_packet_s, maint->variant.pt.packets, - &packet); + maint->variant.pt.packets->push_back (packet); } } @@ -3004,8 +2995,7 @@ btrace_maint_decode_pt (struct btrace_maint_info *maint, break; packet.errcode = pt_errcode (errcode); - VEC_safe_push (btrace_pt_packet_s, maint->variant.pt.packets, - &packet); + maint->variant.pt.packets->push_back (packet); warning (_("Error at trace offset 0x%" PRIx64 ": %s."), packet.offset, pt_errstr (packet.errcode)); @@ -3021,8 +3011,8 @@ btrace_maint_decode_pt (struct btrace_maint_info *maint, static void btrace_maint_update_pt_packets (struct btrace_thread_info *btinfo) { - volatile struct gdb_exception except; struct pt_packet_decoder *decoder; + const struct btrace_cpu *cpu; struct btrace_data_pt *pt; struct pt_config config; int errcode; @@ -3039,32 +3029,39 @@ btrace_maint_update_pt_packets (struct btrace_thread_info *btinfo) config.begin = pt->data; config.end = pt->data + pt->size; - config.cpu.vendor = pt_translate_cpu_vendor (pt->config.cpu.vendor); - config.cpu.family = pt->config.cpu.family; - config.cpu.model = pt->config.cpu.model; - config.cpu.stepping = pt->config.cpu.stepping; + cpu = record_btrace_get_cpu (); + if (cpu == nullptr) + cpu = &pt->config.cpu; + + /* We treat an unknown vendor as 'no errata'. */ + if (cpu->vendor != CV_UNKNOWN) + { + config.cpu.vendor = pt_translate_cpu_vendor (cpu->vendor); + config.cpu.family = cpu->family; + config.cpu.model = cpu->model; + config.cpu.stepping = cpu->stepping; - errcode = pt_cpu_errata (&config.errata, &config.cpu); - if (errcode < 0) - error (_("Failed to configure the Intel Processor Trace decoder: %s."), - pt_errstr (pt_errcode (errcode))); + errcode = pt_cpu_errata (&config.errata, &config.cpu); + if (errcode < 0) + error (_("Failed to configure the Intel Processor Trace " + "decoder: %s."), pt_errstr (pt_errcode (errcode))); + } decoder = pt_pkt_alloc_decoder (&config); if (decoder == NULL) error (_("Failed to allocate the Intel Processor Trace decoder.")); - TRY + try { btrace_maint_decode_pt (&btinfo->maint, decoder); } - CATCH (except, RETURN_MASK_ALL) + catch (const gdb_exception &except) { pt_pkt_free_decoder (decoder); if (except.reason < 0) - throw_exception (except); + throw; } - END_CATCH pt_pkt_free_decoder (decoder); } @@ -3092,18 +3089,21 @@ btrace_maint_update_packets (struct btrace_thread_info *btinfo, case BTRACE_FORMAT_BTS: /* Nothing to do - we operate directly on BTINFO->DATA. */ *begin = 0; - *end = VEC_length (btrace_block_s, btinfo->data.variant.bts.blocks); + *end = btinfo->data.variant.bts.blocks->size (); *from = btinfo->maint.variant.bts.packet_history.begin; *to = btinfo->maint.variant.bts.packet_history.end; break; #if defined (HAVE_LIBIPT) case BTRACE_FORMAT_PT: - if (VEC_empty (btrace_pt_packet_s, btinfo->maint.variant.pt.packets)) + if (btinfo->maint.variant.pt.packets == nullptr) + btinfo->maint.variant.pt.packets = new std::vector; + + if (btinfo->maint.variant.pt.packets->empty ()) btrace_maint_update_pt_packets (btinfo); *begin = 0; - *end = VEC_length (btrace_pt_packet_s, btinfo->maint.variant.pt.packets); + *end = btinfo->maint.variant.pt.packets->size (); *from = btinfo->maint.variant.pt.packet_history.begin; *to = btinfo->maint.variant.pt.packet_history.end; break; @@ -3125,19 +3125,17 @@ btrace_maint_print_packets (struct btrace_thread_info *btinfo, case BTRACE_FORMAT_BTS: { - VEC (btrace_block_s) *blocks; + const std::vector &blocks + = *btinfo->data.variant.bts.blocks; unsigned int blk; - blocks = btinfo->data.variant.bts.blocks; for (blk = begin; blk < end; ++blk) { - const btrace_block_s *block; - - block = VEC_index (btrace_block_s, blocks, blk); + const btrace_block &block = blocks.at (blk); printf_unfiltered ("%u\tbegin: %s, end: %s\n", blk, - core_addr_to_string_nz (block->begin), - core_addr_to_string_nz (block->end)); + core_addr_to_string_nz (block.begin), + core_addr_to_string_nz (block.end)); } btinfo->maint.variant.bts.packet_history.begin = begin; @@ -3148,23 +3146,21 @@ btrace_maint_print_packets (struct btrace_thread_info *btinfo, #if defined (HAVE_LIBIPT) case BTRACE_FORMAT_PT: { - VEC (btrace_pt_packet_s) *packets; + const std::vector &packets + = *btinfo->maint.variant.pt.packets; unsigned int pkt; - packets = btinfo->maint.variant.pt.packets; for (pkt = begin; pkt < end; ++pkt) { - const struct btrace_pt_packet *packet; - - packet = VEC_index (btrace_pt_packet_s, packets, pkt); + const struct btrace_pt_packet &packet = packets.at (pkt); printf_unfiltered ("%u\t", pkt); - printf_unfiltered ("0x%" PRIx64 "\t", packet->offset); + printf_unfiltered ("0x%" PRIx64 "\t", packet.offset); - if (packet->errcode == pte_ok) - pt_print_packet (&packet->packet); + if (packet.errcode == pte_ok) + pt_print_packet (&packet.packet); else - printf_unfiltered ("[error: %s]", pt_errstr (packet->errcode)); + printf_unfiltered ("[error: %s]", pt_errstr (packet.errcode)); printf_unfiltered ("\n"); } @@ -3232,10 +3228,9 @@ static void maint_btrace_packet_history_cmd (const char *arg, int from_tty) { struct btrace_thread_info *btinfo; - struct thread_info *tp; unsigned int size, begin, end, from, to; - tp = find_thread_ptid (inferior_ptid); + thread_info *tp = find_thread_ptid (current_inferior (), inferior_ptid); if (tp == NULL) error (_("No thread.")); @@ -3336,21 +3331,18 @@ maint_btrace_packet_history_cmd (const char *arg, int from_tty) static void maint_btrace_clear_packet_history_cmd (const char *args, int from_tty) { - struct btrace_thread_info *btinfo; - struct thread_info *tp; - if (args != NULL && *args != 0) error (_("Invalid argument.")); - tp = find_thread_ptid (inferior_ptid); - if (tp == NULL) + if (inferior_ptid == null_ptid) error (_("No thread.")); - btinfo = &tp->btrace; + thread_info *tp = inferior_thread (); + btrace_thread_info *btinfo = &tp->btrace; /* Must clear the maint data before - it depends on BTINFO->DATA. */ btrace_maint_clear (btinfo); - btrace_data_clear (&btinfo->data); + btinfo->data.clear (); } /* The "maintenance btrace clear" command. */ @@ -3358,80 +3350,32 @@ maint_btrace_clear_packet_history_cmd (const char *args, int from_tty) static void maint_btrace_clear_cmd (const char *args, int from_tty) { - struct btrace_thread_info *btinfo; - struct thread_info *tp; - if (args != NULL && *args != 0) error (_("Invalid argument.")); - tp = find_thread_ptid (inferior_ptid); - if (tp == NULL) + if (inferior_ptid == null_ptid) error (_("No thread.")); + thread_info *tp = inferior_thread (); btrace_clear (tp); } -/* The "maintenance btrace" command. */ - -static void -maint_btrace_cmd (const char *args, int from_tty) -{ - help_list (maint_btrace_cmdlist, "maintenance btrace ", all_commands, - gdb_stdout); -} - -/* The "maintenance set btrace" command. */ - -static void -maint_btrace_set_cmd (const char *args, int from_tty) -{ - help_list (maint_btrace_set_cmdlist, "maintenance set btrace ", all_commands, - gdb_stdout); -} - -/* The "maintenance show btrace" command. */ - -static void -maint_btrace_show_cmd (const char *args, int from_tty) -{ - help_list (maint_btrace_show_cmdlist, "maintenance show btrace ", - all_commands, gdb_stdout); -} - -/* The "maintenance set btrace pt" command. */ - -static void -maint_btrace_pt_set_cmd (const char *args, int from_tty) -{ - help_list (maint_btrace_pt_set_cmdlist, "maintenance set btrace pt ", - all_commands, gdb_stdout); -} - -/* The "maintenance show btrace pt" command. */ - -static void -maint_btrace_pt_show_cmd (const char *args, int from_tty) -{ - help_list (maint_btrace_pt_show_cmdlist, "maintenance show btrace pt ", - all_commands, gdb_stdout); -} - /* The "maintenance info btrace" command. */ static void maint_info_btrace_cmd (const char *args, int from_tty) { struct btrace_thread_info *btinfo; - struct thread_info *tp; const struct btrace_config *conf; if (args != NULL && *args != 0) error (_("Invalid argument.")); - tp = find_thread_ptid (inferior_ptid); - if (tp == NULL) + if (inferior_ptid == null_ptid) error (_("No thread.")); + thread_info *tp = inferior_thread (); + btinfo = &tp->btrace; conf = btrace_conf (btinfo); @@ -3447,9 +3391,8 @@ maint_info_btrace_cmd (const char *args, int from_tty) break; case BTRACE_FORMAT_BTS: - printf_unfiltered (_("Number of packets: %u.\n"), - VEC_length (btrace_block_s, - btinfo->data.variant.bts.blocks)); + printf_unfiltered (_("Number of packets: %zu.\n"), + btinfo->data.variant.bts.blocks->size ()); break; #if defined (HAVE_LIBIPT) @@ -3463,9 +3406,9 @@ maint_info_btrace_cmd (const char *args, int from_tty) version.ext != NULL ? version.ext : ""); btrace_maint_update_pt_packets (btinfo); - printf_unfiltered (_("Number of packets: %u.\n"), - VEC_length (btrace_pt_packet_s, - btinfo->maint.variant.pt.packets)); + printf_unfiltered (_("Number of packets: %zu.\n"), + ((btinfo->maint.variant.pt.packets == nullptr) + ? 0 : btinfo->maint.variant.pt.packets->size ())); } break; #endif /* defined (HAVE_LIBIPT) */ @@ -3485,36 +3428,39 @@ show_maint_btrace_pt_skip_pad (struct ui_file *file, int from_tty, /* Initialize btrace maintenance commands. */ +void _initialize_btrace (); void -_initialize_btrace (void) +_initialize_btrace () { add_cmd ("btrace", class_maintenance, maint_info_btrace_cmd, _("Info about branch tracing data."), &maintenanceinfolist); - add_prefix_cmd ("btrace", class_maintenance, maint_btrace_cmd, - _("Branch tracing maintenance commands."), - &maint_btrace_cmdlist, "maintenance btrace ", - 0, &maintenancelist); + add_basic_prefix_cmd ("btrace", class_maintenance, + _("Branch tracing maintenance commands."), + &maint_btrace_cmdlist, "maintenance btrace ", + 0, &maintenancelist); - add_prefix_cmd ("btrace", class_maintenance, maint_btrace_set_cmd, _("\ + add_basic_prefix_cmd ("btrace", class_maintenance, _("\ Set branch tracing specific variables."), - &maint_btrace_set_cmdlist, "maintenance set btrace ", - 0, &maintenance_set_cmdlist); + &maint_btrace_set_cmdlist, "maintenance set btrace ", + 0, &maintenance_set_cmdlist); - add_prefix_cmd ("pt", class_maintenance, maint_btrace_pt_set_cmd, _("\ + add_basic_prefix_cmd ("pt", class_maintenance, _("\ Set Intel Processor Trace specific variables."), - &maint_btrace_pt_set_cmdlist, "maintenance set btrace pt ", - 0, &maint_btrace_set_cmdlist); + &maint_btrace_pt_set_cmdlist, + "maintenance set btrace pt ", + 0, &maint_btrace_set_cmdlist); - add_prefix_cmd ("btrace", class_maintenance, maint_btrace_show_cmd, _("\ + add_show_prefix_cmd ("btrace", class_maintenance, _("\ Show branch tracing specific variables."), - &maint_btrace_show_cmdlist, "maintenance show btrace ", - 0, &maintenance_show_cmdlist); + &maint_btrace_show_cmdlist, "maintenance show btrace ", + 0, &maintenance_show_cmdlist); - add_prefix_cmd ("pt", class_maintenance, maint_btrace_pt_show_cmd, _("\ + add_show_prefix_cmd ("pt", class_maintenance, _("\ Show Intel Processor Trace specific variables."), - &maint_btrace_pt_show_cmdlist, "maintenance show btrace pt ", - 0, &maint_btrace_show_cmdlist); + &maint_btrace_pt_show_cmdlist, + "maintenance show btrace pt ", + 0, &maint_btrace_show_cmdlist); add_setshow_boolean_cmd ("skip-pad", class_maintenance, &maint_btrace_pt_skip_pad, _("\ @@ -3533,21 +3479,19 @@ One argument specifies the starting packet of a ten-line print.\n\ Two arguments with comma between specify starting and ending packets to \ print.\n\ Preceded with '+'/'-' the second argument specifies the distance from the \ -first.\n"), +first."), &maint_btrace_cmdlist); add_cmd ("clear-packet-history", class_maintenance, maint_btrace_clear_packet_history_cmd, _("Clears the branch tracing packet history.\n\ -Discards the raw branch tracing data but not the execution history data.\n\ -"), +Discards the raw branch tracing data but not the execution history data."), &maint_btrace_cmdlist); add_cmd ("clear", class_maintenance, maint_btrace_clear_cmd, _("Clears the branch tracing data.\n\ Discards the raw branch tracing data and the execution history data.\n\ -The next 'record' command will fetch the branch tracing data anew.\n\ -"), +The next 'record' command will fetch the branch tracing data anew."), &maint_btrace_cmdlist); }