diff options
author | emaste <emaste@FreeBSD.org> | 2014-03-19 13:11:35 +0000 |
---|---|---|
committer | emaste <emaste@FreeBSD.org> | 2014-03-19 13:11:35 +0000 |
commit | 958843c32b7a29741f2e45996b5b3e89f9e108b0 (patch) | |
tree | 95ae4ffabc848a86b94be3ad3cd42471cdb66b06 /contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp | |
parent | 2a9993c246f3a2463ccd6b8786781e5b97a35065 (diff) | |
download | FreeBSD-src-958843c32b7a29741f2e45996b5b3e89f9e108b0.zip FreeBSD-src-958843c32b7a29741f2e45996b5b3e89f9e108b0.tar.gz |
MFC r258054: Update LLDB to upstream r194122 snapshot
Inludes minor changes relative to upstream, for compatibility with
FreeBSD's in-tree LLVM 3.3:
- Reverted LLDB r191806, restoring use of previous API.
- Reverted part of LLDB r189317, restoring previous enum names.
- Work around missing LLVM r192504, using previous registerEHFrames API
(limited functionality).
- Removed PlatformWindows header include and init/terminate calls.
Sponsored by: DARPA, AFRL
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp | 250 |
1 files changed, 231 insertions, 19 deletions
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp index b8657b4..f46a221 100644 --- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp @@ -258,8 +258,8 @@ protected: OptionDefinition CommandObjectThreadBacktrace::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"}, -{ LLDB_OPT_SET_1, false, "start", 's', required_argument, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"}, +{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"}, +{ LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -591,10 +591,10 @@ g_duo_running_mode[] = OptionDefinition CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_1, false, "avoid-no-debug", 'a', required_argument, NULL, 0, eArgTypeBoolean, "A boolean value that sets whether step-in will step over functions with no debug information."}, -{ LLDB_OPT_SET_1, false, "run-mode", 'm', required_argument, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."}, -{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', required_argument, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in."}, -{ LLDB_OPT_SET_1, false, "step-in-target", 't', required_argument, NULL, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."}, +{ LLDB_OPT_SET_1, false, "avoid-no-debug", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "A boolean value that sets whether step-in will step over functions with no debug information."}, +{ LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."}, +{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', OptionParser::eRequiredArgument, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in."}, +{ LLDB_OPT_SET_1, false, "step-in-target", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -660,11 +660,14 @@ public: StateType state = process->GetState(); if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended)) { - Mutex::Locker locker (process->GetThreadList().GetMutex()); - const uint32_t num_threads = process->GetThreadList().GetSize(); const size_t argc = command.GetArgumentCount(); if (argc > 0) { + // These two lines appear at the beginning of both blocks in + // this if..else, but that is because we need to release the + // lock before calling process->Resume below. + Mutex::Locker locker (process->GetThreadList().GetMutex()); + const uint32_t num_threads = process->GetThreadList().GetSize(); std::vector<Thread *> resume_threads; for (uint32_t i=0; i<argc; ++i) { @@ -674,7 +677,7 @@ public: if (success) { Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get(); - + if (thread) { resume_threads.push_back(thread); @@ -693,7 +696,7 @@ public: return false; } } - + if (resume_threads.empty()) { result.AppendError ("no valid thread indexes were specified"); @@ -706,12 +709,12 @@ public: result.AppendMessageWithFormat ("Resuming thread: "); else result.AppendMessageWithFormat ("Resuming threads: "); - + for (uint32_t idx=0; idx<num_threads; ++idx) { Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); std::vector<Thread *>::iterator this_thread_pos = find(resume_threads.begin(), resume_threads.end(), thread); - + if (this_thread_pos != resume_threads.end()) { resume_threads.erase(this_thread_pos); @@ -719,7 +722,7 @@ public: result.AppendMessageWithFormat ("%u, ", thread->GetIndexID()); else result.AppendMessageWithFormat ("%u ", thread->GetIndexID()); - + thread->SetResumeState (eStateRunning); } else @@ -732,6 +735,11 @@ public: } else { + // These two lines appear at the beginning of both blocks in + // this if..else, but that is because we need to release the + // lock before calling process->Resume below. + Mutex::Locker locker (process->GetThreadList().GetMutex()); + const uint32_t num_threads = process->GetThreadList().GetSize(); Thread *current_thread = process->GetThreadList().GetSelectedThread().get(); if (current_thread == NULL) { @@ -754,7 +762,8 @@ public: } } } - + + // We should not be holding the thread list lock when we do this. Error error (process->Resume()); if (error.Success()) { @@ -762,7 +771,7 @@ public: if (synchronous_execution) { state = process->WaitForProcessToStop (NULL); - + result.SetDidChangeProcessState (true); result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state)); result.SetStatus (eReturnStatusSuccessFinishNoResult); @@ -1120,9 +1129,9 @@ protected: OptionDefinition CommandObjectThreadUntil::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_1, false, "frame", 'f', required_argument, NULL, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"}, -{ LLDB_OPT_SET_1, false, "thread", 't', required_argument, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"}, -{ LLDB_OPT_SET_1, false, "run-mode",'m', required_argument, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"}, +{ LLDB_OPT_SET_1, false, "frame", 'f', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"}, +{ LLDB_OPT_SET_1, false, "thread", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"}, +{ LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -1458,11 +1467,213 @@ protected: OptionDefinition CommandObjectThreadReturn::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_ALL, false, "from-expression", 'x', no_argument, NULL, 0, eArgTypeNone, "Return from the innermost expression evaluation."}, +{ LLDB_OPT_SET_ALL, false, "from-expression", 'x', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Return from the innermost expression evaluation."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; //------------------------------------------------------------------------- +// CommandObjectThreadJump +//------------------------------------------------------------------------- + +class CommandObjectThreadJump : public CommandObjectParsed +{ +public: + class CommandOptions : public Options + { + public: + + CommandOptions (CommandInterpreter &interpreter) : + Options (interpreter) + { + OptionParsingStarting (); + } + + void + OptionParsingStarting () + { + m_filenames.Clear(); + m_line_num = 0; + m_line_offset = 0; + m_load_addr = LLDB_INVALID_ADDRESS; + m_force = false; + } + + virtual + ~CommandOptions () + { + } + + virtual Error + SetOptionValue (uint32_t option_idx, const char *option_arg) + { + bool success; + const int short_option = m_getopt_table[option_idx].val; + Error error; + + switch (short_option) + { + case 'f': + m_filenames.AppendIfUnique (FileSpec(option_arg, false)); + if (m_filenames.GetSize() > 1) + return Error("only one source file expected."); + break; + case 'l': + m_line_num = Args::StringToUInt32 (option_arg, 0, 0, &success); + if (!success || m_line_num == 0) + return Error("invalid line number: '%s'.", option_arg); + break; + case 'b': + m_line_offset = Args::StringToSInt32 (option_arg, 0, 0, &success); + if (!success) + return Error("invalid line offset: '%s'.", option_arg); + break; + case 'a': + { + ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); + m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); + } + break; + case 'r': + m_force = true; + break; + + default: + return Error("invalid short option character '%c'", short_option); + + } + return error; + } + + const OptionDefinition* + GetDefinitions () + { + return g_option_table; + } + + FileSpecList m_filenames; + uint32_t m_line_num; + int32_t m_line_offset; + lldb::addr_t m_load_addr; + bool m_force; + + static OptionDefinition g_option_table[]; + }; + + virtual + Options * + GetOptions () + { + return &m_options; + } + + CommandObjectThreadJump (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "thread jump", + "Sets the program counter to a new address.", + "thread jump", + eFlagRequiresFrame | + eFlagTryTargetAPILock | + eFlagProcessMustBeLaunched | + eFlagProcessMustBePaused ), + m_options (interpreter) + { + } + + ~CommandObjectThreadJump() + { + } + +protected: + + bool DoExecute (Args& args, CommandReturnObject &result) + { + RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); + StackFrame *frame = m_exe_ctx.GetFramePtr(); + Thread *thread = m_exe_ctx.GetThreadPtr(); + Target *target = m_exe_ctx.GetTargetPtr(); + const SymbolContext &sym_ctx = frame->GetSymbolContext (eSymbolContextLineEntry); + + if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) + { + // Use this address directly. + Address dest = Address(m_options.m_load_addr); + + lldb::addr_t callAddr = dest.GetCallableLoadAddress (target); + if (callAddr == LLDB_INVALID_ADDRESS) + { + result.AppendErrorWithFormat ("Invalid destination address."); + result.SetStatus (eReturnStatusFailed); + return false; + } + + if (!reg_ctx->SetPC (callAddr)) + { + result.AppendErrorWithFormat ("Error changing PC value for thread %d.", thread->GetIndexID()); + result.SetStatus (eReturnStatusFailed); + return false; + } + } + else + { + // Pick either the absolute line, or work out a relative one. + int32_t line = (int32_t)m_options.m_line_num; + if (line == 0) + line = sym_ctx.line_entry.line + m_options.m_line_offset; + + // Try the current file, but override if asked. + FileSpec file = sym_ctx.line_entry.file; + if (m_options.m_filenames.GetSize() == 1) + file = m_options.m_filenames.GetFileSpecAtIndex(0); + + if (!file) + { + result.AppendErrorWithFormat ("No source file available for the current location."); + result.SetStatus (eReturnStatusFailed); + return false; + } + + std::string warnings; + Error err = thread->JumpToLine (file, line, m_options.m_force, &warnings); + + if (err.Fail()) + { + result.SetError (err); + return false; + } + + if (!warnings.empty()) + result.AppendWarning (warnings.c_str()); + } + + result.SetStatus (eReturnStatusSuccessFinishResult); + return true; + } + + CommandOptions m_options; +}; +OptionDefinition +CommandObjectThreadJump::CommandOptions::g_option_table[] = +{ + { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, + "Specifies the source file to jump to."}, + + { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum, + "Specifies the line number to jump to."}, + + { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset, + "Jumps by a relative line offset from the current line."}, + + { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeAddressOrExpression, + "Jumps to a specific address."}, + + { LLDB_OPT_SET_1| + LLDB_OPT_SET_2| + LLDB_OPT_SET_3, false, "force",'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,"Allows the PC to leave the current function."}, + + { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } +}; + +//------------------------------------------------------------------------- // CommandObjectMultiwordThread //------------------------------------------------------------------------- @@ -1476,6 +1687,7 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter & LoadSubCommand ("continue", CommandObjectSP (new CommandObjectThreadContinue (interpreter))); LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadList (interpreter))); LoadSubCommand ("return", CommandObjectSP (new CommandObjectThreadReturn (interpreter))); + LoadSubCommand ("jump", CommandObjectSP (new CommandObjectThreadJump (interpreter))); LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter))); LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter))); LoadSubCommand ("step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( |