wallace created this revision.
wallace added reviewers: clayborg, labath.
Herald added subscribers: lldb-commits, dang, mgorny.
Herald added a reviewer: JDevlieghere.
Herald added a project: LLDB.
wallace requested review of this revision.
As per the discussion in the RFC, we'll implement both
thread thread dump [instructions | functions]
This is the first step in implementing the "instructions" dumping command.
It includes:
- A minimal ProcessTrace plugin for representing processes from a trace file. I
noticed that it was a required step to mimic how core-based processes are
initialized, e.g. ProcessElfCore and ProcessMinidump. I haven't had the need to
create ThreadTrace yet, though. So far HistoryThread seems good enough.
- The command handling itself in CommandObjectThread, which outputs a
placeholder text instead of the actual instructions. I'll do that part in the
next diff.
- Tests
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D88769
Files:
lldb/include/lldb/Target/Target.h
lldb/include/lldb/Target/Trace.h
lldb/source/Commands/CommandObjectThread.cpp
lldb/source/Commands/Options.td
lldb/source/Plugins/Process/CMakeLists.txt
lldb/source/Plugins/Process/Trace/CMakeLists.txt
lldb/source/Plugins/Process/Trace/ProcessTrace.cpp
lldb/source/Plugins/Process/Trace/ProcessTrace.h
lldb/source/Plugins/Process/Utility/HistoryThread.cpp
lldb/source/Plugins/Process/Utility/HistoryThread.h
lldb/source/Target/Target.cpp
lldb/source/Target/Trace.cpp
lldb/source/Target/TraceSettingsParser.cpp
lldb/test/API/commands/trace/TestTraceDumpInstructions.py
lldb/test/API/commands/trace/TestTraceLoad.py
Index: lldb/test/API/commands/trace/TestTraceLoad.py
===================================================================
--- lldb/test/API/commands/trace/TestTraceLoad.py
+++ lldb/test/API/commands/trace/TestTraceLoad.py
@@ -35,6 +35,10 @@
self.assertEqual("6AA9A4E2-6F28-2F33-377D-59FECE874C71-5B41261A", module.GetUUIDString())
+ # check that the Process and Thread objects were created correctly
+ self.expect("thread info", substrs=["tid = 3842849"])
+ self.expect("thread list", substrs=["Process 1234 stopped", "tid = 3842849"])
+
def testLoadInvalidTraces(self):
src_dir = self.getSourceDir()
Index: lldb/test/API/commands/trace/TestTraceDumpInstructions.py
===================================================================
--- /dev/null
+++ lldb/test/API/commands/trace/TestTraceDumpInstructions.py
@@ -0,0 +1,49 @@
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+from lldbsuite.test.decorators import *
+
+class TestTraceDumpInstructions(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def setUp(self):
+ TestBase.setUp(self)
+ if 'intel-pt' not in configuration.enabled_plugins:
+ self.skipTest("The intel-pt test plugin is not enabled")
+
+ def testErrorMessages(self):
+ # We first check the output when there are no targets
+ self.expect("thread trace dump instructions",
+ substrs=["error: invalid target, create a target using the 'target create' command"],
+ error=True)
+
+ # We now check the output when there's a non-running target
+ self.expect("target create " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out"))
+
+ self.expect("thread trace dump instructions",
+ substrs=["error: invalid process"],
+ error=True)
+
+ # Now we check the output when there's a running target without a trace
+ self.expect("b main")
+ self.expect("r")
+
+ self.expect("thread trace dump instructions",
+ substrs=["error: no trace in this target"])
+
+ def testDumpInstructions(self):
+ self.expect("trace load -v " + os.path.join(self.getSourceDir(), "intelpt-trace", "trace.json"),
+ substrs=["intel-pt"])
+
+ self.expect("thread trace dump instructions",
+ substrs=['placeholder trace of tid 3842849, count = 10, offset = 0'])
+
+ # We check if we can pass count and offset
+ self.expect("thread trace dump instructions -c 5 -o 10",
+ substrs=['placeholder trace of tid 3842849, count = 5, offset = 10'])
+
+ # We check if we can access the thread by index id
+ self.expect("thread trace dump instructions 1",
+ substrs=['placeholder trace of tid 3842849, count = 10, offset = 0'])
Index: lldb/source/Target/TraceSettingsParser.cpp
===================================================================
--- lldb/source/Target/TraceSettingsParser.cpp
+++ lldb/source/Target/TraceSettingsParser.cpp
@@ -65,7 +65,12 @@
NormalizePath(spec);
m_thread_to_trace_file_map[process_sp->GetID()][tid] = spec;
- ThreadSP thread_sp(new HistoryThread(*process_sp, tid, /*callstack*/ {}));
+ // For now we are setting an invalid PC. Eventually we should be able to
+ // lazyly reconstruct this callstack after decoding the trace.
+ ThreadSP thread_sp(new HistoryThread(*process_sp, tid,
+ /*callstack*/ {LLDB_INVALID_ADDRESS},
+ /*pcs_are_call_addresses*/ false,
+ /*use_invalid_index_id*/ false));
process_sp->GetThreadList().AddThread(thread_sp);
}
@@ -107,8 +112,7 @@
debugger.GetTargetList().SetSelectedTarget(target_sp.get());
ProcessSP process_sp(target_sp->CreateProcess(
- /*listener*/ nullptr, /*plugin_name*/ llvm::StringRef(),
- /*crash_file*/ nullptr));
+ /*listener*/ nullptr, /*plugin_name*/ "trace", /*crash_file*/ nullptr));
process_sp->SetID(static_cast<lldb::pid_t>(process.pid));
for (const JSONThread &thread : process.threads)
@@ -118,6 +122,15 @@
if (llvm::Error err = ParseModule(target_sp, module))
return err;
}
+ if (!process.threads.empty())
+ process_sp->GetThreadList().SetSelectedThreadByIndexID(0);
+
+ // We invoke LoadCore to create a correct stopped state for the process and
+ // its threads
+ error = process_sp->LoadCore();
+ if (error.Fail())
+ return error.ToError();
+
return llvm::Error::success();
}
@@ -166,10 +179,10 @@
return err;
}
- m_trace.m_settings = *raw_settings.getAsObject();
- m_trace.m_settings_dir = m_settings_dir;
+ for (auto target_sp : m_targets)
+ target_sp->SetTrace(m_trace.shared_from_this());
+
m_trace.m_thread_to_trace_file_map = m_thread_to_trace_file_map;
- m_trace.m_targets = m_targets;
return llvm::Error::success();
}
Index: lldb/source/Target/Trace.cpp
===================================================================
--- lldb/source/Target/Trace.cpp
+++ lldb/source/Target/Trace.cpp
@@ -85,11 +85,7 @@
llvm::Error Trace::ParseSettings(Debugger &debugger,
const llvm::json::Value &settings,
llvm::StringRef settings_dir) {
- if (llvm::Error err =
- CreateParser()->ParseSettings(debugger, settings, settings_dir))
- return err;
-
- return llvm::Error::success();
+ return CreateParser()->ParseSettings(debugger, settings, settings_dir);
}
llvm::StringRef Trace::GetSchema() { return CreateParser()->GetSchema(); }
Index: lldb/source/Target/Target.cpp
===================================================================
--- lldb/source/Target/Target.cpp
+++ lldb/source/Target/Target.cpp
@@ -2965,6 +2965,20 @@
return error;
}
+void Target::SetTrace(const lldb::TraceSP &trace_sp) { m_trace_sp = trace_sp; }
+
+lldb::TraceSP &Target::GetTrace() { return m_trace_sp; }
+
+void Target::DumpTraceInstructions(Stream &s, lldb::tid_t tid, size_t count,
+ size_t offset) const {
+ if (!m_trace_sp) {
+ s << "error: no trace in this target";
+ return;
+ }
+ s.Printf("placeholder trace of tid %" PRIu64 ", count = %zu, offset = %zu\n",
+ tid, count, offset);
+}
+
Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) {
auto state = eStateInvalid;
auto process_sp = GetProcessSP();
Index: lldb/source/Plugins/Process/Utility/HistoryThread.h
===================================================================
--- lldb/source/Plugins/Process/Utility/HistoryThread.h
+++ lldb/source/Plugins/Process/Utility/HistoryThread.h
@@ -34,7 +34,8 @@
public:
HistoryThread(lldb_private::Process &process, lldb::tid_t tid,
std::vector<lldb::addr_t> pcs,
- bool pcs_are_call_addresses = false);
+ bool pcs_are_call_addresses = false,
+ bool use_invalid_index_id = true);
~HistoryThread() override;
Index: lldb/source/Plugins/Process/Utility/HistoryThread.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/HistoryThread.cpp
+++ lldb/source/Plugins/Process/Utility/HistoryThread.cpp
@@ -26,10 +26,11 @@
HistoryThread::HistoryThread(lldb_private::Process &process, lldb::tid_t tid,
std::vector<lldb::addr_t> pcs,
- bool pcs_are_call_addresses)
- : Thread(process, tid, true), m_framelist_mutex(), m_framelist(),
- m_pcs(pcs), m_extended_unwind_token(LLDB_INVALID_ADDRESS), m_queue_name(),
- m_thread_name(), m_originating_unique_thread_id(tid),
+ bool pcs_are_call_addresses,
+ bool use_invalid_index_id)
+ : Thread(process, tid, use_invalid_index_id), m_framelist_mutex(),
+ m_framelist(), m_pcs(pcs), m_extended_unwind_token(LLDB_INVALID_ADDRESS),
+ m_queue_name(), m_thread_name(), m_originating_unique_thread_id(tid),
m_queue_id(LLDB_INVALID_QUEUE_ID) {
m_unwinder_up =
std::make_unique<HistoryUnwind>(*this, pcs, pcs_are_call_addresses);
Index: lldb/source/Plugins/Process/Trace/ProcessTrace.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/Trace/ProcessTrace.h
@@ -0,0 +1,82 @@
+//===-- ProcessTrace.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_PROCESS_TRACE_PROCESSTRACE_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_TRACE_PROCESSTRACE_H
+
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Status.h"
+
+struct ThreadData;
+
+class ProcessTrace : public lldb_private::Process {
+public:
+ static lldb::ProcessSP
+ CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
+ const lldb_private::FileSpec *crash_file_path);
+
+ static void Initialize();
+
+ static void Terminate();
+
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ ProcessTrace(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp);
+
+ ~ProcessTrace() override;
+
+ bool CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) override;
+
+ lldb_private::Status DoLoadCore() override;
+
+ lldb_private::DynamicLoader *GetDynamicLoader() override { return nullptr; }
+
+ lldb_private::SystemRuntime *GetSystemRuntime() override { return nullptr; }
+
+ lldb_private::ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+ lldb_private::Status DoDestroy() override;
+
+ void RefreshStateAfterStop() override;
+
+ lldb_private::Status WillResume() override {
+ lldb_private::Status error;
+ error.SetErrorStringWithFormat(
+ "error: %s does not support resuming processes",
+ GetPluginName().GetCString());
+ return error;
+ }
+
+ bool IsAlive() override;
+
+ bool WarnBeforeDetach() const override { return false; }
+
+ size_t ReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ lldb_private::Status &error) override;
+
+ size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ lldb_private::Status &error) override;
+
+ lldb_private::ArchSpec GetArchitecture();
+
+ bool GetProcessInfo(lldb_private::ProcessInstanceInfo &info) override;
+
+protected:
+ void Clear();
+
+ bool UpdateThreadList(lldb_private::ThreadList &old_thread_list,
+ lldb_private::ThreadList &new_thread_list) override;
+};
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_TRACE_PROCESSTRACE_H
Index: lldb/source/Plugins/Process/Trace/ProcessTrace.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/Trace/ProcessTrace.cpp
@@ -0,0 +1,116 @@
+//===-- ProcessTrace.cpp --------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "ProcessTrace.h"
+
+#include <memory>
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb_private;
+
+LLDB_PLUGIN_DEFINE(ProcessTrace)
+
+ConstString ProcessTrace::GetPluginNameStatic() {
+ static ConstString g_name("trace");
+ return g_name;
+}
+
+const char *ProcessTrace::GetPluginDescriptionStatic() {
+ return "Trace process plug-in.";
+}
+
+void ProcessTrace::Terminate() {
+ PluginManager::UnregisterPlugin(ProcessTrace::CreateInstance);
+}
+
+lldb::ProcessSP ProcessTrace::CreateInstance(lldb::TargetSP target_sp,
+ lldb::ListenerSP listener_sp,
+ const FileSpec *crash_file) {
+ return std::make_shared<ProcessTrace>(target_sp, listener_sp);
+}
+
+bool ProcessTrace::CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) {
+ return true;
+}
+
+ProcessTrace::ProcessTrace(lldb::TargetSP target_sp,
+ lldb::ListenerSP listener_sp)
+ : Process(target_sp, listener_sp) {}
+
+ProcessTrace::~ProcessTrace() {
+ Clear();
+ // We need to call finalize on the process before destroying ourselves to
+ // make sure all of the broadcaster cleanup goes as planned. If we destruct
+ // this class, then Process::~Process() might have problems trying to fully
+ // destroy the broadcaster.
+ Finalize();
+}
+
+ConstString ProcessTrace::GetPluginName() { return GetPluginNameStatic(); }
+
+uint32_t ProcessTrace::GetPluginVersion() { return 1; }
+
+Status ProcessTrace::DoLoadCore() {
+ SetCanJIT(false);
+ return Status();
+}
+
+bool ProcessTrace::UpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list) {
+ return false;
+}
+
+void ProcessTrace::RefreshStateAfterStop() {}
+
+Status ProcessTrace::DoDestroy() { return Status(); }
+
+bool ProcessTrace::IsAlive() { return true; }
+
+size_t ProcessTrace::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ Status &error) {
+ // Don't allow the caching that lldb_private::Process::ReadMemory does since
+ // we have it all cached in the trace files.
+ return DoReadMemory(addr, buf, size, error);
+}
+
+void ProcessTrace::Clear() { m_thread_list.Clear(); }
+
+void ProcessTrace::Initialize() {
+ static llvm::once_flag g_once_flag;
+
+ llvm::call_once(g_once_flag, []() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance);
+ });
+}
+
+ArchSpec ProcessTrace::GetArchitecture() {
+ return GetTarget().GetArchitecture();
+}
+
+bool ProcessTrace::GetProcessInfo(ProcessInstanceInfo &info) {
+ info.Clear();
+ info.SetProcessID(GetID());
+ info.SetArchitecture(GetArchitecture());
+ lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
+ if (module_sp) {
+ const bool add_exe_file_as_first_arg = false;
+ info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
+ add_exe_file_as_first_arg);
+ }
+ return true;
+}
+
+size_t ProcessTrace::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ Status &error) {
+ return 0;
+}
Index: lldb/source/Plugins/Process/Trace/CMakeLists.txt
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/Trace/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_lldb_library(lldbPluginProcessTrace PLUGIN
+ ProcessTrace.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbTarget
+ lldbUtility
+ lldbPluginProcessUtility
+ LINK_COMPONENTS
+ BinaryFormat
+ Object
+ Support
+ )
Index: lldb/source/Plugins/Process/CMakeLists.txt
===================================================================
--- lldb/source/Plugins/Process/CMakeLists.txt
+++ lldb/source/Plugins/Process/CMakeLists.txt
@@ -17,3 +17,4 @@
add_subdirectory(elf-core)
add_subdirectory(mach-core)
add_subdirectory(minidump)
+add_subdirectory(Trace)
Index: lldb/source/Commands/Options.td
===================================================================
--- lldb/source/Commands/Options.td
+++ lldb/source/Commands/Options.td
@@ -1005,6 +1005,16 @@
Desc<"Display thread plans for unreported threads">;
}
+let Command = "thread trace dump instructions" in {
+ def thread_trace_dump_instructions_count : Option<"count", "c">, Group<1>,
+ Arg<"Count">,
+ Desc<"The number of total instructions to display.">;
+ def thread_trace_dump_instructions_offset: Option<"offset", "o">, Group<1>,
+ Arg<"Offset">,
+ Desc<"Offset from the last instruction of the trace to start displaying "
+ "instructions from. Defaults to 0.">;
+}
+
let Command = "type summary add" in {
def type_summary_add_category : Option<"category", "w">, Arg<"Name">,
Desc<"Add this to the given category instead of the default one.">;
Index: lldb/source/Commands/CommandObjectThread.cpp
===================================================================
--- lldb/source/Commands/CommandObjectThread.cpp
+++ lldb/source/Commands/CommandObjectThread.cpp
@@ -2165,6 +2165,128 @@
~CommandObjectMultiwordThreadPlan() override = default;
};
+// Next are the subcommands of CommandObjectMultiwordTrace
+
+// CommandObjectTraceDumpInstructions
+#define LLDB_OPTIONS_thread_trace_dump_instructions
+#include "CommandOptions.inc"
+
+class CommandObjectTraceDumpInstructions
+ : public CommandObjectIterateOverThreads {
+public:
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options() { OptionParsingStarting(nullptr); }
+
+ ~CommandOptions() override = default;
+
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override {
+ Status error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 'c': {
+ int32_t count;
+ if (option_arg.empty() || option_arg.getAsInteger(0, count) ||
+ count < 0)
+ error.SetErrorStringWithFormat(
+ "invalid integer value for option '%s'",
+ option_arg.str().c_str());
+ else
+ m_count = count;
+ break;
+ }
+ case 'o': {
+ int32_t offset;
+ if (option_arg.empty() || option_arg.getAsInteger(0, offset) ||
+ offset < 0)
+ error.SetErrorStringWithFormat(
+ "invalid integer value for option '%s'",
+ option_arg.str().c_str());
+ else
+ m_offset = offset;
+ break;
+ }
+ default:
+ llvm_unreachable("Unimplemented option");
+ }
+ return error;
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_count = 10;
+ m_offset = 0;
+ }
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::makeArrayRef(g_thread_trace_dump_instructions_options);
+ }
+
+ // Instance variables to hold the values for command options.
+ uint32_t m_count;
+ uint32_t m_offset;
+ };
+
+ CommandObjectTraceDumpInstructions(CommandInterpreter &interpreter)
+ : CommandObjectIterateOverThreads(
+ interpreter, "thread trace dump instructions",
+ "Dump the traced instructions for one or more threads. If no "
+ "threads are specified, show the current thread. Use the "
+ "thread-index \"all\" to see all threads.",
+ nullptr,
+ eCommandRequiresProcess | eCommandTryTargetAPILock |
+ eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
+ m_options() {}
+
+ ~CommandObjectTraceDumpInstructions() override = default;
+
+ Options *GetOptions() override { return &m_options; }
+
+protected:
+ bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
+ Target *target = m_exe_ctx.GetTargetPtr();
+
+ target->DumpTraceInstructions(result.GetOutputStream(), tid,
+ m_options.m_count, m_options.m_offset);
+ return true;
+ }
+
+ CommandOptions m_options;
+};
+
+// CommandObjectMultiwordTraceDump
+class CommandObjectMultiwordTraceDump : public CommandObjectMultiword {
+public:
+ CommandObjectMultiwordTraceDump(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "dump",
+ "Commands for displaying trace information of the threads "
+ "in the current process.",
+ "thread trace dump <subcommand> [<subcommand objects>]") {
+ LoadSubCommand(
+ "instructions",
+ CommandObjectSP(new CommandObjectTraceDumpInstructions(interpreter)));
+ }
+ ~CommandObjectMultiwordTraceDump() override = default;
+};
+
+// CommandObjectMultiwordTrace
+class CommandObjectMultiwordTrace : public CommandObjectMultiword {
+public:
+ CommandObjectMultiwordTrace(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "trace",
+ "Commands for operating on traces of the threads in the current "
+ "process.",
+ "thread trace <subcommand> [<subcommand objects>]") {
+ LoadSubCommand("dump", CommandObjectSP(new CommandObjectMultiwordTraceDump(
+ interpreter)));
+ }
+
+ ~CommandObjectMultiwordTrace() override = default;
+};
+
// CommandObjectMultiwordThread
CommandObjectMultiwordThread::CommandObjectMultiwordThread(
@@ -2240,6 +2362,8 @@
LoadSubCommand("plan", CommandObjectSP(new CommandObjectMultiwordThreadPlan(
interpreter)));
+ LoadSubCommand("trace",
+ CommandObjectSP(new CommandObjectMultiwordTrace(interpreter)));
}
CommandObjectMultiwordThread::~CommandObjectMultiwordThread() = default;
Index: lldb/include/lldb/Target/Trace.h
===================================================================
--- lldb/include/lldb/Target/Trace.h
+++ lldb/include/lldb/Target/Trace.h
@@ -33,7 +33,8 @@
/// Processor trace information can also be fetched through the process
/// interfaces during a live debug session if your process supports gathering
/// this information.
-class Trace : public PluginInterface {
+class Trace : public PluginInterface,
+ public std::enable_shared_from_this<Trace> {
public:
/// Dump the trace data that this plug-in has access to.
///
@@ -128,14 +129,9 @@
protected:
friend class TraceSettingsParser;
- /// JSON object that holds all settings for this trace session.
- llvm::json::Object m_settings;
- /// The directory that contains the settings file.
- std::string m_settings_dir;
std::map<lldb::pid_t, std::map<lldb::tid_t, lldb_private::FileSpec>>
m_thread_to_trace_file_map;
- std::vector<lldb::TargetSP> m_targets;
};
} // namespace lldb_private
Index: lldb/include/lldb/Target/Target.h
===================================================================
--- lldb/include/lldb/Target/Target.h
+++ lldb/include/lldb/Target/Target.h
@@ -1105,6 +1105,37 @@
void ClearAllLoadedSections();
+ /// Set the \a Trace object containing processor trace information of this
+ /// target.
+ ///
+ /// \param[in] trace_sp
+ /// The trace object.
+ void SetTrace(const lldb::TraceSP &trace_sp);
+
+ /// Get the \a Trace object containing processor trace information of this
+ /// target.
+ ///
+ /// \return
+ /// The trace object. It might be undefined.
+ lldb::TraceSP &GetTrace();
+
+ /// Dump the instructions of the given thread's \a Trace.
+ ///
+ /// \param[in] s
+ /// The stream object where the instructions are printed.
+ ///
+ /// \param[in] tid
+ /// The thread to print the instruction of.
+ ///
+ /// \param[in] count
+ /// The number of instructions to print.
+ ///
+ /// \param[in] offset
+ /// Offset from the last instruction of the trace to start displaying
+ /// instructions from.
+ void DumpTraceInstructions(Stream &s, lldb::tid_t tid, size_t count,
+ size_t offset = 0) const;
+
// Since expressions results can persist beyond the lifetime of a process,
// and the const expression results are available after a process is gone, we
// provide a way for expressions to be evaluated from the Target itself. If
@@ -1394,6 +1425,9 @@
bool m_suppress_stop_hooks;
bool m_is_dummy_target;
unsigned m_next_persistent_variable_index = 0;
+ /// An optional \a lldb_private::Trace object containing processor trace
+ /// information of this target.
+ lldb::TraceSP m_trace_sp;
/// Stores the frame recognizers of this target.
lldb::StackFrameRecognizerManagerUP m_frame_recognizer_manager_up;
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits