diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Target/Thread.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Target/Thread.cpp | 118 |
1 files changed, 112 insertions, 6 deletions
diff --git a/contrib/llvm/tools/lldb/source/Target/Thread.cpp b/contrib/llvm/tools/lldb/source/Target/Thread.cpp index b65434b..98c2601 100644 --- a/contrib/llvm/tools/lldb/source/Target/Thread.cpp +++ b/contrib/llvm/tools/lldb/source/Target/Thread.cpp @@ -282,12 +282,18 @@ Thread::~Thread() void Thread::DestroyThread () { - // Tell any plans on the plan stack that the thread is being destroyed since - // any active plans that have a thread go away in the middle of might need - // to do cleanup. + // Tell any plans on the plan stacks that the thread is being destroyed since + // any plans that have a thread go away in the middle of might need + // to do cleanup, or in some cases NOT do cleanup... for (auto plan : m_plan_stack) plan->ThreadDestroyed(); + for (auto plan : m_discarded_plan_stack) + plan->ThreadDestroyed(); + + for (auto plan : m_completed_plan_stack) + plan->ThreadDestroyed(); + m_destroy_called = true; m_plan_stack.clear(); m_discarded_plan_stack.clear(); @@ -1745,6 +1751,79 @@ Thread::ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return return return_error; } +static void DumpAddressList (Stream &s, const std::vector<Address> &list, ExecutionContextScope *exe_scope) +{ + for (size_t n=0;n<list.size();n++) + { + s << "\t"; + list[n].Dump (&s, exe_scope, Address::DumpStyleResolvedDescription, Address::DumpStyleSectionNameOffset); + s << "\n"; + } +} + +Error +Thread::JumpToLine (const FileSpec &file, uint32_t line, bool can_leave_function, std::string *warnings) +{ + ExecutionContext exe_ctx (GetStackFrameAtIndex(0)); + Target *target = exe_ctx.GetTargetPtr(); + TargetSP target_sp = exe_ctx.GetTargetSP(); + RegisterContext *reg_ctx = exe_ctx.GetRegisterContext(); + StackFrame *frame = exe_ctx.GetFramePtr(); + const SymbolContext &sc = frame->GetSymbolContext(eSymbolContextFunction); + + // Find candidate locations. + std::vector<Address> candidates, within_function, outside_function; + target->GetImages().FindAddressesForLine (target_sp, file, line, sc.function, within_function, outside_function); + + // If possible, we try and stay within the current function. + // Within a function, we accept multiple locations (optimized code may do this, + // there's no solution here so we do the best we can). + // However if we're trying to leave the function, we don't know how to pick the + // right location, so if there's more than one then we bail. + if (!within_function.empty()) + candidates = within_function; + else if (outside_function.size() == 1 && can_leave_function) + candidates = outside_function; + + // Check if we got anything. + if (candidates.empty()) + { + if (outside_function.empty()) + { + return Error("Cannot locate an address for %s:%i.", + file.GetFilename().AsCString(), line); + } + else if (outside_function.size() == 1) + { + return Error("%s:%i is outside the current function.", + file.GetFilename().AsCString(), line); + } + else + { + StreamString sstr; + DumpAddressList(sstr, outside_function, target); + return Error("%s:%i has multiple candidate locations:\n%s", + file.GetFilename().AsCString(), line, sstr.GetString().c_str()); + } + } + + // Accept the first location, warn about any others. + Address dest = candidates[0]; + if (warnings && candidates.size() > 1) + { + StreamString sstr; + sstr.Printf("%s:%i appears multiple times in this function, selecting the first location:\n", + file.GetFilename().AsCString(), line); + DumpAddressList(sstr, candidates, target); + *warnings = sstr.GetString(); + } + + if (!reg_ctx->SetPC (dest)) + return Error("Cannot change PC to target address."); + + return Error(); +} + void Thread::DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx) { @@ -1784,6 +1863,24 @@ Thread::SettingsTerminate () { } +lldb::addr_t +Thread::GetThreadPointer () +{ + return LLDB_INVALID_ADDRESS; +} + +addr_t +Thread::GetThreadLocalData (const ModuleSP module) +{ + // The default implementation is to ask the dynamic loader for it. + // This can be overridden for specific platforms. + DynamicLoader *loader = GetProcess()->GetDynamicLoader(); + if (loader) + return loader->GetThreadLocalData (module, shared_from_this()); + else + return LLDB_INVALID_ADDRESS; +} + lldb::StackFrameSP Thread::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr) { @@ -1863,13 +1960,21 @@ Thread::GetStatus (Stream &strm, uint32_t start_frame, uint32_t num_frames, uint strm.IndentMore(); const bool show_frame_info = true; - strm.IndentMore (); + + const char *selected_frame_marker = NULL; + if (num_frames == 1 || (GetID() != GetProcess()->GetThreadList().GetSelectedThread()->GetID())) + strm.IndentMore (); + else + selected_frame_marker = "* "; + num_frames_shown = GetStackFrameList ()->GetStatus (strm, start_frame, num_frames, show_frame_info, - num_frames_with_source); - strm.IndentLess(); + num_frames_with_source, + selected_frame_marker); + if (num_frames == 1) + strm.IndentLess(); strm.IndentLess(); } return num_frames_shown; @@ -1944,6 +2049,7 @@ Thread::GetUnwinder () case llvm::Triple::x86: case llvm::Triple::arm: case llvm::Triple::thumb: + case llvm::Triple::mips64: m_unwinder_ap.reset (new UnwindLLDB (*this)); break; |