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