1e8d8bef9SDimitry Andric //===-- TraceIntelPT.h ------------------------------------------*- C++ -*-===// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric 9e8d8bef9SDimitry Andric #ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H 10e8d8bef9SDimitry Andric #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H 11e8d8bef9SDimitry Andric 1281ad6265SDimitry Andric #include "TaskTimer.h" 1381ad6265SDimitry Andric #include "ThreadDecoder.h" 1481ad6265SDimitry Andric #include "TraceIntelPTBundleLoader.h" 15bdd1243dSDimitry Andric #include "TraceIntelPTMultiCpuDecoder.h" 16349cc55cSDimitry Andric #include "lldb/Utility/FileSpec.h" 17349cc55cSDimitry Andric #include "lldb/lldb-types.h" 18349cc55cSDimitry Andric #include "llvm/Support/raw_ostream.h" 19bdd1243dSDimitry Andric #include <optional> 20e8d8bef9SDimitry Andric 21e8d8bef9SDimitry Andric namespace lldb_private { 22e8d8bef9SDimitry Andric namespace trace_intel_pt { 23e8d8bef9SDimitry Andric 24e8d8bef9SDimitry Andric class TraceIntelPT : public Trace { 25e8d8bef9SDimitry Andric public: 26bdd1243dSDimitry Andric /// Properties to be used with the `settings` command. 27bdd1243dSDimitry Andric class PluginProperties : public Properties { 28bdd1243dSDimitry Andric public: 29*5f757f3fSDimitry Andric static llvm::StringRef GetSettingName(); 30bdd1243dSDimitry Andric 31bdd1243dSDimitry Andric PluginProperties(); 32bdd1243dSDimitry Andric 33bdd1243dSDimitry Andric ~PluginProperties() override = default; 34bdd1243dSDimitry Andric 35bdd1243dSDimitry Andric uint64_t GetInfiniteDecodingLoopVerificationThreshold(); 36bdd1243dSDimitry Andric 37bdd1243dSDimitry Andric uint64_t GetExtremelyLargeDecodingThreshold(); 38bdd1243dSDimitry Andric }; 39bdd1243dSDimitry Andric 40bdd1243dSDimitry Andric /// Return the global properties for this trace plug-in. 41bdd1243dSDimitry Andric static PluginProperties &GetGlobalProperties(); 42bdd1243dSDimitry Andric 43e8d8bef9SDimitry Andric void Dump(Stream *s) const override; 44e8d8bef9SDimitry Andric 45753f127fSDimitry Andric llvm::Expected<FileSpec> SaveToDisk(FileSpec directory, 46753f127fSDimitry Andric bool compact) override; 47349cc55cSDimitry Andric 48e8d8bef9SDimitry Andric ~TraceIntelPT() override = default; 49e8d8bef9SDimitry Andric 50e8d8bef9SDimitry Andric /// PluginInterface protocol 51e8d8bef9SDimitry Andric /// \{ GetPluginName()52349cc55cSDimitry Andric llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } 53e8d8bef9SDimitry Andric 54e8d8bef9SDimitry Andric static void Initialize(); 55e8d8bef9SDimitry Andric 56e8d8bef9SDimitry Andric static void Terminate(); 57e8d8bef9SDimitry Andric 5881ad6265SDimitry Andric /// Create an instance of this class from a trace bundle. 59e8d8bef9SDimitry Andric /// 6081ad6265SDimitry Andric /// \param[in] trace_bundle_description 6181ad6265SDimitry Andric /// The description of the trace bundle. See \a Trace::FindPlugin. 62e8d8bef9SDimitry Andric /// 6381ad6265SDimitry Andric /// \param[in] bundle_dir 6481ad6265SDimitry Andric /// The path to the directory that contains the trace bundle. 65e8d8bef9SDimitry Andric /// 66e8d8bef9SDimitry Andric /// \param[in] debugger 67e8d8bef9SDimitry Andric /// The debugger instance where new Targets will be created as part of the 68e8d8bef9SDimitry Andric /// JSON data parsing. 69e8d8bef9SDimitry Andric /// 70e8d8bef9SDimitry Andric /// \return 71e8d8bef9SDimitry Andric /// A trace instance or an error in case of failures. 72bdd1243dSDimitry Andric static llvm::Expected<lldb::TraceSP> CreateInstanceForTraceBundle( 73bdd1243dSDimitry Andric const llvm::json::Value &trace_bundle_description, 74bdd1243dSDimitry Andric llvm::StringRef bundle_dir, Debugger &debugger); 75fe6060f1SDimitry Andric 76fe6060f1SDimitry Andric static llvm::Expected<lldb::TraceSP> 77fe6060f1SDimitry Andric CreateInstanceForLiveProcess(Process &process); 78e8d8bef9SDimitry Andric GetPluginNameStatic()79349cc55cSDimitry Andric static llvm::StringRef GetPluginNameStatic() { return "intel-pt"; } 80bdd1243dSDimitry Andric 81bdd1243dSDimitry Andric static void DebuggerInitialize(Debugger &debugger); 82e8d8bef9SDimitry Andric /// \} 83e8d8bef9SDimitry Andric 84fe6060f1SDimitry Andric lldb::CommandObjectSP 85fe6060f1SDimitry Andric GetProcessTraceStartCommand(CommandInterpreter &interpreter) override; 86fe6060f1SDimitry Andric 87fe6060f1SDimitry Andric lldb::CommandObjectSP 88fe6060f1SDimitry Andric GetThreadTraceStartCommand(CommandInterpreter &interpreter) override; 89fe6060f1SDimitry Andric 90e8d8bef9SDimitry Andric llvm::StringRef GetSchema() override; 91e8d8bef9SDimitry Andric 92bdd1243dSDimitry Andric llvm::Expected<lldb::TraceCursorSP> CreateNewCursor(Thread &thread) override; 93e8d8bef9SDimitry Andric 94753f127fSDimitry Andric void DumpTraceInfo(Thread &thread, Stream &s, bool verbose, 95753f127fSDimitry Andric bool json) override; 96e8d8bef9SDimitry Andric 97bdd1243dSDimitry Andric llvm::Expected<std::optional<uint64_t>> GetRawTraceSize(Thread &thread); 98fe6060f1SDimitry Andric 9981ad6265SDimitry Andric llvm::Error DoRefreshLiveProcessState(TraceGetStateResponse state, 10081ad6265SDimitry Andric llvm::StringRef json_response) override; 101fe6060f1SDimitry Andric 102349cc55cSDimitry Andric bool IsTraced(lldb::tid_t tid) override; 103fe6060f1SDimitry Andric 104fe6060f1SDimitry Andric const char *GetStartConfigurationHelp() override; 105fe6060f1SDimitry Andric 106fe6060f1SDimitry Andric /// Start tracing a live process. 107fe6060f1SDimitry Andric /// 10881ad6265SDimitry Andric /// More information on the parameters below can be found in the 10981ad6265SDimitry Andric /// jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt. 11081ad6265SDimitry Andric /// 11181ad6265SDimitry Andric /// \param[in] ipt_trace_size 112fe6060f1SDimitry Andric /// Trace size per thread in bytes. 113fe6060f1SDimitry Andric /// 114fe6060f1SDimitry Andric /// \param[in] total_buffer_size_limit 115fe6060f1SDimitry Andric /// Maximum total trace size per process in bytes. 116fe6060f1SDimitry Andric /// 117fe6060f1SDimitry Andric /// \param[in] enable_tsc 118fe6060f1SDimitry Andric /// Whether to use enable TSC timestamps or not. 119fe6060f1SDimitry Andric /// 120fe6060f1SDimitry Andric /// \param[in] psb_period 121fe6060f1SDimitry Andric /// This value defines the period in which PSB packets will be generated. 12281ad6265SDimitry Andric /// 12381ad6265SDimitry Andric /// \param[in] per_cpu_tracing 12481ad6265SDimitry Andric /// This value defines whether to have an intel pt trace buffer per thread 12581ad6265SDimitry Andric /// or per cpu core. 126fe6060f1SDimitry Andric /// 127753f127fSDimitry Andric /// \param[in] disable_cgroup_filtering 128753f127fSDimitry Andric /// Disable the cgroup filtering that is automatically applied when doing 129753f127fSDimitry Andric /// per cpu tracing. 130753f127fSDimitry Andric /// 131fe6060f1SDimitry Andric /// \return 132fe6060f1SDimitry Andric /// \a llvm::Error::success if the operation was successful, or 133fe6060f1SDimitry Andric /// \a llvm::Error otherwise. 13481ad6265SDimitry Andric llvm::Error Start(uint64_t ipt_trace_size, uint64_t total_buffer_size_limit, 135bdd1243dSDimitry Andric bool enable_tsc, std::optional<uint64_t> psb_period, 136753f127fSDimitry Andric bool m_per_cpu_tracing, bool disable_cgroup_filtering); 137fe6060f1SDimitry Andric 138fe6060f1SDimitry Andric /// \copydoc Trace::Start 139fe6060f1SDimitry Andric llvm::Error Start(StructuredData::ObjectSP configuration = 140fe6060f1SDimitry Andric StructuredData::ObjectSP()) override; 141fe6060f1SDimitry Andric 142fe6060f1SDimitry Andric /// Start tracing live threads. 143fe6060f1SDimitry Andric /// 14481ad6265SDimitry Andric /// More information on the parameters below can be found in the 14581ad6265SDimitry Andric /// jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt. 14681ad6265SDimitry Andric /// 147fe6060f1SDimitry Andric /// \param[in] tids 148fe6060f1SDimitry Andric /// Threads to trace. 149fe6060f1SDimitry Andric /// 15081ad6265SDimitry Andric /// \param[in] ipt_trace_size 15181ad6265SDimitry Andric /// Trace size per thread or per cpu core in bytes. 152fe6060f1SDimitry Andric /// 153fe6060f1SDimitry Andric /// \param[in] enable_tsc 154fe6060f1SDimitry Andric /// Whether to use enable TSC timestamps or not. 155fe6060f1SDimitry Andric /// 156fe6060f1SDimitry Andric /// \param[in] psb_period 157fe6060f1SDimitry Andric /// This value defines the period in which PSB packets will be generated. 158fe6060f1SDimitry Andric /// 159fe6060f1SDimitry Andric /// \return 160fe6060f1SDimitry Andric /// \a llvm::Error::success if the operation was successful, or 161fe6060f1SDimitry Andric /// \a llvm::Error otherwise. 16281ad6265SDimitry Andric llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, uint64_t ipt_trace_size, 163bdd1243dSDimitry Andric bool enable_tsc, std::optional<uint64_t> psb_period); 164fe6060f1SDimitry Andric 165fe6060f1SDimitry Andric /// \copydoc Trace::Start 166fe6060f1SDimitry Andric llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, 167fe6060f1SDimitry Andric StructuredData::ObjectSP configuration = 168fe6060f1SDimitry Andric StructuredData::ObjectSP()) override; 169fe6060f1SDimitry Andric 17081ad6265SDimitry Andric /// See \a Trace::OnThreadBinaryDataRead(). 17181ad6265SDimitry Andric llvm::Error OnThreadBufferRead(lldb::tid_t tid, 17281ad6265SDimitry Andric OnBinaryDataReadCallback callback); 173fe6060f1SDimitry Andric 17481ad6265SDimitry Andric /// Get or fetch the cpu information from, for example, /proc/cpuinfo. 175fe6060f1SDimitry Andric llvm::Expected<pt_cpu> GetCPUInfo(); 176e8d8bef9SDimitry Andric 17781ad6265SDimitry Andric /// Get or fetch the values used to convert to and from TSCs and nanos. 178bdd1243dSDimitry Andric std::optional<LinuxPerfZeroTscConversion> GetPerfZeroTscConversion(); 17981ad6265SDimitry Andric 180349cc55cSDimitry Andric /// \return 18181ad6265SDimitry Andric /// The timer object for this trace. 18281ad6265SDimitry Andric TaskTimer &GetTimer(); 18381ad6265SDimitry Andric 184753f127fSDimitry Andric /// \return 185753f127fSDimitry Andric /// The ScopedTaskTimer object for the given thread in this trace. 186753f127fSDimitry Andric ScopedTaskTimer &GetThreadTimer(lldb::tid_t tid); 187753f127fSDimitry Andric 188753f127fSDimitry Andric /// \return 189753f127fSDimitry Andric /// The global copedTaskTimer object for this trace. 190753f127fSDimitry Andric ScopedTaskTimer &GetGlobalTimer(); 191753f127fSDimitry Andric 19281ad6265SDimitry Andric TraceIntelPTSP GetSharedPtr(); 193349cc55cSDimitry Andric 194bdd1243dSDimitry Andric enum class TraceMode { UserMode, KernelMode }; 195bdd1243dSDimitry Andric 196bdd1243dSDimitry Andric TraceMode GetTraceMode(); 197bdd1243dSDimitry Andric 198e8d8bef9SDimitry Andric private: 19981ad6265SDimitry Andric friend class TraceIntelPTBundleLoader; 200e8d8bef9SDimitry Andric 201fe6060f1SDimitry Andric llvm::Expected<pt_cpu> GetCPUInfoForLiveProcess(); 202fe6060f1SDimitry Andric 20381ad6265SDimitry Andric /// Postmortem trace constructor 20481ad6265SDimitry Andric /// 20581ad6265SDimitry Andric /// \param[in] bundle_description 20681ad6265SDimitry Andric /// The definition file for the postmortem bundle. 20781ad6265SDimitry Andric /// 20881ad6265SDimitry Andric /// \param[in] traced_processes 209bdd1243dSDimitry Andric /// The processes traced in the postmortem session. 21081ad6265SDimitry Andric /// 211e8d8bef9SDimitry Andric /// \param[in] trace_threads 212bdd1243dSDimitry Andric /// The threads traced in the postmortem session. They must belong to the 21381ad6265SDimitry Andric /// processes mentioned above. 21481ad6265SDimitry Andric /// 215bdd1243dSDimitry Andric /// \param[in] trace_mode 216bdd1243dSDimitry Andric /// The tracing mode of the postmortem session. 217bdd1243dSDimitry Andric /// 21881ad6265SDimitry Andric /// \return 21981ad6265SDimitry Andric /// A TraceIntelPT shared pointer instance. 22081ad6265SDimitry Andric /// \{ 22181ad6265SDimitry Andric static TraceIntelPTSP CreateInstanceForPostmortemTrace( 22281ad6265SDimitry Andric JSONTraceBundleDescription &bundle_description, 22381ad6265SDimitry Andric llvm::ArrayRef<lldb::ProcessSP> traced_processes, 224bdd1243dSDimitry Andric llvm::ArrayRef<lldb::ThreadPostMortemTraceSP> traced_threads, 225bdd1243dSDimitry Andric TraceMode trace_mode); 22681ad6265SDimitry Andric 22781ad6265SDimitry Andric /// This constructor is used by CreateInstanceForPostmortemTrace to get the 22881ad6265SDimitry Andric /// instance ready before using shared pointers, which is a limitation of C++. 22981ad6265SDimitry Andric TraceIntelPT(JSONTraceBundleDescription &bundle_description, 230bdd1243dSDimitry Andric llvm::ArrayRef<lldb::ProcessSP> traced_processes, 231bdd1243dSDimitry Andric TraceMode trace_mode); 23281ad6265SDimitry Andric /// \} 233fe6060f1SDimitry Andric 234fe6060f1SDimitry Andric /// Constructor for live processes TraceIntelPT(Process & live_process)235bdd1243dSDimitry Andric TraceIntelPT(Process &live_process) 236bdd1243dSDimitry Andric : Trace(live_process), trace_mode(TraceMode::UserMode){}; 237e8d8bef9SDimitry Andric 238e8d8bef9SDimitry Andric /// Decode the trace of the given thread that, i.e. recontruct the traced 239fe6060f1SDimitry Andric /// instructions. 240e8d8bef9SDimitry Andric /// 241e8d8bef9SDimitry Andric /// \param[in] thread 242e8d8bef9SDimitry Andric /// If \a thread is a \a ThreadTrace, then its internal trace file will be 243e8d8bef9SDimitry Andric /// decoded. Live threads are not currently supported. 244e8d8bef9SDimitry Andric /// 245e8d8bef9SDimitry Andric /// \return 246fe6060f1SDimitry Andric /// A \a DecodedThread shared pointer with the decoded instructions. Any 24781ad6265SDimitry Andric /// errors are embedded in the instruction list. An \a llvm::Error is 24881ad6265SDimitry Andric /// returned if the decoder couldn't be properly set up. 24981ad6265SDimitry Andric llvm::Expected<DecodedThreadSP> Decode(Thread &thread); 250e8d8bef9SDimitry Andric 251972a253aSDimitry Andric /// \return 252972a253aSDimitry Andric /// The lowest timestamp in nanoseconds in all traces if available, \a 253bdd1243dSDimitry Andric /// std::nullopt if all the traces were empty or no trace contained no 254972a253aSDimitry Andric /// timing information, or an \a llvm::Error if it was not possible to set 255972a253aSDimitry Andric /// up the decoder for some trace. 256bdd1243dSDimitry Andric llvm::Expected<std::optional<uint64_t>> FindBeginningOfTimeNanos(); 257972a253aSDimitry Andric 258753f127fSDimitry Andric // Dump out trace info in JSON format 259753f127fSDimitry Andric void DumpTraceInfoAsJson(Thread &thread, Stream &s, bool verbose); 260753f127fSDimitry Andric 26181ad6265SDimitry Andric /// We package all the data that can change upon process stops to make sure 26281ad6265SDimitry Andric /// this contract is very visible. 26381ad6265SDimitry Andric /// This variable should only be accessed directly by constructores or live 26481ad6265SDimitry Andric /// process data refreshers. 26581ad6265SDimitry Andric struct Storage { 266bdd1243dSDimitry Andric std::optional<TraceIntelPTMultiCpuDecoder> multicpu_decoder; 26781ad6265SDimitry Andric /// These decoders are used for the non-per-cpu case 26881ad6265SDimitry Andric llvm::DenseMap<lldb::tid_t, std::unique_ptr<ThreadDecoder>> thread_decoders; 26981ad6265SDimitry Andric /// Helper variable used to track long running operations for telemetry. 27081ad6265SDimitry Andric TaskTimer task_timer; 27181ad6265SDimitry Andric /// It is provided by either a trace bundle or a live process to convert TSC 27281ad6265SDimitry Andric /// counters to and from nanos. It might not be available on all hosts. 273bdd1243dSDimitry Andric std::optional<LinuxPerfZeroTscConversion> tsc_conversion; 274bdd1243dSDimitry Andric std::optional<uint64_t> beginning_of_time_nanos; 275972a253aSDimitry Andric bool beginning_of_time_nanos_calculated = false; 27681ad6265SDimitry Andric } m_storage; 27781ad6265SDimitry Andric 27881ad6265SDimitry Andric /// It is provided by either a trace bundle or a live process' "cpuInfo" 27981ad6265SDimitry Andric /// binary data. We don't put it in the Storage because this variable doesn't 28081ad6265SDimitry Andric /// change. 281bdd1243dSDimitry Andric std::optional<pt_cpu> m_cpu_info; 28281ad6265SDimitry Andric 28381ad6265SDimitry Andric /// Get the storage after refreshing the data in the case of a live process. 28481ad6265SDimitry Andric Storage &GetUpdatedStorage(); 285bdd1243dSDimitry Andric 286bdd1243dSDimitry Andric /// The tracing mode of post mortem trace. 287bdd1243dSDimitry Andric TraceMode trace_mode; 288e8d8bef9SDimitry Andric }; 289e8d8bef9SDimitry Andric 290e8d8bef9SDimitry Andric } // namespace trace_intel_pt 291e8d8bef9SDimitry Andric } // namespace lldb_private 292e8d8bef9SDimitry Andric 293e8d8bef9SDimitry Andric #endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H 294