xref: /llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h (revision 45e6e4d70e1e5bdd7d9f04dfd0f4cc8798bcde0c)
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