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