| //===-- ExecutionContext.cpp ------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "lldb/Target/ExecutionContext.h" |
| |
| #include "lldb/Core/State.h" |
| #include "lldb/Target/ExecutionContextScope.h" |
| #include "lldb/Target/StackFrame.h" |
| #include "lldb/Target/Process.h" |
| #include "lldb/Target/Target.h" |
| #include "lldb/Target/Thread.h" |
| |
| using namespace lldb_private; |
| |
| ExecutionContext::ExecutionContext() : |
| m_target_sp (), |
| m_process_sp (), |
| m_thread_sp (), |
| m_frame_sp () |
| { |
| } |
| |
| ExecutionContext::ExecutionContext (const ExecutionContext &rhs) : |
| m_target_sp(rhs.m_target_sp), |
| m_process_sp(rhs.m_process_sp), |
| m_thread_sp(rhs.m_thread_sp), |
| m_frame_sp(rhs.m_frame_sp) |
| { |
| } |
| |
| ExecutionContext::ExecutionContext (const lldb::TargetSP &target_sp, bool get_process) : |
| m_target_sp (), |
| m_process_sp (), |
| m_thread_sp (), |
| m_frame_sp () |
| { |
| if (target_sp) |
| SetContext (target_sp, get_process); |
| } |
| |
| ExecutionContext::ExecutionContext (const lldb::ProcessSP &process_sp) : |
| m_target_sp (), |
| m_process_sp (), |
| m_thread_sp (), |
| m_frame_sp () |
| { |
| if (process_sp) |
| SetContext (process_sp); |
| } |
| |
| ExecutionContext::ExecutionContext (const lldb::ThreadSP &thread_sp) : |
| m_target_sp (), |
| m_process_sp (), |
| m_thread_sp (), |
| m_frame_sp () |
| { |
| if (thread_sp) |
| SetContext (thread_sp); |
| } |
| |
| ExecutionContext::ExecutionContext (const lldb::StackFrameSP &frame_sp) : |
| m_target_sp (), |
| m_process_sp (), |
| m_thread_sp (), |
| m_frame_sp () |
| { |
| if (frame_sp) |
| SetContext (frame_sp); |
| } |
| |
| ExecutionContext::ExecutionContext (const lldb::TargetWP &target_wp, bool get_process) : |
| m_target_sp (), |
| m_process_sp (), |
| m_thread_sp (), |
| m_frame_sp () |
| { |
| lldb::TargetSP target_sp(target_wp.lock()); |
| if (target_sp) |
| SetContext (target_sp, get_process); |
| } |
| |
| ExecutionContext::ExecutionContext (const lldb::ProcessWP &process_wp) : |
| m_target_sp (), |
| m_process_sp (), |
| m_thread_sp (), |
| m_frame_sp () |
| { |
| lldb::ProcessSP process_sp(process_wp.lock()); |
| if (process_sp) |
| SetContext (process_sp); |
| } |
| |
| ExecutionContext::ExecutionContext (const lldb::ThreadWP &thread_wp) : |
| m_target_sp (), |
| m_process_sp (), |
| m_thread_sp (), |
| m_frame_sp () |
| { |
| lldb::ThreadSP thread_sp(thread_wp.lock()); |
| if (thread_sp) |
| SetContext (thread_sp); |
| } |
| |
| ExecutionContext::ExecutionContext (const lldb::StackFrameWP &frame_wp) : |
| m_target_sp (), |
| m_process_sp (), |
| m_thread_sp (), |
| m_frame_sp () |
| { |
| lldb::StackFrameSP frame_sp(frame_wp.lock()); |
| if (frame_sp) |
| SetContext (frame_sp); |
| } |
| |
| ExecutionContext::ExecutionContext (Target* t, bool fill_current_process_thread_frame) : |
| m_target_sp (t->shared_from_this()), |
| m_process_sp (), |
| m_thread_sp (), |
| m_frame_sp () |
| { |
| if (t && fill_current_process_thread_frame) |
| { |
| m_process_sp = t->GetProcessSP(); |
| if (m_process_sp) |
| { |
| m_thread_sp = m_process_sp->GetThreadList().GetSelectedThread(); |
| if (m_thread_sp) |
| m_frame_sp = m_thread_sp->GetSelectedFrame(); |
| } |
| } |
| } |
| |
| ExecutionContext::ExecutionContext(Process* process, Thread *thread, StackFrame *frame) : |
| m_target_sp (), |
| m_process_sp (process->shared_from_this()), |
| m_thread_sp (thread->shared_from_this()), |
| m_frame_sp (frame->shared_from_this()) |
| { |
| if (process) |
| m_target_sp = process->GetTarget().shared_from_this(); |
| } |
| |
| ExecutionContext::ExecutionContext (const ExecutionContextRef &exe_ctx_ref) : |
| m_target_sp (exe_ctx_ref.GetTargetSP()), |
| m_process_sp (exe_ctx_ref.GetProcessSP()), |
| m_thread_sp (exe_ctx_ref.GetThreadSP()), |
| m_frame_sp (exe_ctx_ref.GetFrameSP()) |
| { |
| } |
| |
| ExecutionContext::ExecutionContext (const ExecutionContextRef *exe_ctx_ref_ptr) : |
| m_target_sp (), |
| m_process_sp (), |
| m_thread_sp (), |
| m_frame_sp () |
| { |
| if (exe_ctx_ref_ptr) |
| { |
| m_target_sp = exe_ctx_ref_ptr->GetTargetSP(); |
| m_process_sp = exe_ctx_ref_ptr->GetProcessSP(); |
| m_thread_sp = exe_ctx_ref_ptr->GetThreadSP(); |
| m_frame_sp = exe_ctx_ref_ptr->GetFrameSP(); |
| } |
| } |
| |
| ExecutionContext::ExecutionContext (const ExecutionContextRef *exe_ctx_ref_ptr, Mutex::Locker &locker) : |
| m_target_sp (), |
| m_process_sp (), |
| m_thread_sp (), |
| m_frame_sp () |
| { |
| if (exe_ctx_ref_ptr) |
| { |
| m_target_sp = exe_ctx_ref_ptr->GetTargetSP(); |
| if (m_target_sp) |
| { |
| locker.Lock(m_target_sp->GetAPIMutex()); |
| m_process_sp = exe_ctx_ref_ptr->GetProcessSP(); |
| m_thread_sp = exe_ctx_ref_ptr->GetThreadSP(); |
| m_frame_sp = exe_ctx_ref_ptr->GetFrameSP(); |
| } |
| } |
| } |
| |
| ExecutionContext::ExecutionContext (const ExecutionContextRef &exe_ctx_ref, Mutex::Locker &locker) : |
| m_target_sp (exe_ctx_ref.GetTargetSP()), |
| m_process_sp (), |
| m_thread_sp (), |
| m_frame_sp () |
| { |
| if (m_target_sp) |
| { |
| locker.Lock(m_target_sp->GetAPIMutex()); |
| m_process_sp = exe_ctx_ref.GetProcessSP(); |
| m_thread_sp = exe_ctx_ref.GetThreadSP(); |
| m_frame_sp = exe_ctx_ref.GetFrameSP(); |
| } |
| } |
| |
| ExecutionContext::ExecutionContext (ExecutionContextScope *exe_scope_ptr) : |
| m_target_sp (), |
| m_process_sp (), |
| m_thread_sp (), |
| m_frame_sp () |
| { |
| if (exe_scope_ptr) |
| exe_scope_ptr->CalculateExecutionContext (*this); |
| } |
| |
| ExecutionContext::ExecutionContext (ExecutionContextScope &exe_scope_ref) |
| { |
| exe_scope_ref.CalculateExecutionContext (*this); |
| } |
| |
| void |
| ExecutionContext::Clear() |
| { |
| m_target_sp.reset(); |
| m_process_sp.reset(); |
| m_thread_sp.reset(); |
| m_frame_sp.reset(); |
| } |
| |
| ExecutionContext::~ExecutionContext() |
| { |
| } |
| |
| uint32_t |
| ExecutionContext::GetAddressByteSize() const |
| { |
| if (m_target_sp && m_target_sp->GetArchitecture().IsValid()) |
| m_target_sp->GetArchitecture().GetAddressByteSize(); |
| if (m_process_sp) |
| m_process_sp->GetAddressByteSize(); |
| return sizeof(void *); |
| } |
| |
| |
| |
| RegisterContext * |
| ExecutionContext::GetRegisterContext () const |
| { |
| if (m_frame_sp) |
| return m_frame_sp->GetRegisterContext().get(); |
| else if (m_thread_sp) |
| return m_thread_sp->GetRegisterContext().get(); |
| return NULL; |
| } |
| |
| Target * |
| ExecutionContext::GetTargetPtr () const |
| { |
| if (m_target_sp) |
| return m_target_sp.get(); |
| if (m_process_sp) |
| return &m_process_sp->GetTarget(); |
| return NULL; |
| } |
| |
| Process * |
| ExecutionContext::GetProcessPtr () const |
| { |
| if (m_process_sp) |
| return m_process_sp.get(); |
| if (m_target_sp) |
| return m_target_sp->GetProcessSP().get(); |
| return NULL; |
| } |
| |
| ExecutionContextScope * |
| ExecutionContext::GetBestExecutionContextScope () const |
| { |
| if (m_frame_sp) |
| return m_frame_sp.get(); |
| if (m_thread_sp) |
| return m_thread_sp.get(); |
| if (m_process_sp) |
| return m_process_sp.get(); |
| return m_target_sp.get(); |
| } |
| |
| Target & |
| ExecutionContext::GetTargetRef () const |
| { |
| #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE) |
| assert (m_target_sp.get()); |
| #endif |
| return *m_target_sp; |
| } |
| |
| Process & |
| ExecutionContext::GetProcessRef () const |
| { |
| #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE) |
| assert (m_process_sp.get()); |
| #endif |
| return *m_process_sp; |
| } |
| |
| Thread & |
| ExecutionContext::GetThreadRef () const |
| { |
| #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE) |
| assert (m_thread_sp.get()); |
| #endif |
| return *m_thread_sp; |
| } |
| |
| StackFrame & |
| ExecutionContext::GetFrameRef () const |
| { |
| #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE) |
| assert (m_frame_sp.get()); |
| #endif |
| return *m_frame_sp; |
| } |
| |
| void |
| ExecutionContext::SetTargetSP (const lldb::TargetSP &target_sp) |
| { |
| m_target_sp = target_sp; |
| } |
| |
| void |
| ExecutionContext::SetProcessSP (const lldb::ProcessSP &process_sp) |
| { |
| m_process_sp = process_sp; |
| } |
| |
| void |
| ExecutionContext::SetThreadSP (const lldb::ThreadSP &thread_sp) |
| { |
| m_thread_sp = thread_sp; |
| } |
| |
| void |
| ExecutionContext::SetFrameSP (const lldb::StackFrameSP &frame_sp) |
| { |
| m_frame_sp = frame_sp; |
| } |
| |
| void |
| ExecutionContext::SetTargetPtr (Target* target) |
| { |
| if (target) |
| m_target_sp = target->shared_from_this(); |
| else |
| m_target_sp.reset(); |
| } |
| |
| void |
| ExecutionContext::SetProcessPtr (Process *process) |
| { |
| if (process) |
| m_process_sp = process->shared_from_this(); |
| else |
| m_process_sp.reset(); |
| } |
| |
| void |
| ExecutionContext::SetThreadPtr (Thread *thread) |
| { |
| if (thread) |
| m_thread_sp = thread->shared_from_this(); |
| else |
| m_thread_sp.reset(); |
| } |
| |
| void |
| ExecutionContext::SetFramePtr (StackFrame *frame) |
| { |
| if (frame) |
| m_frame_sp = frame->shared_from_this(); |
| else |
| m_frame_sp.reset(); |
| } |
| |
| void |
| ExecutionContext::SetContext (const lldb::TargetSP &target_sp, bool get_process) |
| { |
| m_target_sp = target_sp; |
| if (get_process && target_sp) |
| m_process_sp = target_sp->GetProcessSP(); |
| else |
| m_process_sp.reset(); |
| m_thread_sp.reset(); |
| m_frame_sp.reset(); |
| } |
| |
| void |
| ExecutionContext::SetContext (const lldb::ProcessSP &process_sp) |
| { |
| m_process_sp = process_sp; |
| if (process_sp) |
| m_target_sp = process_sp->GetTarget().shared_from_this(); |
| else |
| m_target_sp.reset(); |
| m_thread_sp.reset(); |
| m_frame_sp.reset(); |
| } |
| |
| void |
| ExecutionContext::SetContext (const lldb::ThreadSP &thread_sp) |
| { |
| m_frame_sp.reset(); |
| m_thread_sp = thread_sp; |
| if (thread_sp) |
| { |
| m_process_sp = thread_sp->GetProcess(); |
| if (m_process_sp) |
| m_target_sp = m_process_sp->GetTarget().shared_from_this(); |
| else |
| m_target_sp.reset(); |
| } |
| else |
| { |
| m_target_sp.reset(); |
| m_process_sp.reset(); |
| } |
| } |
| |
| void |
| ExecutionContext::SetContext (const lldb::StackFrameSP &frame_sp) |
| { |
| m_frame_sp = frame_sp; |
| if (frame_sp) |
| { |
| m_thread_sp = frame_sp->CalculateThread(); |
| if (m_thread_sp) |
| { |
| m_process_sp = m_thread_sp->GetProcess(); |
| if (m_process_sp) |
| m_target_sp = m_process_sp->GetTarget().shared_from_this(); |
| else |
| m_target_sp.reset(); |
| } |
| else |
| { |
| m_target_sp.reset(); |
| m_process_sp.reset(); |
| } |
| } |
| else |
| { |
| m_target_sp.reset(); |
| m_process_sp.reset(); |
| m_thread_sp.reset(); |
| } |
| } |
| |
| ExecutionContext & |
| ExecutionContext::operator =(const ExecutionContext &rhs) |
| { |
| if (this != &rhs) |
| { |
| m_target_sp = rhs.m_target_sp; |
| m_process_sp = rhs.m_process_sp; |
| m_thread_sp = rhs.m_thread_sp; |
| m_frame_sp = rhs.m_frame_sp; |
| } |
| return *this; |
| } |
| |
| bool |
| ExecutionContext::operator ==(const ExecutionContext &rhs) const |
| { |
| // Check that the frame shared pointers match, or both are valid and their stack |
| // IDs match since sometimes we get new objects that represent the same |
| // frame within a thread. |
| if ((m_frame_sp == rhs.m_frame_sp) || (m_frame_sp && rhs.m_frame_sp && m_frame_sp->GetStackID() == rhs.m_frame_sp->GetStackID())) |
| { |
| // Check that the thread shared pointers match, or both are valid and |
| // their thread IDs match since sometimes we get new objects that |
| // represent the same thread within a process. |
| if ((m_thread_sp == rhs.m_thread_sp) || (m_thread_sp && rhs.m_thread_sp && m_thread_sp->GetID() == rhs.m_thread_sp->GetID())) |
| { |
| // Processes and targets don't change much |
| return m_process_sp == rhs.m_process_sp && m_target_sp == rhs.m_target_sp; |
| } |
| } |
| return false; |
| } |
| |
| bool |
| ExecutionContext::operator !=(const ExecutionContext &rhs) const |
| { |
| return !(*this == rhs); |
| } |
| |
| bool |
| ExecutionContext::HasTargetScope () const |
| { |
| return ((bool) m_target_sp |
| && m_target_sp->IsValid()); |
| } |
| |
| bool |
| ExecutionContext::HasProcessScope () const |
| { |
| return (HasTargetScope() |
| && ((bool) m_process_sp && m_process_sp->IsValid())); |
| } |
| |
| bool |
| ExecutionContext::HasThreadScope () const |
| { |
| return (HasProcessScope() |
| && ((bool) m_thread_sp && m_thread_sp->IsValid())); |
| } |
| |
| bool |
| ExecutionContext::HasFrameScope () const |
| { |
| return HasThreadScope() && m_frame_sp; |
| } |
| |
| ExecutionContextRef::ExecutionContextRef() : |
| m_target_wp (), |
| m_process_wp (), |
| m_thread_wp (), |
| m_frame_wp (), |
| m_tid(LLDB_INVALID_THREAD_ID), |
| m_stack_id () |
| { |
| } |
| |
| ExecutionContextRef::ExecutionContextRef (const ExecutionContext *exe_ctx) : |
| m_target_wp (), |
| m_process_wp (), |
| m_thread_wp (), |
| m_frame_wp (), |
| m_tid(LLDB_INVALID_THREAD_ID), |
| m_stack_id () |
| { |
| if (exe_ctx) |
| *this = *exe_ctx; |
| } |
| |
| ExecutionContextRef::ExecutionContextRef (const ExecutionContext &exe_ctx) : |
| m_target_wp (), |
| m_process_wp (), |
| m_thread_wp (), |
| m_frame_wp (), |
| m_tid(LLDB_INVALID_THREAD_ID), |
| m_stack_id () |
| { |
| *this = exe_ctx; |
| } |
| |
| |
| ExecutionContextRef::ExecutionContextRef (Target *target, bool adopt_selected) : |
| m_target_wp(), |
| m_process_wp(), |
| m_thread_wp(), |
| m_frame_wp(), |
| m_tid(LLDB_INVALID_THREAD_ID), |
| m_stack_id () |
| { |
| SetTargetPtr (target, adopt_selected); |
| } |
| |
| |
| |
| |
| ExecutionContextRef::ExecutionContextRef (const ExecutionContextRef &rhs) : |
| m_target_wp (rhs.m_target_wp), |
| m_process_wp(rhs.m_process_wp), |
| m_thread_wp (rhs.m_thread_wp), |
| m_frame_wp (rhs.m_frame_wp), |
| m_tid (rhs.m_tid), |
| m_stack_id (rhs.m_stack_id) |
| { |
| } |
| |
| ExecutionContextRef & |
| ExecutionContextRef::operator =(const ExecutionContextRef &rhs) |
| { |
| if (this != &rhs) |
| { |
| m_target_wp = rhs.m_target_wp; |
| m_process_wp = rhs.m_process_wp; |
| m_thread_wp = rhs.m_thread_wp; |
| m_frame_wp = rhs.m_frame_wp; |
| m_tid = rhs.m_tid; |
| m_stack_id = rhs.m_stack_id; |
| } |
| return *this; |
| } |
| |
| ExecutionContextRef & |
| ExecutionContextRef::operator =(const ExecutionContext &exe_ctx) |
| { |
| m_target_wp = exe_ctx.GetTargetSP(); |
| m_process_wp = exe_ctx.GetProcessSP(); |
| lldb::ThreadSP thread_sp (exe_ctx.GetThreadSP()); |
| m_thread_wp = thread_sp; |
| if (thread_sp) |
| m_tid = thread_sp->GetID(); |
| else |
| m_tid = LLDB_INVALID_THREAD_ID; |
| lldb::StackFrameSP frame_sp (exe_ctx.GetFrameSP()); |
| m_frame_wp = frame_sp; |
| if (frame_sp) |
| m_stack_id = frame_sp->GetStackID(); |
| else |
| m_stack_id.Clear(); |
| return *this; |
| } |
| |
| void |
| ExecutionContextRef::Clear() |
| { |
| m_target_wp.reset(); |
| m_process_wp.reset(); |
| ClearThread(); |
| ClearFrame(); |
| } |
| |
| ExecutionContextRef::~ExecutionContextRef() |
| { |
| } |
| |
| void |
| ExecutionContextRef::SetTargetSP (const lldb::TargetSP &target_sp) |
| { |
| m_target_wp = target_sp; |
| } |
| |
| void |
| ExecutionContextRef::SetProcessSP (const lldb::ProcessSP &process_sp) |
| { |
| if (process_sp) |
| { |
| m_process_wp = process_sp; |
| SetTargetSP (process_sp->GetTarget().shared_from_this()); |
| } |
| else |
| { |
| m_process_wp.reset(); |
| m_target_wp.reset(); |
| } |
| } |
| |
| void |
| ExecutionContextRef::SetThreadSP (const lldb::ThreadSP &thread_sp) |
| { |
| if (thread_sp) |
| { |
| m_thread_wp = thread_sp; |
| m_tid = thread_sp->GetID(); |
| SetProcessSP (thread_sp->GetProcess()); |
| } |
| else |
| { |
| ClearThread(); |
| m_process_wp.reset(); |
| m_target_wp.reset(); |
| } |
| } |
| |
| void |
| ExecutionContextRef::SetFrameSP (const lldb::StackFrameSP &frame_sp) |
| { |
| if (frame_sp) |
| { |
| m_frame_wp = frame_sp; |
| m_stack_id = frame_sp->GetStackID(); |
| SetThreadSP (frame_sp->GetThread()); |
| } |
| else |
| { |
| ClearFrame(); |
| ClearThread(); |
| m_process_wp.reset(); |
| m_target_wp.reset(); |
| } |
| |
| } |
| |
| void |
| ExecutionContextRef::SetTargetPtr (Target* target, bool adopt_selected) |
| { |
| Clear(); |
| if (target) |
| { |
| lldb::TargetSP target_sp (target->shared_from_this()); |
| if (target_sp) |
| { |
| m_target_wp = target_sp; |
| if (adopt_selected) |
| { |
| lldb::ProcessSP process_sp (target_sp->GetProcessSP()); |
| if (process_sp) |
| { |
| m_process_wp = process_sp; |
| if (process_sp) |
| { |
| // Only fill in the thread and frame if our process is stopped |
| if (StateIsStoppedState (process_sp->GetState(), true)) |
| { |
| lldb::ThreadSP thread_sp (process_sp->GetThreadList().GetSelectedThread()); |
| if (!thread_sp) |
| thread_sp = process_sp->GetThreadList().GetThreadAtIndex(0); |
| |
| if (thread_sp) |
| { |
| SetThreadSP (thread_sp); |
| lldb::StackFrameSP frame_sp (thread_sp->GetSelectedFrame()); |
| if (!frame_sp) |
| frame_sp = thread_sp->GetStackFrameAtIndex(0); |
| if (frame_sp) |
| SetFrameSP (frame_sp); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| void |
| ExecutionContextRef::SetProcessPtr (Process *process) |
| { |
| if (process) |
| { |
| SetProcessSP(process->shared_from_this()); |
| } |
| else |
| { |
| m_process_wp.reset(); |
| m_target_wp.reset(); |
| } |
| } |
| |
| void |
| ExecutionContextRef::SetThreadPtr (Thread *thread) |
| { |
| if (thread) |
| { |
| SetThreadSP (thread->shared_from_this()); |
| } |
| else |
| { |
| ClearThread(); |
| m_process_wp.reset(); |
| m_target_wp.reset(); |
| } |
| } |
| |
| void |
| ExecutionContextRef::SetFramePtr (StackFrame *frame) |
| { |
| if (frame) |
| SetFrameSP (frame->shared_from_this()); |
| else |
| Clear(); |
| } |
| |
| lldb::TargetSP |
| ExecutionContextRef::GetTargetSP () const |
| { |
| lldb::TargetSP target_sp(m_target_wp.lock()); |
| if (target_sp && !target_sp->IsValid()) |
| target_sp.reset(); |
| return target_sp; |
| } |
| |
| lldb::ProcessSP |
| ExecutionContextRef::GetProcessSP () const |
| { |
| lldb::ProcessSP process_sp(m_process_wp.lock()); |
| if (process_sp && !process_sp->IsValid()) |
| process_sp.reset(); |
| return process_sp; |
| } |
| |
| lldb::ThreadSP |
| ExecutionContextRef::GetThreadSP () const |
| { |
| lldb::ThreadSP thread_sp (m_thread_wp.lock()); |
| |
| if (m_tid != LLDB_INVALID_THREAD_ID) |
| { |
| // We check if the thread has been destroyed in cases where clients |
| // might still have shared pointer to a thread, but the thread is |
| // not valid anymore (not part of the process) |
| if (!thread_sp || !thread_sp->IsValid()) |
| { |
| lldb::ProcessSP process_sp(GetProcessSP()); |
| if (process_sp && process_sp->IsValid()) |
| { |
| thread_sp = process_sp->GetThreadList().FindThreadByID(m_tid); |
| m_thread_wp = thread_sp; |
| } |
| } |
| } |
| |
| // Check that we aren't about to return an invalid thread sp. We might return a NULL thread_sp, |
| // but don't return an invalid one. |
| |
| if (thread_sp && !thread_sp->IsValid()) |
| thread_sp.reset(); |
| |
| return thread_sp; |
| } |
| |
| lldb::StackFrameSP |
| ExecutionContextRef::GetFrameSP () const |
| { |
| lldb::StackFrameSP frame_sp (m_frame_wp.lock()); |
| if (!frame_sp && m_stack_id.IsValid()) |
| { |
| lldb::ThreadSP thread_sp (GetThreadSP()); |
| if (thread_sp) |
| { |
| frame_sp = thread_sp->GetFrameWithStackID (m_stack_id); |
| m_frame_wp = frame_sp; |
| } |
| else |
| { |
| // If the thread that this frame was supposed to belong to is not valid, then |
| // return a NULL frame_sp. |
| frame_sp.reset(); |
| } |
| } |
| return frame_sp; |
| } |
| |
| ExecutionContext |
| ExecutionContextRef::Lock () const |
| { |
| return ExecutionContext(this); |
| } |
| |
| |