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