174c93956SWalter Erquinigo //===-- TraceIntelPT.h ------------------------------------------*- C++ -*-===// 274c93956SWalter Erquinigo // 374c93956SWalter Erquinigo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 474c93956SWalter Erquinigo // See https://llvm.org/LICENSE.txt for license information. 574c93956SWalter Erquinigo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 674c93956SWalter Erquinigo // 774c93956SWalter Erquinigo //===----------------------------------------------------------------------===// 874c93956SWalter Erquinigo 9ea1f4974SWalter Erquinigo #ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H 10ea1f4974SWalter Erquinigo #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H 1174c93956SWalter Erquinigo 12bdf3e7e5SWalter Erquinigo #include "TaskTimer.h" 136423b502SWalter Erquinigo #include "ThreadDecoder.h" 14b8dcd0baSWalter Erquinigo #include "TraceIntelPTBundleLoader.h" 15d179ea12SWalter Erquinigo #include "TraceIntelPTMultiCpuDecoder.h" 16602497d6SWalter Erquinigo #include "lldb/Utility/FileSpec.h" 17602497d6SWalter Erquinigo #include "lldb/lldb-types.h" 18602497d6SWalter Erquinigo #include "llvm/Support/raw_ostream.h" 19f190ce62SKazu Hirata #include <optional> 2074c93956SWalter Erquinigo 21ea1f4974SWalter Erquinigo namespace lldb_private { 22ea1f4974SWalter Erquinigo namespace trace_intel_pt { 23ea1f4974SWalter Erquinigo 24ea1f4974SWalter Erquinigo class TraceIntelPT : public Trace { 2574c93956SWalter Erquinigo public: 26c49d14acSWalter Erquinigo /// Properties to be used with the `settings` command. 27c49d14acSWalter Erquinigo class PluginProperties : public Properties { 28c49d14acSWalter Erquinigo public: 29*45e6e4d7SAlex Langford static llvm::StringRef GetSettingName(); 30c49d14acSWalter Erquinigo 31c49d14acSWalter Erquinigo PluginProperties(); 32c49d14acSWalter Erquinigo 33c49d14acSWalter Erquinigo ~PluginProperties() override = default; 34c49d14acSWalter Erquinigo 35c49d14acSWalter Erquinigo uint64_t GetInfiniteDecodingLoopVerificationThreshold(); 36c49d14acSWalter Erquinigo 37c49d14acSWalter Erquinigo uint64_t GetExtremelyLargeDecodingThreshold(); 38c49d14acSWalter Erquinigo }; 39c49d14acSWalter Erquinigo 40c49d14acSWalter Erquinigo /// Return the global properties for this trace plug-in. 41c49d14acSWalter Erquinigo static PluginProperties &GetGlobalProperties(); 42c49d14acSWalter Erquinigo 43ea1f4974SWalter Erquinigo void Dump(Stream *s) const override; 4474c93956SWalter Erquinigo 45b532dd54SWalter Erquinigo llvm::Expected<FileSpec> SaveToDisk(FileSpec directory, 46b532dd54SWalter Erquinigo bool compact) override; 47602497d6SWalter Erquinigo 4892e1ebeaSWalter Erquinigo ~TraceIntelPT() override = default; 4992e1ebeaSWalter Erquinigo 5074c93956SWalter Erquinigo /// PluginInterface protocol 5174c93956SWalter Erquinigo /// \{ GetPluginName()52a3942318SPavel Labath llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } 5374c93956SWalter Erquinigo 5474c93956SWalter Erquinigo static void Initialize(); 5574c93956SWalter Erquinigo 5674c93956SWalter Erquinigo static void Terminate(); 5774c93956SWalter Erquinigo 58ea37cd52SWalter Erquinigo /// Create an instance of this class from a trace bundle. 59ea1f4974SWalter Erquinigo /// 60b8dcd0baSWalter Erquinigo /// \param[in] trace_bundle_description 61b8dcd0baSWalter Erquinigo /// The description of the trace bundle. See \a Trace::FindPlugin. 62ea1f4974SWalter Erquinigo /// 63b8dcd0baSWalter Erquinigo /// \param[in] bundle_dir 64b8dcd0baSWalter Erquinigo /// The path to the directory that contains the trace bundle. 65ea1f4974SWalter Erquinigo /// 66ea1f4974SWalter Erquinigo /// \param[in] debugger 67ea1f4974SWalter Erquinigo /// The debugger instance where new Targets will be created as part of the 68ea1f4974SWalter Erquinigo /// JSON data parsing. 69ea1f4974SWalter Erquinigo /// 70ea1f4974SWalter Erquinigo /// \return 71ea1f4974SWalter Erquinigo /// A trace instance or an error in case of failures. 72d179ea12SWalter Erquinigo static llvm::Expected<lldb::TraceSP> CreateInstanceForTraceBundle( 73d179ea12SWalter Erquinigo const llvm::json::Value &trace_bundle_description, 74d179ea12SWalter Erquinigo llvm::StringRef bundle_dir, Debugger &debugger); 750b697561SWalter Erquinigo 760b697561SWalter Erquinigo static llvm::Expected<lldb::TraceSP> 770b697561SWalter Erquinigo CreateInstanceForLiveProcess(Process &process); 7874c93956SWalter Erquinigo GetPluginNameStatic()79a3942318SPavel Labath static llvm::StringRef GetPluginNameStatic() { return "intel-pt"; } 80c49d14acSWalter Erquinigo 81c49d14acSWalter Erquinigo static void DebuggerInitialize(Debugger &debugger); 8274c93956SWalter Erquinigo /// \} 8374c93956SWalter Erquinigo 840b697561SWalter Erquinigo lldb::CommandObjectSP 850b697561SWalter Erquinigo GetProcessTraceStartCommand(CommandInterpreter &interpreter) override; 860b697561SWalter Erquinigo 870b697561SWalter Erquinigo lldb::CommandObjectSP 880b697561SWalter Erquinigo GetThreadTraceStartCommand(CommandInterpreter &interpreter) override; 890b697561SWalter Erquinigo 90ea1f4974SWalter Erquinigo llvm::StringRef GetSchema() override; 9174c93956SWalter Erquinigo 923bec33b1SJakob Johnson llvm::Expected<lldb::TraceCursorSP> CreateNewCursor(Thread &thread) override; 932aa1dd1cSWalter Erquinigo 940466d1dfSymeng void DumpTraceInfo(Thread &thread, Stream &s, bool verbose, 950466d1dfSymeng bool json) override; 96345ace02SWalter Erquinigo 972fe83274SKazu Hirata llvm::Expected<std::optional<uint64_t>> GetRawTraceSize(Thread &thread); 98345ace02SWalter Erquinigo 99a0a46473SWalter Erquinigo llvm::Error DoRefreshLiveProcessState(TraceGetStateResponse state, 100a0a46473SWalter Erquinigo llvm::StringRef json_response) override; 1010b697561SWalter Erquinigo 102602497d6SWalter Erquinigo bool IsTraced(lldb::tid_t tid) override; 1030b697561SWalter Erquinigo 104bf9f21a2SWalter Erquinigo const char *GetStartConfigurationHelp() override; 105bf9f21a2SWalter Erquinigo 1060b697561SWalter Erquinigo /// Start tracing a live process. 1070b697561SWalter Erquinigo /// 108b8d1776fSWalter Erquinigo /// More information on the parameters below can be found in the 109b8d1776fSWalter Erquinigo /// jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt. 110b8d1776fSWalter Erquinigo /// 1116a5355e8SWalter Erquinigo /// \param[in] ipt_trace_size 1120b697561SWalter Erquinigo /// Trace size per thread in bytes. 1130b697561SWalter Erquinigo /// 1140b697561SWalter Erquinigo /// \param[in] total_buffer_size_limit 11504195843SWalter Erquinigo /// Maximum total trace size per process in bytes. 1160b697561SWalter Erquinigo /// 11704195843SWalter Erquinigo /// \param[in] enable_tsc 11804195843SWalter Erquinigo /// Whether to use enable TSC timestamps or not. 11904195843SWalter Erquinigo /// 12004195843SWalter Erquinigo /// \param[in] psb_period 12104195843SWalter Erquinigo /// This value defines the period in which PSB packets will be generated. 122b8d1776fSWalter Erquinigo /// 1236a5355e8SWalter Erquinigo /// \param[in] per_cpu_tracing 1246a5355e8SWalter Erquinigo /// This value defines whether to have an intel pt trace buffer per thread 1256a5355e8SWalter Erquinigo /// or per cpu core. 1260b697561SWalter Erquinigo /// 127d30fd5c3SGaurav Gaur /// \param[in] disable_cgroup_filtering 128d30fd5c3SGaurav Gaur /// Disable the cgroup filtering that is automatically applied when doing 129d30fd5c3SGaurav Gaur /// per cpu tracing. 130d30fd5c3SGaurav Gaur /// 1310b697561SWalter Erquinigo /// \return 1320b697561SWalter Erquinigo /// \a llvm::Error::success if the operation was successful, or 1330b697561SWalter Erquinigo /// \a llvm::Error otherwise. 1346a5355e8SWalter Erquinigo llvm::Error Start(uint64_t ipt_trace_size, uint64_t total_buffer_size_limit, 1352fe83274SKazu Hirata bool enable_tsc, std::optional<uint64_t> psb_period, 136d30fd5c3SGaurav Gaur bool m_per_cpu_tracing, bool disable_cgroup_filtering); 1370b697561SWalter Erquinigo 138bf9f21a2SWalter Erquinigo /// \copydoc Trace::Start 139bf9f21a2SWalter Erquinigo llvm::Error Start(StructuredData::ObjectSP configuration = 140bf9f21a2SWalter Erquinigo StructuredData::ObjectSP()) override; 141bf9f21a2SWalter Erquinigo 142bf9f21a2SWalter Erquinigo /// Start tracing live threads. 1430b697561SWalter Erquinigo /// 144b8d1776fSWalter Erquinigo /// More information on the parameters below can be found in the 145b8d1776fSWalter Erquinigo /// jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt. 146b8d1776fSWalter Erquinigo /// 1470b697561SWalter Erquinigo /// \param[in] tids 1480b697561SWalter Erquinigo /// Threads to trace. 1490b697561SWalter Erquinigo /// 1506a5355e8SWalter Erquinigo /// \param[in] ipt_trace_size 1516a5355e8SWalter Erquinigo /// Trace size per thread or per cpu core in bytes. 1520b697561SWalter Erquinigo /// 15304195843SWalter Erquinigo /// \param[in] enable_tsc 15404195843SWalter Erquinigo /// Whether to use enable TSC timestamps or not. 15504195843SWalter Erquinigo /// 15604195843SWalter Erquinigo /// \param[in] psb_period 15704195843SWalter Erquinigo /// This value defines the period in which PSB packets will be generated. 15804195843SWalter Erquinigo /// 1590b697561SWalter Erquinigo /// \return 1600b697561SWalter Erquinigo /// \a llvm::Error::success if the operation was successful, or 1610b697561SWalter Erquinigo /// \a llvm::Error otherwise. 1626a5355e8SWalter Erquinigo llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, uint64_t ipt_trace_size, 1632fe83274SKazu Hirata bool enable_tsc, std::optional<uint64_t> psb_period); 1640b697561SWalter Erquinigo 165bf9f21a2SWalter Erquinigo /// \copydoc Trace::Start 166bf9f21a2SWalter Erquinigo llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, 167bf9f21a2SWalter Erquinigo StructuredData::ObjectSP configuration = 168bf9f21a2SWalter Erquinigo StructuredData::ObjectSP()) override; 169bf9f21a2SWalter Erquinigo 170e0cfe20aSWalter Erquinigo /// See \a Trace::OnThreadBinaryDataRead(). 171e0cfe20aSWalter Erquinigo llvm::Error OnThreadBufferRead(lldb::tid_t tid, 172e0cfe20aSWalter Erquinigo OnBinaryDataReadCallback callback); 1730b697561SWalter Erquinigo 174fc5ef57cSWalter Erquinigo /// Get or fetch the cpu information from, for example, /proc/cpuinfo. 1750b697561SWalter Erquinigo llvm::Expected<pt_cpu> GetCPUInfo(); 176cfd96f05SWalter Erquinigo 177fc5ef57cSWalter Erquinigo /// Get or fetch the values used to convert to and from TSCs and nanos. 1782fe83274SKazu Hirata std::optional<LinuxPerfZeroTscConversion> GetPerfZeroTscConversion(); 179602497d6SWalter Erquinigo 180bdf3e7e5SWalter Erquinigo /// \return 181bdf3e7e5SWalter Erquinigo /// The timer object for this trace. 182bdf3e7e5SWalter Erquinigo TaskTimer &GetTimer(); 183bdf3e7e5SWalter Erquinigo 1849f9464e0SPeicong Wu /// \return 1859f9464e0SPeicong Wu /// The ScopedTaskTimer object for the given thread in this trace. 1869f9464e0SPeicong Wu ScopedTaskTimer &GetThreadTimer(lldb::tid_t tid); 1879f9464e0SPeicong Wu 1889f9464e0SPeicong Wu /// \return 1899f9464e0SPeicong Wu /// The global copedTaskTimer object for this trace. 1909f9464e0SPeicong Wu ScopedTaskTimer &GetGlobalTimer(); 1919f9464e0SPeicong Wu 192ea37cd52SWalter Erquinigo TraceIntelPTSP GetSharedPtr(); 193ea37cd52SWalter Erquinigo 1946fb744beSWalter Erquinigo enum class TraceMode { UserMode, KernelMode }; 1956fb744beSWalter Erquinigo 1966fb744beSWalter Erquinigo TraceMode GetTraceMode(); 1976fb744beSWalter Erquinigo 19826d861cbSWalter Erquinigo private: 199b8dcd0baSWalter Erquinigo friend class TraceIntelPTBundleLoader; 2008a203bb2SWalter Erquinigo 2010b697561SWalter Erquinigo llvm::Expected<pt_cpu> GetCPUInfoForLiveProcess(); 2020b697561SWalter Erquinigo 203fc5ef57cSWalter Erquinigo /// Postmortem trace constructor 204fc5ef57cSWalter Erquinigo /// 205b8dcd0baSWalter Erquinigo /// \param[in] bundle_description 206b8dcd0baSWalter Erquinigo /// The definition file for the postmortem bundle. 207fc5ef57cSWalter Erquinigo /// 208561a61fbSWalter Erquinigo /// \param[in] traced_processes 2096fb744beSWalter Erquinigo /// The processes traced in the postmortem session. 210fc5ef57cSWalter Erquinigo /// 2118a203bb2SWalter Erquinigo /// \param[in] trace_threads 2126fb744beSWalter Erquinigo /// The threads traced in the postmortem session. They must belong to the 213fc5ef57cSWalter Erquinigo /// processes mentioned above. 214ea37cd52SWalter Erquinigo /// 2156fb744beSWalter Erquinigo /// \param[in] trace_mode 2166fb744beSWalter Erquinigo /// The tracing mode of the postmortem session. 2176fb744beSWalter Erquinigo /// 218ea37cd52SWalter Erquinigo /// \return 219ea37cd52SWalter Erquinigo /// A TraceIntelPT shared pointer instance. 220ea37cd52SWalter Erquinigo /// \{ 221ea37cd52SWalter Erquinigo static TraceIntelPTSP CreateInstanceForPostmortemTrace( 222b8dcd0baSWalter Erquinigo JSONTraceBundleDescription &bundle_description, 223fc5ef57cSWalter Erquinigo llvm::ArrayRef<lldb::ProcessSP> traced_processes, 2246fb744beSWalter Erquinigo llvm::ArrayRef<lldb::ThreadPostMortemTraceSP> traced_threads, 2256fb744beSWalter Erquinigo TraceMode trace_mode); 2260b697561SWalter Erquinigo 227ea37cd52SWalter Erquinigo /// This constructor is used by CreateInstanceForPostmortemTrace to get the 228ea37cd52SWalter Erquinigo /// instance ready before using shared pointers, which is a limitation of C++. 229b8dcd0baSWalter Erquinigo TraceIntelPT(JSONTraceBundleDescription &bundle_description, 2306fb744beSWalter Erquinigo llvm::ArrayRef<lldb::ProcessSP> traced_processes, 2316fb744beSWalter Erquinigo TraceMode trace_mode); 232ea37cd52SWalter Erquinigo /// \} 233ea37cd52SWalter Erquinigo 2340b697561SWalter Erquinigo /// Constructor for live processes TraceIntelPT(Process & live_process)2356fb744beSWalter Erquinigo TraceIntelPT(Process &live_process) 2366fb744beSWalter Erquinigo : Trace(live_process), trace_mode(TraceMode::UserMode){}; 23774c93956SWalter Erquinigo 238cfd96f05SWalter Erquinigo /// Decode the trace of the given thread that, i.e. recontruct the traced 239b0aa7076SWalter Erquinigo /// instructions. 240cfd96f05SWalter Erquinigo /// 241cfd96f05SWalter Erquinigo /// \param[in] thread 242cfd96f05SWalter Erquinigo /// If \a thread is a \a ThreadTrace, then its internal trace file will be 243cfd96f05SWalter Erquinigo /// decoded. Live threads are not currently supported. 244cfd96f05SWalter Erquinigo /// 245cfd96f05SWalter Erquinigo /// \return 246b0aa7076SWalter Erquinigo /// A \a DecodedThread shared pointer with the decoded instructions. Any 247a7d6c3efSWalter Erquinigo /// errors are embedded in the instruction list. An \a llvm::Error is 248a7d6c3efSWalter Erquinigo /// returned if the decoder couldn't be properly set up. 249a7d6c3efSWalter Erquinigo llvm::Expected<DecodedThreadSP> Decode(Thread &thread); 250cfd96f05SWalter Erquinigo 2514f676c25SWalter Erquinigo /// \return 2524f676c25SWalter Erquinigo /// The lowest timestamp in nanoseconds in all traces if available, \a 253768cae4aSKazu Hirata /// std::nullopt if all the traces were empty or no trace contained no 2544f676c25SWalter Erquinigo /// timing information, or an \a llvm::Error if it was not possible to set 2554f676c25SWalter Erquinigo /// up the decoder for some trace. 2562fe83274SKazu Hirata llvm::Expected<std::optional<uint64_t>> FindBeginningOfTimeNanos(); 2574f676c25SWalter Erquinigo 2580466d1dfSymeng // Dump out trace info in JSON format 2590466d1dfSymeng void DumpTraceInfoAsJson(Thread &thread, Stream &s, bool verbose); 2600466d1dfSymeng 26103cc58ffSWalter Erquinigo /// We package all the data that can change upon process stops to make sure 26203cc58ffSWalter Erquinigo /// this contract is very visible. 26303cc58ffSWalter Erquinigo /// This variable should only be accessed directly by constructores or live 26403cc58ffSWalter Erquinigo /// process data refreshers. 26503cc58ffSWalter Erquinigo struct Storage { 2662fe83274SKazu Hirata std::optional<TraceIntelPTMultiCpuDecoder> multicpu_decoder; 2676a5355e8SWalter Erquinigo /// These decoders are used for the non-per-cpu case 268561a61fbSWalter Erquinigo llvm::DenseMap<lldb::tid_t, std::unique_ptr<ThreadDecoder>> thread_decoders; 269a0a46473SWalter Erquinigo /// Helper variable used to track long running operations for telemetry. 27003cc58ffSWalter Erquinigo TaskTimer task_timer; 271b8dcd0baSWalter Erquinigo /// It is provided by either a trace bundle or a live process to convert TSC 272a0a46473SWalter Erquinigo /// counters to and from nanos. It might not be available on all hosts. 2732fe83274SKazu Hirata std::optional<LinuxPerfZeroTscConversion> tsc_conversion; 2742fe83274SKazu Hirata std::optional<uint64_t> beginning_of_time_nanos; 2754f676c25SWalter Erquinigo bool beginning_of_time_nanos_calculated = false; 27603cc58ffSWalter Erquinigo } m_storage; 27774c93956SWalter Erquinigo 278b8dcd0baSWalter Erquinigo /// It is provided by either a trace bundle or a live process' "cpuInfo" 27903cc58ffSWalter Erquinigo /// binary data. We don't put it in the Storage because this variable doesn't 28003cc58ffSWalter Erquinigo /// change. 2812fe83274SKazu Hirata std::optional<pt_cpu> m_cpu_info; 28203cc58ffSWalter Erquinigo 28303cc58ffSWalter Erquinigo /// Get the storage after refreshing the data in the case of a live process. 28403cc58ffSWalter Erquinigo Storage &GetUpdatedStorage(); 2856fb744beSWalter Erquinigo 2866fb744beSWalter Erquinigo /// The tracing mode of post mortem trace. 2876fb744beSWalter Erquinigo TraceMode trace_mode; 28803cc58ffSWalter Erquinigo }; 289ff15efc1SWalter Erquinigo 290ea1f4974SWalter Erquinigo } // namespace trace_intel_pt 291ea1f4974SWalter Erquinigo } // namespace lldb_private 292ea1f4974SWalter Erquinigo 293ea1f4974SWalter Erquinigo #endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H 294