diff options
author | Felix Willgerodt <felix.willgerodt@intel.com> | 2019-02-18 15:50:49 +0100 |
---|---|---|
committer | Felix Willgerodt <felix.willgerodt@intel.com> | 2024-08-14 11:20:57 +0200 |
commit | 3bf62223f0f5591c70523e363a496dba6c699e3a (patch) | |
tree | 2d1f60312520648fd630cb563c56b7f87fe7326c /gdb/btrace.c | |
parent | 6be9971c93f3bbcd4b779e5591697748da6b093e (diff) | |
download | gdb-3bf62223f0f5591c70523e363a496dba6c699e3a.zip gdb-3bf62223f0f5591c70523e363a496dba6c699e3a.tar.gz gdb-3bf62223f0f5591c70523e363a496dba6c699e3a.tar.bz2 |
btrace: Extend ptwrite event decoding.
Call the ptwrite filter function whenever a ptwrite event is decoded.
The returned string is written to the aux_data string table and a
corresponding auxiliary instruction is appended to the function segment.
Approved-By: Markus Metzger <markus.t.metzger@intel.com>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Diffstat (limited to 'gdb/btrace.c')
-rw-r--r-- | gdb/btrace.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/gdb/btrace.c b/gdb/btrace.c index d493fbe..95ff27c 100644 --- a/gdb/btrace.c +++ b/gdb/btrace.c @@ -41,6 +41,7 @@ #include <inttypes.h> #include <ctype.h> #include <algorithm> +#include <string> /* Command lists for btrace maintenance commands. */ static struct cmd_list_element *maint_btrace_cmdlist; @@ -1204,6 +1205,24 @@ pt_btrace_insn (const struct pt_insn &insn) pt_btrace_insn_flags (insn)}; } +#if defined (HAVE_PT_INSN_EVENT) +/* Helper for events that will result in an aux_insn. */ + +static void +handle_pt_aux_insn (btrace_thread_info *btinfo, btrace_function *bfun, + std::string &aux_str, CORE_ADDR ip) +{ + btinfo->aux_data.emplace_back (std::move (aux_str)); + bfun = ftrace_update_function (btinfo, ip); + + btrace_insn insn {btinfo->aux_data.size () - 1, 0, + BTRACE_INSN_AUX, 0}; + + ftrace_update_insns (bfun, insn); +} + +#endif /* defined (HAVE_PT_INSN_EVENT) */ + /* Handle instruction decode events (libipt-v2). */ static int @@ -1252,6 +1271,60 @@ handle_pt_insn_events (struct btrace_thread_info *btinfo, bfun->insn_offset - 1, offset); break; +#if defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE) + case ptev_ptwrite: + { + uint64_t pc = 0; + std::optional<std::string> ptw_string; + + /* Lookup the PC if available. The event often doesn't provide + one, so we look into the last function segment as well. + Looking further back makes limited sense for ptwrite. */ + if (event.ip_suppressed == 0) + pc = event.variant.ptwrite.ip; + else if (!btinfo->functions.empty ()) + { + std::vector<btrace_insn> &insns + = btinfo->functions.back ().insn; + for (auto insn = insns.rbegin (); insn != insns.rend (); + ++insn) + { + switch (insn->iclass) + { + case BTRACE_INSN_AUX: + continue; + + case BTRACE_INSN_OTHER: + case BTRACE_INSN_CALL: + case BTRACE_INSN_RETURN: + case BTRACE_INSN_JUMP: + pc = insn->pc; + break; + /* No default to rely on compiler warnings. */ + } + break; + } + } + + if (pc == 0) + warning (_("Failed to determine the PC for ptwrite.")); + + if (btinfo->ptw_callback_fun != nullptr) + ptw_string + = btinfo->ptw_callback_fun (event.variant.ptwrite.payload, + pc, btinfo->ptw_context); + + if (ptw_string.has_value () && (*ptw_string).empty ()) + continue; + + if (!ptw_string.has_value ()) + *ptw_string = hex_string (event.variant.ptwrite.payload); + + handle_pt_aux_insn (btinfo, bfun, *ptw_string, pc); + + break; + } +#endif /* defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE) */ } } #endif /* defined (HAVE_PT_INSN_EVENT) */ |