1 //===-- TraceIntelPT.h ------------------------------------------*- C++ -*-===// 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 #ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H 10 #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H 11 12 #include "TaskTimer.h" 13 #include "ThreadDecoder.h" 14 #include "TraceIntelPTMultiCpuDecoder.h" 15 #include "TraceIntelPTBundleLoader.h" 16 17 #include "lldb/Utility/FileSpec.h" 18 #include "lldb/lldb-types.h" 19 #include "llvm/Support/raw_ostream.h" 20 21 namespace lldb_private { 22 namespace trace_intel_pt { 23 24 class TraceIntelPT : public Trace { 25 public: 26 void Dump(Stream *s) const override; 27 28 llvm::Error SaveLiveTraceToDisk(FileSpec directory) override; 29 30 ~TraceIntelPT() override = default; 31 32 /// PluginInterface protocol 33 /// \{ 34 llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } 35 36 static void Initialize(); 37 38 static void Terminate(); 39 40 /// Create an instance of this class from a trace bundle. 41 /// 42 /// \param[in] trace_bundle_description 43 /// The description of the trace bundle. See \a Trace::FindPlugin. 44 /// 45 /// \param[in] bundle_dir 46 /// The path to the directory that contains the trace bundle. 47 /// 48 /// \param[in] debugger 49 /// The debugger instance where new Targets will be created as part of the 50 /// JSON data parsing. 51 /// 52 /// \return 53 /// A trace instance or an error in case of failures. 54 static llvm::Expected<lldb::TraceSP> 55 CreateInstanceForTraceBundle(const llvm::json::Value &trace_bundle_description, 56 llvm::StringRef bundle_dir, 57 Debugger &debugger); 58 59 static llvm::Expected<lldb::TraceSP> 60 CreateInstanceForLiveProcess(Process &process); 61 62 static llvm::StringRef GetPluginNameStatic() { return "intel-pt"; } 63 /// \} 64 65 lldb::CommandObjectSP 66 GetProcessTraceStartCommand(CommandInterpreter &interpreter) override; 67 68 lldb::CommandObjectSP 69 GetThreadTraceStartCommand(CommandInterpreter &interpreter) override; 70 71 llvm::StringRef GetSchema() override; 72 73 llvm::Expected<lldb::TraceCursorUP> CreateNewCursor(Thread &thread) override; 74 75 void DumpTraceInfo(Thread &thread, Stream &s, bool verbose) override; 76 77 llvm::Expected<llvm::Optional<uint64_t>> GetRawTraceSize(Thread &thread); 78 79 llvm::Error DoRefreshLiveProcessState(TraceGetStateResponse state, 80 llvm::StringRef json_response) override; 81 82 bool IsTraced(lldb::tid_t tid) override; 83 84 const char *GetStartConfigurationHelp() override; 85 86 /// Start tracing a live process. 87 /// 88 /// More information on the parameters below can be found in the 89 /// jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt. 90 /// 91 /// \param[in] ipt_trace_size 92 /// Trace size per thread in bytes. 93 /// 94 /// \param[in] total_buffer_size_limit 95 /// Maximum total trace size per process in bytes. 96 /// 97 /// \param[in] enable_tsc 98 /// Whether to use enable TSC timestamps or not. 99 /// 100 /// \param[in] psb_period 101 /// This value defines the period in which PSB packets will be generated. 102 /// 103 /// \param[in] per_cpu_tracing 104 /// This value defines whether to have an intel pt trace buffer per thread 105 /// or per cpu core. 106 /// 107 /// \return 108 /// \a llvm::Error::success if the operation was successful, or 109 /// \a llvm::Error otherwise. 110 llvm::Error Start(uint64_t ipt_trace_size, uint64_t total_buffer_size_limit, 111 bool enable_tsc, llvm::Optional<uint64_t> psb_period, 112 bool m_per_cpu_tracing); 113 114 /// \copydoc Trace::Start 115 llvm::Error Start(StructuredData::ObjectSP configuration = 116 StructuredData::ObjectSP()) override; 117 118 /// Start tracing live threads. 119 /// 120 /// More information on the parameters below can be found in the 121 /// jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt. 122 /// 123 /// \param[in] tids 124 /// Threads to trace. 125 /// 126 /// \param[in] ipt_trace_size 127 /// Trace size per thread or per cpu core in bytes. 128 /// 129 /// \param[in] enable_tsc 130 /// Whether to use enable TSC timestamps or not. 131 /// 132 /// \param[in] psb_period 133 /// This value defines the period in which PSB packets will be generated. 134 /// 135 /// \return 136 /// \a llvm::Error::success if the operation was successful, or 137 /// \a llvm::Error otherwise. 138 llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, uint64_t ipt_trace_size, 139 bool enable_tsc, llvm::Optional<uint64_t> psb_period); 140 141 /// \copydoc Trace::Start 142 llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, 143 StructuredData::ObjectSP configuration = 144 StructuredData::ObjectSP()) override; 145 146 /// See \a Trace::OnThreadBinaryDataRead(). 147 llvm::Error OnThreadBufferRead(lldb::tid_t tid, 148 OnBinaryDataReadCallback callback); 149 150 /// Get or fetch the cpu information from, for example, /proc/cpuinfo. 151 llvm::Expected<pt_cpu> GetCPUInfo(); 152 153 /// Get or fetch the values used to convert to and from TSCs and nanos. 154 llvm::Optional<LinuxPerfZeroTscConversion> GetPerfZeroTscConversion(); 155 156 /// \return 157 /// The timer object for this trace. 158 TaskTimer &GetTimer(); 159 160 TraceIntelPTSP GetSharedPtr(); 161 162 private: 163 friend class TraceIntelPTBundleLoader; 164 165 llvm::Expected<pt_cpu> GetCPUInfoForLiveProcess(); 166 167 /// Postmortem trace constructor 168 /// 169 /// \param[in] bundle_description 170 /// The definition file for the postmortem bundle. 171 /// 172 /// \param[in] traced_processes 173 /// The processes traced in the live session. 174 /// 175 /// \param[in] trace_threads 176 /// The threads traced in the live session. They must belong to the 177 /// processes mentioned above. 178 /// 179 /// \return 180 /// A TraceIntelPT shared pointer instance. 181 /// \{ 182 static TraceIntelPTSP CreateInstanceForPostmortemTrace( 183 JSONTraceBundleDescription &bundle_description, 184 llvm::ArrayRef<lldb::ProcessSP> traced_processes, 185 llvm::ArrayRef<lldb::ThreadPostMortemTraceSP> traced_threads); 186 187 /// This constructor is used by CreateInstanceForPostmortemTrace to get the 188 /// instance ready before using shared pointers, which is a limitation of C++. 189 TraceIntelPT(JSONTraceBundleDescription &bundle_description, 190 llvm::ArrayRef<lldb::ProcessSP> traced_processes); 191 /// \} 192 193 /// Constructor for live processes 194 TraceIntelPT(Process &live_process) : Trace(live_process){}; 195 196 /// Decode the trace of the given thread that, i.e. recontruct the traced 197 /// instructions. 198 /// 199 /// \param[in] thread 200 /// If \a thread is a \a ThreadTrace, then its internal trace file will be 201 /// decoded. Live threads are not currently supported. 202 /// 203 /// \return 204 /// A \a DecodedThread shared pointer with the decoded instructions. Any 205 /// errors are embedded in the instruction list. An \a llvm::Error is 206 /// returned if the decoder couldn't be properly set up. 207 llvm::Expected<DecodedThreadSP> Decode(Thread &thread); 208 209 /// We package all the data that can change upon process stops to make sure 210 /// this contract is very visible. 211 /// This variable should only be accessed directly by constructores or live 212 /// process data refreshers. 213 struct Storage { 214 llvm::Optional<TraceIntelPTMultiCpuDecoder> multicpu_decoder; 215 /// These decoders are used for the non-per-cpu case 216 llvm::DenseMap<lldb::tid_t, std::unique_ptr<ThreadDecoder>> thread_decoders; 217 /// Helper variable used to track long running operations for telemetry. 218 TaskTimer task_timer; 219 /// It is provided by either a trace bundle or a live process to convert TSC 220 /// counters to and from nanos. It might not be available on all hosts. 221 llvm::Optional<LinuxPerfZeroTscConversion> tsc_conversion; 222 } m_storage; 223 224 /// It is provided by either a trace bundle or a live process' "cpuInfo" 225 /// binary data. We don't put it in the Storage because this variable doesn't 226 /// change. 227 llvm::Optional<pt_cpu> m_cpu_info; 228 229 /// Get the storage after refreshing the data in the case of a live process. 230 Storage &GetUpdatedStorage(); 231 }; 232 233 } // namespace trace_intel_pt 234 } // namespace lldb_private 235 236 #endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H 237