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