1 | //===-- ExecutionContext.cpp ----------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "lldb/Target/ExecutionContext.h" |
10 | #include "lldb/Target/ExecutionContextScope.h" |
11 | #include "lldb/Target/Process.h" |
12 | #include "lldb/Target/StackFrame.h" |
13 | #include "lldb/Target/Target.h" |
14 | #include "lldb/Target/Thread.h" |
15 | #include "lldb/Utility/State.h" |
16 | |
17 | using namespace lldb_private; |
18 | |
19 | ExecutionContext::ExecutionContext() |
20 | : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {} |
21 | |
22 | ExecutionContext::ExecutionContext(const ExecutionContext &rhs) = default; |
23 | |
24 | ExecutionContext::ExecutionContext(const lldb::TargetSP &target_sp, |
25 | bool get_process) |
26 | : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() { |
27 | if (target_sp) |
28 | SetContext(target_sp, get_process); |
29 | } |
30 | |
31 | ExecutionContext::ExecutionContext(const lldb::ProcessSP &process_sp) |
32 | : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() { |
33 | if (process_sp) |
34 | SetContext(process_sp); |
35 | } |
36 | |
37 | ExecutionContext::ExecutionContext(const lldb::ThreadSP &thread_sp) |
38 | : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() { |
39 | if (thread_sp) |
40 | SetContext(thread_sp); |
41 | } |
42 | |
43 | ExecutionContext::ExecutionContext(const lldb::StackFrameSP &frame_sp) |
44 | : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() { |
45 | if (frame_sp) |
46 | SetContext(frame_sp); |
47 | } |
48 | |
49 | ExecutionContext::ExecutionContext(const lldb::TargetWP &target_wp, |
50 | bool get_process) |
51 | : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() { |
52 | lldb::TargetSP target_sp(target_wp.lock()); |
53 | if (target_sp) |
54 | SetContext(target_sp, get_process); |
55 | } |
56 | |
57 | ExecutionContext::ExecutionContext(const lldb::ProcessWP &process_wp) |
58 | : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() { |
59 | lldb::ProcessSP process_sp(process_wp.lock()); |
60 | if (process_sp) |
61 | SetContext(process_sp); |
62 | } |
63 | |
64 | ExecutionContext::ExecutionContext(const lldb::ThreadWP &thread_wp) |
65 | : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() { |
66 | lldb::ThreadSP thread_sp(thread_wp.lock()); |
67 | if (thread_sp) |
68 | SetContext(thread_sp); |
69 | } |
70 | |
71 | ExecutionContext::ExecutionContext(const lldb::StackFrameWP &frame_wp) |
72 | : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() { |
73 | lldb::StackFrameSP frame_sp(frame_wp.lock()); |
74 | if (frame_sp) |
75 | SetContext(frame_sp); |
76 | } |
77 | |
78 | ExecutionContext::ExecutionContext(Target *t, |
79 | bool fill_current_process_thread_frame) |
80 | : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() { |
81 | if (t) { |
82 | m_target_sp = t->shared_from_this(); |
83 | if (fill_current_process_thread_frame) { |
84 | m_process_sp = t->GetProcessSP(); |
85 | if (m_process_sp) { |
86 | m_thread_sp = m_process_sp->GetThreadList().GetSelectedThread(); |
87 | if (m_thread_sp) |
88 | m_frame_sp = |
89 | m_thread_sp->GetSelectedFrame(select_most_relevant: DoNoSelectMostRelevantFrame); |
90 | } |
91 | } |
92 | } |
93 | } |
94 | |
95 | ExecutionContext::ExecutionContext(Process *process, Thread *thread, |
96 | StackFrame *frame) |
97 | : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() { |
98 | if (process) { |
99 | m_process_sp = process->shared_from_this(); |
100 | m_target_sp = process->GetTarget().shared_from_this(); |
101 | } |
102 | if (thread) |
103 | m_thread_sp = thread->shared_from_this(); |
104 | if (frame) |
105 | m_frame_sp = frame->shared_from_this(); |
106 | } |
107 | |
108 | ExecutionContext::ExecutionContext(const ExecutionContextRef &exe_ctx_ref) |
109 | : m_target_sp(exe_ctx_ref.GetTargetSP()), |
110 | m_process_sp(exe_ctx_ref.GetProcessSP()), |
111 | m_thread_sp(exe_ctx_ref.GetThreadSP()), |
112 | m_frame_sp(exe_ctx_ref.GetFrameSP()) {} |
113 | |
114 | ExecutionContext::ExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr, |
115 | bool thread_and_frame_only_if_stopped) |
116 | : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() { |
117 | if (exe_ctx_ref_ptr) { |
118 | m_target_sp = exe_ctx_ref_ptr->GetTargetSP(); |
119 | m_process_sp = exe_ctx_ref_ptr->GetProcessSP(); |
120 | if (!thread_and_frame_only_if_stopped || |
121 | (m_process_sp && StateIsStoppedState(state: m_process_sp->GetState(), must_exist: true))) { |
122 | m_thread_sp = exe_ctx_ref_ptr->GetThreadSP(); |
123 | m_frame_sp = exe_ctx_ref_ptr->GetFrameSP(); |
124 | } |
125 | } |
126 | } |
127 | |
128 | ExecutionContext::ExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr, |
129 | std::unique_lock<std::recursive_mutex> &lock) |
130 | : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() { |
131 | if (exe_ctx_ref_ptr) { |
132 | m_target_sp = exe_ctx_ref_ptr->GetTargetSP(); |
133 | if (m_target_sp) { |
134 | lock = std::unique_lock<std::recursive_mutex>(m_target_sp->GetAPIMutex()); |
135 | |
136 | m_process_sp = exe_ctx_ref_ptr->GetProcessSP(); |
137 | m_thread_sp = exe_ctx_ref_ptr->GetThreadSP(); |
138 | m_frame_sp = exe_ctx_ref_ptr->GetFrameSP(); |
139 | } |
140 | } |
141 | } |
142 | |
143 | ExecutionContext::ExecutionContext(const ExecutionContextRef &exe_ctx_ref, |
144 | std::unique_lock<std::recursive_mutex> &lock) |
145 | : m_target_sp(exe_ctx_ref.GetTargetSP()), m_process_sp(), m_thread_sp(), |
146 | m_frame_sp() { |
147 | if (m_target_sp) { |
148 | lock = std::unique_lock<std::recursive_mutex>(m_target_sp->GetAPIMutex()); |
149 | |
150 | m_process_sp = exe_ctx_ref.GetProcessSP(); |
151 | m_thread_sp = exe_ctx_ref.GetThreadSP(); |
152 | m_frame_sp = exe_ctx_ref.GetFrameSP(); |
153 | } |
154 | } |
155 | |
156 | ExecutionContext::ExecutionContext(ExecutionContextScope *exe_scope_ptr) |
157 | : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() { |
158 | if (exe_scope_ptr) |
159 | exe_scope_ptr->CalculateExecutionContext(exe_ctx&: *this); |
160 | } |
161 | |
162 | ExecutionContext::ExecutionContext(ExecutionContextScope &exe_scope_ref) { |
163 | exe_scope_ref.CalculateExecutionContext(exe_ctx&: *this); |
164 | } |
165 | |
166 | void ExecutionContext::Clear() { |
167 | m_target_sp.reset(); |
168 | m_process_sp.reset(); |
169 | m_thread_sp.reset(); |
170 | m_frame_sp.reset(); |
171 | } |
172 | |
173 | ExecutionContext::~ExecutionContext() = default; |
174 | |
175 | uint32_t ExecutionContext::GetAddressByteSize() const { |
176 | if (m_target_sp && m_target_sp->GetArchitecture().IsValid()) |
177 | return m_target_sp->GetArchitecture().GetAddressByteSize(); |
178 | if (m_process_sp) |
179 | return m_process_sp->GetAddressByteSize(); |
180 | return sizeof(void *); |
181 | } |
182 | |
183 | lldb::ByteOrder ExecutionContext::GetByteOrder() const { |
184 | if (m_target_sp && m_target_sp->GetArchitecture().IsValid()) |
185 | return m_target_sp->GetArchitecture().GetByteOrder(); |
186 | if (m_process_sp) |
187 | return m_process_sp->GetByteOrder(); |
188 | return endian::InlHostByteOrder(); |
189 | } |
190 | |
191 | RegisterContext *ExecutionContext::GetRegisterContext() const { |
192 | if (m_frame_sp) |
193 | return m_frame_sp->GetRegisterContext().get(); |
194 | else if (m_thread_sp) |
195 | return m_thread_sp->GetRegisterContext().get(); |
196 | return nullptr; |
197 | } |
198 | |
199 | Target *ExecutionContext::GetTargetPtr() const { |
200 | if (m_target_sp) |
201 | return m_target_sp.get(); |
202 | if (m_process_sp) |
203 | return &m_process_sp->GetTarget(); |
204 | return nullptr; |
205 | } |
206 | |
207 | Process *ExecutionContext::GetProcessPtr() const { |
208 | if (m_process_sp) |
209 | return m_process_sp.get(); |
210 | if (m_target_sp) |
211 | return m_target_sp->GetProcessSP().get(); |
212 | return nullptr; |
213 | } |
214 | |
215 | ExecutionContextScope *ExecutionContext::GetBestExecutionContextScope() const { |
216 | if (m_frame_sp) |
217 | return m_frame_sp.get(); |
218 | if (m_thread_sp) |
219 | return m_thread_sp.get(); |
220 | if (m_process_sp) |
221 | return m_process_sp.get(); |
222 | return m_target_sp.get(); |
223 | } |
224 | |
225 | Target &ExecutionContext::GetTargetRef() const { |
226 | assert(m_target_sp); |
227 | return *m_target_sp; |
228 | } |
229 | |
230 | Process &ExecutionContext::GetProcessRef() const { |
231 | assert(m_process_sp); |
232 | return *m_process_sp; |
233 | } |
234 | |
235 | Thread &ExecutionContext::GetThreadRef() const { |
236 | assert(m_thread_sp); |
237 | return *m_thread_sp; |
238 | } |
239 | |
240 | StackFrame &ExecutionContext::GetFrameRef() const { |
241 | assert(m_frame_sp); |
242 | return *m_frame_sp; |
243 | } |
244 | |
245 | void ExecutionContext::SetTargetSP(const lldb::TargetSP &target_sp) { |
246 | m_target_sp = target_sp; |
247 | } |
248 | |
249 | void ExecutionContext::SetProcessSP(const lldb::ProcessSP &process_sp) { |
250 | m_process_sp = process_sp; |
251 | } |
252 | |
253 | void ExecutionContext::SetThreadSP(const lldb::ThreadSP &thread_sp) { |
254 | m_thread_sp = thread_sp; |
255 | } |
256 | |
257 | void ExecutionContext::SetFrameSP(const lldb::StackFrameSP &frame_sp) { |
258 | m_frame_sp = frame_sp; |
259 | } |
260 | |
261 | void ExecutionContext::SetTargetPtr(Target *target) { |
262 | if (target) |
263 | m_target_sp = target->shared_from_this(); |
264 | else |
265 | m_target_sp.reset(); |
266 | } |
267 | |
268 | void ExecutionContext::SetProcessPtr(Process *process) { |
269 | if (process) |
270 | m_process_sp = process->shared_from_this(); |
271 | else |
272 | m_process_sp.reset(); |
273 | } |
274 | |
275 | void ExecutionContext::SetThreadPtr(Thread *thread) { |
276 | if (thread) |
277 | m_thread_sp = thread->shared_from_this(); |
278 | else |
279 | m_thread_sp.reset(); |
280 | } |
281 | |
282 | void ExecutionContext::SetFramePtr(StackFrame *frame) { |
283 | if (frame) |
284 | m_frame_sp = frame->shared_from_this(); |
285 | else |
286 | m_frame_sp.reset(); |
287 | } |
288 | |
289 | void ExecutionContext::SetContext(const lldb::TargetSP &target_sp, |
290 | bool get_process) { |
291 | m_target_sp = target_sp; |
292 | if (get_process && target_sp) |
293 | m_process_sp = target_sp->GetProcessSP(); |
294 | else |
295 | m_process_sp.reset(); |
296 | m_thread_sp.reset(); |
297 | m_frame_sp.reset(); |
298 | } |
299 | |
300 | void ExecutionContext::SetContext(const lldb::ProcessSP &process_sp) { |
301 | m_process_sp = process_sp; |
302 | if (process_sp) |
303 | m_target_sp = process_sp->GetTarget().shared_from_this(); |
304 | else |
305 | m_target_sp.reset(); |
306 | m_thread_sp.reset(); |
307 | m_frame_sp.reset(); |
308 | } |
309 | |
310 | void ExecutionContext::SetContext(const lldb::ThreadSP &thread_sp) { |
311 | m_frame_sp.reset(); |
312 | m_thread_sp = thread_sp; |
313 | if (thread_sp) { |
314 | m_process_sp = thread_sp->GetProcess(); |
315 | if (m_process_sp) |
316 | m_target_sp = m_process_sp->GetTarget().shared_from_this(); |
317 | else |
318 | m_target_sp.reset(); |
319 | } else { |
320 | m_target_sp.reset(); |
321 | m_process_sp.reset(); |
322 | } |
323 | } |
324 | |
325 | void ExecutionContext::SetContext(const lldb::StackFrameSP &frame_sp) { |
326 | m_frame_sp = frame_sp; |
327 | if (frame_sp) { |
328 | m_thread_sp = frame_sp->CalculateThread(); |
329 | if (m_thread_sp) { |
330 | m_process_sp = m_thread_sp->GetProcess(); |
331 | if (m_process_sp) |
332 | m_target_sp = m_process_sp->GetTarget().shared_from_this(); |
333 | else |
334 | m_target_sp.reset(); |
335 | } else { |
336 | m_target_sp.reset(); |
337 | m_process_sp.reset(); |
338 | } |
339 | } else { |
340 | m_target_sp.reset(); |
341 | m_process_sp.reset(); |
342 | m_thread_sp.reset(); |
343 | } |
344 | } |
345 | |
346 | ExecutionContext &ExecutionContext::operator=(const ExecutionContext &rhs) { |
347 | if (this != &rhs) { |
348 | m_target_sp = rhs.m_target_sp; |
349 | m_process_sp = rhs.m_process_sp; |
350 | m_thread_sp = rhs.m_thread_sp; |
351 | m_frame_sp = rhs.m_frame_sp; |
352 | } |
353 | return *this; |
354 | } |
355 | |
356 | bool ExecutionContext::operator==(const ExecutionContext &rhs) const { |
357 | // Check that the frame shared pointers match, or both are valid and their |
358 | // stack IDs match since sometimes we get new objects that represent the same |
359 | // frame within a thread. |
360 | if ((m_frame_sp == rhs.m_frame_sp) || |
361 | (m_frame_sp && rhs.m_frame_sp && |
362 | m_frame_sp->GetStackID() == rhs.m_frame_sp->GetStackID())) { |
363 | // Check that the thread shared pointers match, or both are valid and their |
364 | // thread IDs match since sometimes we get new objects that represent the |
365 | // same thread within a process. |
366 | if ((m_thread_sp == rhs.m_thread_sp) || |
367 | (m_thread_sp && rhs.m_thread_sp && |
368 | m_thread_sp->GetID() == rhs.m_thread_sp->GetID())) { |
369 | // Processes and targets don't change much |
370 | return m_process_sp == rhs.m_process_sp && m_target_sp == rhs.m_target_sp; |
371 | } |
372 | } |
373 | return false; |
374 | } |
375 | |
376 | bool ExecutionContext::operator!=(const ExecutionContext &rhs) const { |
377 | return !(*this == rhs); |
378 | } |
379 | |
380 | bool ExecutionContext::HasTargetScope() const { |
381 | return ((bool)m_target_sp && m_target_sp->IsValid()); |
382 | } |
383 | |
384 | bool ExecutionContext::HasProcessScope() const { |
385 | return (HasTargetScope() && ((bool)m_process_sp && m_process_sp->IsValid())); |
386 | } |
387 | |
388 | bool ExecutionContext::HasThreadScope() const { |
389 | return (HasProcessScope() && ((bool)m_thread_sp && m_thread_sp->IsValid())); |
390 | } |
391 | |
392 | bool ExecutionContext::HasFrameScope() const { |
393 | return HasThreadScope() && m_frame_sp; |
394 | } |
395 | |
396 | ExecutionContextRef::ExecutionContextRef() |
397 | : m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() {} |
398 | |
399 | ExecutionContextRef::ExecutionContextRef(const ExecutionContext *exe_ctx) |
400 | : m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() { |
401 | if (exe_ctx) |
402 | *this = *exe_ctx; |
403 | } |
404 | |
405 | ExecutionContextRef::ExecutionContextRef(const ExecutionContext &exe_ctx) |
406 | : m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() { |
407 | *this = exe_ctx; |
408 | } |
409 | |
410 | ExecutionContextRef::ExecutionContextRef(Target *target, bool adopt_selected) |
411 | : m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() { |
412 | SetTargetPtr(target, adopt_selected); |
413 | } |
414 | |
415 | ExecutionContextRef::ExecutionContextRef(const ExecutionContextRef &rhs) |
416 | |
417 | = default; |
418 | |
419 | ExecutionContextRef &ExecutionContextRef:: |
420 | operator=(const ExecutionContextRef &rhs) { |
421 | if (this != &rhs) { |
422 | m_target_wp = rhs.m_target_wp; |
423 | m_process_wp = rhs.m_process_wp; |
424 | m_thread_wp = rhs.m_thread_wp; |
425 | m_tid = rhs.m_tid; |
426 | m_stack_id = rhs.m_stack_id; |
427 | } |
428 | return *this; |
429 | } |
430 | |
431 | ExecutionContextRef &ExecutionContextRef:: |
432 | operator=(const ExecutionContext &exe_ctx) { |
433 | m_target_wp = exe_ctx.GetTargetSP(); |
434 | m_process_wp = exe_ctx.GetProcessSP(); |
435 | lldb::ThreadSP thread_sp(exe_ctx.GetThreadSP()); |
436 | m_thread_wp = thread_sp; |
437 | if (thread_sp) |
438 | m_tid = thread_sp->GetID(); |
439 | else |
440 | m_tid = LLDB_INVALID_THREAD_ID; |
441 | lldb::StackFrameSP frame_sp(exe_ctx.GetFrameSP()); |
442 | if (frame_sp) |
443 | m_stack_id = frame_sp->GetStackID(); |
444 | else |
445 | m_stack_id.Clear(); |
446 | return *this; |
447 | } |
448 | |
449 | void ExecutionContextRef::Clear() { |
450 | m_target_wp.reset(); |
451 | m_process_wp.reset(); |
452 | ClearThread(); |
453 | ClearFrame(); |
454 | } |
455 | |
456 | ExecutionContextRef::~ExecutionContextRef() = default; |
457 | |
458 | void ExecutionContextRef::SetTargetSP(const lldb::TargetSP &target_sp) { |
459 | m_target_wp = target_sp; |
460 | } |
461 | |
462 | void ExecutionContextRef::SetProcessSP(const lldb::ProcessSP &process_sp) { |
463 | if (process_sp) { |
464 | m_process_wp = process_sp; |
465 | SetTargetSP(process_sp->GetTarget().shared_from_this()); |
466 | } else { |
467 | m_process_wp.reset(); |
468 | m_target_wp.reset(); |
469 | } |
470 | } |
471 | |
472 | void ExecutionContextRef::SetThreadSP(const lldb::ThreadSP &thread_sp) { |
473 | if (thread_sp) { |
474 | m_thread_wp = thread_sp; |
475 | m_tid = thread_sp->GetID(); |
476 | SetProcessSP(thread_sp->GetProcess()); |
477 | } else { |
478 | ClearThread(); |
479 | m_process_wp.reset(); |
480 | m_target_wp.reset(); |
481 | } |
482 | } |
483 | |
484 | void ExecutionContextRef::SetFrameSP(const lldb::StackFrameSP &frame_sp) { |
485 | if (frame_sp) { |
486 | m_stack_id = frame_sp->GetStackID(); |
487 | SetThreadSP(frame_sp->GetThread()); |
488 | } else { |
489 | ClearFrame(); |
490 | ClearThread(); |
491 | m_process_wp.reset(); |
492 | m_target_wp.reset(); |
493 | } |
494 | } |
495 | |
496 | void ExecutionContextRef::SetTargetPtr(Target *target, bool adopt_selected) { |
497 | Clear(); |
498 | if (target) { |
499 | lldb::TargetSP target_sp(target->shared_from_this()); |
500 | if (target_sp) { |
501 | m_target_wp = target_sp; |
502 | if (adopt_selected) { |
503 | lldb::ProcessSP process_sp(target_sp->GetProcessSP()); |
504 | if (process_sp) { |
505 | m_process_wp = process_sp; |
506 | if (process_sp) { |
507 | // Only fill in the thread and frame if our process is stopped |
508 | // Don't just check the state, since we might be in the middle of |
509 | // resuming. |
510 | Process::StopLocker stop_locker; |
511 | |
512 | if (stop_locker.TryLock(lock: &process_sp->GetRunLock()) && |
513 | StateIsStoppedState(state: process_sp->GetState(), must_exist: true)) { |
514 | lldb::ThreadSP thread_sp( |
515 | process_sp->GetThreadList().GetSelectedThread()); |
516 | if (!thread_sp) |
517 | thread_sp = process_sp->GetThreadList().GetThreadAtIndex(idx: 0); |
518 | |
519 | if (thread_sp) { |
520 | SetThreadSP(thread_sp); |
521 | lldb::StackFrameSP frame_sp( |
522 | thread_sp->GetSelectedFrame(select_most_relevant: DoNoSelectMostRelevantFrame)); |
523 | if (!frame_sp) |
524 | frame_sp = thread_sp->GetStackFrameAtIndex(idx: 0); |
525 | if (frame_sp) |
526 | SetFrameSP(frame_sp); |
527 | } |
528 | } |
529 | } |
530 | } |
531 | } |
532 | } |
533 | } |
534 | } |
535 | |
536 | void ExecutionContextRef::SetProcessPtr(Process *process) { |
537 | if (process) { |
538 | SetProcessSP(process->shared_from_this()); |
539 | } else { |
540 | m_process_wp.reset(); |
541 | m_target_wp.reset(); |
542 | } |
543 | } |
544 | |
545 | void ExecutionContextRef::SetThreadPtr(Thread *thread) { |
546 | if (thread) { |
547 | SetThreadSP(thread->shared_from_this()); |
548 | } else { |
549 | ClearThread(); |
550 | m_process_wp.reset(); |
551 | m_target_wp.reset(); |
552 | } |
553 | } |
554 | |
555 | void ExecutionContextRef::SetFramePtr(StackFrame *frame) { |
556 | if (frame) |
557 | SetFrameSP(frame->shared_from_this()); |
558 | else |
559 | Clear(); |
560 | } |
561 | |
562 | lldb::TargetSP ExecutionContextRef::GetTargetSP() const { |
563 | lldb::TargetSP target_sp(m_target_wp.lock()); |
564 | if (target_sp && !target_sp->IsValid()) |
565 | target_sp.reset(); |
566 | return target_sp; |
567 | } |
568 | |
569 | lldb::ProcessSP ExecutionContextRef::GetProcessSP() const { |
570 | lldb::ProcessSP process_sp(m_process_wp.lock()); |
571 | if (process_sp && !process_sp->IsValid()) |
572 | process_sp.reset(); |
573 | return process_sp; |
574 | } |
575 | |
576 | lldb::ThreadSP ExecutionContextRef::GetThreadSP() const { |
577 | lldb::ThreadSP thread_sp(m_thread_wp.lock()); |
578 | |
579 | if (m_tid != LLDB_INVALID_THREAD_ID) { |
580 | // We check if the thread has been destroyed in cases where clients might |
581 | // still have shared pointer to a thread, but the thread is not valid |
582 | // anymore (not part of the process) |
583 | if (!thread_sp || !thread_sp->IsValid()) { |
584 | lldb::ProcessSP process_sp(GetProcessSP()); |
585 | if (process_sp && process_sp->IsValid()) { |
586 | thread_sp = process_sp->GetThreadList().FindThreadByID(tid: m_tid); |
587 | m_thread_wp = thread_sp; |
588 | } |
589 | } |
590 | } |
591 | |
592 | // Check that we aren't about to return an invalid thread sp. We might |
593 | // return a nullptr thread_sp, but don't return an invalid one. |
594 | |
595 | if (thread_sp && !thread_sp->IsValid()) |
596 | thread_sp.reset(); |
597 | |
598 | return thread_sp; |
599 | } |
600 | |
601 | lldb::StackFrameSP ExecutionContextRef::GetFrameSP() const { |
602 | if (m_stack_id.IsValid()) { |
603 | lldb::ThreadSP thread_sp(GetThreadSP()); |
604 | if (thread_sp) |
605 | return thread_sp->GetFrameWithStackID(stack_id: m_stack_id); |
606 | } |
607 | return lldb::StackFrameSP(); |
608 | } |
609 | |
610 | ExecutionContext |
611 | ExecutionContextRef::Lock(bool thread_and_frame_only_if_stopped) const { |
612 | return ExecutionContext(this, thread_and_frame_only_if_stopped); |
613 | } |
614 | |