294 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H10#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H11 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 21namespace lldb_private {22namespace trace_intel_pt {23 24class TraceIntelPT : public Trace {25public: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 protocol51 /// \{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_description61 /// The description of the trace bundle. See \a Trace::FindPlugin.62 ///63 /// \param[in] bundle_dir64 /// The path to the directory that contains the trace bundle.65 ///66 /// \param[in] debugger67 /// The debugger instance where new Targets will be created as part of the68 /// JSON data parsing.69 ///70 /// \return71 /// 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::CommandObjectSP85 GetProcessTraceStartCommand(CommandInterpreter &interpreter) override;86 87 lldb::CommandObjectSP88 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 the109 /// jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt.110 ///111 /// \param[in] ipt_trace_size112 /// Trace size per thread in bytes.113 ///114 /// \param[in] total_buffer_size_limit115 /// Maximum total trace size per process in bytes.116 ///117 /// \param[in] enable_tsc118 /// Whether to use enable TSC timestamps or not.119 ///120 /// \param[in] psb_period121 /// This value defines the period in which PSB packets will be generated.122 ///123 /// \param[in] per_cpu_tracing124 /// This value defines whether to have an intel pt trace buffer per thread125 /// or per cpu core.126 ///127 /// \param[in] disable_cgroup_filtering128 /// Disable the cgroup filtering that is automatically applied when doing129 /// per cpu tracing.130 ///131 /// \return132 /// \a llvm::Error::success if the operation was successful, or133 /// \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::Start139 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 the145 /// jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt.146 ///147 /// \param[in] tids148 /// Threads to trace.149 ///150 /// \param[in] ipt_trace_size151 /// Trace size per thread or per cpu core in bytes.152 ///153 /// \param[in] enable_tsc154 /// Whether to use enable TSC timestamps or not.155 ///156 /// \param[in] psb_period157 /// This value defines the period in which PSB packets will be generated.158 ///159 /// \return160 /// \a llvm::Error::success if the operation was successful, or161 /// \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::Start166 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 /// \return181 /// The timer object for this trace.182 TaskTimer &GetTimer();183 184 /// \return185 /// The ScopedTaskTimer object for the given thread in this trace.186 ScopedTaskTimer &GetThreadTimer(lldb::tid_t tid);187 188 /// \return189 /// 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 198private:199 friend class TraceIntelPTBundleLoader;200 201 llvm::Expected<pt_cpu> GetCPUInfoForLiveProcess();202 203 /// Postmortem trace constructor204 ///205 /// \param[in] bundle_description206 /// The definition file for the postmortem bundle.207 ///208 /// \param[in] traced_processes209 /// The processes traced in the postmortem session.210 ///211 /// \param[in] trace_threads212 /// The threads traced in the postmortem session. They must belong to the213 /// processes mentioned above.214 ///215 /// \param[in] trace_mode216 /// The tracing mode of the postmortem session.217 ///218 /// \return219 /// 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 the228 /// 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 processes235 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 traced239 /// instructions.240 ///241 /// \param[in] thread242 /// If \a thread is a \a ThreadTrace, then its internal trace file will be243 /// decoded. Live threads are not currently supported.244 ///245 /// \return246 /// A \a DecodedThread shared pointer with the decoded instructions. Any247 /// errors are embedded in the instruction list. An \a llvm::Error is248 /// returned if the decoder couldn't be properly set up.249 llvm::Expected<DecodedThreadSP> Decode(Thread &thread);250 251 /// \return252 /// The lowest timestamp in nanoseconds in all traces if available, \a253 /// std::nullopt if all the traces were empty or no trace contained no254 /// timing information, or an \a llvm::Error if it was not possible to set255 /// up the decoder for some trace.256 llvm::Expected<std::optional<uint64_t>> FindBeginningOfTimeNanos();257 258 // Dump out trace info in JSON format259 void DumpTraceInfoAsJson(Thread &thread, Stream &s, bool verbose);260 261 /// We package all the data that can change upon process stops to make sure262 /// this contract is very visible.263 /// This variable should only be accessed directly by constructores or live264 /// process data refreshers.265 struct Storage {266 std::optional<TraceIntelPTMultiCpuDecoder> multicpu_decoder;267 /// These decoders are used for the non-per-cpu case268 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 TSC272 /// 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't280 /// 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_pt291} // namespace lldb_private292 293#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H294