LLDB  mainline
Trace.cpp
Go to the documentation of this file.
1 //===-- Trace.cpp ---------------------------------------------------------===//
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 #include "lldb/Target/Trace.h"
10 
11 #include "llvm/Support/Format.h"
12 
13 #include "lldb/Core/Module.h"
15 #include "lldb/Symbol/Function.h"
17 #include "lldb/Target/Process.h"
19 #include "lldb/Target/Thread.h"
20 #include "lldb/Utility/Stream.h"
21 
22 using namespace lldb;
23 using namespace lldb_private;
24 using namespace llvm;
25 
26 // Helper structs used to extract the type of a trace session json without
27 // having to parse the entire object.
28 
31 };
32 
35 };
36 
37 namespace llvm {
38 namespace json {
39 
40 bool fromJSON(const Value &value, JSONSimplePluginSettings &plugin_settings,
41  Path path) {
42  json::ObjectMapper o(value, path);
43  return o && o.map("type", plugin_settings.type);
44 }
45 
46 bool fromJSON(const Value &value, JSONSimpleTraceSession &session, Path path) {
47  json::ObjectMapper o(value, path);
48  return o && o.map("trace", session.trace);
49 }
50 
51 } // namespace json
52 } // namespace llvm
53 
54 static Error createInvalidPlugInError(StringRef plugin_name) {
55  return createStringError(
56  std::errc::invalid_argument,
57  "no trace plug-in matches the specified type: \"%s\"",
58  plugin_name.data());
59 }
60 
61 Expected<lldb::TraceSP>
62 Trace::FindPluginForPostMortemProcess(Debugger &debugger,
63  const json::Value &trace_session_file,
64  StringRef session_file_dir) {
65  JSONSimpleTraceSession json_session;
66  json::Path::Root root("traceSession");
67  if (!json::fromJSON(trace_session_file, json_session, root))
68  return root.getError();
69 
70  ConstString plugin_name(json_session.trace.type);
71  if (auto create_callback = PluginManager::GetTraceCreateCallback(plugin_name))
72  return create_callback(trace_session_file, session_file_dir, debugger);
73 
74  return createInvalidPlugInError(json_session.trace.type);
75 }
76 
77 Expected<lldb::TraceSP>
78 Trace::FindPluginForLiveProcess(llvm::StringRef plugin_name, Process &process) {
79  if (!process.IsLiveDebugSession())
80  return createStringError(inconvertibleErrorCode(),
81  "Can't trace non-live processes");
82 
83  ConstString name(plugin_name);
84  if (auto create_callback =
85  PluginManager::GetTraceCreateCallbackForLiveProcess(name))
86  return create_callback(process);
87 
88  return createInvalidPlugInError(plugin_name);
89 }
90 
91 Expected<StringRef> Trace::FindPluginSchema(StringRef name) {
92  ConstString plugin_name(name);
93  StringRef schema = PluginManager::GetTraceSchema(plugin_name);
94  if (!schema.empty())
95  return schema;
96 
97  return createInvalidPlugInError(name);
98 }
99 
100 Error Trace::Start(const llvm::json::Value &request) {
101  if (!m_live_process)
102  return createStringError(inconvertibleErrorCode(),
103  "Tracing requires a live process.");
104  return m_live_process->TraceStart(request);
105 }
106 
107 Error Trace::Stop() {
108  if (!m_live_process)
109  return createStringError(inconvertibleErrorCode(),
110  "Tracing requires a live process.");
111  return m_live_process->TraceStop(TraceStopRequest(GetPluginName()));
112 }
113 
114 Error Trace::Stop(llvm::ArrayRef<lldb::tid_t> tids) {
115  if (!m_live_process)
116  return createStringError(inconvertibleErrorCode(),
117  "Tracing requires a live process.");
118  return m_live_process->TraceStop(TraceStopRequest(GetPluginName(), tids));
119 }
120 
121 Expected<std::string> Trace::GetLiveProcessState() {
122  if (!m_live_process)
123  return createStringError(inconvertibleErrorCode(),
124  "Tracing requires a live process.");
125  return m_live_process->TraceGetState(GetPluginName());
126 }
127 
128 Optional<size_t> Trace::GetLiveThreadBinaryDataSize(lldb::tid_t tid,
129  llvm::StringRef kind) {
130  auto it = m_live_thread_data.find(tid);
131  if (it == m_live_thread_data.end())
132  return None;
133  std::unordered_map<std::string, size_t> &single_thread_data = it->second;
134  auto single_thread_data_it = single_thread_data.find(kind.str());
135  if (single_thread_data_it == single_thread_data.end())
136  return None;
137  return single_thread_data_it->second;
138 }
139 
140 Optional<size_t> Trace::GetLiveProcessBinaryDataSize(llvm::StringRef kind) {
141  auto data_it = m_live_process_data.find(kind.str());
142  if (data_it == m_live_process_data.end())
143  return None;
144  return data_it->second;
145 }
146 
147 Expected<ArrayRef<uint8_t>>
148 Trace::GetLiveThreadBinaryData(lldb::tid_t tid, llvm::StringRef kind) {
149  if (!m_live_process)
150  return createStringError(inconvertibleErrorCode(),
151  "Tracing requires a live process.");
152  llvm::Optional<size_t> size = GetLiveThreadBinaryDataSize(tid, kind);
153  if (!size)
154  return createStringError(
155  inconvertibleErrorCode(),
156  "Tracing data \"%s\" is not available for thread %" PRIu64 ".",
157  kind.data(), tid);
158 
159  TraceGetBinaryDataRequest request{GetPluginName().str(), kind.str(),
160  static_cast<int64_t>(tid), 0,
161  static_cast<int64_t>(*size)};
162  return m_live_process->TraceGetBinaryData(request);
163 }
164 
165 Expected<ArrayRef<uint8_t>>
166 Trace::GetLiveProcessBinaryData(llvm::StringRef kind) {
167  if (!m_live_process)
168  return createStringError(inconvertibleErrorCode(),
169  "Tracing requires a live process.");
170  llvm::Optional<size_t> size = GetLiveProcessBinaryDataSize(kind);
171  if (!size)
172  return createStringError(
173  inconvertibleErrorCode(),
174  "Tracing data \"%s\" is not available for the process.", kind.data());
175 
176  TraceGetBinaryDataRequest request{GetPluginName().str(), kind.str(), None, 0,
177  static_cast<int64_t>(*size)};
178  return m_live_process->TraceGetBinaryData(request);
179 }
180 
181 void Trace::RefreshLiveProcessState() {
182  if (!m_live_process)
183  return;
184 
185  uint32_t new_stop_id = m_live_process->GetStopID();
186  if (new_stop_id == m_stop_id)
187  return;
188 
189  m_stop_id = new_stop_id;
190  m_live_thread_data.clear();
191 
192  Expected<std::string> json_string = GetLiveProcessState();
193  if (!json_string) {
194  DoRefreshLiveProcessState(json_string.takeError());
195  return;
196  }
197  Expected<TraceGetStateResponse> live_process_state =
198  json::parse<TraceGetStateResponse>(*json_string, "TraceGetStateResponse");
199  if (!live_process_state) {
200  DoRefreshLiveProcessState(live_process_state.takeError());
201  return;
202  }
203 
204  for (const TraceThreadState &thread_state :
205  live_process_state->tracedThreads) {
206  for (const TraceBinaryData &item : thread_state.binaryData)
207  m_live_thread_data[thread_state.tid][item.kind] = item.size;
208  }
209 
210  for (const TraceBinaryData &item : live_process_state->processBinaryData)
211  m_live_process_data[item.kind] = item.size;
212 
213  DoRefreshLiveProcessState(std::move(live_process_state));
214 }
215 
216 uint32_t Trace::GetStopID() {
217  RefreshLiveProcessState();
218  return m_stop_id;
219 }
llvm
Definition: Debugger.h:49
lldb_private::TraceGetBinaryDataRequest
jLLDBTraceGetBinaryData gdb-remote packet
Definition: TraceGDBRemotePackets.h:132
lldb_private::Value
Definition: Value.h:38
lldb_private::TraceThreadState::tid
int64_t tid
Definition: TraceGDBRemotePackets.h:109
lldb_private::Process
Definition: Process.h:340
Module.h
SectionLoadList.h
Trace.h
Process.h
lldb_private::TraceBinaryData::size
int64_t size
Size in bytes for this data.
Definition: TraceGDBRemotePackets.h:100
lldb_private::Process::IsLiveDebugSession
virtual bool IsLiveDebugSession() const
Definition: Process.h:1405
lldb_private::TraceBinaryData::kind
std::string kind
Identifier of data to fetch with jLLDBTraceGetBinaryData.
Definition: TraceGDBRemotePackets.h:98
lldb_private::ConstString
Definition: ConstString.h:40
JSONSimplePluginSettings
Definition: Trace.cpp:29
lldb_private::Debugger
Definition: Debugger.h:70
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
Thread.h
JSONSimpleTraceSession
Definition: Trace.cpp:33
lldb_private::TraceStopRequest
jLLDBTraceStop gdb-remote packet
Definition: TraceGDBRemotePackets.h:62
lldb_private::TraceThreadState::binaryData
std::vector< TraceBinaryData > binaryData
List of binary data objects for this thread.
Definition: TraceGDBRemotePackets.h:111
JSONSimpleTraceSession::trace
JSONSimplePluginSettings trace
Definition: Trace.cpp:34
uint32_t
JSONSimplePluginSettings::type
std::string type
Definition: Trace.cpp:30
llvm::json::fromJSON
bool fromJSON(const Value &value, JSONSimpleTraceSession &session, Path path)
Definition: Trace.cpp:46
PluginManager.h
Function.h
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::TraceBinaryData
Definition: TraceGDBRemotePackets.h:96
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:29
createInvalidPlugInError
static Error createInvalidPlugInError(StringRef plugin_name)
Definition: Trace.cpp:54
Stream.h
lldb
Definition: SBAddress.h:15
ExecutionContext.h
lldb::tid_t
uint64_t tid_t
Definition: lldb-types.h:86
lldb_private::TraceThreadState
Definition: TraceGDBRemotePackets.h:108