xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
1*e8d8bef9SDimitry Andric //===-- TraceIntelPT.cpp --------------------------------------------------===//
2*e8d8bef9SDimitry Andric //
3*e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*e8d8bef9SDimitry Andric //
7*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
8*e8d8bef9SDimitry Andric 
9*e8d8bef9SDimitry Andric #include "TraceIntelPT.h"
10*e8d8bef9SDimitry Andric 
11*e8d8bef9SDimitry Andric #include "CommandObjectTraceStartIntelPT.h"
12*e8d8bef9SDimitry Andric #include "TraceIntelPTSessionFileParser.h"
13*e8d8bef9SDimitry Andric #include "lldb/Core/PluginManager.h"
14*e8d8bef9SDimitry Andric #include "lldb/Target/Process.h"
15*e8d8bef9SDimitry Andric #include "lldb/Target/Target.h"
16*e8d8bef9SDimitry Andric #include "lldb/Target/ThreadTrace.h"
17*e8d8bef9SDimitry Andric 
18*e8d8bef9SDimitry Andric using namespace lldb;
19*e8d8bef9SDimitry Andric using namespace lldb_private;
20*e8d8bef9SDimitry Andric using namespace lldb_private::trace_intel_pt;
21*e8d8bef9SDimitry Andric using namespace llvm;
22*e8d8bef9SDimitry Andric 
23*e8d8bef9SDimitry Andric LLDB_PLUGIN_DEFINE(TraceIntelPT)
24*e8d8bef9SDimitry Andric 
25*e8d8bef9SDimitry Andric CommandObjectSP GetStartCommand(CommandInterpreter &interpreter) {
26*e8d8bef9SDimitry Andric   return CommandObjectSP(new CommandObjectTraceStartIntelPT(interpreter));
27*e8d8bef9SDimitry Andric }
28*e8d8bef9SDimitry Andric 
29*e8d8bef9SDimitry Andric void TraceIntelPT::Initialize() {
30*e8d8bef9SDimitry Andric   PluginManager::RegisterPlugin(
31*e8d8bef9SDimitry Andric       GetPluginNameStatic(), "Intel Processor Trace", CreateInstance,
32*e8d8bef9SDimitry Andric       TraceIntelPTSessionFileParser::GetSchema(), GetStartCommand);
33*e8d8bef9SDimitry Andric }
34*e8d8bef9SDimitry Andric 
35*e8d8bef9SDimitry Andric void TraceIntelPT::Terminate() {
36*e8d8bef9SDimitry Andric   PluginManager::UnregisterPlugin(CreateInstance);
37*e8d8bef9SDimitry Andric }
38*e8d8bef9SDimitry Andric 
39*e8d8bef9SDimitry Andric ConstString TraceIntelPT::GetPluginNameStatic() {
40*e8d8bef9SDimitry Andric   static ConstString g_name("intel-pt");
41*e8d8bef9SDimitry Andric   return g_name;
42*e8d8bef9SDimitry Andric }
43*e8d8bef9SDimitry Andric 
44*e8d8bef9SDimitry Andric StringRef TraceIntelPT::GetSchema() {
45*e8d8bef9SDimitry Andric   return TraceIntelPTSessionFileParser::GetSchema();
46*e8d8bef9SDimitry Andric }
47*e8d8bef9SDimitry Andric 
48*e8d8bef9SDimitry Andric //------------------------------------------------------------------
49*e8d8bef9SDimitry Andric // PluginInterface protocol
50*e8d8bef9SDimitry Andric //------------------------------------------------------------------
51*e8d8bef9SDimitry Andric 
52*e8d8bef9SDimitry Andric ConstString TraceIntelPT::GetPluginName() { return GetPluginNameStatic(); }
53*e8d8bef9SDimitry Andric 
54*e8d8bef9SDimitry Andric uint32_t TraceIntelPT::GetPluginVersion() { return 1; }
55*e8d8bef9SDimitry Andric 
56*e8d8bef9SDimitry Andric void TraceIntelPT::Dump(Stream *s) const {}
57*e8d8bef9SDimitry Andric 
58*e8d8bef9SDimitry Andric Expected<TraceSP>
59*e8d8bef9SDimitry Andric TraceIntelPT::CreateInstance(const json::Value &trace_session_file,
60*e8d8bef9SDimitry Andric                              StringRef session_file_dir, Debugger &debugger) {
61*e8d8bef9SDimitry Andric   return TraceIntelPTSessionFileParser(debugger, trace_session_file,
62*e8d8bef9SDimitry Andric                                        session_file_dir)
63*e8d8bef9SDimitry Andric       .Parse();
64*e8d8bef9SDimitry Andric }
65*e8d8bef9SDimitry Andric 
66*e8d8bef9SDimitry Andric TraceIntelPT::TraceIntelPT(
67*e8d8bef9SDimitry Andric     const pt_cpu &pt_cpu,
68*e8d8bef9SDimitry Andric     const std::vector<std::shared_ptr<ThreadTrace>> &traced_threads)
69*e8d8bef9SDimitry Andric     : m_pt_cpu(pt_cpu) {
70*e8d8bef9SDimitry Andric   for (const std::shared_ptr<ThreadTrace> &thread : traced_threads)
71*e8d8bef9SDimitry Andric     m_trace_threads.emplace(
72*e8d8bef9SDimitry Andric         std::piecewise_construct,
73*e8d8bef9SDimitry Andric         std::forward_as_tuple(thread->GetProcess()->GetID(), thread->GetID()),
74*e8d8bef9SDimitry Andric         std::forward_as_tuple(thread, pt_cpu));
75*e8d8bef9SDimitry Andric }
76*e8d8bef9SDimitry Andric 
77*e8d8bef9SDimitry Andric const DecodedThread *TraceIntelPT::Decode(const Thread &thread) {
78*e8d8bef9SDimitry Andric   auto it = m_trace_threads.find(
79*e8d8bef9SDimitry Andric       std::make_pair(thread.GetProcess()->GetID(), thread.GetID()));
80*e8d8bef9SDimitry Andric   if (it == m_trace_threads.end())
81*e8d8bef9SDimitry Andric     return nullptr;
82*e8d8bef9SDimitry Andric   return &it->second.Decode();
83*e8d8bef9SDimitry Andric }
84*e8d8bef9SDimitry Andric 
85*e8d8bef9SDimitry Andric size_t TraceIntelPT::GetCursorPosition(const Thread &thread) {
86*e8d8bef9SDimitry Andric   const DecodedThread *decoded_thread = Decode(thread);
87*e8d8bef9SDimitry Andric   if (!decoded_thread)
88*e8d8bef9SDimitry Andric     return 0;
89*e8d8bef9SDimitry Andric   return decoded_thread->GetCursorPosition();
90*e8d8bef9SDimitry Andric }
91*e8d8bef9SDimitry Andric 
92*e8d8bef9SDimitry Andric void TraceIntelPT::TraverseInstructions(
93*e8d8bef9SDimitry Andric     const Thread &thread, size_t position, TraceDirection direction,
94*e8d8bef9SDimitry Andric     std::function<bool(size_t index, Expected<lldb::addr_t> load_addr)>
95*e8d8bef9SDimitry Andric         callback) {
96*e8d8bef9SDimitry Andric   const DecodedThread *decoded_thread = Decode(thread);
97*e8d8bef9SDimitry Andric   if (!decoded_thread)
98*e8d8bef9SDimitry Andric     return;
99*e8d8bef9SDimitry Andric 
100*e8d8bef9SDimitry Andric   ArrayRef<IntelPTInstruction> instructions = decoded_thread->GetInstructions();
101*e8d8bef9SDimitry Andric 
102*e8d8bef9SDimitry Andric   ssize_t delta = direction == TraceDirection::Forwards ? 1 : -1;
103*e8d8bef9SDimitry Andric   for (ssize_t i = position; i < (ssize_t)instructions.size() && i >= 0;
104*e8d8bef9SDimitry Andric        i += delta)
105*e8d8bef9SDimitry Andric     if (!callback(i, instructions[i].GetLoadAddress()))
106*e8d8bef9SDimitry Andric       break;
107*e8d8bef9SDimitry Andric }
108*e8d8bef9SDimitry Andric 
109*e8d8bef9SDimitry Andric size_t TraceIntelPT::GetInstructionCount(const Thread &thread) {
110*e8d8bef9SDimitry Andric   if (const DecodedThread *decoded_thread = Decode(thread))
111*e8d8bef9SDimitry Andric     return decoded_thread->GetInstructions().size();
112*e8d8bef9SDimitry Andric   else
113*e8d8bef9SDimitry Andric     return 0;
114*e8d8bef9SDimitry Andric }
115