1dda28197Spatrick //===-- ExecutionContext.cpp ----------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Target/ExecutionContext.h"
10061da546Spatrick #include "lldb/Target/ExecutionContextScope.h"
11061da546Spatrick #include "lldb/Target/Process.h"
12061da546Spatrick #include "lldb/Target/StackFrame.h"
13061da546Spatrick #include "lldb/Target/Target.h"
14061da546Spatrick #include "lldb/Target/Thread.h"
15061da546Spatrick #include "lldb/Utility/State.h"
16061da546Spatrick 
17061da546Spatrick using namespace lldb_private;
18061da546Spatrick 
ExecutionContext()19061da546Spatrick ExecutionContext::ExecutionContext()
20061da546Spatrick     : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {}
21061da546Spatrick 
22*f6aab3d8Srobert ExecutionContext::ExecutionContext(const ExecutionContext &rhs) = default;
23061da546Spatrick 
ExecutionContext(const lldb::TargetSP & target_sp,bool get_process)24061da546Spatrick ExecutionContext::ExecutionContext(const lldb::TargetSP &target_sp,
25061da546Spatrick                                    bool get_process)
26061da546Spatrick     : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
27061da546Spatrick   if (target_sp)
28061da546Spatrick     SetContext(target_sp, get_process);
29061da546Spatrick }
30061da546Spatrick 
ExecutionContext(const lldb::ProcessSP & process_sp)31061da546Spatrick ExecutionContext::ExecutionContext(const lldb::ProcessSP &process_sp)
32061da546Spatrick     : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
33061da546Spatrick   if (process_sp)
34061da546Spatrick     SetContext(process_sp);
35061da546Spatrick }
36061da546Spatrick 
ExecutionContext(const lldb::ThreadSP & thread_sp)37061da546Spatrick ExecutionContext::ExecutionContext(const lldb::ThreadSP &thread_sp)
38061da546Spatrick     : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
39061da546Spatrick   if (thread_sp)
40061da546Spatrick     SetContext(thread_sp);
41061da546Spatrick }
42061da546Spatrick 
ExecutionContext(const lldb::StackFrameSP & frame_sp)43061da546Spatrick ExecutionContext::ExecutionContext(const lldb::StackFrameSP &frame_sp)
44061da546Spatrick     : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
45061da546Spatrick   if (frame_sp)
46061da546Spatrick     SetContext(frame_sp);
47061da546Spatrick }
48061da546Spatrick 
ExecutionContext(const lldb::TargetWP & target_wp,bool get_process)49061da546Spatrick ExecutionContext::ExecutionContext(const lldb::TargetWP &target_wp,
50061da546Spatrick                                    bool get_process)
51061da546Spatrick     : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
52061da546Spatrick   lldb::TargetSP target_sp(target_wp.lock());
53061da546Spatrick   if (target_sp)
54061da546Spatrick     SetContext(target_sp, get_process);
55061da546Spatrick }
56061da546Spatrick 
ExecutionContext(const lldb::ProcessWP & process_wp)57061da546Spatrick ExecutionContext::ExecutionContext(const lldb::ProcessWP &process_wp)
58061da546Spatrick     : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
59061da546Spatrick   lldb::ProcessSP process_sp(process_wp.lock());
60061da546Spatrick   if (process_sp)
61061da546Spatrick     SetContext(process_sp);
62061da546Spatrick }
63061da546Spatrick 
ExecutionContext(const lldb::ThreadWP & thread_wp)64061da546Spatrick ExecutionContext::ExecutionContext(const lldb::ThreadWP &thread_wp)
65061da546Spatrick     : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
66061da546Spatrick   lldb::ThreadSP thread_sp(thread_wp.lock());
67061da546Spatrick   if (thread_sp)
68061da546Spatrick     SetContext(thread_sp);
69061da546Spatrick }
70061da546Spatrick 
ExecutionContext(const lldb::StackFrameWP & frame_wp)71061da546Spatrick ExecutionContext::ExecutionContext(const lldb::StackFrameWP &frame_wp)
72061da546Spatrick     : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
73061da546Spatrick   lldb::StackFrameSP frame_sp(frame_wp.lock());
74061da546Spatrick   if (frame_sp)
75061da546Spatrick     SetContext(frame_sp);
76061da546Spatrick }
77061da546Spatrick 
ExecutionContext(Target * t,bool fill_current_process_thread_frame)78061da546Spatrick ExecutionContext::ExecutionContext(Target *t,
79061da546Spatrick                                    bool fill_current_process_thread_frame)
80061da546Spatrick     : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
81061da546Spatrick   if (t) {
82061da546Spatrick     m_target_sp = t->shared_from_this();
83061da546Spatrick     if (fill_current_process_thread_frame) {
84061da546Spatrick       m_process_sp = t->GetProcessSP();
85061da546Spatrick       if (m_process_sp) {
86061da546Spatrick         m_thread_sp = m_process_sp->GetThreadList().GetSelectedThread();
87061da546Spatrick         if (m_thread_sp)
88061da546Spatrick           m_frame_sp = m_thread_sp->GetSelectedFrame();
89061da546Spatrick       }
90061da546Spatrick     }
91061da546Spatrick   }
92061da546Spatrick }
93061da546Spatrick 
ExecutionContext(Process * process,Thread * thread,StackFrame * frame)94061da546Spatrick ExecutionContext::ExecutionContext(Process *process, Thread *thread,
95061da546Spatrick                                    StackFrame *frame)
96061da546Spatrick     : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
97061da546Spatrick   if (process) {
98061da546Spatrick     m_process_sp = process->shared_from_this();
99061da546Spatrick     m_target_sp = process->GetTarget().shared_from_this();
100061da546Spatrick   }
101061da546Spatrick   if (thread)
102061da546Spatrick     m_thread_sp = thread->shared_from_this();
103061da546Spatrick   if (frame)
104061da546Spatrick     m_frame_sp = frame->shared_from_this();
105061da546Spatrick }
106061da546Spatrick 
ExecutionContext(const ExecutionContextRef & exe_ctx_ref)107061da546Spatrick ExecutionContext::ExecutionContext(const ExecutionContextRef &exe_ctx_ref)
108061da546Spatrick     : m_target_sp(exe_ctx_ref.GetTargetSP()),
109061da546Spatrick       m_process_sp(exe_ctx_ref.GetProcessSP()),
110061da546Spatrick       m_thread_sp(exe_ctx_ref.GetThreadSP()),
111061da546Spatrick       m_frame_sp(exe_ctx_ref.GetFrameSP()) {}
112061da546Spatrick 
ExecutionContext(const ExecutionContextRef * exe_ctx_ref_ptr,bool thread_and_frame_only_if_stopped)113061da546Spatrick ExecutionContext::ExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr,
114061da546Spatrick                                    bool thread_and_frame_only_if_stopped)
115061da546Spatrick     : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
116061da546Spatrick   if (exe_ctx_ref_ptr) {
117061da546Spatrick     m_target_sp = exe_ctx_ref_ptr->GetTargetSP();
118061da546Spatrick     m_process_sp = exe_ctx_ref_ptr->GetProcessSP();
119061da546Spatrick     if (!thread_and_frame_only_if_stopped ||
120061da546Spatrick         (m_process_sp && StateIsStoppedState(m_process_sp->GetState(), true))) {
121061da546Spatrick       m_thread_sp = exe_ctx_ref_ptr->GetThreadSP();
122061da546Spatrick       m_frame_sp = exe_ctx_ref_ptr->GetFrameSP();
123061da546Spatrick     }
124061da546Spatrick   }
125061da546Spatrick }
126061da546Spatrick 
ExecutionContext(const ExecutionContextRef * exe_ctx_ref_ptr,std::unique_lock<std::recursive_mutex> & lock)127061da546Spatrick ExecutionContext::ExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr,
128061da546Spatrick                                    std::unique_lock<std::recursive_mutex> &lock)
129061da546Spatrick     : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
130061da546Spatrick   if (exe_ctx_ref_ptr) {
131061da546Spatrick     m_target_sp = exe_ctx_ref_ptr->GetTargetSP();
132061da546Spatrick     if (m_target_sp) {
133061da546Spatrick       lock = std::unique_lock<std::recursive_mutex>(m_target_sp->GetAPIMutex());
134061da546Spatrick 
135061da546Spatrick       m_process_sp = exe_ctx_ref_ptr->GetProcessSP();
136061da546Spatrick       m_thread_sp = exe_ctx_ref_ptr->GetThreadSP();
137061da546Spatrick       m_frame_sp = exe_ctx_ref_ptr->GetFrameSP();
138061da546Spatrick     }
139061da546Spatrick   }
140061da546Spatrick }
141061da546Spatrick 
ExecutionContext(const ExecutionContextRef & exe_ctx_ref,std::unique_lock<std::recursive_mutex> & lock)142061da546Spatrick ExecutionContext::ExecutionContext(const ExecutionContextRef &exe_ctx_ref,
143061da546Spatrick                                    std::unique_lock<std::recursive_mutex> &lock)
144061da546Spatrick     : m_target_sp(exe_ctx_ref.GetTargetSP()), m_process_sp(), m_thread_sp(),
145061da546Spatrick       m_frame_sp() {
146061da546Spatrick   if (m_target_sp) {
147061da546Spatrick     lock = std::unique_lock<std::recursive_mutex>(m_target_sp->GetAPIMutex());
148061da546Spatrick 
149061da546Spatrick     m_process_sp = exe_ctx_ref.GetProcessSP();
150061da546Spatrick     m_thread_sp = exe_ctx_ref.GetThreadSP();
151061da546Spatrick     m_frame_sp = exe_ctx_ref.GetFrameSP();
152061da546Spatrick   }
153061da546Spatrick }
154061da546Spatrick 
ExecutionContext(ExecutionContextScope * exe_scope_ptr)155061da546Spatrick ExecutionContext::ExecutionContext(ExecutionContextScope *exe_scope_ptr)
156061da546Spatrick     : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {
157061da546Spatrick   if (exe_scope_ptr)
158061da546Spatrick     exe_scope_ptr->CalculateExecutionContext(*this);
159061da546Spatrick }
160061da546Spatrick 
ExecutionContext(ExecutionContextScope & exe_scope_ref)161061da546Spatrick ExecutionContext::ExecutionContext(ExecutionContextScope &exe_scope_ref) {
162061da546Spatrick   exe_scope_ref.CalculateExecutionContext(*this);
163061da546Spatrick }
164061da546Spatrick 
Clear()165061da546Spatrick void ExecutionContext::Clear() {
166061da546Spatrick   m_target_sp.reset();
167061da546Spatrick   m_process_sp.reset();
168061da546Spatrick   m_thread_sp.reset();
169061da546Spatrick   m_frame_sp.reset();
170061da546Spatrick }
171061da546Spatrick 
172061da546Spatrick ExecutionContext::~ExecutionContext() = default;
173061da546Spatrick 
GetAddressByteSize() const174061da546Spatrick uint32_t ExecutionContext::GetAddressByteSize() const {
175061da546Spatrick   if (m_target_sp && m_target_sp->GetArchitecture().IsValid())
176061da546Spatrick     return m_target_sp->GetArchitecture().GetAddressByteSize();
177061da546Spatrick   if (m_process_sp)
178061da546Spatrick     return m_process_sp->GetAddressByteSize();
179061da546Spatrick   return sizeof(void *);
180061da546Spatrick }
181061da546Spatrick 
GetByteOrder() const182061da546Spatrick lldb::ByteOrder ExecutionContext::GetByteOrder() const {
183061da546Spatrick   if (m_target_sp && m_target_sp->GetArchitecture().IsValid())
184061da546Spatrick     return m_target_sp->GetArchitecture().GetByteOrder();
185061da546Spatrick   if (m_process_sp)
186061da546Spatrick     return m_process_sp->GetByteOrder();
187061da546Spatrick   return endian::InlHostByteOrder();
188061da546Spatrick }
189061da546Spatrick 
GetRegisterContext() const190061da546Spatrick RegisterContext *ExecutionContext::GetRegisterContext() const {
191061da546Spatrick   if (m_frame_sp)
192061da546Spatrick     return m_frame_sp->GetRegisterContext().get();
193061da546Spatrick   else if (m_thread_sp)
194061da546Spatrick     return m_thread_sp->GetRegisterContext().get();
195061da546Spatrick   return nullptr;
196061da546Spatrick }
197061da546Spatrick 
GetTargetPtr() const198061da546Spatrick Target *ExecutionContext::GetTargetPtr() const {
199061da546Spatrick   if (m_target_sp)
200061da546Spatrick     return m_target_sp.get();
201061da546Spatrick   if (m_process_sp)
202061da546Spatrick     return &m_process_sp->GetTarget();
203061da546Spatrick   return nullptr;
204061da546Spatrick }
205061da546Spatrick 
GetProcessPtr() const206061da546Spatrick Process *ExecutionContext::GetProcessPtr() const {
207061da546Spatrick   if (m_process_sp)
208061da546Spatrick     return m_process_sp.get();
209061da546Spatrick   if (m_target_sp)
210061da546Spatrick     return m_target_sp->GetProcessSP().get();
211061da546Spatrick   return nullptr;
212061da546Spatrick }
213061da546Spatrick 
GetBestExecutionContextScope() const214061da546Spatrick ExecutionContextScope *ExecutionContext::GetBestExecutionContextScope() const {
215061da546Spatrick   if (m_frame_sp)
216061da546Spatrick     return m_frame_sp.get();
217061da546Spatrick   if (m_thread_sp)
218061da546Spatrick     return m_thread_sp.get();
219061da546Spatrick   if (m_process_sp)
220061da546Spatrick     return m_process_sp.get();
221061da546Spatrick   return m_target_sp.get();
222061da546Spatrick }
223061da546Spatrick 
GetTargetRef() const224061da546Spatrick Target &ExecutionContext::GetTargetRef() const {
225061da546Spatrick   assert(m_target_sp);
226061da546Spatrick   return *m_target_sp;
227061da546Spatrick }
228061da546Spatrick 
GetProcessRef() const229061da546Spatrick Process &ExecutionContext::GetProcessRef() const {
230061da546Spatrick   assert(m_process_sp);
231061da546Spatrick   return *m_process_sp;
232061da546Spatrick }
233061da546Spatrick 
GetThreadRef() const234061da546Spatrick Thread &ExecutionContext::GetThreadRef() const {
235061da546Spatrick   assert(m_thread_sp);
236061da546Spatrick   return *m_thread_sp;
237061da546Spatrick }
238061da546Spatrick 
GetFrameRef() const239061da546Spatrick StackFrame &ExecutionContext::GetFrameRef() const {
240061da546Spatrick   assert(m_frame_sp);
241061da546Spatrick   return *m_frame_sp;
242061da546Spatrick }
243061da546Spatrick 
SetTargetSP(const lldb::TargetSP & target_sp)244061da546Spatrick void ExecutionContext::SetTargetSP(const lldb::TargetSP &target_sp) {
245061da546Spatrick   m_target_sp = target_sp;
246061da546Spatrick }
247061da546Spatrick 
SetProcessSP(const lldb::ProcessSP & process_sp)248061da546Spatrick void ExecutionContext::SetProcessSP(const lldb::ProcessSP &process_sp) {
249061da546Spatrick   m_process_sp = process_sp;
250061da546Spatrick }
251061da546Spatrick 
SetThreadSP(const lldb::ThreadSP & thread_sp)252061da546Spatrick void ExecutionContext::SetThreadSP(const lldb::ThreadSP &thread_sp) {
253061da546Spatrick   m_thread_sp = thread_sp;
254061da546Spatrick }
255061da546Spatrick 
SetFrameSP(const lldb::StackFrameSP & frame_sp)256061da546Spatrick void ExecutionContext::SetFrameSP(const lldb::StackFrameSP &frame_sp) {
257061da546Spatrick   m_frame_sp = frame_sp;
258061da546Spatrick }
259061da546Spatrick 
SetTargetPtr(Target * target)260061da546Spatrick void ExecutionContext::SetTargetPtr(Target *target) {
261061da546Spatrick   if (target)
262061da546Spatrick     m_target_sp = target->shared_from_this();
263061da546Spatrick   else
264061da546Spatrick     m_target_sp.reset();
265061da546Spatrick }
266061da546Spatrick 
SetProcessPtr(Process * process)267061da546Spatrick void ExecutionContext::SetProcessPtr(Process *process) {
268061da546Spatrick   if (process)
269061da546Spatrick     m_process_sp = process->shared_from_this();
270061da546Spatrick   else
271061da546Spatrick     m_process_sp.reset();
272061da546Spatrick }
273061da546Spatrick 
SetThreadPtr(Thread * thread)274061da546Spatrick void ExecutionContext::SetThreadPtr(Thread *thread) {
275061da546Spatrick   if (thread)
276061da546Spatrick     m_thread_sp = thread->shared_from_this();
277061da546Spatrick   else
278061da546Spatrick     m_thread_sp.reset();
279061da546Spatrick }
280061da546Spatrick 
SetFramePtr(StackFrame * frame)281061da546Spatrick void ExecutionContext::SetFramePtr(StackFrame *frame) {
282061da546Spatrick   if (frame)
283061da546Spatrick     m_frame_sp = frame->shared_from_this();
284061da546Spatrick   else
285061da546Spatrick     m_frame_sp.reset();
286061da546Spatrick }
287061da546Spatrick 
SetContext(const lldb::TargetSP & target_sp,bool get_process)288061da546Spatrick void ExecutionContext::SetContext(const lldb::TargetSP &target_sp,
289061da546Spatrick                                   bool get_process) {
290061da546Spatrick   m_target_sp = target_sp;
291061da546Spatrick   if (get_process && target_sp)
292061da546Spatrick     m_process_sp = target_sp->GetProcessSP();
293061da546Spatrick   else
294061da546Spatrick     m_process_sp.reset();
295061da546Spatrick   m_thread_sp.reset();
296061da546Spatrick   m_frame_sp.reset();
297061da546Spatrick }
298061da546Spatrick 
SetContext(const lldb::ProcessSP & process_sp)299061da546Spatrick void ExecutionContext::SetContext(const lldb::ProcessSP &process_sp) {
300061da546Spatrick   m_process_sp = process_sp;
301061da546Spatrick   if (process_sp)
302061da546Spatrick     m_target_sp = process_sp->GetTarget().shared_from_this();
303061da546Spatrick   else
304061da546Spatrick     m_target_sp.reset();
305061da546Spatrick   m_thread_sp.reset();
306061da546Spatrick   m_frame_sp.reset();
307061da546Spatrick }
308061da546Spatrick 
SetContext(const lldb::ThreadSP & thread_sp)309061da546Spatrick void ExecutionContext::SetContext(const lldb::ThreadSP &thread_sp) {
310061da546Spatrick   m_frame_sp.reset();
311061da546Spatrick   m_thread_sp = thread_sp;
312061da546Spatrick   if (thread_sp) {
313061da546Spatrick     m_process_sp = thread_sp->GetProcess();
314061da546Spatrick     if (m_process_sp)
315061da546Spatrick       m_target_sp = m_process_sp->GetTarget().shared_from_this();
316061da546Spatrick     else
317061da546Spatrick       m_target_sp.reset();
318061da546Spatrick   } else {
319061da546Spatrick     m_target_sp.reset();
320061da546Spatrick     m_process_sp.reset();
321061da546Spatrick   }
322061da546Spatrick }
323061da546Spatrick 
SetContext(const lldb::StackFrameSP & frame_sp)324061da546Spatrick void ExecutionContext::SetContext(const lldb::StackFrameSP &frame_sp) {
325061da546Spatrick   m_frame_sp = frame_sp;
326061da546Spatrick   if (frame_sp) {
327061da546Spatrick     m_thread_sp = frame_sp->CalculateThread();
328061da546Spatrick     if (m_thread_sp) {
329061da546Spatrick       m_process_sp = m_thread_sp->GetProcess();
330061da546Spatrick       if (m_process_sp)
331061da546Spatrick         m_target_sp = m_process_sp->GetTarget().shared_from_this();
332061da546Spatrick       else
333061da546Spatrick         m_target_sp.reset();
334061da546Spatrick     } else {
335061da546Spatrick       m_target_sp.reset();
336061da546Spatrick       m_process_sp.reset();
337061da546Spatrick     }
338061da546Spatrick   } else {
339061da546Spatrick     m_target_sp.reset();
340061da546Spatrick     m_process_sp.reset();
341061da546Spatrick     m_thread_sp.reset();
342061da546Spatrick   }
343061da546Spatrick }
344061da546Spatrick 
operator =(const ExecutionContext & rhs)345061da546Spatrick ExecutionContext &ExecutionContext::operator=(const ExecutionContext &rhs) {
346061da546Spatrick   if (this != &rhs) {
347061da546Spatrick     m_target_sp = rhs.m_target_sp;
348061da546Spatrick     m_process_sp = rhs.m_process_sp;
349061da546Spatrick     m_thread_sp = rhs.m_thread_sp;
350061da546Spatrick     m_frame_sp = rhs.m_frame_sp;
351061da546Spatrick   }
352061da546Spatrick   return *this;
353061da546Spatrick }
354061da546Spatrick 
operator ==(const ExecutionContext & rhs) const355061da546Spatrick bool ExecutionContext::operator==(const ExecutionContext &rhs) const {
356061da546Spatrick   // Check that the frame shared pointers match, or both are valid and their
357061da546Spatrick   // stack IDs match since sometimes we get new objects that represent the same
358061da546Spatrick   // frame within a thread.
359061da546Spatrick   if ((m_frame_sp == rhs.m_frame_sp) ||
360061da546Spatrick       (m_frame_sp && rhs.m_frame_sp &&
361061da546Spatrick        m_frame_sp->GetStackID() == rhs.m_frame_sp->GetStackID())) {
362061da546Spatrick     // Check that the thread shared pointers match, or both are valid and their
363061da546Spatrick     // thread IDs match since sometimes we get new objects that represent the
364061da546Spatrick     // same thread within a process.
365061da546Spatrick     if ((m_thread_sp == rhs.m_thread_sp) ||
366061da546Spatrick         (m_thread_sp && rhs.m_thread_sp &&
367061da546Spatrick          m_thread_sp->GetID() == rhs.m_thread_sp->GetID())) {
368061da546Spatrick       // Processes and targets don't change much
369061da546Spatrick       return m_process_sp == rhs.m_process_sp && m_target_sp == rhs.m_target_sp;
370061da546Spatrick     }
371061da546Spatrick   }
372061da546Spatrick   return false;
373061da546Spatrick }
374061da546Spatrick 
operator !=(const ExecutionContext & rhs) const375061da546Spatrick bool ExecutionContext::operator!=(const ExecutionContext &rhs) const {
376061da546Spatrick   return !(*this == rhs);
377061da546Spatrick }
378061da546Spatrick 
HasTargetScope() const379061da546Spatrick bool ExecutionContext::HasTargetScope() const {
380061da546Spatrick   return ((bool)m_target_sp && m_target_sp->IsValid());
381061da546Spatrick }
382061da546Spatrick 
HasProcessScope() const383061da546Spatrick bool ExecutionContext::HasProcessScope() const {
384061da546Spatrick   return (HasTargetScope() && ((bool)m_process_sp && m_process_sp->IsValid()));
385061da546Spatrick }
386061da546Spatrick 
HasThreadScope() const387061da546Spatrick bool ExecutionContext::HasThreadScope() const {
388061da546Spatrick   return (HasProcessScope() && ((bool)m_thread_sp && m_thread_sp->IsValid()));
389061da546Spatrick }
390061da546Spatrick 
HasFrameScope() const391061da546Spatrick bool ExecutionContext::HasFrameScope() const {
392061da546Spatrick   return HasThreadScope() && m_frame_sp;
393061da546Spatrick }
394061da546Spatrick 
ExecutionContextRef()395061da546Spatrick ExecutionContextRef::ExecutionContextRef()
396be691f3bSpatrick     : m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() {}
397061da546Spatrick 
ExecutionContextRef(const ExecutionContext * exe_ctx)398061da546Spatrick ExecutionContextRef::ExecutionContextRef(const ExecutionContext *exe_ctx)
399*f6aab3d8Srobert     : m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() {
400061da546Spatrick   if (exe_ctx)
401061da546Spatrick     *this = *exe_ctx;
402061da546Spatrick }
403061da546Spatrick 
ExecutionContextRef(const ExecutionContext & exe_ctx)404061da546Spatrick ExecutionContextRef::ExecutionContextRef(const ExecutionContext &exe_ctx)
405*f6aab3d8Srobert     : m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() {
406061da546Spatrick   *this = exe_ctx;
407061da546Spatrick }
408061da546Spatrick 
ExecutionContextRef(Target * target,bool adopt_selected)409061da546Spatrick ExecutionContextRef::ExecutionContextRef(Target *target, bool adopt_selected)
410*f6aab3d8Srobert     : m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() {
411061da546Spatrick   SetTargetPtr(target, adopt_selected);
412061da546Spatrick }
413061da546Spatrick 
414061da546Spatrick ExecutionContextRef::ExecutionContextRef(const ExecutionContextRef &rhs)
415*f6aab3d8Srobert 
416*f6aab3d8Srobert     = default;
417061da546Spatrick 
418061da546Spatrick ExecutionContextRef &ExecutionContextRef::
operator =(const ExecutionContextRef & rhs)419061da546Spatrick operator=(const ExecutionContextRef &rhs) {
420061da546Spatrick   if (this != &rhs) {
421061da546Spatrick     m_target_wp = rhs.m_target_wp;
422061da546Spatrick     m_process_wp = rhs.m_process_wp;
423061da546Spatrick     m_thread_wp = rhs.m_thread_wp;
424061da546Spatrick     m_tid = rhs.m_tid;
425061da546Spatrick     m_stack_id = rhs.m_stack_id;
426061da546Spatrick   }
427061da546Spatrick   return *this;
428061da546Spatrick }
429061da546Spatrick 
430061da546Spatrick ExecutionContextRef &ExecutionContextRef::
operator =(const ExecutionContext & exe_ctx)431061da546Spatrick operator=(const ExecutionContext &exe_ctx) {
432061da546Spatrick   m_target_wp = exe_ctx.GetTargetSP();
433061da546Spatrick   m_process_wp = exe_ctx.GetProcessSP();
434061da546Spatrick   lldb::ThreadSP thread_sp(exe_ctx.GetThreadSP());
435061da546Spatrick   m_thread_wp = thread_sp;
436061da546Spatrick   if (thread_sp)
437061da546Spatrick     m_tid = thread_sp->GetID();
438061da546Spatrick   else
439061da546Spatrick     m_tid = LLDB_INVALID_THREAD_ID;
440061da546Spatrick   lldb::StackFrameSP frame_sp(exe_ctx.GetFrameSP());
441061da546Spatrick   if (frame_sp)
442061da546Spatrick     m_stack_id = frame_sp->GetStackID();
443061da546Spatrick   else
444061da546Spatrick     m_stack_id.Clear();
445061da546Spatrick   return *this;
446061da546Spatrick }
447061da546Spatrick 
Clear()448061da546Spatrick void ExecutionContextRef::Clear() {
449061da546Spatrick   m_target_wp.reset();
450061da546Spatrick   m_process_wp.reset();
451061da546Spatrick   ClearThread();
452061da546Spatrick   ClearFrame();
453061da546Spatrick }
454061da546Spatrick 
455061da546Spatrick ExecutionContextRef::~ExecutionContextRef() = default;
456061da546Spatrick 
SetTargetSP(const lldb::TargetSP & target_sp)457061da546Spatrick void ExecutionContextRef::SetTargetSP(const lldb::TargetSP &target_sp) {
458061da546Spatrick   m_target_wp = target_sp;
459061da546Spatrick }
460061da546Spatrick 
SetProcessSP(const lldb::ProcessSP & process_sp)461061da546Spatrick void ExecutionContextRef::SetProcessSP(const lldb::ProcessSP &process_sp) {
462061da546Spatrick   if (process_sp) {
463061da546Spatrick     m_process_wp = process_sp;
464061da546Spatrick     SetTargetSP(process_sp->GetTarget().shared_from_this());
465061da546Spatrick   } else {
466061da546Spatrick     m_process_wp.reset();
467061da546Spatrick     m_target_wp.reset();
468061da546Spatrick   }
469061da546Spatrick }
470061da546Spatrick 
SetThreadSP(const lldb::ThreadSP & thread_sp)471061da546Spatrick void ExecutionContextRef::SetThreadSP(const lldb::ThreadSP &thread_sp) {
472061da546Spatrick   if (thread_sp) {
473061da546Spatrick     m_thread_wp = thread_sp;
474061da546Spatrick     m_tid = thread_sp->GetID();
475061da546Spatrick     SetProcessSP(thread_sp->GetProcess());
476061da546Spatrick   } else {
477061da546Spatrick     ClearThread();
478061da546Spatrick     m_process_wp.reset();
479061da546Spatrick     m_target_wp.reset();
480061da546Spatrick   }
481061da546Spatrick }
482061da546Spatrick 
SetFrameSP(const lldb::StackFrameSP & frame_sp)483061da546Spatrick void ExecutionContextRef::SetFrameSP(const lldb::StackFrameSP &frame_sp) {
484061da546Spatrick   if (frame_sp) {
485061da546Spatrick     m_stack_id = frame_sp->GetStackID();
486061da546Spatrick     SetThreadSP(frame_sp->GetThread());
487061da546Spatrick   } else {
488061da546Spatrick     ClearFrame();
489061da546Spatrick     ClearThread();
490061da546Spatrick     m_process_wp.reset();
491061da546Spatrick     m_target_wp.reset();
492061da546Spatrick   }
493061da546Spatrick }
494061da546Spatrick 
SetTargetPtr(Target * target,bool adopt_selected)495061da546Spatrick void ExecutionContextRef::SetTargetPtr(Target *target, bool adopt_selected) {
496061da546Spatrick   Clear();
497061da546Spatrick   if (target) {
498061da546Spatrick     lldb::TargetSP target_sp(target->shared_from_this());
499061da546Spatrick     if (target_sp) {
500061da546Spatrick       m_target_wp = target_sp;
501061da546Spatrick       if (adopt_selected) {
502061da546Spatrick         lldb::ProcessSP process_sp(target_sp->GetProcessSP());
503061da546Spatrick         if (process_sp) {
504061da546Spatrick           m_process_wp = process_sp;
505061da546Spatrick           if (process_sp) {
506061da546Spatrick             // Only fill in the thread and frame if our process is stopped
507061da546Spatrick             // Don't just check the state, since we might be in the middle of
508061da546Spatrick             // resuming.
509061da546Spatrick             Process::StopLocker stop_locker;
510061da546Spatrick 
511061da546Spatrick             if (stop_locker.TryLock(&process_sp->GetRunLock()) &&
512061da546Spatrick                 StateIsStoppedState(process_sp->GetState(), true)) {
513061da546Spatrick               lldb::ThreadSP thread_sp(
514061da546Spatrick                   process_sp->GetThreadList().GetSelectedThread());
515061da546Spatrick               if (!thread_sp)
516061da546Spatrick                 thread_sp = process_sp->GetThreadList().GetThreadAtIndex(0);
517061da546Spatrick 
518061da546Spatrick               if (thread_sp) {
519061da546Spatrick                 SetThreadSP(thread_sp);
520061da546Spatrick                 lldb::StackFrameSP frame_sp(thread_sp->GetSelectedFrame());
521061da546Spatrick                 if (!frame_sp)
522061da546Spatrick                   frame_sp = thread_sp->GetStackFrameAtIndex(0);
523061da546Spatrick                 if (frame_sp)
524061da546Spatrick                   SetFrameSP(frame_sp);
525061da546Spatrick               }
526061da546Spatrick             }
527061da546Spatrick           }
528061da546Spatrick         }
529061da546Spatrick       }
530061da546Spatrick     }
531061da546Spatrick   }
532061da546Spatrick }
533061da546Spatrick 
SetProcessPtr(Process * process)534061da546Spatrick void ExecutionContextRef::SetProcessPtr(Process *process) {
535061da546Spatrick   if (process) {
536061da546Spatrick     SetProcessSP(process->shared_from_this());
537061da546Spatrick   } else {
538061da546Spatrick     m_process_wp.reset();
539061da546Spatrick     m_target_wp.reset();
540061da546Spatrick   }
541061da546Spatrick }
542061da546Spatrick 
SetThreadPtr(Thread * thread)543061da546Spatrick void ExecutionContextRef::SetThreadPtr(Thread *thread) {
544061da546Spatrick   if (thread) {
545061da546Spatrick     SetThreadSP(thread->shared_from_this());
546061da546Spatrick   } else {
547061da546Spatrick     ClearThread();
548061da546Spatrick     m_process_wp.reset();
549061da546Spatrick     m_target_wp.reset();
550061da546Spatrick   }
551061da546Spatrick }
552061da546Spatrick 
SetFramePtr(StackFrame * frame)553061da546Spatrick void ExecutionContextRef::SetFramePtr(StackFrame *frame) {
554061da546Spatrick   if (frame)
555061da546Spatrick     SetFrameSP(frame->shared_from_this());
556061da546Spatrick   else
557061da546Spatrick     Clear();
558061da546Spatrick }
559061da546Spatrick 
GetTargetSP() const560061da546Spatrick lldb::TargetSP ExecutionContextRef::GetTargetSP() const {
561061da546Spatrick   lldb::TargetSP target_sp(m_target_wp.lock());
562061da546Spatrick   if (target_sp && !target_sp->IsValid())
563061da546Spatrick     target_sp.reset();
564061da546Spatrick   return target_sp;
565061da546Spatrick }
566061da546Spatrick 
GetProcessSP() const567061da546Spatrick lldb::ProcessSP ExecutionContextRef::GetProcessSP() const {
568061da546Spatrick   lldb::ProcessSP process_sp(m_process_wp.lock());
569061da546Spatrick   if (process_sp && !process_sp->IsValid())
570061da546Spatrick     process_sp.reset();
571061da546Spatrick   return process_sp;
572061da546Spatrick }
573061da546Spatrick 
GetThreadSP() const574061da546Spatrick lldb::ThreadSP ExecutionContextRef::GetThreadSP() const {
575061da546Spatrick   lldb::ThreadSP thread_sp(m_thread_wp.lock());
576061da546Spatrick 
577061da546Spatrick   if (m_tid != LLDB_INVALID_THREAD_ID) {
578061da546Spatrick     // We check if the thread has been destroyed in cases where clients might
579061da546Spatrick     // still have shared pointer to a thread, but the thread is not valid
580061da546Spatrick     // anymore (not part of the process)
581061da546Spatrick     if (!thread_sp || !thread_sp->IsValid()) {
582061da546Spatrick       lldb::ProcessSP process_sp(GetProcessSP());
583061da546Spatrick       if (process_sp && process_sp->IsValid()) {
584061da546Spatrick         thread_sp = process_sp->GetThreadList().FindThreadByID(m_tid);
585061da546Spatrick         m_thread_wp = thread_sp;
586061da546Spatrick       }
587061da546Spatrick     }
588061da546Spatrick   }
589061da546Spatrick 
590061da546Spatrick   // Check that we aren't about to return an invalid thread sp.  We might
591061da546Spatrick   // return a nullptr thread_sp, but don't return an invalid one.
592061da546Spatrick 
593061da546Spatrick   if (thread_sp && !thread_sp->IsValid())
594061da546Spatrick     thread_sp.reset();
595061da546Spatrick 
596061da546Spatrick   return thread_sp;
597061da546Spatrick }
598061da546Spatrick 
GetFrameSP() const599061da546Spatrick lldb::StackFrameSP ExecutionContextRef::GetFrameSP() const {
600061da546Spatrick   if (m_stack_id.IsValid()) {
601061da546Spatrick     lldb::ThreadSP thread_sp(GetThreadSP());
602061da546Spatrick     if (thread_sp)
603061da546Spatrick       return thread_sp->GetFrameWithStackID(m_stack_id);
604061da546Spatrick   }
605061da546Spatrick   return lldb::StackFrameSP();
606061da546Spatrick }
607061da546Spatrick 
608061da546Spatrick ExecutionContext
Lock(bool thread_and_frame_only_if_stopped) const609061da546Spatrick ExecutionContextRef::Lock(bool thread_and_frame_only_if_stopped) const {
610061da546Spatrick   return ExecutionContext(this, thread_and_frame_only_if_stopped);
611061da546Spatrick }
612