From 8a203bb22d161d23c6b1195f85ae025e87f03bae Mon Sep 17 00:00:00 2001 From: Walter Erquinigo Date: Wed, 14 Oct 2020 10:25:39 -0700 Subject: [PATCH] [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 --- .../Trace => include/lldb/Target}/ProcessTrace.h | 17 ++-- lldb/include/lldb/Target/ThreadTrace.h | 61 ++++++++++++++ lldb/include/lldb/Target/TraceSessionFileParser.h | 49 +++++++++-- lldb/include/lldb/lldb-forward.h | 1 + lldb/source/API/SystemInitializerFull.cpp | 7 ++ lldb/source/Plugins/Process/CMakeLists.txt | 1 - lldb/source/Plugins/Process/Trace/CMakeLists.txt | 13 --- lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt | 1 - lldb/source/Plugins/Trace/intel-pt/ThreadIntelPT.h | 54 ------------ .../source/Plugins/Trace/intel-pt/TraceIntelPT.cpp | 16 ++-- lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h | 30 ++----- .../intel-pt/TraceIntelPTSessionFileParser.cpp | 98 ++++++---------------- .../Trace/intel-pt/TraceIntelPTSessionFileParser.h | 26 ++---- lldb/source/Target/CMakeLists.txt | 2 + .../Process/Trace => Target}/ProcessTrace.cpp | 5 +- .../ThreadIntelPT.cpp => Target/ThreadTrace.cpp} | 15 ++-- lldb/source/Target/TraceSessionFileParser.cpp | 85 +++++++++++++++++++ 17 files changed, 266 insertions(+), 215 deletions(-) rename lldb/{source/Plugins/Process/Trace => include/lldb/Target}/ProcessTrace.h (90%) create mode 100644 lldb/include/lldb/Target/ThreadTrace.h delete mode 100644 lldb/source/Plugins/Process/Trace/CMakeLists.txt delete mode 100644 lldb/source/Plugins/Trace/intel-pt/ThreadIntelPT.h rename lldb/source/{Plugins/Process/Trace => Target}/ProcessTrace.cpp (97%) rename lldb/source/{Plugins/Trace/intel-pt/ThreadIntelPT.cpp => Target/ThreadTrace.cpp} (68%) diff --git a/lldb/source/Plugins/Process/Trace/ProcessTrace.h b/lldb/include/lldb/Target/ProcessTrace.h similarity index 90% rename from lldb/source/Plugins/Process/Trace/ProcessTrace.h rename to lldb/include/lldb/Target/ProcessTrace.h index 450aa1e..d5a052c 100644 --- a/lldb/source/Plugins/Process/Trace/ProcessTrace.h +++ b/lldb/include/lldb/Target/ProcessTrace.h @@ -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 diff --git a/lldb/include/lldb/Target/ThreadTrace.h b/lldb/include/lldb/Target/ThreadTrace.h new file mode 100644 index 0000000..a32b338 --- /dev/null +++ b/lldb/include/lldb/Target/ThreadTrace.h @@ -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 ThreadTraceSP; + +} // namespace lldb_private + +#endif // LLDB_TARGET_THREADTRACE_H diff --git a/lldb/include/lldb/Target/TraceSessionFileParser.h b/lldb/include/lldb/Target/TraceSessionFileParser.h index 4bcce9d..52cc27c 100644 --- a/lldb/include/lldb/Target/TraceSessionFileParser.h +++ b/lldb/include/lldb/Target/TraceSessionFileParser.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 processes; + }; + /// The trace plug-in implementation should provide its own TPluginSettings, /// which corresponds to the "trace" section of the schema. - template struct JSONTraceSession { - std::vector processes; + template + 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 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> + 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 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 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 diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index d7f476a..a297a92 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -226,6 +226,7 @@ class ThreadPlanStepRange; class ThreadPlanStepThrough; class ThreadPlanTracer; class ThreadSpec; +class ThreadTrace; class Trace; class TraceSessionFileParser; class TraceOptions; diff --git a/lldb/source/API/SystemInitializerFull.cpp b/lldb/source/API/SystemInitializerFull.cpp index 7f95e7a..a9723f7 100644 --- a/lldb/source/API/SystemInitializerFull.cpp +++ b/lldb/source/API/SystemInitializerFull.cpp @@ -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(); diff --git a/lldb/source/Plugins/Process/CMakeLists.txt b/lldb/source/Plugins/Process/CMakeLists.txt index a028793..91f20ec 100644 --- a/lldb/source/Plugins/Process/CMakeLists.txt +++ b/lldb/source/Plugins/Process/CMakeLists.txt @@ -18,4 +18,3 @@ add_subdirectory(Utility) add_subdirectory(elf-core) add_subdirectory(mach-core) add_subdirectory(minidump) -add_subdirectory(Trace) diff --git a/lldb/source/Plugins/Process/Trace/CMakeLists.txt b/lldb/source/Plugins/Process/Trace/CMakeLists.txt deleted file mode 100644 index 10a5c60..0000000 --- a/lldb/source/Plugins/Process/Trace/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -add_lldb_library(lldbPluginProcessTrace PLUGIN - ProcessTrace.cpp - - LINK_LIBS - lldbCore - lldbTarget - lldbUtility - lldbPluginProcessUtility - LINK_COMPONENTS - BinaryFormat - Object - Support - ) diff --git a/lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt b/lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt index 5b30919..fabdb39 100644 --- a/lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt +++ b/lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt @@ -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 diff --git a/lldb/source/Plugins/Trace/intel-pt/ThreadIntelPT.h b/lldb/source/Plugins/Trace/intel-pt/ThreadIntelPT.h deleted file mode 100644 index ad6b772..0000000 --- a/lldb/source/Plugins/Trace/intel-pt/ThreadIntelPT.h +++ /dev/null @@ -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 diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp index e2b2467..ef45fdd 100644 --- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp +++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp @@ -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 &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> &traced_threads) + : m_pt_cpu(pt_cpu) { + for (const std::shared_ptr &thread : traced_threads) + m_trace_threads.emplace( + std::make_pair(thread->GetProcess()->GetID(), thread->GetID()), thread); } diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h index bf34d89..39f3db4 100644 --- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h +++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h @@ -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 &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 &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> &traced_threads); pt_cpu m_pt_cpu; - std::vector> m_targets; + std::map, std::shared_ptr> + m_trace_threads; }; } // namespace trace_intel_pt diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp index 4b43900..beef5c3 100644 --- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp +++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp @@ -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(thread.tid); - - FileSpec trace_file(thread.trace_file); - NormalizePath(trace_file); - - ThreadSP thread_sp = - std::make_shared(*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(pt_cpu.family), + static_cast(pt_cpu.model), + static_cast(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(process.pid)); +TraceSP TraceIntelPTSessionFileParser::CreateTraceIntelPTInstance( + const pt_cpu &pt_cpu, std::vector &parsed_processes) { + std::vector 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(pt_cpu.family), - static_cast(pt_cpu.model), - static_cast(pt_cpu.stepping)}; -} - -Error TraceIntelPTSessionFileParser::ParseImpl() { +Expected TraceIntelPTSessionFileParser::Parse() { json::Path::Root root("traceSession"); TraceSessionFileParser::JSONTraceSession 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 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> parsed_processes = + ParseCommonSessionFile(session)) + return CreateTraceIntelPTInstance(ParsePTCPU(session.trace.pt_cpu), + *parsed_processes); + else + return parsed_processes.takeError(); } namespace llvm { diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h index 64f6200..6a896de 100644 --- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h +++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h @@ -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 Parse(); -private: - llvm::Error ParseImpl(); - - llvm::Error ParseProcess(const TraceSessionFileParser::JSONProcess &process); + lldb::TraceSP + CreateTraceIntelPTInstance(const pt_cpu &pt_cpu, + std::vector &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 m_targets; - /// \} }; } // namespace trace_intel_pt diff --git a/lldb/source/Target/CMakeLists.txt b/lldb/source/Target/CMakeLists.txt index 8374fcc..383ac5a 100644 --- a/lldb/source/Target/CMakeLists.txt +++ b/lldb/source/Target/CMakeLists.txt @@ -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 diff --git a/lldb/source/Plugins/Process/Trace/ProcessTrace.cpp b/lldb/source/Target/ProcessTrace.cpp similarity index 97% rename from lldb/source/Plugins/Process/Trace/ProcessTrace.cpp rename to lldb/source/Target/ProcessTrace.cpp index f727336..768df0b 100644 --- a/lldb/source/Plugins/Process/Trace/ProcessTrace.cpp +++ b/lldb/source/Target/ProcessTrace.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "ProcessTrace.h" +#include "lldb/Target/ProcessTrace.h" #include @@ -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"); diff --git a/lldb/source/Plugins/Trace/intel-pt/ThreadIntelPT.cpp b/lldb/source/Target/ThreadTrace.cpp similarity index 68% rename from lldb/source/Plugins/Trace/intel-pt/ThreadIntelPT.cpp rename to lldb/source/Target/ThreadTrace.cpp index 0565001..346f36a 100644 --- a/lldb/source/Plugins/Trace/intel-pt/ThreadIntelPT.cpp +++ b/lldb/source/Target/ThreadTrace.cpp @@ -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 @@ -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( *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; } diff --git a/lldb/source/Target/TraceSessionFileParser.cpp b/lldb/source/Target/TraceSessionFileParser.cpp index d164d1f..41fc35c 100644 --- a/lldb/source/Target/TraceSessionFileParser.cpp +++ b/lldb/source/Target/TraceSessionFileParser.cpp @@ -10,8 +10,11 @@ #include +#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(thread.tid); + + FileSpec trace_file(thread.trace_file); + NormalizePath(trace_file); + + ThreadTraceSP thread_sp = + std::make_shared(*process_sp, tid, trace_file); + process_sp->GetThreadList().AddThread(thread_sp); + return thread_sp; +} + +Expected +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(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> +TraceSessionFileParser::ParseCommonSessionFile( + const JSONTraceSessionBase &session) { + std::vector 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 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 -- 2.7.4