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