Renamed ThreadIntelPT to TreaceThread, making it a top-level class. I noticed that this class can and shuld work for any trace plugin and there's nothing intel-pt specific in it.
With that TraceThread change, I was able to move most of the json file parsing logic to the base class TraceSessionFileParser, which makes adding new plug-ins easier.
This originally was part of https://reviews.llvm.org/D89283
Differential Revision: https://reviews.llvm.org/D89408
//
//===----------------------------------------------------------------------===//
-#ifndef LLDB_SOURCE_PLUGINS_PROCESS_TRACE_PROCESSTRACE_H
-#define LLDB_SOURCE_PLUGINS_PROCESS_TRACE_PROCESSTRACE_H
+#ifndef LLDB_TARGET_PROCESSTRACE_H
+#define LLDB_TARGET_PROCESSTRACE_H
#include "lldb/Target/Process.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Status.h"
namespace lldb_private {
-namespace process_trace {
class ProcessTrace : public Process {
public:
- static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp,
- lldb::ListenerSP listener_sp,
- const FileSpec *crash_file_path);
-
static void Initialize();
static void Terminate();
bool UpdateThreadList(ThreadList &old_thread_list,
ThreadList &new_thread_list) override;
+
+private:
+ static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp,
+ lldb::ListenerSP listener_sp,
+ const FileSpec *crash_file_path);
};
-} // namespace process_trace
} // namespace lldb_private
-#endif // LLDB_SOURCE_PLUGINS_PROCESS_TRACE_PROCESSTRACE_H
+#endif // LLDB_TARGET_PROCESSTRACE_H
--- /dev/null
+//===-- ThreadTrace.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_TARGET_THREADTRACE_H
+#define LLDB_TARGET_THREADTRACE_H
+
+#include "lldb/Target/Thread.h"
+
+namespace lldb_private {
+
+/// \class ThreadTrace ThreadTrace.h
+///
+/// Thread implementation used for representing threads gotten from trace
+/// session files, which are similar to threads from core files.
+///
+/// See \a TraceSessionFileParser for more information regarding trace session
+/// files.
+class ThreadTrace : public Thread {
+public:
+ /// \param[in] process
+ /// The process who owns this thread.
+ ///
+ /// \param[in] tid
+ /// The tid of this thread.
+ ///
+ /// \param[in] trace_file.
+ /// The file that contains the list of instructions that were traced when
+ /// this thread was being executed.
+ ThreadTrace(Process &process, lldb::tid_t tid, const FileSpec &trace_file)
+ : Thread(process, tid), m_trace_file(trace_file) {}
+
+ void RefreshStateAfterStop() override;
+
+ lldb::RegisterContextSP GetRegisterContext() override;
+
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame(StackFrame *frame) override;
+
+ /// \return
+ /// The trace file of this thread.
+ const FileSpec &GetTraceFile() const;
+
+protected:
+ bool CalculateStopInfo() override;
+
+ lldb::RegisterContextSP m_thread_reg_ctx_sp;
+
+private:
+ FileSpec m_trace_file;
+};
+
+typedef std::shared_ptr<ThreadTrace> ThreadTraceSP;
+
+} // namespace lldb_private
+
+#endif // LLDB_TARGET_THREADTRACE_H
#include "llvm/Support/JSON.h"
-#include "lldb/lldb-private.h"
+#include "lldb/Target/ThreadTrace.h"
namespace lldb_private {
std::string type;
};
+ struct JSONTraceSessionBase {
+ std::vector<JSONProcess> processes;
+ };
+
/// The trace plug-in implementation should provide its own TPluginSettings,
/// which corresponds to the "trace" section of the schema.
- template <class TPluginSettings> struct JSONTraceSession {
- std::vector<JSONProcess> processes;
+ template <class TPluginSettings>
+ struct JSONTraceSession : JSONTraceSessionBase {
TPluginSettings trace;
};
/// \}
- TraceSessionFileParser(llvm::StringRef session_file_dir,
+ /// Helper struct holding the objects created when parsing a process
+ struct ParsedProcess {
+ lldb::TargetSP target_sp;
+ std::vector<ThreadTraceSP> threads;
+ };
+
+ TraceSessionFileParser(Debugger &debugger, llvm::StringRef session_file_dir,
llvm::StringRef schema)
- : m_session_file_dir(session_file_dir), m_schema(schema) {}
+ : m_debugger(debugger), m_session_file_dir(session_file_dir),
+ m_schema(schema) {}
/// Build the full schema for a Trace plug-in.
///
/// specific attributes.
static std::string BuildSchema(llvm::StringRef plugin_schema);
+ /// Parse the fields common to all trace session schemas.
+ ///
+ /// \param[in] session
+ /// The session json objects already deserialized.
+ ///
+ /// \return
+ /// A list of \a ParsedProcess containing all threads and targets created
+ /// during the parsing, or an error in case of failures. In case of
+ /// errors, no side effects are produced.
+ llvm::Expected<std::vector<ParsedProcess>>
+ ParseCommonSessionFile(const JSONTraceSessionBase &session);
+
protected:
/// Resolve non-absolute paths relative to the session file folder. It
/// modifies the given file_spec.
void NormalizePath(lldb_private::FileSpec &file_spec);
+ ThreadTraceSP ParseThread(lldb::ProcessSP &process_sp,
+ const JSONThread &thread);
+
+ llvm::Expected<ParsedProcess> ParseProcess(const JSONProcess &process);
+
llvm::Error ParseModule(lldb::TargetSP &target_sp, const JSONModule &module);
/// Create a user-friendly error message upon a JSON-parsing failure using the
llvm::Error CreateJSONError(llvm::json::Path::Root &root,
const llvm::json::Value &value);
+ Debugger &m_debugger;
std::string m_session_file_dir;
llvm::StringRef m_schema;
};
&plugin_settings,
Path path);
+bool fromJSON(
+ const Value &value,
+ lldb_private::TraceSessionFileParser::JSONTraceSessionBase &session,
+ Path path);
+
template <class TPluginSettings>
bool fromJSON(
const Value &value,
Path path) {
ObjectMapper o(value, path);
return o && o.map("trace", session.trace) &&
- o.map("processes", session.processes);
+ fromJSON(value,
+ (lldb_private::TraceSessionFileParser::JSONTraceSessionBase &)
+ session,
+ path);
}
} // namespace json
class ThreadPlanStepThrough;
class ThreadPlanTracer;
class ThreadSpec;
+class ThreadTrace;
class Trace;
class TraceSessionFileParser;
class TraceOptions;
#include "lldb/Host/Host.h"
#include "lldb/Initialization/SystemInitializerCommon.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Target/ProcessTrace.h"
#include "lldb/Utility/Timer.h"
#include "llvm/Support/TargetSelect.h"
#define LLDB_PLUGIN(p) LLDB_PLUGIN_INITIALIZE(p);
#include "Plugins/Plugins.def"
+ // Initialize plug-ins in core LLDB
+ ProcessTrace::Initialize();
+
// Scan for any system or user LLDB plug-ins
PluginManager::Initialize();
Debugger::SettingsTerminate();
+ // Terminate plug-ins in core LLDB
+ ProcessTrace::Terminate();
+
// Terminate and unload and loaded system or user LLDB plug-ins
PluginManager::Terminate();
add_subdirectory(elf-core)
add_subdirectory(mach-core)
add_subdirectory(minidump)
-add_subdirectory(Trace)
+++ /dev/null
-add_lldb_library(lldbPluginProcessTrace PLUGIN
- ProcessTrace.cpp
-
- LINK_LIBS
- lldbCore
- lldbTarget
- lldbUtility
- lldbPluginProcessUtility
- LINK_COMPONENTS
- BinaryFormat
- Object
- Support
- )
add_lldb_library(lldbPluginTraceIntelPT PLUGIN
TraceIntelPT.cpp
TraceIntelPTSessionFileParser.cpp
- ThreadIntelPT.cpp
LINK_LIBS
lldbCore
+++ /dev/null
-//===-- ThreadIntelPT.h -----------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_THREADINTELPT_H
-#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_THREADINTELPT_H
-
-#include "lldb/Target/Thread.h"
-
-namespace lldb_private {
-namespace trace_intel_pt {
-
-class ThreadIntelPT : public Thread {
-public:
- /// Create an Intel PT-traced thread.
- ///
- /// \param[in] process
- /// The process that owns this thread.
- ///
- /// \param[in] tid
- /// The thread id of this thread.
- ///
- /// \param[in] trace_file
- /// The trace file for this thread.
- ///
- /// \param[in] pt_cpu
- /// The Intel CPU information required to decode the \a trace_file.
- ThreadIntelPT(Process &process, lldb::tid_t tid, const FileSpec &trace_file)
- : Thread(process, tid), m_trace_file(trace_file) {}
-
- void RefreshStateAfterStop() override;
-
- lldb::RegisterContextSP GetRegisterContext() override;
-
- lldb::RegisterContextSP
- CreateRegisterContextForFrame(StackFrame *frame) override;
-
-protected:
- bool CalculateStopInfo() override;
-
- lldb::RegisterContextSP m_thread_reg_ctx_sp;
-
-private:
- FileSpec m_trace_file;
-};
-
-} // namespace trace_intel_pt
-} // namespace lldb_private
-
-#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_THREADINTELPT_H
#include "TraceIntelPTSessionFileParser.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadTrace.h"
using namespace lldb;
using namespace lldb_private;
.Parse();
}
-TraceSP TraceIntelPT::CreateInstance(const pt_cpu &pt_cpu,
- const std::vector<TargetSP> &targets) {
- TraceSP trace_instance(new TraceIntelPT(pt_cpu, targets));
- for (const TargetSP &target_sp : targets)
- target_sp->SetTrace(trace_instance);
-
- return trace_instance;
+TraceIntelPT::TraceIntelPT(
+ const pt_cpu &pt_cpu,
+ const std::vector<std::shared_ptr<ThreadTrace>> &traced_threads)
+ : m_pt_cpu(pt_cpu) {
+ for (const std::shared_ptr<ThreadTrace> &thread : traced_threads)
+ m_trace_threads.emplace(
+ std::make_pair(thread->GetProcess()->GetID(), thread->GetID()), thread);
}
CreateInstance(const llvm::json::Value &trace_session_file,
llvm::StringRef session_file_dir, Debugger &debugger);
- /// Create an instance of this class.
- ///
- /// \param[in] pt_cpu
- /// The libipt.h cpu information needed for decoding correctling the
- /// traces.
- ///
- /// \param[in] targets
- /// The list of targets to associate with this trace instance
- ///
- /// \return
- /// An intel-pt trace instance.
- static lldb::TraceSP
- CreateInstance(const pt_cpu &pt_cpu,
- const std::vector<lldb::TargetSP> &targets);
-
static ConstString GetPluginNameStatic();
uint32_t GetPluginVersion() override;
llvm::StringRef GetSchema() override;
private:
- TraceIntelPT(const pt_cpu &pt_cpu, const std::vector<lldb::TargetSP> &targets)
- : m_pt_cpu(pt_cpu) {
- for (const lldb::TargetSP &target_sp : targets)
- m_targets.push_back(target_sp);
- }
+ friend class TraceIntelPTSessionFileParser;
+
+ /// \param[in] trace_threads
+ /// ThreadTrace instances, which are not live-processes and whose trace
+ /// files are fixed.
+ TraceIntelPT(const pt_cpu &pt_cpu,
+ const std::vector<std::shared_ptr<ThreadTrace>> &traced_threads);
pt_cpu m_pt_cpu;
- std::vector<std::weak_ptr<Target>> m_targets;
+ std::map<std::pair<lldb::pid_t, lldb::tid_t>, std::shared_ptr<ThreadTrace>>
+ m_trace_threads;
};
} // namespace trace_intel_pt
#include "TraceIntelPTSessionFileParser.h"
-#include "ThreadIntelPT.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadList.h"
+#include "lldb/Target/ThreadTrace.h"
using namespace lldb;
using namespace lldb_private;
return schema;
}
-void TraceIntelPTSessionFileParser::ParseThread(
- ProcessSP &process_sp, const TraceSessionFileParser::JSONThread &thread) {
- lldb::tid_t tid = static_cast<lldb::tid_t>(thread.tid);
-
- FileSpec trace_file(thread.trace_file);
- NormalizePath(trace_file);
-
- ThreadSP thread_sp =
- std::make_shared<ThreadIntelPT>(*process_sp, tid, trace_file);
- process_sp->GetThreadList().AddThread(thread_sp);
+pt_cpu TraceIntelPTSessionFileParser::ParsePTCPU(const JSONPTCPU &pt_cpu) {
+ return {pt_cpu.vendor.compare("intel") == 0 ? pcv_intel : pcv_unknown,
+ static_cast<uint16_t>(pt_cpu.family),
+ static_cast<uint8_t>(pt_cpu.model),
+ static_cast<uint8_t>(pt_cpu.stepping)};
}
-Error TraceIntelPTSessionFileParser::ParseProcess(
- const TraceSessionFileParser::JSONProcess &process) {
- TargetSP target_sp;
- Status error = m_debugger.GetTargetList().CreateTarget(
- m_debugger, /*user_exe_path*/ StringRef(), process.triple,
- eLoadDependentsNo,
- /*platform_options*/ nullptr, target_sp);
-
- if (!target_sp)
- return error.ToError();
-
- m_targets.push_back(target_sp);
- m_debugger.GetTargetList().SetSelectedTarget(target_sp.get());
-
- ProcessSP process_sp(target_sp->CreateProcess(
- /*listener*/ nullptr, "trace",
- /*crash_file*/ nullptr));
- process_sp->SetID(static_cast<lldb::pid_t>(process.pid));
+TraceSP TraceIntelPTSessionFileParser::CreateTraceIntelPTInstance(
+ const pt_cpu &pt_cpu, std::vector<ParsedProcess> &parsed_processes) {
+ std::vector<ThreadTraceSP> threads;
+ for (const ParsedProcess &parsed_process : parsed_processes)
+ threads.insert(threads.end(), parsed_process.threads.begin(),
+ parsed_process.threads.end());
- for (const TraceSessionFileParser::JSONThread &thread : process.threads)
- ParseThread(process_sp, thread);
+ TraceSP trace_instance(new TraceIntelPT(pt_cpu, threads));
+ for (const ParsedProcess &parsed_process : parsed_processes)
+ parsed_process.target_sp->SetTrace(trace_instance);
- for (const TraceSessionFileParser::JSONModule &module : process.modules) {
- if (Error err = ParseModule(target_sp, module))
- return err;
- }
-
- if (!process.threads.empty())
- process_sp->GetThreadList().SetSelectedThreadByIndexID(0);
-
- // We invoke DidAttach to create a correct stopped state for the process and
- // its threads.
- ArchSpec process_arch;
- process_sp->DidAttach(process_arch);
-
- return llvm::Error::success();
+ return trace_instance;
}
-void TraceIntelPTSessionFileParser::ParsePTCPU(const JSONPTCPU &pt_cpu) {
- m_pt_cpu = {pt_cpu.vendor.compare("intel") == 0 ? pcv_intel : pcv_unknown,
- static_cast<uint16_t>(pt_cpu.family),
- static_cast<uint8_t>(pt_cpu.model),
- static_cast<uint8_t>(pt_cpu.stepping)};
-}
-
-Error TraceIntelPTSessionFileParser::ParseImpl() {
+Expected<TraceSP> TraceIntelPTSessionFileParser::Parse() {
json::Path::Root root("traceSession");
TraceSessionFileParser::JSONTraceSession<JSONTraceIntelPTSettings> session;
- if (!json::fromJSON(m_trace_session_file, session, root)) {
+ if (!json::fromJSON(m_trace_session_file, session, root))
return CreateJSONError(root, m_trace_session_file);
- }
-
- ParsePTCPU(session.trace.pt_cpu);
- for (const TraceSessionFileParser::JSONProcess &process : session.processes) {
- if (Error err = ParseProcess(process))
- return err;
- }
- return Error::success();
-}
-
-Expected<TraceSP> TraceIntelPTSessionFileParser::Parse() {
- if (Error err = ParseImpl()) {
- // Delete all targets that were created
- for (auto target_sp : m_targets)
- m_debugger.GetTargetList().DeleteTarget(target_sp);
- m_targets.clear();
- return std::move(err);
- }
- return TraceIntelPT::CreateInstance(m_pt_cpu, m_targets);
+ if (Expected<std::vector<ParsedProcess>> parsed_processes =
+ ParseCommonSessionFile(session))
+ return CreateTraceIntelPTInstance(ParsePTCPU(session.trace.pt_cpu),
+ *parsed_processes);
+ else
+ return parsed_processes.takeError();
}
namespace llvm {
#ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTSESSIONFILEPARSER_H
#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTSESSIONFILEPARSER_H
-#include "intel-pt.h"
-
#include "TraceIntelPT.h"
#include "lldb/Target/TraceSessionFileParser.h"
TraceIntelPTSessionFileParser(Debugger &debugger,
const llvm::json::Value &trace_session_file,
llvm::StringRef session_file_dir)
- : TraceSessionFileParser(session_file_dir, GetSchema()),
- m_debugger(debugger), m_trace_session_file(trace_session_file) {}
+ : TraceSessionFileParser(debugger, session_file_dir, GetSchema()),
+ m_trace_session_file(trace_session_file) {}
/// \return
/// The JSON schema for the session data.
/// errors, return a null pointer.
llvm::Expected<lldb::TraceSP> Parse();
-private:
- llvm::Error ParseImpl();
-
- llvm::Error ParseProcess(const TraceSessionFileParser::JSONProcess &process);
+ lldb::TraceSP
+ CreateTraceIntelPTInstance(const pt_cpu &pt_cpu,
+ std::vector<ParsedProcess> &parsed_processes);
- void ParseThread(lldb::ProcessSP &process_sp,
- const TraceSessionFileParser::JSONThread &thread);
-
- void ParsePTCPU(const JSONPTCPU &pt_cpu);
+private:
+ pt_cpu ParsePTCPU(const JSONPTCPU &pt_cpu);
- Debugger &m_debugger;
const llvm::json::Value &m_trace_session_file;
-
- /// Objects created as product of the parsing
- /// \{
- pt_cpu m_pt_cpu;
- std::vector<lldb::TargetSP> m_targets;
- /// \}
};
} // namespace trace_intel_pt
PathMappingList.cpp
Platform.cpp
Process.cpp
+ ProcessTrace.cpp
Queue.cpp
QueueItem.cpp
QueueList.cpp
ThreadPlanTracer.cpp
ThreadPlanStack.cpp
ThreadSpec.cpp
+ ThreadTrace.cpp
Trace.cpp
TraceSessionFileParser.cpp
UnixSignals.cpp
//
//===----------------------------------------------------------------------===//
-#include "ProcessTrace.h"
+#include "lldb/Target/ProcessTrace.h"
#include <memory>
using namespace lldb;
using namespace lldb_private;
-using namespace lldb_private::process_trace;
-
-LLDB_PLUGIN_DEFINE(ProcessTrace)
ConstString ProcessTrace::GetPluginNameStatic() {
static ConstString g_name("trace");
-//===-- ThreadIntelPT.cpp -------------------------------------------------===//
+//===-- ThreadTrace.cpp ---------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
//
//===----------------------------------------------------------------------===//
-#include "ThreadIntelPT.h"
+#include "lldb/Target/ThreadTrace.h"
#include <memory>
using namespace lldb;
using namespace lldb_private;
-using namespace lldb_private::trace_intel_pt;
-void ThreadIntelPT::RefreshStateAfterStop() {}
+void ThreadTrace::RefreshStateAfterStop() {}
-RegisterContextSP ThreadIntelPT::GetRegisterContext() {
+RegisterContextSP ThreadTrace::GetRegisterContext() {
if (!m_reg_context_sp)
m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
}
RegisterContextSP
-ThreadIntelPT::CreateRegisterContextForFrame(StackFrame *frame) {
+ThreadTrace::CreateRegisterContextForFrame(StackFrame *frame) {
// Eventually this will calculate the register context based on the current
// trace position.
return std::make_shared<RegisterContextHistory>(
*this, 0, GetProcess()->GetAddressByteSize(), LLDB_INVALID_ADDRESS);
}
-bool ThreadIntelPT::CalculateStopInfo() { return false; }
+bool ThreadTrace::CalculateStopInfo() { return false; }
+
+const FileSpec &ThreadTrace::GetTraceFile() const { return m_trace_file; }
#include <sstream>
+#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadTrace.h"
using namespace lldb;
using namespace lldb_private;
return schema_builder.str();
}
+ThreadTraceSP TraceSessionFileParser::ParseThread(ProcessSP &process_sp,
+ const JSONThread &thread) {
+ lldb::tid_t tid = static_cast<lldb::tid_t>(thread.tid);
+
+ FileSpec trace_file(thread.trace_file);
+ NormalizePath(trace_file);
+
+ ThreadTraceSP thread_sp =
+ std::make_shared<ThreadTrace>(*process_sp, tid, trace_file);
+ process_sp->GetThreadList().AddThread(thread_sp);
+ return thread_sp;
+}
+
+Expected<TraceSessionFileParser::ParsedProcess>
+TraceSessionFileParser::ParseProcess(const JSONProcess &process) {
+ TargetSP target_sp;
+ Status error = m_debugger.GetTargetList().CreateTarget(
+ m_debugger, /*user_exe_path*/ StringRef(), process.triple,
+ eLoadDependentsNo,
+ /*platform_options*/ nullptr, target_sp);
+
+ if (!target_sp)
+ return error.ToError();
+
+ ParsedProcess parsed_process;
+ parsed_process.target_sp = target_sp;
+
+ m_debugger.GetTargetList().SetSelectedTarget(target_sp.get());
+
+ ProcessSP process_sp = target_sp->CreateProcess(
+ /*listener*/ nullptr, "trace",
+ /*crash_file*/ nullptr);
+
+ process_sp->SetID(static_cast<lldb::pid_t>(process.pid));
+
+ for (const JSONThread &thread : process.threads)
+ parsed_process.threads.push_back(ParseThread(process_sp, thread));
+
+ for (const JSONModule &module : process.modules)
+ if (Error err = ParseModule(target_sp, module))
+ return std::move(err);
+
+ if (!process.threads.empty())
+ process_sp->GetThreadList().SetSelectedThreadByIndexID(0);
+
+ // We invoke DidAttach to create a correct stopped state for the process and
+ // its threads.
+ ArchSpec process_arch;
+ process_sp->DidAttach(process_arch);
+
+ return parsed_process;
+}
+
+Expected<std::vector<TraceSessionFileParser::ParsedProcess>>
+TraceSessionFileParser::ParseCommonSessionFile(
+ const JSONTraceSessionBase &session) {
+ std::vector<ParsedProcess> parsed_processes;
+
+ auto onError = [&]() {
+ // Delete all targets that were created so far in case of failures
+ for (ParsedProcess &parsed_process : parsed_processes)
+ m_debugger.GetTargetList().DeleteTarget(parsed_process.target_sp);
+ };
+
+ for (const JSONProcess &process : session.processes) {
+ if (Expected<ParsedProcess> parsed_process = ParseProcess(process))
+ parsed_processes.push_back(std::move(*parsed_process));
+ else {
+ onError();
+ return parsed_process.takeError();
+ }
+ }
+ return parsed_processes;
+}
+
namespace llvm {
namespace json {
return o && o.map("type", plugin_settings.type);
}
+bool fromJSON(const Value &value,
+ TraceSessionFileParser::JSONTraceSessionBase &session,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("processes", session.processes);
+}
+
} // namespace json
} // namespace llvm