Coverage Report

Created: 2022-01-25 06:29

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Target/Trace.h
Line
Count
Source (jump to first uncovered line)
1
//===-- Trace.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_TARGET_TRACE_H
10
#define LLDB_TARGET_TRACE_H
11
12
#include <unordered_map>
13
14
#include "llvm/Support/JSON.h"
15
16
#include "lldb/Core/PluginInterface.h"
17
#include "lldb/Target/Thread.h"
18
#include "lldb/Target/TraceCursor.h"
19
#include "lldb/Utility/ArchSpec.h"
20
#include "lldb/Utility/TraceGDBRemotePackets.h"
21
#include "lldb/Utility/UnimplementedError.h"
22
#include "lldb/lldb-private.h"
23
#include "lldb/lldb-types.h"
24
25
namespace lldb_private {
26
27
/// \class Trace Trace.h "lldb/Target/Trace.h"
28
/// A plug-in interface definition class for trace information.
29
///
30
/// Trace plug-ins allow processor trace information to be loaded into LLDB so
31
/// that the data can be dumped, used for reverse and forward stepping to allow
32
/// introspection into the reason your process crashed or found its way to its
33
/// current state.
34
///
35
/// Trace information can be loaded into a target without a process to allow
36
/// introspection of the trace information during post mortem analysis, such as
37
/// when loading core files.
38
///
39
/// Processor trace information can also be fetched through the process
40
/// interfaces during a live debug session if your process supports gathering
41
/// this information.
42
///
43
/// In order to support live tracing, the name of the plug-in should match the
44
/// name of the tracing type returned by the gdb-remote packet
45
/// \a jLLDBTraceSupported.
46
class Trace : public PluginInterface,
47
              public std::enable_shared_from_this<Trace> {
48
public:
49
  /// Dump the trace data that this plug-in has access to.
50
  ///
51
  /// This function will dump all of the trace data for all threads in a user
52
  /// readable format. Options for dumping can be added as this API is iterated
53
  /// on.
54
  ///
55
  /// \param[in] s
56
  ///     A stream object to dump the information to.
57
  virtual void Dump(Stream *s) const = 0;
58
59
  /// Save the trace of a live process to the specified directory, which
60
  /// will be created if needed.
61
  /// This will also create a a file \a <directory>/trace.json with the main
62
  /// properties of the trace session, along with others files which contain
63
  /// the actual trace data. The trace.json file can be used later as input
64
  /// for the "trace load" command to load the trace in LLDB.
65
  /// The process being trace is not a live process, return an error.
66
  ///
67
  /// \param[in] directory
68
  ///   The directory where the trace files will be saved.
69
  ///
70
  /// \return
71
  ///   \a llvm::success if the operation was successful, or an \a llvm::Error
72
  ///   otherwise.
73
  virtual llvm::Error SaveLiveTraceToDisk(FileSpec directory) = 0;
74
75
  /// Find a trace plug-in using JSON data.
76
  ///
77
  /// When loading trace data from disk, the information for the trace data
78
  /// can be contained in multiple files and require plug-in specific
79
  /// information about the CPU. Using data like JSON provides an
80
  /// easy way to specify all of the settings and information that we will need
81
  /// to load trace data into LLDB. This structured data can include:
82
  ///   - The plug-in name (this allows a specific plug-in to be selected)
83
  ///   - Architecture or target triple
84
  ///   - one or more paths to the trace data file on disk
85
  ///     - core trace data
86
  ///     - thread events or related information
87
  ///   - shared library load information to use for this trace data that
88
  ///     allows a target to be created so the trace information can be
89
  ///     symbolicated so that the trace information can be displayed to the
90
  ///     user
91
  ///     - shared library path
92
  ///     - load address
93
  ///     - information on how to fetch the shared library
94
  ///       - path to locally cached file on disk
95
  ///       - URL to download the file
96
  ///   - Any information needed to load the trace file
97
  ///     - CPU information
98
  ///     - Custom plug-in information needed to decode the trace information
99
  ///       correctly.
100
  ///
101
  /// \param[in] debugger
102
  ///     The debugger instance where new Targets will be created as part of the
103
  ///     JSON data parsing.
104
  ///
105
  /// \param[in] trace_session_file
106
  ///     The contents of the trace session file describing the trace session.
107
  ///     See \a TraceSessionFileParser::BuildSchema for more information about
108
  ///     the schema of this JSON file.
109
  ///
110
  /// \param[in] session_file_dir
111
  ///     The path to the directory that contains the session file. It's used to
112
  ///     resolved relative paths in the session file.
113
  static llvm::Expected<lldb::TraceSP>
114
  FindPluginForPostMortemProcess(Debugger &debugger,
115
                                 const llvm::json::Value &trace_session_file,
116
                                 llvm::StringRef session_file_dir);
117
118
  /// Find a trace plug-in to trace a live process.
119
  ///
120
  /// \param[in] plugin_name
121
  ///     Plug-in name to search.
122
  ///
123
  /// \param[in] process
124
  ///     Live process to trace.
125
  ///
126
  /// \return
127
  ///     A \a TraceSP instance, or an \a llvm::Error if the plug-in name
128
  ///     doesn't match any registered plug-ins or tracing couldn't be
129
  ///     started.
130
  static llvm::Expected<lldb::TraceSP>
131
  FindPluginForLiveProcess(llvm::StringRef plugin_name, Process &process);
132
133
  /// Get the schema of a Trace plug-in given its name.
134
  ///
135
  /// \param[in] plugin_name
136
  ///     Name of the trace plugin.
137
  static llvm::Expected<llvm::StringRef>
138
  FindPluginSchema(llvm::StringRef plugin_name);
139
140
  /// Get the command handle for the "process trace start" command.
141
  virtual lldb::CommandObjectSP
142
  GetProcessTraceStartCommand(CommandInterpreter &interpreter) = 0;
143
144
  /// Get the command handle for the "thread trace start" command.
145
  virtual lldb::CommandObjectSP
146
  GetThreadTraceStartCommand(CommandInterpreter &interpreter) = 0;
147
148
  /// \return
149
  ///     The JSON schema of this Trace plug-in.
150
  virtual llvm::StringRef GetSchema() = 0;
151
152
  /// Get a \a TraceCursor for the given thread's trace.
153
  ///
154
  /// \return
155
  ///     A \a TraceCursorUP. If the thread is not traced or its trace
156
  ///     information failed to load, the corresponding error is embedded in the
157
  ///     trace.
158
  virtual lldb::TraceCursorUP GetCursor(Thread &thread) = 0;
159
160
  /// Dump general info about a given thread's trace. Each Trace plug-in
161
  /// decides which data to show.
162
  ///
163
  /// \param[in] thread
164
  ///     The thread that owns the trace in question.
165
  ///
166
  /// \param[in] s
167
  ///     The stream object where the info will be printed printed.
168
  ///
169
  /// \param[in] verbose
170
  ///     If \b true, print detailed info
171
  ///     If \b false, print compact info
172
  virtual void DumpTraceInfo(Thread &thread, Stream &s, bool verbose) = 0;
173
174
  /// Check if a thread is currently traced by this object.
175
  ///
176
  /// \param[in] tid
177
  ///     The id of the thread in question.
178
  ///
179
  /// \return
180
  ///     \b true if the thread is traced by this instance, \b false otherwise.
181
  virtual bool IsTraced(lldb::tid_t tid) = 0;
182
183
  /// \return
184
  ///     A description of the parameters to use for the \a Trace::Start method.
185
  virtual const char *GetStartConfigurationHelp() = 0;
186
187
  /// Start tracing a live process.
188
  ///
189
  /// \param[in] configuration
190
  ///     See \a SBTrace::Start(const lldb::SBStructuredData &) for more
191
  ///     information.
192
  ///
193
  /// \return
194
  ///     \a llvm::Error::success if the operation was successful, or
195
  ///     \a llvm::Error otherwise.
196
  virtual llvm::Error Start(
197
      StructuredData::ObjectSP configuration = StructuredData::ObjectSP()) = 0;
198
199
  /// Start tracing live threads.
200
  ///
201
  /// \param[in] tids
202
  ///     Threads to trace. This method tries to trace as many threads as
203
  ///     possible.
204
  ///
205
  /// \param[in] configuration
206
  ///     See \a SBTrace::Start(const lldb::SBThread &, const
207
  ///     lldb::SBStructuredData &) for more information.
208
  ///
209
  /// \return
210
  ///     \a llvm::Error::success if the operation was successful, or
211
  ///     \a llvm::Error otherwise.
212
  virtual llvm::Error Start(
213
      llvm::ArrayRef<lldb::tid_t> tids,
214
      StructuredData::ObjectSP configuration = StructuredData::ObjectSP()) = 0;
215
216
  /// Stop tracing live threads.
217
  ///
218
  /// \param[in] tids
219
  ///     The threads to stop tracing on.
220
  ///
221
  /// \return
222
  ///     \a llvm::Error::success if the operation was successful, or
223
  ///     \a llvm::Error otherwise.
224
  llvm::Error Stop(llvm::ArrayRef<lldb::tid_t> tids);
225
226
  /// Stop tracing all current and future threads of a live process.
227
  ///
228
  /// \param[in] request
229
  ///     The information determining which threads or process to stop tracing.
230
  ///
231
  /// \return
232
  ///     \a llvm::Error::success if the operation was successful, or
233
  ///     \a llvm::Error otherwise.
234
  llvm::Error Stop();
235
236
  /// Get the trace file of the given post mortem thread.
237
  llvm::Expected<const FileSpec &> GetPostMortemTraceFile(lldb::tid_t tid);
238
239
  /// \return
240
  ///     The stop ID of the live process being traced, or an invalid stop ID
241
  ///     if the trace is in an error or invalid state.
242
  uint32_t GetStopID();
243
244
protected:
245
  /// Get binary data of a live thread given a data identifier.
246
  ///
247
  /// \param[in] tid
248
  ///     The thread whose data is requested.
249
  ///
250
  /// \param[in] kind
251
  ///     The kind of data requested.
252
  ///
253
  /// \return
254
  ///     A vector of bytes with the requested data, or an \a llvm::Error in
255
  ///     case of failures.
256
  llvm::Expected<llvm::ArrayRef<uint8_t>>
257
  GetLiveThreadBinaryData(lldb::tid_t tid, llvm::StringRef kind);
258
259
  /// Get binary data of the current process given a data identifier.
260
  ///
261
  /// \param[in] kind
262
  ///     The kind of data requested.
263
  ///
264
  /// \return
265
  ///     A vector of bytes with the requested data, or an \a llvm::Error in
266
  ///     case of failures.
267
  llvm::Expected<llvm::ArrayRef<uint8_t>>
268
  GetLiveProcessBinaryData(llvm::StringRef kind);
269
270
  /// Get the size of the data returned by \a GetLiveThreadBinaryData
271
  llvm::Optional<size_t> GetLiveThreadBinaryDataSize(lldb::tid_t tid,
272
                                                     llvm::StringRef kind);
273
274
  /// Get the size of the data returned by \a GetLiveProcessBinaryData
275
  llvm::Optional<size_t> GetLiveProcessBinaryDataSize(llvm::StringRef kind);
276
  /// Constructor for post mortem processes
277
  Trace() = default;
278
279
  /// Constructor for a live process
280
0
  Trace(Process &live_process) : m_live_process(&live_process) {}
281
282
  /// Start tracing a live process or its threads.
283
  ///
284
  /// \param[in] request
285
  ///     JSON object with the information necessary to start tracing. In the
286
  ///     case of gdb-remote processes, this JSON object should conform to the
287
  ///     jLLDBTraceStart packet.
288
  ///
289
  /// \return
290
  ///     \a llvm::Error::success if the operation was successful, or
291
  ///     \a llvm::Error otherwise.
292
  llvm::Error Start(const llvm::json::Value &request);
293
294
  /// Get the current tracing state of a live process and its threads.
295
  ///
296
  /// \return
297
  ///     A JSON object string with custom data depending on the trace
298
  ///     technology, or an \a llvm::Error in case of errors.
299
  llvm::Expected<std::string> GetLiveProcessState();
300
301
  /// Method to be overriden by the plug-in to refresh its own state.
302
  ///
303
  /// This is invoked by RefreshLiveProcessState when a new state is found.
304
  ///
305
  /// \param[in] state
306
  ///     The jLLDBTraceGetState response.
307
  virtual void
308
  DoRefreshLiveProcessState(llvm::Expected<TraceGetStateResponse> state) = 0;
309
310
  /// Method to be invoked by the plug-in to refresh the live process state.
311
  ///
312
  /// The result is cached through the same process stop.
313
  void RefreshLiveProcessState();
314
315
  uint32_t m_stop_id = LLDB_INVALID_STOP_ID;
316
  /// Process traced by this object if doing live tracing. Otherwise it's null.
317
  Process *m_live_process = nullptr;
318
  /// tid -> data kind -> size
319
  std::map<lldb::tid_t, std::unordered_map<std::string, size_t>>
320
      m_live_thread_data;
321
  /// data kind -> size
322
  std::unordered_map<std::string, size_t> m_live_process_data;
323
};
324
325
} // namespace lldb_private
326
327
#endif // LLDB_TARGET_TRACE_H