xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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