X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;ds=sidebyside;f=gdb%2Fbtrace.h;h=4c6a93d4268262e835f8191adfe64f9aacfd78dc;hb=441af85bd9c68dbc0c2a1dbe23bf07c6cb3c3f5d;hp=26b1686071f66d3ce14ba5c8cd103d035665c2f5;hpb=02d27625761a91b9ea78ab4048e1171a7b47a603;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/btrace.h b/gdb/btrace.h index 26b1686071..4c6a93d426 100644 --- a/gdb/btrace.h +++ b/gdb/btrace.h @@ -1,6 +1,6 @@ /* Branch trace support for GDB, the GNU debugger. - Copyright (C) 2013 Free Software Foundation, Inc. + Copyright (C) 2013-2020 Free Software Foundation, Inc. Contributed by Intel Corp. . @@ -26,68 +26,287 @@ inferior. For presentation purposes, the branch trace is represented as a list of sequential control-flow blocks, one such list per thread. */ -#include "btrace-common.h" +#include "gdbsupport/btrace-common.h" +#include "target/waitstatus.h" /* For enum target_stop_reason. */ +#include "gdbsupport/enum-flags.h" + +#if defined (HAVE_LIBIPT) +# include +#endif + +#include struct thread_info; +struct btrace_function; + +/* A coarse instruction classification. */ +enum btrace_insn_class +{ + /* The instruction is something not listed below. */ + BTRACE_INSN_OTHER, + + /* The instruction is a function call. */ + BTRACE_INSN_CALL, + + /* The instruction is a function return. */ + BTRACE_INSN_RETURN, + + /* The instruction is an unconditional jump. */ + BTRACE_INSN_JUMP +}; + +/* Instruction flags. */ +enum btrace_insn_flag +{ + /* The instruction has been executed speculatively. */ + BTRACE_INSN_FLAG_SPECULATIVE = (1 << 0) +}; +DEF_ENUM_FLAGS_TYPE (enum btrace_insn_flag, btrace_insn_flags); /* A branch trace instruction. This represents a single instruction in a branch trace. */ -struct btrace_inst +struct btrace_insn { /* The address of this instruction. */ CORE_ADDR pc; + + /* The size of this instruction in bytes. */ + gdb_byte size; + + /* The instruction class of this instruction. */ + enum btrace_insn_class iclass; + + /* A bit vector of BTRACE_INSN_FLAGS. */ + btrace_insn_flags flags; +}; + +/* Flags for btrace function segments. */ +enum btrace_function_flag +{ + /* The 'up' link interpretation. + If set, it points to the function segment we returned to. + If clear, it points to the function segment we called from. */ + BFUN_UP_LINKS_TO_RET = (1 << 0), + + /* The 'up' link points to a tail call. This obviously only makes sense + if bfun_up_links_to_ret is clear. */ + BFUN_UP_LINKS_TO_TAILCALL = (1 << 1) +}; +DEF_ENUM_FLAGS_TYPE (enum btrace_function_flag, btrace_function_flags); + +/* Decode errors for the BTS recording format. */ +enum btrace_bts_error +{ + /* The instruction trace overflowed the end of the trace block. */ + BDE_BTS_OVERFLOW = 1, + + /* The instruction size could not be determined. */ + BDE_BTS_INSN_SIZE +}; + +/* Decode errors for the Intel Processor Trace recording format. */ +enum btrace_pt_error +{ + /* The user cancelled trace processing. */ + BDE_PT_USER_QUIT = 1, + + /* Tracing was temporarily disabled. */ + BDE_PT_DISABLED, + + /* Trace recording overflowed. */ + BDE_PT_OVERFLOW + + /* Negative numbers are used by the decoder library. */ }; -/* A branch trace function. +/* A branch trace function segment. This represents a function segment in a branch trace, i.e. a consecutive - number of instructions belonging to the same function. */ -struct btrace_func + number of instructions belonging to the same function. + + In case of decode errors, we add an empty function segment to indicate + the gap in the trace. + + We do not allow function segments without instructions otherwise. */ +struct btrace_function { - /* The full and minimal symbol for the function. One of them may be NULL. */ + btrace_function (struct minimal_symbol *msym_, struct symbol *sym_, + unsigned int number_, unsigned int insn_offset_, int level_) + : msym (msym_), sym (sym_), insn_offset (insn_offset_), number (number_), + level (level_) + { + } + + /* The full and minimal symbol for the function. Both may be NULL. */ struct minimal_symbol *msym; struct symbol *sym; - /* The source line range of this function segment (both inclusive). */ - int lbegin, lend; - - /* The instruction number range in the instruction trace corresponding - to this function segment (both inclusive). */ - unsigned int ibegin, iend; + /* The function segment numbers of the previous and next segment belonging to + the same function. If a function calls another function, the former will + have at least two segments: one before the call and another after the + return. Will be zero if there is no such function segment. */ + unsigned int prev = 0; + unsigned int next = 0; + + /* The function segment number of the directly preceding function segment in + a (fake) call stack. Will be zero if there is no such function segment in + the record. */ + unsigned int up = 0; + + /* The instructions in this function segment. + The instruction vector will be empty if the function segment + represents a decode error. */ + std::vector insn; + + /* The error code of a decode error that led to a gap. + Must be zero unless INSN is empty; non-zero otherwise. */ + int errcode = 0; + + /* The instruction number offset for the first instruction in this + function segment. + If INSN is empty this is the insn_offset of the succeding function + segment in control-flow order. */ + unsigned int insn_offset; + + /* The 1-based function number in control-flow order. + If INSN is empty indicating a gap in the trace due to a decode error, + we still count the gap as a function. */ + unsigned int number; + + /* The function level in a back trace across the entire branch trace. + A caller's level is one lower than the level of its callee. + + Levels can be negative if we see returns for which we have not seen + the corresponding calls. The branch trace thread information provides + a fixup to normalize function levels so the smallest level is zero. */ + int level; + + /* A bit-vector of btrace_function_flag. */ + btrace_function_flags flags = 0; }; -/* Branch trace may also be represented as a vector of: +/* A branch trace instruction iterator. */ +struct btrace_insn_iterator +{ + /* The branch trace information for this thread. Will never be NULL. */ + const struct btrace_thread_info *btinfo; - - branch trace instructions starting with the oldest instruction. - - branch trace functions starting with the oldest function. */ -typedef struct btrace_inst btrace_inst_s; -typedef struct btrace_func btrace_func_s; + /* The index of the function segment in BTINFO->FUNCTIONS. */ + unsigned int call_index; + + /* The index into the function segment's instruction vector. */ + unsigned int insn_index; +}; + +/* A branch trace function call iterator. */ +struct btrace_call_iterator +{ + /* The branch trace information for this thread. Will never be NULL. */ + const struct btrace_thread_info *btinfo; -/* Define functions operating on branch trace vectors. */ -DEF_VEC_O (btrace_inst_s); -DEF_VEC_O (btrace_func_s); + /* The index of the function segment in BTINFO->FUNCTIONS. */ + unsigned int index; +}; /* Branch trace iteration state for "record instruction-history". */ -struct btrace_insn_iterator +struct btrace_insn_history { - /* The instruction index range from begin (inclusive) to end (exclusive) - that has been covered last time. - If end < begin, the branch trace has just been updated. */ - unsigned int begin; - unsigned int end; + /* The branch trace instruction range from BEGIN (inclusive) to + END (exclusive) that has been covered last time. */ + struct btrace_insn_iterator begin; + struct btrace_insn_iterator end; }; /* Branch trace iteration state for "record function-call-history". */ -struct btrace_func_iterator +struct btrace_call_history +{ + /* The branch trace function range from BEGIN (inclusive) to END (exclusive) + that has been covered last time. */ + struct btrace_call_iterator begin; + struct btrace_call_iterator end; +}; + +/* Branch trace thread flags. */ +enum btrace_thread_flag : unsigned +{ + /* The thread is to be stepped forwards. */ + BTHR_STEP = (1 << 0), + + /* The thread is to be stepped backwards. */ + BTHR_RSTEP = (1 << 1), + + /* The thread is to be continued forwards. */ + BTHR_CONT = (1 << 2), + + /* The thread is to be continued backwards. */ + BTHR_RCONT = (1 << 3), + + /* The thread is to be moved. */ + BTHR_MOVE = (BTHR_STEP | BTHR_RSTEP | BTHR_CONT | BTHR_RCONT), + + /* The thread is to be stopped. */ + BTHR_STOP = (1 << 4) +}; +DEF_ENUM_FLAGS_TYPE (enum btrace_thread_flag, btrace_thread_flags); + +#if defined (HAVE_LIBIPT) +/* A packet. */ +struct btrace_pt_packet +{ + /* The offset in the trace stream. */ + uint64_t offset; + + /* The decode error code. */ + enum pt_error_code errcode; + + /* The decoded packet. Only valid if ERRCODE == pte_ok. */ + struct pt_packet packet; +}; + +#endif /* defined (HAVE_LIBIPT) */ + +/* Branch trace iteration state for "maintenance btrace packet-history". */ +struct btrace_maint_packet_history { - /* The function index range from begin (inclusive) to end (exclusive) - that has been covered last time. - If end < begin, the branch trace has just been updated. */ + /* The branch trace packet range from BEGIN (inclusive) to + END (exclusive) that has been covered last time. */ unsigned int begin; unsigned int end; }; +/* Branch trace maintenance information per thread. + + This information is used by "maintenance btrace" commands. */ +struct btrace_maint_info +{ + /* Most information is format-specific. + The format can be found in the BTRACE.DATA.FORMAT field of each thread. */ + union + { + /* BTRACE.DATA.FORMAT == BTRACE_FORMAT_BTS */ + struct + { + /* The packet history iterator. + We are iterating over BTRACE.DATA.FORMAT.VARIANT.BTS.BLOCKS. */ + struct btrace_maint_packet_history packet_history; + } bts; + +#if defined (HAVE_LIBIPT) + /* BTRACE.DATA.FORMAT == BTRACE_FORMAT_PT */ + struct + { + /* A vector of decoded packets. */ + std::vector *packets; + + /* The packet history iterator. + We are iterating over the above PACKETS vector. */ + struct btrace_maint_packet_history packet_history; + } pt; +#endif /* defined (HAVE_LIBIPT) */ + } variant; +}; + /* Branch trace information per thread. This represents the branch trace configuration as well as the entry point @@ -103,20 +322,51 @@ struct btrace_thread_info the underlying architecture. */ struct btrace_target_info *target; - /* The current branch trace for this thread. */ - VEC (btrace_block_s) *btrace; - VEC (btrace_inst_s) *itrace; - VEC (btrace_func_s) *ftrace; + /* The raw branch trace data for the below branch trace. */ + struct btrace_data data; + + /* Vector of decoded function segments in execution flow order. + Note that the numbering for btrace function segments starts with 1, so + function segment i will be at index (i - 1). */ + std::vector functions; + + /* The function level offset. When added to each function's LEVEL, + this normalizes the function levels such that the smallest level + becomes zero. */ + int level; + + /* The number of gaps in the trace. */ + unsigned int ngaps; + + /* A bit-vector of btrace_thread_flag. */ + btrace_thread_flags flags; /* The instruction history iterator. */ - struct btrace_insn_iterator insn_iterator; + struct btrace_insn_history *insn_history; /* The function call history iterator. */ - struct btrace_func_iterator func_iterator; + struct btrace_call_history *call_history; + + /* The current replay position. NULL if not replaying. + Gaps are skipped during replay, so REPLAY always points to a valid + instruction. */ + struct btrace_insn_iterator *replay; + + /* Why the thread stopped, if we need to track it. */ + enum target_stop_reason stop_reason; + + /* Maintenance information. */ + struct btrace_maint_info maint; }; /* Enable branch tracing for a thread. */ -extern void btrace_enable (struct thread_info *tp); +extern void btrace_enable (struct thread_info *tp, + const struct btrace_config *conf); + +/* Get the branch trace configuration for a thread. + Return NULL if branch tracing is not enabled for that thread. */ +extern const struct btrace_config * + btrace_conf (const struct btrace_thread_info *); /* Disable branch tracing for a thread. This will also delete the current branch trace data. */ @@ -127,8 +377,15 @@ extern void btrace_disable (struct thread_info *); target_teardown_btrace instead of target_disable_btrace. */ extern void btrace_teardown (struct thread_info *); -/* Fetch the branch trace for a single thread. */ -extern void btrace_fetch (struct thread_info *); +/* Return a human readable error string for the given ERRCODE in FORMAT. + The pointer will never be NULL and must not be freed. */ + +extern const char *btrace_decode_error (enum btrace_format format, int errcode); + +/* Fetch the branch trace for a single thread. If CPU is not NULL, assume + CPU for trace decode. */ +extern void btrace_fetch (struct thread_info *, + const struct btrace_cpu *cpu); /* Clear the branch trace for a single thread. */ extern void btrace_clear (struct thread_info *); @@ -136,4 +393,115 @@ extern void btrace_clear (struct thread_info *); /* Clear the branch trace for all threads when an object file goes away. */ extern void btrace_free_objfile (struct objfile *); +/* Parse a branch trace xml document XML into DATA. */ +extern void parse_xml_btrace (struct btrace_data *data, const char *xml); + +/* Parse a branch trace configuration xml document XML into CONF. */ +extern void parse_xml_btrace_conf (struct btrace_config *conf, const char *xml); + +/* Dereference a branch trace instruction iterator. Return a pointer to the + instruction the iterator points to. + May return NULL if the iterator points to a gap in the trace. */ +extern const struct btrace_insn * + btrace_insn_get (const struct btrace_insn_iterator *); + +/* Return the error code for a branch trace instruction iterator. Returns zero + if there is no error, i.e. the instruction is valid. */ +extern int btrace_insn_get_error (const struct btrace_insn_iterator *); + +/* Return the instruction number for a branch trace iterator. + Returns one past the maximum instruction number for the end iterator. */ +extern unsigned int btrace_insn_number (const struct btrace_insn_iterator *); + +/* Initialize a branch trace instruction iterator to point to the begin/end of + the branch trace. Throws an error if there is no branch trace. */ +extern void btrace_insn_begin (struct btrace_insn_iterator *, + const struct btrace_thread_info *); +extern void btrace_insn_end (struct btrace_insn_iterator *, + const struct btrace_thread_info *); + +/* Increment/decrement a branch trace instruction iterator by at most STRIDE + instructions. Return the number of instructions by which the instruction + iterator has been advanced. + Returns zero, if the operation failed or STRIDE had been zero. */ +extern unsigned int btrace_insn_next (struct btrace_insn_iterator *, + unsigned int stride); +extern unsigned int btrace_insn_prev (struct btrace_insn_iterator *, + unsigned int stride); + +/* Compare two branch trace instruction iterators. + Return a negative number if LHS < RHS. + Return zero if LHS == RHS. + Return a positive number if LHS > RHS. */ +extern int btrace_insn_cmp (const struct btrace_insn_iterator *lhs, + const struct btrace_insn_iterator *rhs); + +/* Find an instruction or gap in the function branch trace by its number. + If the instruction is found, initialize the branch trace instruction + iterator to point to this instruction and return non-zero. + Return zero otherwise. */ +extern int btrace_find_insn_by_number (struct btrace_insn_iterator *, + const struct btrace_thread_info *, + unsigned int number); + +/* Dereference a branch trace call iterator. Return a pointer to the + function the iterator points to or NULL if the iterator points past + the end of the branch trace. */ +extern const struct btrace_function * + btrace_call_get (const struct btrace_call_iterator *); + +/* Return the function number for a branch trace call iterator. + Returns one past the maximum function number for the end iterator. + Returns zero if the iterator does not point to a valid function. */ +extern unsigned int btrace_call_number (const struct btrace_call_iterator *); + +/* Initialize a branch trace call iterator to point to the begin/end of + the branch trace. Throws an error if there is no branch trace. */ +extern void btrace_call_begin (struct btrace_call_iterator *, + const struct btrace_thread_info *); +extern void btrace_call_end (struct btrace_call_iterator *, + const struct btrace_thread_info *); + +/* Increment/decrement a branch trace call iterator by at most STRIDE function + segments. Return the number of function segments by which the call + iterator has been advanced. + Returns zero, if the operation failed or STRIDE had been zero. */ +extern unsigned int btrace_call_next (struct btrace_call_iterator *, + unsigned int stride); +extern unsigned int btrace_call_prev (struct btrace_call_iterator *, + unsigned int stride); + +/* Compare two branch trace call iterators. + Return a negative number if LHS < RHS. + Return zero if LHS == RHS. + Return a positive number if LHS > RHS. */ +extern int btrace_call_cmp (const struct btrace_call_iterator *lhs, + const struct btrace_call_iterator *rhs); + +/* Find a function in the function branch trace by its NUMBER. + If the function is found, initialize the branch trace call + iterator to point to this function and return non-zero. + Return zero otherwise. */ +extern int btrace_find_call_by_number (struct btrace_call_iterator *, + const struct btrace_thread_info *, + unsigned int number); + +/* Set the branch trace instruction history from BEGIN (inclusive) to + END (exclusive). */ +extern void btrace_set_insn_history (struct btrace_thread_info *, + const struct btrace_insn_iterator *begin, + const struct btrace_insn_iterator *end); + +/* Set the branch trace function call history from BEGIN (inclusive) to + END (exclusive). */ +extern void btrace_set_call_history (struct btrace_thread_info *, + const struct btrace_call_iterator *begin, + const struct btrace_call_iterator *end); + +/* Determine if branch tracing is currently replaying TP. */ +extern int btrace_is_replaying (struct thread_info *tp); + +/* Return non-zero if the branch trace for TP is empty; zero otherwise. */ +extern int btrace_is_empty (struct thread_info *tp); + #endif /* BTRACE_H */