aboutsummaryrefslogtreecommitdiff
path: root/source/Target/Thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Target/Thread.cpp')
-rw-r--r--source/Target/Thread.cpp118
1 files changed, 112 insertions, 6 deletions
diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp
index b65434bf9482..98c26019b4a1 100644
--- a/source/Target/Thread.cpp
+++ b/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;