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 23 LLDB_PLUGIN_DEFINE(TraceIntelPT) 24 25 CommandObjectSP GetStartCommand(CommandInterpreter &interpreter) { 26 return CommandObjectSP(new CommandObjectTraceStartIntelPT(interpreter)); 27 } 28 29 void TraceIntelPT::Initialize() { 30 PluginManager::RegisterPlugin( 31 GetPluginNameStatic(), "Intel Processor Trace", CreateInstance, 32 TraceIntelPTSessionFileParser::GetSchema(), GetStartCommand); 33 } 34 35 void TraceIntelPT::Terminate() { 36 PluginManager::UnregisterPlugin(CreateInstance); 37 } 38 39 ConstString TraceIntelPT::GetPluginNameStatic() { 40 static ConstString g_name("intel-pt"); 41 return g_name; 42 } 43 44 StringRef TraceIntelPT::GetSchema() { 45 return TraceIntelPTSessionFileParser::GetSchema(); 46 } 47 48 //------------------------------------------------------------------ 49 // PluginInterface protocol 50 //------------------------------------------------------------------ 51 52 ConstString TraceIntelPT::GetPluginName() { return GetPluginNameStatic(); } 53 54 uint32_t TraceIntelPT::GetPluginVersion() { return 1; } 55 56 void TraceIntelPT::Dump(Stream *s) const {} 57 58 Expected<TraceSP> 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 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 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 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 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 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