xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1be691f3bSpatrick //===-- TraceIntelPT.h ------------------------------------------*- C++ -*-===//
2be691f3bSpatrick //
3be691f3bSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4be691f3bSpatrick // See https://llvm.org/LICENSE.txt for license information.
5be691f3bSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6be691f3bSpatrick //
7be691f3bSpatrick //===----------------------------------------------------------------------===//
8be691f3bSpatrick 
9be691f3bSpatrick #ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H
10be691f3bSpatrick #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H
11be691f3bSpatrick 
12*f6aab3d8Srobert #include "TaskTimer.h"
13*f6aab3d8Srobert #include "ThreadDecoder.h"
14*f6aab3d8Srobert #include "TraceIntelPTBundleLoader.h"
15*f6aab3d8Srobert #include "TraceIntelPTMultiCpuDecoder.h"
16*f6aab3d8Srobert #include "lldb/Utility/FileSpec.h"
17*f6aab3d8Srobert #include "lldb/lldb-types.h"
18*f6aab3d8Srobert #include "llvm/Support/raw_ostream.h"
19*f6aab3d8Srobert #include <optional>
20be691f3bSpatrick 
21be691f3bSpatrick namespace lldb_private {
22be691f3bSpatrick namespace trace_intel_pt {
23be691f3bSpatrick 
24be691f3bSpatrick class TraceIntelPT : public Trace {
25be691f3bSpatrick public:
26*f6aab3d8Srobert   /// Properties to be used with the `settings` command.
27*f6aab3d8Srobert   class PluginProperties : public Properties {
28*f6aab3d8Srobert   public:
29*f6aab3d8Srobert     static ConstString GetSettingName();
30*f6aab3d8Srobert 
31*f6aab3d8Srobert     PluginProperties();
32*f6aab3d8Srobert 
33*f6aab3d8Srobert     ~PluginProperties() override = default;
34*f6aab3d8Srobert 
35*f6aab3d8Srobert     uint64_t GetInfiniteDecodingLoopVerificationThreshold();
36*f6aab3d8Srobert 
37*f6aab3d8Srobert     uint64_t GetExtremelyLargeDecodingThreshold();
38*f6aab3d8Srobert   };
39*f6aab3d8Srobert 
40*f6aab3d8Srobert   /// Return the global properties for this trace plug-in.
41*f6aab3d8Srobert   static PluginProperties &GetGlobalProperties();
42*f6aab3d8Srobert 
43be691f3bSpatrick   void Dump(Stream *s) const override;
44be691f3bSpatrick 
45*f6aab3d8Srobert   llvm::Expected<FileSpec> SaveToDisk(FileSpec directory,
46*f6aab3d8Srobert                                       bool compact) override;
47*f6aab3d8Srobert 
48be691f3bSpatrick   ~TraceIntelPT() override = default;
49be691f3bSpatrick 
50be691f3bSpatrick   /// PluginInterface protocol
51be691f3bSpatrick   /// \{
GetPluginName()52*f6aab3d8Srobert   llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
53be691f3bSpatrick 
54be691f3bSpatrick   static void Initialize();
55be691f3bSpatrick 
56be691f3bSpatrick   static void Terminate();
57be691f3bSpatrick 
58*f6aab3d8Srobert   /// Create an instance of this class from a trace bundle.
59be691f3bSpatrick   ///
60*f6aab3d8Srobert   /// \param[in] trace_bundle_description
61*f6aab3d8Srobert   ///     The description of the trace bundle. See \a Trace::FindPlugin.
62be691f3bSpatrick   ///
63*f6aab3d8Srobert   /// \param[in] bundle_dir
64*f6aab3d8Srobert   ///     The path to the directory that contains the trace bundle.
65be691f3bSpatrick   ///
66be691f3bSpatrick   /// \param[in] debugger
67be691f3bSpatrick   ///     The debugger instance where new Targets will be created as part of the
68be691f3bSpatrick   ///     JSON data parsing.
69be691f3bSpatrick   ///
70be691f3bSpatrick   /// \return
71be691f3bSpatrick   ///     A trace instance or an error in case of failures.
72*f6aab3d8Srobert   static llvm::Expected<lldb::TraceSP> CreateInstanceForTraceBundle(
73*f6aab3d8Srobert       const llvm::json::Value &trace_bundle_description,
74*f6aab3d8Srobert       llvm::StringRef bundle_dir, Debugger &debugger);
75be691f3bSpatrick 
76be691f3bSpatrick   static llvm::Expected<lldb::TraceSP>
77be691f3bSpatrick   CreateInstanceForLiveProcess(Process &process);
78be691f3bSpatrick 
GetPluginNameStatic()79*f6aab3d8Srobert   static llvm::StringRef GetPluginNameStatic() { return "intel-pt"; }
80be691f3bSpatrick 
81*f6aab3d8Srobert   static void DebuggerInitialize(Debugger &debugger);
82be691f3bSpatrick   /// \}
83be691f3bSpatrick 
84be691f3bSpatrick   lldb::CommandObjectSP
85be691f3bSpatrick   GetProcessTraceStartCommand(CommandInterpreter &interpreter) override;
86be691f3bSpatrick 
87be691f3bSpatrick   lldb::CommandObjectSP
88be691f3bSpatrick   GetThreadTraceStartCommand(CommandInterpreter &interpreter) override;
89be691f3bSpatrick 
90be691f3bSpatrick   llvm::StringRef GetSchema() override;
91be691f3bSpatrick 
92*f6aab3d8Srobert   llvm::Expected<lldb::TraceCursorSP> CreateNewCursor(Thread &thread) override;
93be691f3bSpatrick 
94*f6aab3d8Srobert   void DumpTraceInfo(Thread &thread, Stream &s, bool verbose,
95*f6aab3d8Srobert                      bool json) override;
96be691f3bSpatrick 
97*f6aab3d8Srobert   llvm::Expected<std::optional<uint64_t>> GetRawTraceSize(Thread &thread);
98be691f3bSpatrick 
99*f6aab3d8Srobert   llvm::Error DoRefreshLiveProcessState(TraceGetStateResponse state,
100*f6aab3d8Srobert                                         llvm::StringRef json_response) override;
101be691f3bSpatrick 
102*f6aab3d8Srobert   bool IsTraced(lldb::tid_t tid) override;
103be691f3bSpatrick 
104be691f3bSpatrick   const char *GetStartConfigurationHelp() override;
105be691f3bSpatrick 
106be691f3bSpatrick   /// Start tracing a live process.
107be691f3bSpatrick   ///
108*f6aab3d8Srobert   /// More information on the parameters below can be found in the
109*f6aab3d8Srobert   /// jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt.
110*f6aab3d8Srobert   ///
111*f6aab3d8Srobert   /// \param[in] ipt_trace_size
112be691f3bSpatrick   ///     Trace size per thread in bytes.
113be691f3bSpatrick   ///
114be691f3bSpatrick   /// \param[in] total_buffer_size_limit
115be691f3bSpatrick   ///     Maximum total trace size per process in bytes.
116be691f3bSpatrick   ///
117be691f3bSpatrick   /// \param[in] enable_tsc
118be691f3bSpatrick   ///     Whether to use enable TSC timestamps or not.
119be691f3bSpatrick   ///
120be691f3bSpatrick   /// \param[in] psb_period
121be691f3bSpatrick   ///     This value defines the period in which PSB packets will be generated.
122*f6aab3d8Srobert   ///
123*f6aab3d8Srobert   /// \param[in] per_cpu_tracing
124*f6aab3d8Srobert   ///     This value defines whether to have an intel pt trace buffer per thread
125*f6aab3d8Srobert   ///     or per cpu core.
126*f6aab3d8Srobert   ///
127*f6aab3d8Srobert   /// \param[in] disable_cgroup_filtering
128*f6aab3d8Srobert   ///     Disable the cgroup filtering that is automatically applied when doing
129*f6aab3d8Srobert   ///     per cpu tracing.
130be691f3bSpatrick   ///
131be691f3bSpatrick   /// \return
132be691f3bSpatrick   ///     \a llvm::Error::success if the operation was successful, or
133be691f3bSpatrick   ///     \a llvm::Error otherwise.
134*f6aab3d8Srobert   llvm::Error Start(uint64_t ipt_trace_size, uint64_t total_buffer_size_limit,
135*f6aab3d8Srobert                     bool enable_tsc, std::optional<uint64_t> psb_period,
136*f6aab3d8Srobert                     bool m_per_cpu_tracing, bool disable_cgroup_filtering);
137be691f3bSpatrick 
138be691f3bSpatrick   /// \copydoc Trace::Start
139be691f3bSpatrick   llvm::Error Start(StructuredData::ObjectSP configuration =
140be691f3bSpatrick                         StructuredData::ObjectSP()) override;
141be691f3bSpatrick 
142be691f3bSpatrick   /// Start tracing live threads.
143be691f3bSpatrick   ///
144*f6aab3d8Srobert   /// More information on the parameters below can be found in the
145*f6aab3d8Srobert   /// jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt.
146*f6aab3d8Srobert   ///
147be691f3bSpatrick   /// \param[in] tids
148be691f3bSpatrick   ///     Threads to trace.
149be691f3bSpatrick   ///
150*f6aab3d8Srobert   /// \param[in] ipt_trace_size
151*f6aab3d8Srobert   ///     Trace size per thread or per cpu core in bytes.
152be691f3bSpatrick   ///
153be691f3bSpatrick   /// \param[in] enable_tsc
154be691f3bSpatrick   ///     Whether to use enable TSC timestamps or not.
155be691f3bSpatrick   ///
156be691f3bSpatrick   /// \param[in] psb_period
157be691f3bSpatrick   ///     This value defines the period in which PSB packets will be generated.
158be691f3bSpatrick   ///
159be691f3bSpatrick   /// \return
160be691f3bSpatrick   ///     \a llvm::Error::success if the operation was successful, or
161be691f3bSpatrick   ///     \a llvm::Error otherwise.
162*f6aab3d8Srobert   llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, uint64_t ipt_trace_size,
163*f6aab3d8Srobert                     bool enable_tsc, std::optional<uint64_t> psb_period);
164be691f3bSpatrick 
165be691f3bSpatrick   /// \copydoc Trace::Start
166be691f3bSpatrick   llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids,
167be691f3bSpatrick                     StructuredData::ObjectSP configuration =
168be691f3bSpatrick                         StructuredData::ObjectSP()) override;
169be691f3bSpatrick 
170*f6aab3d8Srobert   /// See \a Trace::OnThreadBinaryDataRead().
171*f6aab3d8Srobert   llvm::Error OnThreadBufferRead(lldb::tid_t tid,
172*f6aab3d8Srobert                                  OnBinaryDataReadCallback callback);
173be691f3bSpatrick 
174*f6aab3d8Srobert   /// Get or fetch the cpu information from, for example, /proc/cpuinfo.
175be691f3bSpatrick   llvm::Expected<pt_cpu> GetCPUInfo();
176be691f3bSpatrick 
177*f6aab3d8Srobert   /// Get or fetch the values used to convert to and from TSCs and nanos.
178*f6aab3d8Srobert   std::optional<LinuxPerfZeroTscConversion> GetPerfZeroTscConversion();
179*f6aab3d8Srobert 
180*f6aab3d8Srobert   /// \return
181*f6aab3d8Srobert   ///     The timer object for this trace.
182*f6aab3d8Srobert   TaskTimer &GetTimer();
183*f6aab3d8Srobert 
184*f6aab3d8Srobert   /// \return
185*f6aab3d8Srobert   ///     The ScopedTaskTimer object for the given thread in this trace.
186*f6aab3d8Srobert   ScopedTaskTimer &GetThreadTimer(lldb::tid_t tid);
187*f6aab3d8Srobert 
188*f6aab3d8Srobert   /// \return
189*f6aab3d8Srobert   ///     The global copedTaskTimer object for this trace.
190*f6aab3d8Srobert   ScopedTaskTimer &GetGlobalTimer();
191*f6aab3d8Srobert 
192*f6aab3d8Srobert   TraceIntelPTSP GetSharedPtr();
193*f6aab3d8Srobert 
194*f6aab3d8Srobert   enum class TraceMode { UserMode, KernelMode };
195*f6aab3d8Srobert 
196*f6aab3d8Srobert   TraceMode GetTraceMode();
197*f6aab3d8Srobert 
198be691f3bSpatrick private:
199*f6aab3d8Srobert   friend class TraceIntelPTBundleLoader;
200be691f3bSpatrick 
201be691f3bSpatrick   llvm::Expected<pt_cpu> GetCPUInfoForLiveProcess();
202be691f3bSpatrick 
203*f6aab3d8Srobert   /// Postmortem trace constructor
204*f6aab3d8Srobert   ///
205*f6aab3d8Srobert   /// \param[in] bundle_description
206*f6aab3d8Srobert   ///     The definition file for the postmortem bundle.
207*f6aab3d8Srobert   ///
208*f6aab3d8Srobert   /// \param[in] traced_processes
209*f6aab3d8Srobert   ///     The processes traced in the postmortem session.
210*f6aab3d8Srobert   ///
211be691f3bSpatrick   /// \param[in] trace_threads
212*f6aab3d8Srobert   ///     The threads traced in the postmortem session. They must belong to the
213*f6aab3d8Srobert   ///     processes mentioned above.
214*f6aab3d8Srobert   ///
215*f6aab3d8Srobert   /// \param[in] trace_mode
216*f6aab3d8Srobert   ///     The tracing mode of the postmortem session.
217*f6aab3d8Srobert   ///
218*f6aab3d8Srobert   /// \return
219*f6aab3d8Srobert   ///     A TraceIntelPT shared pointer instance.
220*f6aab3d8Srobert   /// \{
221*f6aab3d8Srobert   static TraceIntelPTSP CreateInstanceForPostmortemTrace(
222*f6aab3d8Srobert       JSONTraceBundleDescription &bundle_description,
223*f6aab3d8Srobert       llvm::ArrayRef<lldb::ProcessSP> traced_processes,
224*f6aab3d8Srobert       llvm::ArrayRef<lldb::ThreadPostMortemTraceSP> traced_threads,
225*f6aab3d8Srobert       TraceMode trace_mode);
226*f6aab3d8Srobert 
227*f6aab3d8Srobert   /// This constructor is used by CreateInstanceForPostmortemTrace to get the
228*f6aab3d8Srobert   /// instance ready before using shared pointers, which is a limitation of C++.
229*f6aab3d8Srobert   TraceIntelPT(JSONTraceBundleDescription &bundle_description,
230*f6aab3d8Srobert                llvm::ArrayRef<lldb::ProcessSP> traced_processes,
231*f6aab3d8Srobert                TraceMode trace_mode);
232*f6aab3d8Srobert   /// \}
233be691f3bSpatrick 
234be691f3bSpatrick   /// Constructor for live processes
TraceIntelPT(Process & live_process)235be691f3bSpatrick   TraceIntelPT(Process &live_process)
236*f6aab3d8Srobert       : Trace(live_process), trace_mode(TraceMode::UserMode){};
237be691f3bSpatrick 
238be691f3bSpatrick   /// Decode the trace of the given thread that, i.e. recontruct the traced
239be691f3bSpatrick   /// instructions.
240be691f3bSpatrick   ///
241be691f3bSpatrick   /// \param[in] thread
242be691f3bSpatrick   ///     If \a thread is a \a ThreadTrace, then its internal trace file will be
243be691f3bSpatrick   ///     decoded. Live threads are not currently supported.
244be691f3bSpatrick   ///
245be691f3bSpatrick   /// \return
246be691f3bSpatrick   ///     A \a DecodedThread shared pointer with the decoded instructions. Any
247*f6aab3d8Srobert   ///     errors are embedded in the instruction list. An \a llvm::Error is
248*f6aab3d8Srobert   ///     returned if the decoder couldn't be properly set up.
249*f6aab3d8Srobert   llvm::Expected<DecodedThreadSP> Decode(Thread &thread);
250be691f3bSpatrick 
251*f6aab3d8Srobert   /// \return
252*f6aab3d8Srobert   ///     The lowest timestamp in nanoseconds in all traces if available, \a
253*f6aab3d8Srobert   ///     std::nullopt if all the traces were empty or no trace contained no
254*f6aab3d8Srobert   ///     timing information, or an \a llvm::Error if it was not possible to set
255*f6aab3d8Srobert   ///     up the decoder for some trace.
256*f6aab3d8Srobert   llvm::Expected<std::optional<uint64_t>> FindBeginningOfTimeNanos();
257*f6aab3d8Srobert 
258*f6aab3d8Srobert   // Dump out trace info in JSON format
259*f6aab3d8Srobert   void DumpTraceInfoAsJson(Thread &thread, Stream &s, bool verbose);
260*f6aab3d8Srobert 
261*f6aab3d8Srobert   /// We package all the data that can change upon process stops to make sure
262*f6aab3d8Srobert   /// this contract is very visible.
263*f6aab3d8Srobert   /// This variable should only be accessed directly by constructores or live
264*f6aab3d8Srobert   /// process data refreshers.
265*f6aab3d8Srobert   struct Storage {
266*f6aab3d8Srobert     std::optional<TraceIntelPTMultiCpuDecoder> multicpu_decoder;
267*f6aab3d8Srobert     /// These decoders are used for the non-per-cpu case
268*f6aab3d8Srobert     llvm::DenseMap<lldb::tid_t, std::unique_ptr<ThreadDecoder>> thread_decoders;
269*f6aab3d8Srobert     /// Helper variable used to track long running operations for telemetry.
270*f6aab3d8Srobert     TaskTimer task_timer;
271*f6aab3d8Srobert     /// It is provided by either a trace bundle or a live process to convert TSC
272*f6aab3d8Srobert     /// counters to and from nanos. It might not be available on all hosts.
273*f6aab3d8Srobert     std::optional<LinuxPerfZeroTscConversion> tsc_conversion;
274*f6aab3d8Srobert     std::optional<uint64_t> beginning_of_time_nanos;
275*f6aab3d8Srobert     bool beginning_of_time_nanos_calculated = false;
276*f6aab3d8Srobert   } m_storage;
277*f6aab3d8Srobert 
278*f6aab3d8Srobert   /// It is provided by either a trace bundle or a live process' "cpuInfo"
279*f6aab3d8Srobert   /// binary data. We don't put it in the Storage because this variable doesn't
280*f6aab3d8Srobert   /// change.
281*f6aab3d8Srobert   std::optional<pt_cpu> m_cpu_info;
282*f6aab3d8Srobert 
283*f6aab3d8Srobert   /// Get the storage after refreshing the data in the case of a live process.
284*f6aab3d8Srobert   Storage &GetUpdatedStorage();
285*f6aab3d8Srobert 
286*f6aab3d8Srobert   /// The tracing mode of post mortem trace.
287*f6aab3d8Srobert   TraceMode trace_mode;
288be691f3bSpatrick };
289be691f3bSpatrick 
290be691f3bSpatrick } // namespace trace_intel_pt
291be691f3bSpatrick } // namespace lldb_private
292be691f3bSpatrick 
293be691f3bSpatrick #endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H
294