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