mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-10-09 12:24:08 +00:00
[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:
parent
8a377f1e3c
commit
8a203bb22d
@ -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
|
61
lldb/include/lldb/Target/ThreadTrace.h
Normal file
61
lldb/include/lldb/Target/ThreadTrace.h
Normal 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
|
@ -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
|
||||
|
@ -226,6 +226,7 @@ class ThreadPlanStepRange;
|
||||
class ThreadPlanStepThrough;
|
||||
class ThreadPlanTracer;
|
||||
class ThreadSpec;
|
||||
class ThreadTrace;
|
||||
class Trace;
|
||||
class TraceSessionFileParser;
|
||||
class TraceOptions;
|
||||
|
@ -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();
|
||||
|
||||
|
@ -18,4 +18,3 @@ add_subdirectory(Utility)
|
||||
add_subdirectory(elf-core)
|
||||
add_subdirectory(mach-core)
|
||||
add_subdirectory(minidump)
|
||||
add_subdirectory(Trace)
|
||||
|
@ -1,13 +0,0 @@
|
||||
add_lldb_library(lldbPluginProcessTrace PLUGIN
|
||||
ProcessTrace.cpp
|
||||
|
||||
LINK_LIBS
|
||||
lldbCore
|
||||
lldbTarget
|
||||
lldbUtility
|
||||
lldbPluginProcessUtility
|
||||
LINK_COMPONENTS
|
||||
BinaryFormat
|
||||
Object
|
||||
Support
|
||||
)
|
@ -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
|
||||
|
@ -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
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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");
|
@ -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; }
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user