[trace] rename ThreadIntelPT into TraceTrace

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
This commit is contained in:
Walter Erquinigo 2020-10-14 10:25:39 -07:00
parent 8a377f1e3c
commit 8a203bb22d
17 changed files with 268 additions and 217 deletions

View File

@ -6,22 +6,17 @@
//
//===----------------------------------------------------------------------===//
#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();
@ -78,9 +73,13 @@ protected:
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

View File

@ -0,0 +1,61 @@
//===-- 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

View File

@ -11,7 +11,7 @@
#include "llvm/Support/JSON.h"
#include "lldb/lldb-private.h"
#include "lldb/Target/ThreadTrace.h"
namespace lldb_private {
@ -53,17 +53,28 @@ public:
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.
///
@ -75,11 +86,28 @@ public:
/// 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
@ -96,6 +124,7 @@ protected:
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;
};
@ -125,6 +154,11 @@ bool fromJSON(const Value &value,
&plugin_settings,
Path path);
bool fromJSON(
const Value &value,
lldb_private::TraceSessionFileParser::JSONTraceSessionBase &session,
Path path);
template <class TPluginSettings>
bool fromJSON(
const Value &value,
@ -133,7 +167,10 @@ bool fromJSON(
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

View File

@ -226,6 +226,7 @@ class ThreadPlanStepRange;
class ThreadPlanStepThrough;
class ThreadPlanTracer;
class ThreadSpec;
class ThreadTrace;
class Trace;
class TraceSessionFileParser;
class TraceOptions;

View File

@ -14,6 +14,7 @@
#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"
@ -45,6 +46,9 @@ llvm::Error SystemInitializerFull::Initialize() {
#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();
@ -61,6 +65,9 @@ void SystemInitializerFull::Terminate() {
Debugger::SettingsTerminate();
// Terminate plug-ins in core LLDB
ProcessTrace::Terminate();
// Terminate and unload and loaded system or user LLDB plug-ins
PluginManager::Terminate();

View File

@ -18,4 +18,3 @@ add_subdirectory(Utility)
add_subdirectory(elf-core)
add_subdirectory(mach-core)
add_subdirectory(minidump)
add_subdirectory(Trace)

View File

@ -1,13 +0,0 @@
add_lldb_library(lldbPluginProcessTrace PLUGIN
ProcessTrace.cpp
LINK_LIBS
lldbCore
lldbTarget
lldbUtility
lldbPluginProcessUtility
LINK_COMPONENTS
BinaryFormat
Object
Support
)

View File

@ -12,7 +12,6 @@ find_library(LIBIPT_LIBRARY ipt PATHS ${LIBIPT_LIBRARY_PATH} REQUIRED)
add_lldb_library(lldbPluginTraceIntelPT PLUGIN
TraceIntelPT.cpp
TraceIntelPTSessionFileParser.cpp
ThreadIntelPT.cpp
LINK_LIBS
lldbCore

View File

@ -1,54 +0,0 @@
//===-- 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

View File

@ -10,7 +10,9 @@
#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;
@ -56,11 +58,11 @@ TraceIntelPT::CreateInstance(const json::Value &trace_session_file,
.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);
}

View File

@ -52,21 +52,6 @@ public:
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;
@ -75,14 +60,17 @@ public:
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

View File

@ -8,10 +8,11 @@
#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;
@ -34,88 +35,39 @@ StringRef TraceIntelPTSessionFileParser::GetSchema() {
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);
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());
if (!target_sp)
return error.ToError();
TraceSP trace_instance(new TraceIntelPT(pt_cpu, threads));
for (const ParsedProcess &parsed_process : parsed_processes)
parsed_process.target_sp->SetTrace(trace_instance);
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));
for (const TraceSessionFileParser::JSONThread &thread : process.threads)
ParseThread(process_sp, thread);
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();
}
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() {
json::Path::Root root("traceSession");
TraceSessionFileParser::JSONTraceSession<JSONTraceIntelPTSettings> session;
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();
return trace_instance;
}
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);
}
json::Path::Root root("traceSession");
TraceSessionFileParser::JSONTraceSession<JSONTraceIntelPTSettings> session;
if (!json::fromJSON(m_trace_session_file, session, root))
return CreateJSONError(root, m_trace_session_file);
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 {

View File

@ -9,8 +9,6 @@
#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"
@ -38,8 +36,8 @@ public:
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.
@ -53,24 +51,14 @@ public:
/// errors, return a null pointer.
llvm::Expected<lldb::TraceSP> Parse();
lldb::TraceSP
CreateTraceIntelPTInstance(const pt_cpu &pt_cpu,
std::vector<ParsedProcess> &parsed_processes);
private:
llvm::Error ParseImpl();
pt_cpu ParsePTCPU(const JSONPTCPU &pt_cpu);
llvm::Error ParseProcess(const TraceSessionFileParser::JSONProcess &process);
void ParseThread(lldb::ProcessSP &process_sp,
const TraceSessionFileParser::JSONThread &thread);
void 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

View File

@ -24,6 +24,7 @@ add_lldb_library(lldbTarget
PathMappingList.cpp
Platform.cpp
Process.cpp
ProcessTrace.cpp
Queue.cpp
QueueItem.cpp
QueueList.cpp
@ -65,6 +66,7 @@ add_lldb_library(lldbTarget
ThreadPlanTracer.cpp
ThreadPlanStack.cpp
ThreadSpec.cpp
ThreadTrace.cpp
Trace.cpp
TraceSessionFileParser.cpp
UnixSignals.cpp

View File

@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
#include "ProcessTrace.h"
#include "lldb/Target/ProcessTrace.h"
#include <memory>
@ -16,9 +16,6 @@
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");

View File

@ -1,4 +1,4 @@
//===-- 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.
@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
#include "ThreadIntelPT.h"
#include "lldb/Target/ThreadTrace.h"
#include <memory>
@ -16,11 +16,10 @@
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);
@ -28,11 +27,13 @@ RegisterContextSP ThreadIntelPT::GetRegisterContext() {
}
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; }

View File

@ -10,8 +10,11 @@
#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;
@ -87,6 +90,81 @@ std::string TraceSessionFileParser::BuildSchema(StringRef plugin_schema) {
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 {
@ -129,5 +207,12 @@ bool fromJSON(const Value &value,
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