aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Commands/CommandObjectThread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Commands/CommandObjectThread.cpp')
-rw-r--r--lldb/source/Commands/CommandObjectThread.cpp120
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