From 0b69756110db444282c40ea16929186b2910c3b1 Mon Sep 17 00:00:00 2001 From: Walter Erquinigo Date: Mon, 9 Nov 2020 13:36:26 -0800 Subject: [trace][intel-pt] Implement trace start and trace stop This implements the interactive trace start and stop methods. This diff ended up being much larger than I anticipated because, by doing it, I found that I had implemented in the beginning many things in a non optimal way. In any case, the code is much better now. There's a lot of boilerplate code due to the gdb-remote protocol, but the main changes are: - New tracing packets: jLLDBTraceStop, jLLDBTraceStart, jLLDBTraceGetBinaryData. The gdb-remote packet definitions are quite comprehensive. - Implementation of the "process trace start|stop" and "thread trace start|stop" commands. - Implementaiton of an API in Trace.h to interact with live traces. - Created an IntelPTDecoder for live threads, that use the debugger's stop id as checkpoint for its internal cache. - Added a functionality to stop the process in case "process tracing" is enabled and a new thread can't traced. - Added tests I have some ideas to unify the code paths for post mortem and live threads, but I'll do that in another diff. Differential Revision: https://reviews.llvm.org/D91679 --- lldb/source/Commands/CommandObjectThread.cpp | 94 ++++++++-------------------- 1 file changed, 26 insertions(+), 68 deletions(-) (limited to 'lldb/source/Commands/CommandObjectThread.cpp') diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index f4ce5cc..a88fda9 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -11,6 +11,7 @@ #include #include "CommandObjectThreadUtil.h" +#include "CommandObjectTrace.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/ValueObject.h" #include "lldb/Host/OptionParser.h" @@ -1978,75 +1979,34 @@ public: // CommandObjectTraceStart -/// This class works by delegating the logic to the actual trace plug-in that -/// can support the current process. -class CommandObjectTraceStart : public CommandObjectProxy { +class CommandObjectTraceStart : public CommandObjectTraceProxy { public: CommandObjectTraceStart(CommandInterpreter &interpreter) - : CommandObjectProxy(interpreter, "thread trace start", - "Start tracing threads with the corresponding trace " - "plug-in for the current process.", - "thread trace start []") {} + : CommandObjectTraceProxy( + /*live_debug_session_only*/ true, interpreter, "thread trace start", + "Start tracing threads with the corresponding trace " + "plug-in for the current process.", + "thread trace start []") {} protected: - llvm::Expected DoGetProxyCommandObject() { - ProcessSP process_sp = m_interpreter.GetExecutionContext().GetProcessSP(); - - if (!process_sp) - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "Process not available."); - if (!process_sp->IsAlive()) - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "Process must be launched."); - - llvm::Expected trace_type = - process_sp->GetSupportedTraceType(); - - if (!trace_type) - return llvm::createStringError( - llvm::inconvertibleErrorCode(), "Tracing is not supported. %s", - llvm::toString(trace_type.takeError()).c_str()); - - CommandObjectSP delegate_sp = - PluginManager::GetTraceStartCommand(trace_type->name, m_interpreter); - if (!delegate_sp) - return llvm::createStringError( - llvm::inconvertibleErrorCode(), - "No trace plug-in matches the specified type: \"%s\"", - trace_type->name.c_str()); - return delegate_sp; + lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override { + return trace.GetThreadTraceStartCommand(m_interpreter); } - - CommandObject *GetProxyCommandObject() override { - if (llvm::Expected delegate = DoGetProxyCommandObject()) { - m_delegate_sp = *delegate; - m_delegate_error.clear(); - return m_delegate_sp.get(); - } else { - m_delegate_sp.reset(); - m_delegate_error = llvm::toString(delegate.takeError()); - return nullptr; - } - } - -private: - llvm::StringRef GetUnsupportedError() override { return m_delegate_error; } - - CommandObjectSP m_delegate_sp; - std::string m_delegate_error; }; // CommandObjectTraceStop -class CommandObjectTraceStop : public CommandObjectIterateOverThreads { +class CommandObjectTraceStop : public CommandObjectMultipleThreads { public: CommandObjectTraceStop(CommandInterpreter &interpreter) - : CommandObjectIterateOverThreads( + : CommandObjectMultipleThreads( interpreter, "thread trace stop", - "Stop tracing threads. " + "Stop tracing threads, including the ones traced with the " + "\"process trace start\" command." "Defaults to the current thread. Thread indices can be " - "specified as arguments.\n Use the thread-index \"all\" to trace " - "all threads.", + "specified as arguments.\n Use the thread-index \"all\" to stop " + "tracing " + "for all existing threads.", "thread trace stop [ ...]", eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused | @@ -2054,20 +2014,18 @@ public: ~CommandObjectTraceStop() override = default; - bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { - const Thread &thread = - *m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); - Trace &trace = *m_exe_ctx.GetTargetSP()->GetTrace(); + bool DoExecuteOnThreads(Args &command, CommandReturnObject &result, + const std::vector &tids) override { + ProcessSP process_sp = m_exe_ctx.GetProcessSP(); - if (llvm::Error err = trace.StopTracingThread(thread)) { - result.AppendErrorWithFormat("Failed stopping thread %" PRIu64 ": %s\n", - tid, toString(std::move(err)).c_str()); - result.SetStatus(eReturnStatusFailed); - } + TraceSP trace_sp = process_sp->GetTarget().GetTrace(); - // We don't return false on errors to try to stop as many threads as - // possible. - return true; + if (llvm::Error err = trace_sp->StopThreads(tids)) + result.SetError(toString(std::move(err))); + else + result.SetStatus(eReturnStatusSuccessFinishResult); + + return result.Succeeded(); } }; -- cgit v1.1