174c93956SWalter Erquinigo //===-- Trace.cpp ---------------------------------------------------------===//
274c93956SWalter Erquinigo //
374c93956SWalter Erquinigo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
474c93956SWalter Erquinigo // See https://llvm.org/LICENSE.txt for license information.
574c93956SWalter Erquinigo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
674c93956SWalter Erquinigo //
774c93956SWalter Erquinigo //===----------------------------------------------------------------------===//
874c93956SWalter Erquinigo 
974c93956SWalter Erquinigo #include "lldb/Target/Trace.h"
1074c93956SWalter Erquinigo 
1174c93956SWalter Erquinigo #include "llvm/Support/Format.h"
1274c93956SWalter Erquinigo 
13cfd96f05SWalter Erquinigo #include "lldb/Core/Module.h"
1474c93956SWalter Erquinigo #include "lldb/Core/PluginManager.h"
15cfd96f05SWalter Erquinigo #include "lldb/Symbol/Function.h"
16ade59d53SWalter Erquinigo #include "lldb/Target/ExecutionContext.h"
17cfd96f05SWalter Erquinigo #include "lldb/Target/Process.h"
18cfd96f05SWalter Erquinigo #include "lldb/Target/SectionLoadList.h"
1926d861cbSWalter Erquinigo #include "lldb/Target/Thread.h"
20a0a46473SWalter Erquinigo #include "lldb/Utility/LLDBLog.h"
2126d861cbSWalter Erquinigo #include "lldb/Utility/Stream.h"
2274c93956SWalter Erquinigo 
2374c93956SWalter Erquinigo using namespace lldb;
2474c93956SWalter Erquinigo using namespace lldb_private;
2574c93956SWalter Erquinigo using namespace llvm;
2674c93956SWalter Erquinigo 
27b8dcd0baSWalter Erquinigo // Helper structs used to extract the type of a JSON trace bundle description
28b8dcd0baSWalter Erquinigo // object without having to parse the entire object.
29bddebca6SWalter Erquinigo 
30b8dcd0baSWalter Erquinigo struct JSONSimpleTraceBundleDescription {
31fc5ef57cSWalter Erquinigo   std::string type;
32bddebca6SWalter Erquinigo };
33bddebca6SWalter Erquinigo 
34bddebca6SWalter Erquinigo namespace llvm {
35bddebca6SWalter Erquinigo namespace json {
36bddebca6SWalter Erquinigo 
fromJSON(const Value & value,JSONSimpleTraceBundleDescription & bundle,Path path)37b8dcd0baSWalter Erquinigo bool fromJSON(const Value &value, JSONSimpleTraceBundleDescription &bundle,
38b8dcd0baSWalter Erquinigo               Path path) {
39bddebca6SWalter Erquinigo   json::ObjectMapper o(value, path);
40b8dcd0baSWalter Erquinigo   return o && o.map("type", bundle.type);
41bddebca6SWalter Erquinigo }
42bddebca6SWalter Erquinigo 
43bddebca6SWalter Erquinigo } // namespace json
44bddebca6SWalter Erquinigo } // namespace llvm
45bddebca6SWalter Erquinigo 
46561a61fbSWalter Erquinigo /// Helper functions for fetching data in maps and returning Optionals or
47561a61fbSWalter Erquinigo /// pointers instead of iterators for simplicity. It's worth mentioning that the
48561a61fbSWalter Erquinigo /// Optionals version can't return the inner data by reference because of
49561a61fbSWalter Erquinigo /// limitations in move constructors.
50561a61fbSWalter Erquinigo /// \{
51561a61fbSWalter Erquinigo template <typename K, typename V>
Lookup(DenseMap<K,V> & map,K k)52561a61fbSWalter Erquinigo static Optional<V> Lookup(DenseMap<K, V> &map, K k) {
53561a61fbSWalter Erquinigo   auto it = map.find(k);
54561a61fbSWalter Erquinigo   if (it == map.end())
55561a61fbSWalter Erquinigo     return None;
56561a61fbSWalter Erquinigo   return it->second;
57561a61fbSWalter Erquinigo }
58561a61fbSWalter Erquinigo 
59561a61fbSWalter Erquinigo template <typename K, typename V>
LookupAsPtr(DenseMap<K,V> & map,K k)60561a61fbSWalter Erquinigo static V *LookupAsPtr(DenseMap<K, V> &map, K k) {
61561a61fbSWalter Erquinigo   auto it = map.find(k);
62561a61fbSWalter Erquinigo   if (it == map.end())
63561a61fbSWalter Erquinigo     return nullptr;
64561a61fbSWalter Erquinigo   return &it->second;
65561a61fbSWalter Erquinigo }
66561a61fbSWalter Erquinigo 
67ea37cd52SWalter Erquinigo /// Similar to the methods above but it looks for an item in a map of maps.
68561a61fbSWalter Erquinigo template <typename K1, typename K2, typename V>
Lookup(DenseMap<K1,DenseMap<K2,V>> & map,K1 k1,K2 k2)69ea37cd52SWalter Erquinigo static Optional<V> Lookup(DenseMap<K1, DenseMap<K2, V>> &map, K1 k1, K2 k2) {
70561a61fbSWalter Erquinigo   auto it = map.find(k1);
71561a61fbSWalter Erquinigo   if (it == map.end())
72561a61fbSWalter Erquinigo     return None;
73561a61fbSWalter Erquinigo   return Lookup(it->second, k2);
74561a61fbSWalter Erquinigo }
75561a61fbSWalter Erquinigo 
76ea37cd52SWalter Erquinigo /// Similar to the methods above but it looks for an item in a map of maps.
77561a61fbSWalter Erquinigo template <typename K1, typename K2, typename V>
LookupAsPtr(DenseMap<K1,DenseMap<K2,V>> & map,K1 k1,K2 k2)78ea37cd52SWalter Erquinigo static V *LookupAsPtr(DenseMap<K1, DenseMap<K2, V>> &map, K1 k1, K2 k2) {
79561a61fbSWalter Erquinigo   auto it = map.find(k1);
80561a61fbSWalter Erquinigo   if (it == map.end())
81561a61fbSWalter Erquinigo     return nullptr;
82561a61fbSWalter Erquinigo   return LookupAsPtr(it->second, k2);
83561a61fbSWalter Erquinigo }
84561a61fbSWalter Erquinigo /// \}
85561a61fbSWalter Erquinigo 
createInvalidPlugInError(StringRef plugin_name)86ea1f4974SWalter Erquinigo static Error createInvalidPlugInError(StringRef plugin_name) {
87ea1f4974SWalter Erquinigo   return createStringError(
88ea1f4974SWalter Erquinigo       std::errc::invalid_argument,
89ea1f4974SWalter Erquinigo       "no trace plug-in matches the specified type: \"%s\"",
90ea1f4974SWalter Erquinigo       plugin_name.data());
91ea1f4974SWalter Erquinigo }
92ea1f4974SWalter Erquinigo 
930b697561SWalter Erquinigo Expected<lldb::TraceSP>
LoadPostMortemTraceFromFile(Debugger & debugger,const FileSpec & trace_description_file)9450f93679SJakob Johnson Trace::LoadPostMortemTraceFromFile(Debugger &debugger,
9550f93679SJakob Johnson                                    const FileSpec &trace_description_file) {
9650f93679SJakob Johnson 
9750f93679SJakob Johnson   auto buffer_or_error =
9850f93679SJakob Johnson       MemoryBuffer::getFile(trace_description_file.GetPath());
9950f93679SJakob Johnson   if (!buffer_or_error) {
10050f93679SJakob Johnson     return createStringError(std::errc::invalid_argument,
10150f93679SJakob Johnson                              "could not open input file: %s - %s.",
10250f93679SJakob Johnson                              trace_description_file.GetPath().c_str(),
10350f93679SJakob Johnson                              buffer_or_error.getError().message().c_str());
10450f93679SJakob Johnson   }
10550f93679SJakob Johnson 
10650f93679SJakob Johnson   Expected<json::Value> session_file =
10750f93679SJakob Johnson       json::parse(buffer_or_error.get()->getBuffer().str());
10850f93679SJakob Johnson   if (!session_file) {
10950f93679SJakob Johnson     return session_file.takeError();
11050f93679SJakob Johnson   }
11150f93679SJakob Johnson 
11250f93679SJakob Johnson   return Trace::FindPluginForPostMortemProcess(
11350f93679SJakob Johnson       debugger, *session_file,
11450f93679SJakob Johnson       trace_description_file.GetDirectory().AsCString());
11550f93679SJakob Johnson }
11650f93679SJakob Johnson 
FindPluginForPostMortemProcess(Debugger & debugger,const json::Value & trace_bundle_description,StringRef bundle_dir)117b8dcd0baSWalter Erquinigo Expected<lldb::TraceSP> Trace::FindPluginForPostMortemProcess(
118b8dcd0baSWalter Erquinigo     Debugger &debugger, const json::Value &trace_bundle_description,
119b8dcd0baSWalter Erquinigo     StringRef bundle_dir) {
120b8dcd0baSWalter Erquinigo   JSONSimpleTraceBundleDescription json_bundle;
121b8dcd0baSWalter Erquinigo   json::Path::Root root("traceBundle");
122b8dcd0baSWalter Erquinigo   if (!json::fromJSON(trace_bundle_description, json_bundle, root))
123bddebca6SWalter Erquinigo     return root.getError();
12474c93956SWalter Erquinigo 
125a3942318SPavel Labath   if (auto create_callback =
126b8dcd0baSWalter Erquinigo           PluginManager::GetTraceCreateCallback(json_bundle.type))
127b8dcd0baSWalter Erquinigo     return create_callback(trace_bundle_description, bundle_dir, debugger);
128ea1f4974SWalter Erquinigo 
129b8dcd0baSWalter Erquinigo   return createInvalidPlugInError(json_bundle.type);
13074c93956SWalter Erquinigo }
13174c93956SWalter Erquinigo 
FindPluginForLiveProcess(llvm::StringRef name,Process & process)132a3942318SPavel Labath Expected<lldb::TraceSP> Trace::FindPluginForLiveProcess(llvm::StringRef name,
133a3942318SPavel Labath                                                         Process &process) {
1340b697561SWalter Erquinigo   if (!process.IsLiveDebugSession())
1350b697561SWalter Erquinigo     return createStringError(inconvertibleErrorCode(),
1360b697561SWalter Erquinigo                              "Can't trace non-live processes");
1370b697561SWalter Erquinigo 
1380b697561SWalter Erquinigo   if (auto create_callback =
1390b697561SWalter Erquinigo           PluginManager::GetTraceCreateCallbackForLiveProcess(name))
1400b697561SWalter Erquinigo     return create_callback(process);
1410b697561SWalter Erquinigo 
142a3942318SPavel Labath   return createInvalidPlugInError(name);
1430b697561SWalter Erquinigo }
1440b697561SWalter Erquinigo 
FindPluginSchema(StringRef name)145ea1f4974SWalter Erquinigo Expected<StringRef> Trace::FindPluginSchema(StringRef name) {
146a3942318SPavel Labath   StringRef schema = PluginManager::GetTraceSchema(name);
147ea1f4974SWalter Erquinigo   if (!schema.empty())
148ea1f4974SWalter Erquinigo     return schema;
14974c93956SWalter Erquinigo 
150ea1f4974SWalter Erquinigo   return createInvalidPlugInError(name);
15174c93956SWalter Erquinigo }
15226d861cbSWalter Erquinigo 
Start(const llvm::json::Value & request)1530b697561SWalter Erquinigo Error Trace::Start(const llvm::json::Value &request) {
1540b697561SWalter Erquinigo   if (!m_live_process)
155561a61fbSWalter Erquinigo     return createStringError(
156561a61fbSWalter Erquinigo         inconvertibleErrorCode(),
157561a61fbSWalter Erquinigo         "Attempted to start tracing without a live process.");
1580b697561SWalter Erquinigo   return m_live_process->TraceStart(request);
1590b697561SWalter Erquinigo }
1600b697561SWalter Erquinigo 
Stop()161bf9f21a2SWalter Erquinigo Error Trace::Stop() {
1620b697561SWalter Erquinigo   if (!m_live_process)
163561a61fbSWalter Erquinigo     return createStringError(
164561a61fbSWalter Erquinigo         inconvertibleErrorCode(),
165561a61fbSWalter Erquinigo         "Attempted to stop tracing without a live process.");
166a3939e15SPavel Labath   return m_live_process->TraceStop(TraceStopRequest(GetPluginName()));
1670b697561SWalter Erquinigo }
1680b697561SWalter Erquinigo 
Stop(llvm::ArrayRef<lldb::tid_t> tids)169bf9f21a2SWalter Erquinigo Error Trace::Stop(llvm::ArrayRef<lldb::tid_t> tids) {
1700b697561SWalter Erquinigo   if (!m_live_process)
171561a61fbSWalter Erquinigo     return createStringError(
172561a61fbSWalter Erquinigo         inconvertibleErrorCode(),
173561a61fbSWalter Erquinigo         "Attempted to stop tracing without a live process.");
174a3939e15SPavel Labath   return m_live_process->TraceStop(TraceStopRequest(GetPluginName(), tids));
1750b697561SWalter Erquinigo }
1760b697561SWalter Erquinigo 
GetLiveProcessState()1770b697561SWalter Erquinigo Expected<std::string> Trace::GetLiveProcessState() {
1780b697561SWalter Erquinigo   if (!m_live_process)
179561a61fbSWalter Erquinigo     return createStringError(
180561a61fbSWalter Erquinigo         inconvertibleErrorCode(),
181561a61fbSWalter Erquinigo         "Attempted to fetch live trace information without a live process.");
182a3939e15SPavel Labath   return m_live_process->TraceGetState(GetPluginName());
1830b697561SWalter Erquinigo }
1840b697561SWalter Erquinigo 
GetLiveThreadBinaryDataSize(lldb::tid_t tid,llvm::StringRef kind)1851a3f9969SWalter Erquinigo Optional<uint64_t> Trace::GetLiveThreadBinaryDataSize(lldb::tid_t tid,
1860b697561SWalter Erquinigo                                                       llvm::StringRef kind) {
18703cc58ffSWalter Erquinigo   Storage &storage = GetUpdatedStorage();
188ea37cd52SWalter Erquinigo   return Lookup(storage.live_thread_data, tid, ConstString(kind));
1890b697561SWalter Erquinigo }
1900b697561SWalter Erquinigo 
GetLiveCpuBinaryDataSize(lldb::cpu_id_t cpu_id,llvm::StringRef kind)1916a5355e8SWalter Erquinigo Optional<uint64_t> Trace::GetLiveCpuBinaryDataSize(lldb::cpu_id_t cpu_id,
192fc5ef57cSWalter Erquinigo                                                    llvm::StringRef kind) {
19303cc58ffSWalter Erquinigo   Storage &storage = GetUpdatedStorage();
194ea37cd52SWalter Erquinigo   return Lookup(storage.live_cpu_data_sizes, cpu_id, ConstString(kind));
195fc5ef57cSWalter Erquinigo }
196fc5ef57cSWalter Erquinigo 
GetLiveProcessBinaryDataSize(llvm::StringRef kind)1971a3f9969SWalter Erquinigo Optional<uint64_t> Trace::GetLiveProcessBinaryDataSize(llvm::StringRef kind) {
19803cc58ffSWalter Erquinigo   Storage &storage = GetUpdatedStorage();
199561a61fbSWalter Erquinigo   return Lookup(storage.live_process_data, ConstString(kind));
200561a61fbSWalter Erquinigo }
201561a61fbSWalter Erquinigo 
202561a61fbSWalter Erquinigo Expected<std::vector<uint8_t>>
GetLiveTraceBinaryData(const TraceGetBinaryDataRequest & request,uint64_t expected_size)203561a61fbSWalter Erquinigo Trace::GetLiveTraceBinaryData(const TraceGetBinaryDataRequest &request,
204561a61fbSWalter Erquinigo                               uint64_t expected_size) {
205561a61fbSWalter Erquinigo   if (!m_live_process)
206561a61fbSWalter Erquinigo     return createStringError(
207561a61fbSWalter Erquinigo         inconvertibleErrorCode(),
208561a61fbSWalter Erquinigo         formatv("Attempted to fetch live trace data without a live process. "
2096a5355e8SWalter Erquinigo                 "Data kind = {0}, tid = {1}, cpu id = {2}.",
2106a5355e8SWalter Erquinigo                 request.kind, request.tid, request.cpu_id));
211561a61fbSWalter Erquinigo 
212561a61fbSWalter Erquinigo   Expected<std::vector<uint8_t>> data =
213561a61fbSWalter Erquinigo       m_live_process->TraceGetBinaryData(request);
214561a61fbSWalter Erquinigo 
215561a61fbSWalter Erquinigo   if (!data)
216561a61fbSWalter Erquinigo     return data.takeError();
217561a61fbSWalter Erquinigo 
218561a61fbSWalter Erquinigo   if (data->size() != expected_size)
219561a61fbSWalter Erquinigo     return createStringError(
220561a61fbSWalter Erquinigo         inconvertibleErrorCode(),
221561a61fbSWalter Erquinigo         formatv("Got incomplete live trace data. Data kind = {0}, expected "
2226a5355e8SWalter Erquinigo                 "size = {1}, actual size = {2}, tid = {3}, cpu id = {4}",
223561a61fbSWalter Erquinigo                 request.kind, expected_size, data->size(), request.tid,
2246a5355e8SWalter Erquinigo                 request.cpu_id));
225561a61fbSWalter Erquinigo 
226561a61fbSWalter Erquinigo   return data;
2270b697561SWalter Erquinigo }
2280b697561SWalter Erquinigo 
22931e44c01SWalter Erquinigo Expected<std::vector<uint8_t>>
GetLiveThreadBinaryData(lldb::tid_t tid,llvm::StringRef kind)2300b697561SWalter Erquinigo Trace::GetLiveThreadBinaryData(lldb::tid_t tid, llvm::StringRef kind) {
2311a3f9969SWalter Erquinigo   llvm::Optional<uint64_t> size = GetLiveThreadBinaryDataSize(tid, kind);
2320b697561SWalter Erquinigo   if (!size)
2330b697561SWalter Erquinigo     return createStringError(
2340b697561SWalter Erquinigo         inconvertibleErrorCode(),
2350b697561SWalter Erquinigo         "Tracing data \"%s\" is not available for thread %" PRIu64 ".",
2360b697561SWalter Erquinigo         kind.data(), tid);
2370b697561SWalter Erquinigo 
238fc5ef57cSWalter Erquinigo   TraceGetBinaryDataRequest request{GetPluginName().str(), kind.str(), tid,
2396a5355e8SWalter Erquinigo                                     /*cpu_id=*/None};
240561a61fbSWalter Erquinigo   return GetLiveTraceBinaryData(request, *size);
241fc5ef57cSWalter Erquinigo }
242fc5ef57cSWalter Erquinigo 
243fc5ef57cSWalter Erquinigo Expected<std::vector<uint8_t>>
GetLiveCpuBinaryData(lldb::cpu_id_t cpu_id,llvm::StringRef kind)2446a5355e8SWalter Erquinigo Trace::GetLiveCpuBinaryData(lldb::cpu_id_t cpu_id, llvm::StringRef kind) {
245fc5ef57cSWalter Erquinigo   if (!m_live_process)
246561a61fbSWalter Erquinigo     return createStringError(
247561a61fbSWalter Erquinigo         inconvertibleErrorCode(),
248561a61fbSWalter Erquinigo         "Attempted to fetch live cpu data without a live process.");
2496a5355e8SWalter Erquinigo   llvm::Optional<uint64_t> size = GetLiveCpuBinaryDataSize(cpu_id, kind);
250fc5ef57cSWalter Erquinigo   if (!size)
251fc5ef57cSWalter Erquinigo     return createStringError(
252fc5ef57cSWalter Erquinigo         inconvertibleErrorCode(),
2536a5355e8SWalter Erquinigo         "Tracing data \"%s\" is not available for cpu_id %" PRIu64 ".",
2546a5355e8SWalter Erquinigo         kind.data(), cpu_id);
255fc5ef57cSWalter Erquinigo 
256fc5ef57cSWalter Erquinigo   TraceGetBinaryDataRequest request{GetPluginName().str(), kind.str(),
2576a5355e8SWalter Erquinigo                                     /*tid=*/None, cpu_id};
2580b697561SWalter Erquinigo   return m_live_process->TraceGetBinaryData(request);
2590b697561SWalter Erquinigo }
2600b697561SWalter Erquinigo 
26131e44c01SWalter Erquinigo Expected<std::vector<uint8_t>>
GetLiveProcessBinaryData(llvm::StringRef kind)2620b697561SWalter Erquinigo Trace::GetLiveProcessBinaryData(llvm::StringRef kind) {
2631a3f9969SWalter Erquinigo   llvm::Optional<uint64_t> size = GetLiveProcessBinaryDataSize(kind);
2640b697561SWalter Erquinigo   if (!size)
2650b697561SWalter Erquinigo     return createStringError(
2660b697561SWalter Erquinigo         inconvertibleErrorCode(),
2670b697561SWalter Erquinigo         "Tracing data \"%s\" is not available for the process.", kind.data());
2680b697561SWalter Erquinigo 
269fc5ef57cSWalter Erquinigo   TraceGetBinaryDataRequest request{GetPluginName().str(), kind.str(),
2706a5355e8SWalter Erquinigo                                     /*tid=*/None, /*cpu_id*/ None};
271561a61fbSWalter Erquinigo   return GetLiveTraceBinaryData(request, *size);
2720b697561SWalter Erquinigo }
2730b697561SWalter Erquinigo 
GetUpdatedStorage()27403cc58ffSWalter Erquinigo Trace::Storage &Trace::GetUpdatedStorage() {
27503cc58ffSWalter Erquinigo   RefreshLiveProcessState();
27603cc58ffSWalter Erquinigo   return m_storage;
27703cc58ffSWalter Erquinigo }
27803cc58ffSWalter Erquinigo 
RefreshLiveProcessState()279a0a46473SWalter Erquinigo const char *Trace::RefreshLiveProcessState() {
2800b697561SWalter Erquinigo   if (!m_live_process)
281a0a46473SWalter Erquinigo     return nullptr;
2820b697561SWalter Erquinigo 
2830b697561SWalter Erquinigo   uint32_t new_stop_id = m_live_process->GetStopID();
2840b697561SWalter Erquinigo   if (new_stop_id == m_stop_id)
285a0a46473SWalter Erquinigo     return nullptr;
286a0a46473SWalter Erquinigo 
287a0a46473SWalter Erquinigo   Log *log = GetLog(LLDBLog::Target);
288a0a46473SWalter Erquinigo   LLDB_LOG(log, "Trace::RefreshLiveProcessState invoked");
2890b697561SWalter Erquinigo 
2900b697561SWalter Erquinigo   m_stop_id = new_stop_id;
29103cc58ffSWalter Erquinigo   m_storage = Trace::Storage();
292a0a46473SWalter Erquinigo 
293561a61fbSWalter Erquinigo   auto do_refresh = [&]() -> Error {
2940b697561SWalter Erquinigo     Expected<std::string> json_string = GetLiveProcessState();
295a0a46473SWalter Erquinigo     if (!json_string)
296561a61fbSWalter Erquinigo       return json_string.takeError();
297a0a46473SWalter Erquinigo 
2980b697561SWalter Erquinigo     Expected<TraceGetStateResponse> live_process_state =
299561a61fbSWalter Erquinigo         json::parse<TraceGetStateResponse>(*json_string,
300561a61fbSWalter Erquinigo                                            "TraceGetStateResponse");
301a0a46473SWalter Erquinigo     if (!live_process_state)
302561a61fbSWalter Erquinigo       return live_process_state.takeError();
303a0a46473SWalter Erquinigo 
304fc5ef57cSWalter Erquinigo     if (live_process_state->warnings) {
305fc5ef57cSWalter Erquinigo       for (std::string &warning : *live_process_state->warnings)
306fc5ef57cSWalter Erquinigo         LLDB_LOG(log, "== Warning when fetching the trace state: {0}", warning);
307fc5ef57cSWalter Erquinigo     }
3080b697561SWalter Erquinigo 
3090b697561SWalter Erquinigo     for (const TraceThreadState &thread_state :
3101f49714dSWalter Erquinigo          live_process_state->traced_threads) {
3111f49714dSWalter Erquinigo       for (const TraceBinaryData &item : thread_state.binary_data)
312561a61fbSWalter Erquinigo         m_storage.live_thread_data[thread_state.tid].insert(
313561a61fbSWalter Erquinigo             {ConstString(item.kind), item.size});
3140b697561SWalter Erquinigo     }
3150b697561SWalter Erquinigo 
316fc5ef57cSWalter Erquinigo     LLDB_LOG(log, "== Found {0} threads being traced",
317fc5ef57cSWalter Erquinigo              live_process_state->traced_threads.size());
318fc5ef57cSWalter Erquinigo 
3196a5355e8SWalter Erquinigo     if (live_process_state->cpus) {
3206a5355e8SWalter Erquinigo       m_storage.cpus.emplace();
3216a5355e8SWalter Erquinigo       for (const TraceCpuState &cpu_state : *live_process_state->cpus) {
3226a5355e8SWalter Erquinigo         m_storage.cpus->push_back(cpu_state.id);
3236a5355e8SWalter Erquinigo         for (const TraceBinaryData &item : cpu_state.binary_data)
3246a5355e8SWalter Erquinigo           m_storage.live_cpu_data_sizes[cpu_state.id].insert(
325561a61fbSWalter Erquinigo               {ConstString(item.kind), item.size});
326fc5ef57cSWalter Erquinigo       }
3276a5355e8SWalter Erquinigo       LLDB_LOG(log, "== Found {0} cpu cpus being traced",
3286a5355e8SWalter Erquinigo                live_process_state->cpus->size());
329fc5ef57cSWalter Erquinigo     }
330fc5ef57cSWalter Erquinigo 
3311f49714dSWalter Erquinigo     for (const TraceBinaryData &item : live_process_state->process_binary_data)
332561a61fbSWalter Erquinigo       m_storage.live_process_data.insert({ConstString(item.kind), item.size});
3330b697561SWalter Erquinigo 
334561a61fbSWalter Erquinigo     return DoRefreshLiveProcessState(std::move(*live_process_state),
335561a61fbSWalter Erquinigo                                      *json_string);
336561a61fbSWalter Erquinigo   };
337561a61fbSWalter Erquinigo 
338561a61fbSWalter Erquinigo   if (Error err = do_refresh()) {
339561a61fbSWalter Erquinigo     m_storage.live_refresh_error = toString(std::move(err));
340561a61fbSWalter Erquinigo     return m_storage.live_refresh_error->c_str();
341561a61fbSWalter Erquinigo   }
342a0a46473SWalter Erquinigo 
343a0a46473SWalter Erquinigo   return nullptr;
3440b697561SWalter Erquinigo }
3452aa1dd1cSWalter Erquinigo 
Trace(ArrayRef<ProcessSP> postmortem_processes,Optional<std::vector<lldb::cpu_id_t>> postmortem_cpus)346fc5ef57cSWalter Erquinigo Trace::Trace(ArrayRef<ProcessSP> postmortem_processes,
3476a5355e8SWalter Erquinigo              Optional<std::vector<lldb::cpu_id_t>> postmortem_cpus) {
348fc5ef57cSWalter Erquinigo   for (ProcessSP process_sp : postmortem_processes)
34903cc58ffSWalter Erquinigo     m_storage.postmortem_processes.push_back(process_sp.get());
3506a5355e8SWalter Erquinigo   m_storage.cpus = postmortem_cpus;
351fc5ef57cSWalter Erquinigo }
352fc5ef57cSWalter Erquinigo 
GetLiveProcess()353a0a46473SWalter Erquinigo Process *Trace::GetLiveProcess() { return m_live_process; }
354a0a46473SWalter Erquinigo 
GetPostMortemProcesses()355fc5ef57cSWalter Erquinigo ArrayRef<Process *> Trace::GetPostMortemProcesses() {
35603cc58ffSWalter Erquinigo   return m_storage.postmortem_processes;
357fc5ef57cSWalter Erquinigo }
358fc5ef57cSWalter Erquinigo 
GetAllProcesses()359fc5ef57cSWalter Erquinigo std::vector<Process *> Trace::GetAllProcesses() {
360fc5ef57cSWalter Erquinigo   if (Process *proc = GetLiveProcess())
361fc5ef57cSWalter Erquinigo     return {proc};
362fc5ef57cSWalter Erquinigo   return GetPostMortemProcesses();
363fc5ef57cSWalter Erquinigo }
364fc5ef57cSWalter Erquinigo 
GetStopID()3652aa1dd1cSWalter Erquinigo uint32_t Trace::GetStopID() {
3662aa1dd1cSWalter Erquinigo   RefreshLiveProcessState();
3672aa1dd1cSWalter Erquinigo   return m_stop_id;
3682aa1dd1cSWalter Erquinigo }
369e0cfe20aSWalter Erquinigo 
370e0cfe20aSWalter Erquinigo llvm::Expected<FileSpec>
GetPostMortemThreadDataFile(lldb::tid_t tid,llvm::StringRef kind)371e0cfe20aSWalter Erquinigo Trace::GetPostMortemThreadDataFile(lldb::tid_t tid, llvm::StringRef kind) {
372561a61fbSWalter Erquinigo   Storage &storage = GetUpdatedStorage();
373561a61fbSWalter Erquinigo   if (Optional<FileSpec> file =
374ea37cd52SWalter Erquinigo           Lookup(storage.postmortem_thread_data, tid, ConstString(kind)))
375561a61fbSWalter Erquinigo     return *file;
376561a61fbSWalter Erquinigo   else
377e0cfe20aSWalter Erquinigo     return createStringError(
378e0cfe20aSWalter Erquinigo         inconvertibleErrorCode(),
379e0cfe20aSWalter Erquinigo         formatv("The thread with tid={0} doesn't have the tracing data {1}",
380e0cfe20aSWalter Erquinigo                 tid, kind));
381e0cfe20aSWalter Erquinigo }
382e0cfe20aSWalter Erquinigo 
GetPostMortemCpuDataFile(lldb::cpu_id_t cpu_id,llvm::StringRef kind)3836a5355e8SWalter Erquinigo llvm::Expected<FileSpec> Trace::GetPostMortemCpuDataFile(lldb::cpu_id_t cpu_id,
384fc5ef57cSWalter Erquinigo                                                          llvm::StringRef kind) {
385561a61fbSWalter Erquinigo   Storage &storage = GetUpdatedStorage();
386561a61fbSWalter Erquinigo   if (Optional<FileSpec> file =
387ea37cd52SWalter Erquinigo           Lookup(storage.postmortem_cpu_data, cpu_id, ConstString(kind)))
388561a61fbSWalter Erquinigo     return *file;
389561a61fbSWalter Erquinigo   else
390fc5ef57cSWalter Erquinigo     return createStringError(
391fc5ef57cSWalter Erquinigo         inconvertibleErrorCode(),
3926a5355e8SWalter Erquinigo         formatv("The cpu with id={0} doesn't have the tracing data {1}", cpu_id,
3936a5355e8SWalter Erquinigo                 kind));
394fc5ef57cSWalter Erquinigo }
395fc5ef57cSWalter Erquinigo 
SetPostMortemThreadDataFile(lldb::tid_t tid,llvm::StringRef kind,FileSpec file_spec)396e0cfe20aSWalter Erquinigo void Trace::SetPostMortemThreadDataFile(lldb::tid_t tid, llvm::StringRef kind,
397e0cfe20aSWalter Erquinigo                                         FileSpec file_spec) {
39803cc58ffSWalter Erquinigo   Storage &storage = GetUpdatedStorage();
399561a61fbSWalter Erquinigo   storage.postmortem_thread_data[tid].insert({ConstString(kind), file_spec});
400e0cfe20aSWalter Erquinigo }
401e0cfe20aSWalter Erquinigo 
SetPostMortemCpuDataFile(lldb::cpu_id_t cpu_id,llvm::StringRef kind,FileSpec file_spec)4026a5355e8SWalter Erquinigo void Trace::SetPostMortemCpuDataFile(lldb::cpu_id_t cpu_id,
4036a5355e8SWalter Erquinigo                                      llvm::StringRef kind, FileSpec file_spec) {
40403cc58ffSWalter Erquinigo   Storage &storage = GetUpdatedStorage();
4056a5355e8SWalter Erquinigo   storage.postmortem_cpu_data[cpu_id].insert({ConstString(kind), file_spec});
406fc5ef57cSWalter Erquinigo }
407fc5ef57cSWalter Erquinigo 
408e0cfe20aSWalter Erquinigo llvm::Error
OnLiveThreadBinaryDataRead(lldb::tid_t tid,llvm::StringRef kind,OnBinaryDataReadCallback callback)409e0cfe20aSWalter Erquinigo Trace::OnLiveThreadBinaryDataRead(lldb::tid_t tid, llvm::StringRef kind,
410e0cfe20aSWalter Erquinigo                                   OnBinaryDataReadCallback callback) {
411e0cfe20aSWalter Erquinigo   Expected<std::vector<uint8_t>> data = GetLiveThreadBinaryData(tid, kind);
412e0cfe20aSWalter Erquinigo   if (!data)
413e0cfe20aSWalter Erquinigo     return data.takeError();
414e0cfe20aSWalter Erquinigo   return callback(*data);
415e0cfe20aSWalter Erquinigo }
416e0cfe20aSWalter Erquinigo 
OnLiveCpuBinaryDataRead(lldb::cpu_id_t cpu_id,llvm::StringRef kind,OnBinaryDataReadCallback callback)4176a5355e8SWalter Erquinigo llvm::Error Trace::OnLiveCpuBinaryDataRead(lldb::cpu_id_t cpu_id,
418fc5ef57cSWalter Erquinigo                                            llvm::StringRef kind,
419e0cfe20aSWalter Erquinigo                                            OnBinaryDataReadCallback callback) {
42003cc58ffSWalter Erquinigo   Storage &storage = GetUpdatedStorage();
4216a5355e8SWalter Erquinigo   if (std::vector<uint8_t> *cpu_data =
422ea37cd52SWalter Erquinigo           LookupAsPtr(storage.live_cpu_data, cpu_id, ConstString(kind)))
4236a5355e8SWalter Erquinigo     return callback(*cpu_data);
424a19fcc2bSWalter Erquinigo 
4256a5355e8SWalter Erquinigo   Expected<std::vector<uint8_t>> data = GetLiveCpuBinaryData(cpu_id, kind);
426fc5ef57cSWalter Erquinigo   if (!data)
427fc5ef57cSWalter Erquinigo     return data.takeError();
4286a5355e8SWalter Erquinigo   auto it = storage.live_cpu_data[cpu_id].insert(
429561a61fbSWalter Erquinigo       {ConstString(kind), std::move(*data)});
430a19fcc2bSWalter Erquinigo   return callback(it.first->second);
431fc5ef57cSWalter Erquinigo }
432fc5ef57cSWalter Erquinigo 
OnDataFileRead(FileSpec file,OnBinaryDataReadCallback callback)433fc5ef57cSWalter Erquinigo llvm::Error Trace::OnDataFileRead(FileSpec file,
434fc5ef57cSWalter Erquinigo                                   OnBinaryDataReadCallback callback) {
435e0cfe20aSWalter Erquinigo   ErrorOr<std::unique_ptr<MemoryBuffer>> trace_or_error =
436fc5ef57cSWalter Erquinigo       MemoryBuffer::getFile(file.GetPath());
437e0cfe20aSWalter Erquinigo   if (std::error_code err = trace_or_error.getError())
43803cc58ffSWalter Erquinigo     return createStringError(
43903cc58ffSWalter Erquinigo         inconvertibleErrorCode(), "Failed fetching trace-related file %s. %s",
440*1b4b12a3SNico Weber         file.GetCString(), toString(errorCodeToError(err)).c_str());
441e0cfe20aSWalter Erquinigo 
442e0cfe20aSWalter Erquinigo   MemoryBuffer &data = **trace_or_error;
443e0cfe20aSWalter Erquinigo   ArrayRef<uint8_t> array_ref(
444e0cfe20aSWalter Erquinigo       reinterpret_cast<const uint8_t *>(data.getBufferStart()),
445e0cfe20aSWalter Erquinigo       data.getBufferSize());
446e0cfe20aSWalter Erquinigo   return callback(array_ref);
447e0cfe20aSWalter Erquinigo }
448e0cfe20aSWalter Erquinigo 
449fc5ef57cSWalter Erquinigo llvm::Error
OnPostMortemThreadBinaryDataRead(lldb::tid_t tid,llvm::StringRef kind,OnBinaryDataReadCallback callback)450fc5ef57cSWalter Erquinigo Trace::OnPostMortemThreadBinaryDataRead(lldb::tid_t tid, llvm::StringRef kind,
451fc5ef57cSWalter Erquinigo                                         OnBinaryDataReadCallback callback) {
452561a61fbSWalter Erquinigo   if (Expected<FileSpec> file = GetPostMortemThreadDataFile(tid, kind))
453fc5ef57cSWalter Erquinigo     return OnDataFileRead(*file, callback);
454561a61fbSWalter Erquinigo   else
455561a61fbSWalter Erquinigo     return file.takeError();
456fc5ef57cSWalter Erquinigo }
457fc5ef57cSWalter Erquinigo 
458fc5ef57cSWalter Erquinigo llvm::Error
OnPostMortemCpuBinaryDataRead(lldb::cpu_id_t cpu_id,llvm::StringRef kind,OnBinaryDataReadCallback callback)4596a5355e8SWalter Erquinigo Trace::OnPostMortemCpuBinaryDataRead(lldb::cpu_id_t cpu_id,
460fc5ef57cSWalter Erquinigo                                      llvm::StringRef kind,
461fc5ef57cSWalter Erquinigo                                      OnBinaryDataReadCallback callback) {
4626a5355e8SWalter Erquinigo   if (Expected<FileSpec> file = GetPostMortemCpuDataFile(cpu_id, kind))
463fc5ef57cSWalter Erquinigo     return OnDataFileRead(*file, callback);
464561a61fbSWalter Erquinigo   else
465561a61fbSWalter Erquinigo     return file.takeError();
466fc5ef57cSWalter Erquinigo }
467fc5ef57cSWalter Erquinigo 
OnThreadBinaryDataRead(lldb::tid_t tid,llvm::StringRef kind,OnBinaryDataReadCallback callback)468e0cfe20aSWalter Erquinigo llvm::Error Trace::OnThreadBinaryDataRead(lldb::tid_t tid, llvm::StringRef kind,
469e0cfe20aSWalter Erquinigo                                           OnBinaryDataReadCallback callback) {
470e0cfe20aSWalter Erquinigo   if (m_live_process)
471e0cfe20aSWalter Erquinigo     return OnLiveThreadBinaryDataRead(tid, kind, callback);
472e0cfe20aSWalter Erquinigo   else
473e0cfe20aSWalter Erquinigo     return OnPostMortemThreadBinaryDataRead(tid, kind, callback);
474e0cfe20aSWalter Erquinigo }
475fc5ef57cSWalter Erquinigo 
476a19fcc2bSWalter Erquinigo llvm::Error
OnAllCpusBinaryDataRead(llvm::StringRef kind,OnCpusBinaryDataReadCallback callback)4776a5355e8SWalter Erquinigo Trace::OnAllCpusBinaryDataRead(llvm::StringRef kind,
4786a5355e8SWalter Erquinigo                                OnCpusBinaryDataReadCallback callback) {
4796a5355e8SWalter Erquinigo   DenseMap<cpu_id_t, ArrayRef<uint8_t>> buffers;
48003cc58ffSWalter Erquinigo   Storage &storage = GetUpdatedStorage();
4816a5355e8SWalter Erquinigo   if (!storage.cpus)
48203cc58ffSWalter Erquinigo     return Error::success();
483a19fcc2bSWalter Erquinigo 
4846a5355e8SWalter Erquinigo   std::function<Error(std::vector<cpu_id_t>::iterator)> process_cpu =
4856a5355e8SWalter Erquinigo       [&](std::vector<cpu_id_t>::iterator cpu_id) -> Error {
4866a5355e8SWalter Erquinigo     if (cpu_id == storage.cpus->end())
487a19fcc2bSWalter Erquinigo       return callback(buffers);
488a19fcc2bSWalter Erquinigo 
4896a5355e8SWalter Erquinigo     return OnCpuBinaryDataRead(*cpu_id, kind,
490a19fcc2bSWalter Erquinigo                                [&](ArrayRef<uint8_t> data) -> Error {
4916a5355e8SWalter Erquinigo                                  buffers.try_emplace(*cpu_id, data);
4926a5355e8SWalter Erquinigo                                  auto next_id = cpu_id;
493a19fcc2bSWalter Erquinigo                                  next_id++;
4946a5355e8SWalter Erquinigo                                  return process_cpu(next_id);
495a19fcc2bSWalter Erquinigo                                });
496a19fcc2bSWalter Erquinigo   };
4976a5355e8SWalter Erquinigo   return process_cpu(storage.cpus->begin());
498a19fcc2bSWalter Erquinigo }
499a19fcc2bSWalter Erquinigo 
OnCpuBinaryDataRead(lldb::cpu_id_t cpu_id,llvm::StringRef kind,OnBinaryDataReadCallback callback)5006a5355e8SWalter Erquinigo llvm::Error Trace::OnCpuBinaryDataRead(lldb::cpu_id_t cpu_id,
501fc5ef57cSWalter Erquinigo                                        llvm::StringRef kind,
502fc5ef57cSWalter Erquinigo                                        OnBinaryDataReadCallback callback) {
503fc5ef57cSWalter Erquinigo   if (m_live_process)
5046a5355e8SWalter Erquinigo     return OnLiveCpuBinaryDataRead(cpu_id, kind, callback);
505fc5ef57cSWalter Erquinigo   else
5066a5355e8SWalter Erquinigo     return OnPostMortemCpuBinaryDataRead(cpu_id, kind, callback);
507fc5ef57cSWalter Erquinigo }
508fc5ef57cSWalter Erquinigo 
GetTracedCpus()5096a5355e8SWalter Erquinigo ArrayRef<lldb::cpu_id_t> Trace::GetTracedCpus() {
51003cc58ffSWalter Erquinigo   Storage &storage = GetUpdatedStorage();
5116a5355e8SWalter Erquinigo   if (storage.cpus)
5126a5355e8SWalter Erquinigo     return *storage.cpus;
513fc5ef57cSWalter Erquinigo   return {};
514fc5ef57cSWalter Erquinigo }
515ff15efc1SWalter Erquinigo 
GetTracedProcesses()51603cc58ffSWalter Erquinigo std::vector<Process *> Trace::GetTracedProcesses() {
517ff15efc1SWalter Erquinigo   std::vector<Process *> processes;
51803cc58ffSWalter Erquinigo   Storage &storage = GetUpdatedStorage();
519ff15efc1SWalter Erquinigo 
52003cc58ffSWalter Erquinigo   for (Process *proc : storage.postmortem_processes)
521ff15efc1SWalter Erquinigo     processes.push_back(proc);
522ff15efc1SWalter Erquinigo 
523ff15efc1SWalter Erquinigo   if (m_live_process)
524ff15efc1SWalter Erquinigo     processes.push_back(m_live_process);
525ff15efc1SWalter Erquinigo   return processes;
526ff15efc1SWalter Erquinigo }
527