diff options
Diffstat (limited to 'lldb/source/Commands/CommandObjectThread.cpp')
-rw-r--r-- | lldb/source/Commands/CommandObjectThread.cpp | 120 |
1 files changed, 64 insertions, 56 deletions
diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index a87addc..78ec540 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -2099,8 +2099,7 @@ public: #define LLDB_OPTIONS_thread_trace_dump_instructions #include "CommandOptions.inc" -class CommandObjectTraceDumpInstructions - : public CommandObjectIterateOverThreads { +class CommandObjectTraceDumpInstructions : public CommandObjectParsed { public: class CommandOptions : public Options { public: @@ -2132,19 +2131,29 @@ public: "invalid integer value for option '%s'", option_arg.str().c_str()); else - m_skip = skip; + m_dumper_options.skip = skip; + break; + } + case 'i': { + uint64_t id; + if (option_arg.empty() || option_arg.getAsInteger(0, id)) + error.SetErrorStringWithFormat( + "invalid integer value for option '%s'", + option_arg.str().c_str()); + else + m_dumper_options.id = id; break; } case 'r': { - m_raw = true; + m_dumper_options.raw = true; break; } case 'f': { - m_forwards = true; + m_dumper_options.forwards = true; break; } case 't': { - m_show_tsc = true; + m_dumper_options.show_tsc = true; break; } case 'C': { @@ -2159,11 +2168,8 @@ public: void OptionParsingStarting(ExecutionContext *execution_context) override { m_count = kDefaultCount; - m_skip = 0; - m_raw = false; - m_forwards = false; - m_show_tsc = false; m_continue = false; + m_dumper_options = {}; } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { @@ -2174,23 +2180,19 @@ public: // Instance variables to hold the values for command options. size_t m_count; - size_t m_skip; - bool m_raw; - bool m_forwards; - bool m_show_tsc; - bool m_continue; + size_t m_continue; + TraceInstructionDumperOptions m_dumper_options; }; CommandObjectTraceDumpInstructions(CommandInterpreter &interpreter) - : CommandObjectIterateOverThreads( + : CommandObjectParsed( 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.", + "Dump the traced instructions for one thread. If no " + "thread is specified, show the current thread.", nullptr, - eCommandRequiresProcess | eCommandTryTargetAPILock | - eCommandProcessMustBeLaunched | eCommandProcessMustBePaused | - eCommandProcessMustBeTraced) {} + eCommandRequiresProcess | eCommandRequiresThread | + eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused | eCommandProcessMustBeTraced) {} ~CommandObjectTraceDumpInstructions() override = default; @@ -2200,57 +2202,63 @@ public: uint32_t index) override { std::string cmd; current_command_args.GetCommandString(cmd); - if (cmd.find("--continue") == std::string::npos) + if (cmd.find(" --continue") == std::string::npos) cmd += " --continue"; return cmd; } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { - if (!m_options.m_continue) - m_dumpers.clear(); + ThreadSP GetThread(Args &args, CommandReturnObject &result) { + if (args.GetArgumentCount() == 0) + return m_exe_ctx.GetThreadSP(); - return CommandObjectIterateOverThreads::DoExecute(args, result); - } - - bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { - Stream &s = result.GetOutputStream(); + const char *arg = args.GetArgumentAtIndex(0); + uint32_t thread_idx; - const TraceSP &trace_sp = m_exe_ctx.GetTargetSP()->GetTrace(); + if (!llvm::to_integer(arg, thread_idx)) { + result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n", + arg); + return nullptr; + } ThreadSP thread_sp = - m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); - - if (!m_dumpers.count(thread_sp->GetID())) { - lldb::TraceCursorUP cursor_up = trace_sp->GetCursor(*thread_sp); - // Set up the cursor and return the presentation index of the first - // instruction to dump after skipping instructions. - auto setUpCursor = [&]() { - cursor_up->SetForwards(m_options.m_forwards); - if (m_options.m_forwards) - return cursor_up->Seek(m_options.m_skip, TraceCursor::SeekType::Set); - return -cursor_up->Seek(-m_options.m_skip, TraceCursor::SeekType::End); - }; - - int initial_index = setUpCursor(); + m_exe_ctx.GetProcessRef().GetThreadList().FindThreadByIndexID( + thread_idx); + if (!thread_sp) + result.AppendErrorWithFormat("no thread with index: \"%s\"\n", arg); + return thread_sp; + } - auto dumper = std::make_unique<TraceInstructionDumper>( - std::move(cursor_up), initial_index, m_options.m_raw, - m_options.m_show_tsc); + bool DoExecute(Args &args, CommandReturnObject &result) override { + ThreadSP thread_sp = GetThread(args, result); + if (!thread_sp) + return false; - // This happens when the seek value was more than the number of available - // instructions. - if (std::abs(initial_index) < (int)m_options.m_skip) - dumper->SetNoMoreData(); + Stream &s = result.GetOutputStream(); + s.Printf("thread #%u: tid = %" PRIu64 "\n", thread_sp->GetIndexID(), + thread_sp->GetID()); - m_dumpers[thread_sp->GetID()] = std::move(dumper); + if (m_options.m_continue) { + if (!m_last_id) { + result.AppendMessage(" no more data\n"); + return true; + } + // We set up the options to continue one instruction past where + // the previous iteration stopped. + m_options.m_dumper_options.skip = 1; + m_options.m_dumper_options.id = m_last_id; } - m_dumpers[thread_sp->GetID()]->DumpInstructions(s, m_options.m_count); + const TraceSP &trace_sp = m_exe_ctx.GetTargetSP()->GetTrace(); + TraceInstructionDumper dumper(trace_sp->GetCursor(*thread_sp), s, + m_options.m_dumper_options); + m_last_id = dumper.DumpInstructions(m_options.m_count); return true; } CommandOptions m_options; - std::map<lldb::tid_t, std::unique_ptr<TraceInstructionDumper>> m_dumpers; + // Last traversed id used to continue a repeat command. None means + // that all the trace has been consumed. + llvm::Optional<lldb::user_id_t> m_last_id; }; // CommandObjectTraceDumpInfo |