diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -209,7 +209,7 @@ bool GetInjectLocalVariables(ExecutionContext *exe_ctx) const; void SetInjectLocalVariables(ExecutionContext *exe_ctx, bool b); - + void SetRequireHardwareBreakpoints(bool b); bool GetRequireHardwareBreakpoints() const; @@ -1102,6 +1102,10 @@ void ClearAllLoadedSections(); + void SetTrace(const lldb::TraceSP &trace_sp); + + lldb::TraceSP &GetTrace(); + // 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 @@ -1294,12 +1298,12 @@ lldb::PlatformSP m_platform_sp; ///< The platform for this target. std::recursive_mutex m_mutex; ///< An API mutex that is used by the lldb::SB* /// classes make the SB interface thread safe - /// When the private state thread calls SB API's - usually because it is + /// When the private state thread calls SB API's - usually because it is /// running OS plugin or Python ThreadPlan code - it should not block on the /// API mutex that is held by the code that kicked off the sequence of events - /// that led us to run the code. We hand out this mutex instead when we + /// that led us to run the code. We hand out this mutex instead when we /// detect that code is running on the private state thread. - std::recursive_mutex m_private_mutex; + std::recursive_mutex m_private_mutex; Arch m_arch; ModuleList m_images; ///< The list of images for this process (shared /// libraries and anything dynamically loaded). @@ -1334,6 +1338,7 @@ bool m_suppress_stop_hooks; bool m_is_dummy_target; unsigned m_next_persistent_variable_index = 0; + lldb::TraceSP m_trace; /// Stores the frame recognizers of this target. lldb::StackFrameRecognizerManagerUP m_frame_recognizer_manager_up; diff --git a/lldb/include/lldb/Target/Trace.h b/lldb/include/lldb/Target/Trace.h --- a/lldb/include/lldb/Target/Trace.h +++ b/lldb/include/lldb/Target/Trace.h @@ -35,7 +35,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 { public: ~Trace() override = default; diff --git a/lldb/source/Commands/CommandObjectTrace.cpp b/lldb/source/Commands/CommandObjectTrace.cpp --- a/lldb/source/Commands/CommandObjectTrace.cpp +++ b/lldb/source/Commands/CommandObjectTrace.cpp @@ -160,9 +160,10 @@ }; CommandObjectTraceDump(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "trace dump", - "Dump the loaded processor trace data.", - "trace dump"), + : CommandObjectParsed( + interpreter, "trace dump", + "Dump the loaded processor trace data from the current target.", + "trace dump"), m_options() {} ~CommandObjectTraceDump() override = default; @@ -172,7 +173,14 @@ protected: bool DoExecute(Args &command, CommandReturnObject &result) override { Status error; - // TODO: fill in the dumping code here! + TraceSP trace = GetSelectedOrDummyTarget().GetTrace(); + if (trace) { + trace->Dump(&result.GetOutputStream()); + result.AppendMessage("\n"); + } else + error.SetErrorString( + "the current target does not have any traces loaded."); + if (error.Success()) { result.SetStatus(eReturnStatusSuccessFinishResult); } else { diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp --- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp +++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp @@ -94,7 +94,17 @@ uint32_t TraceIntelPT::GetPluginVersion() { return 1; } -void TraceIntelPT::Dump(lldb_private::Stream *s) const {} +void TraceIntelPT::Dump(lldb_private::Stream *s) const { + s->PutCString("Settings\n"); + s->Indent(); + m_settings.Dump(*s, /*pretty_print*/ true); + s->IndentLess(); + + s->PutCString("\nSettings directory\n"); + s->Indent(); + s->PutCString(m_settings_dir.c_str()); + s->IndentLess(); +} lldb::TraceSP TraceIntelPT::CreateInstance(StructuredData::Dictionary settings, const char *settings_dir) { diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -2965,6 +2965,10 @@ return error; } +void Target::SetTrace(const lldb::TraceSP &trace_sp) { m_trace = trace_sp; } + +lldb::TraceSP &Target::GetTrace() { return m_trace; } + Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) { auto state = eStateInvalid; auto process_sp = GetProcessSP(); diff --git a/lldb/source/Target/Trace.cpp b/lldb/source/Target/Trace.cpp --- a/lldb/source/Target/Trace.cpp +++ b/lldb/source/Target/Trace.cpp @@ -235,6 +235,7 @@ if (!target_sp) return error.ToError(); + target_sp->SetTrace(shared_from_this()); debugger.GetTargetList().SetSelectedTarget(target_sp.get()); ProcessSP process_sp(target_sp->CreateProcess( diff --git a/lldb/test/API/commands/trace/TestTraceLoad.py b/lldb/test/API/commands/trace/TestTraceLoad.py --- a/lldb/test/API/commands/trace/TestTraceLoad.py +++ b/lldb/test/API/commands/trace/TestTraceLoad.py @@ -35,6 +35,8 @@ self.assertEqual("6AA9A4E2-6F28-2F33-377D-59FECE874C71-5B41261A", module.GetUUIDString()) + self.expect("trace dump", substrs=["Settings", "intel-pt", "3842849.trace", "Settings directory"]) + def testLoadInvalidTraces(self): src_dir = self.getSourceDir() @@ -64,3 +66,5 @@ } Schema""" self.expect("trace load -v " + trace_definition_file2, substrs=[failed_output2], error=True) + + self.expect("trace dump", substrs=["the current target does not have any traces"], error=True)