LLDB mainline
ExecutionContext.cpp
Go to the documentation of this file.
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
11#include "lldb/Target/Process.h"
13#include "lldb/Target/Target.h"
14#include "lldb/Target/Thread.h"
16#include "lldb/Utility/State.h"
17#include <mutex>
18
19using namespace lldb_private;
20
23
25
27 bool get_process)
29 if (target_sp)
30 SetContext(target_sp, get_process);
31}
32
35 if (process_sp)
36 SetContext(process_sp);
37}
38
41 if (thread_sp)
42 SetContext(thread_sp);
43}
44
47 if (frame_sp)
48 SetContext(frame_sp);
49}
50
52 bool get_process)
54 lldb::TargetSP target_sp(target_wp.lock());
55 if (target_sp)
56 SetContext(target_sp, get_process);
57}
58
61 lldb::ProcessSP process_sp(process_wp.lock());
62 if (process_sp)
63 SetContext(process_sp);
64}
65
68 lldb::ThreadSP thread_sp(thread_wp.lock());
69 if (thread_sp)
70 SetContext(thread_sp);
71}
72
75 lldb::StackFrameSP frame_sp(frame_wp.lock());
76 if (frame_sp)
77 SetContext(frame_sp);
78}
79
81 bool fill_current_process_thread_frame)
83 if (t) {
84 m_target_sp = t->shared_from_this();
85 if (fill_current_process_thread_frame) {
87 if (m_process_sp) {
88 m_thread_sp = m_process_sp->GetThreadList().GetSelectedThread();
89 if (m_thread_sp)
92 }
93 }
94 }
95}
96
98 StackFrame *frame)
100 if (process) {
101 m_process_sp = process->shared_from_this();
102 m_target_sp = process->GetTarget().shared_from_this();
103 }
104 if (thread)
105 m_thread_sp = thread->shared_from_this();
106 if (frame)
107 m_frame_sp = frame->shared_from_this();
108}
109
111 : m_target_sp(exe_ctx_ref.GetTargetSP()),
112 m_process_sp(exe_ctx_ref.GetProcessSP()),
113 m_thread_sp(exe_ctx_ref.GetThreadSP()),
114 m_frame_sp(exe_ctx_ref.GetFrameSP()) {}
115
117 bool thread_and_frame_only_if_stopped)
119 if (exe_ctx_ref_ptr) {
120 m_target_sp = exe_ctx_ref_ptr->GetTargetSP();
121 m_process_sp = exe_ctx_ref_ptr->GetProcessSP();
122 if (!thread_and_frame_only_if_stopped ||
123 (m_process_sp && StateIsStoppedState(m_process_sp->GetState(), true))) {
124 m_thread_sp = exe_ctx_ref_ptr->GetThreadSP();
125 m_frame_sp = exe_ctx_ref_ptr->GetFrameSP();
126 }
127 }
128}
129
130llvm::Expected<StoppedExecutionContext>
132 const lldb::ExecutionContextRefSP &exe_ctx_ref_ptr) {
133 return GetStoppedExecutionContext(exe_ctx_ref_ptr.get());
134}
135
136llvm::Expected<StoppedExecutionContext>
138 const ExecutionContextRef *exe_ctx_ref_ptr) {
139 if (!exe_ctx_ref_ptr)
140 return llvm::createStringError(
141 "StoppedExecutionContext created with an empty ExecutionContextRef");
142
143 lldb::TargetSP target_sp = exe_ctx_ref_ptr->GetTargetSP();
144 if (!target_sp)
145 return llvm::createStringError(
146 "StoppedExecutionContext created with a null target");
147
148 auto api_lock =
149 std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
150
151 auto process_sp = exe_ctx_ref_ptr->GetProcessSP();
152 if (!process_sp)
153 return llvm::createStringError(
154 "StoppedExecutionContext created with a null process");
155
157 if (!stop_locker.TryLock(&process_sp->GetRunLock()))
158 return llvm::createStringError(
159 "attempted to create a StoppedExecutionContext with a running process");
160
161 auto thread_sp = exe_ctx_ref_ptr->GetThreadSP();
162 auto frame_sp = exe_ctx_ref_ptr->GetFrameSP();
163 return StoppedExecutionContext(target_sp, process_sp, thread_sp, frame_sp,
164 std::move(api_lock), std::move(stop_locker));
165}
166
167std::unique_lock<std::recursive_mutex> StoppedExecutionContext::AllowResume() {
168 Clear();
170 return std::move(m_api_lock);
171}
172
175 if (exe_scope_ptr)
176 exe_scope_ptr->CalculateExecutionContext(*this);
177}
178
182
184 m_target_sp.reset();
185 m_process_sp.reset();
186 m_thread_sp.reset();
187 m_frame_sp.reset();
188}
189
191
193 if (m_target_sp && m_target_sp->GetArchitecture().IsValid())
194 return m_target_sp->GetArchitecture().GetAddressByteSize();
195 if (m_process_sp)
196 return m_process_sp->GetAddressByteSize();
197 return sizeof(void *);
198}
199
201 if (m_target_sp && m_target_sp->GetArchitecture().IsValid())
202 return m_target_sp->GetArchitecture().GetByteOrder();
203 if (m_process_sp)
204 return m_process_sp->GetByteOrder();
206}
207
209 if (m_frame_sp)
210 return m_frame_sp->GetRegisterContext().get();
211 else if (m_thread_sp)
212 return m_thread_sp->GetRegisterContext().get();
213 return nullptr;
214}
215
217 if (m_target_sp)
218 return m_target_sp.get();
219 if (m_process_sp)
220 return &m_process_sp->GetTarget();
221 return nullptr;
222}
223
225 if (m_process_sp)
226 return m_process_sp.get();
227 if (m_target_sp)
228 return m_target_sp->GetProcessSP().get();
229 return nullptr;
230}
231
233 if (m_frame_sp)
234 return m_frame_sp.get();
235 if (m_thread_sp)
236 return m_thread_sp.get();
237 if (m_process_sp)
238 return m_process_sp.get();
239 return m_target_sp.get();
240}
241
243 assert(m_target_sp);
244 return *m_target_sp;
245}
246
248 assert(m_process_sp);
249 return *m_process_sp;
250}
251
253 assert(m_thread_sp);
254 return *m_thread_sp;
255}
256
258 assert(m_frame_sp);
259 return *m_frame_sp;
260}
261
263 m_target_sp = target_sp;
264}
265
267 m_process_sp = process_sp;
268}
269
271 m_thread_sp = thread_sp;
272}
273
275 m_frame_sp = frame_sp;
276}
277
279 if (target)
280 m_target_sp = target->shared_from_this();
281 else
282 m_target_sp.reset();
283}
284
286 if (process)
287 m_process_sp = process->shared_from_this();
288 else
289 m_process_sp.reset();
290}
291
293 if (thread)
294 m_thread_sp = thread->shared_from_this();
295 else
296 m_thread_sp.reset();
297}
298
300 if (frame)
301 m_frame_sp = frame->shared_from_this();
302 else
303 m_frame_sp.reset();
304}
305
307 bool get_process) {
308 m_target_sp = target_sp;
309 if (get_process && target_sp)
310 m_process_sp = target_sp->GetProcessSP();
311 else
312 m_process_sp.reset();
313 m_thread_sp.reset();
314 m_frame_sp.reset();
315}
316
318 m_process_sp = process_sp;
319 if (process_sp)
320 m_target_sp = process_sp->GetTarget().shared_from_this();
321 else
322 m_target_sp.reset();
323 m_thread_sp.reset();
324 m_frame_sp.reset();
325}
326
328 m_frame_sp.reset();
329 m_thread_sp = thread_sp;
330 if (thread_sp) {
331 m_process_sp = thread_sp->GetProcess();
332 if (m_process_sp)
333 m_target_sp = m_process_sp->GetTarget().shared_from_this();
334 else
335 m_target_sp.reset();
336 } else {
337 m_target_sp.reset();
338 m_process_sp.reset();
339 }
340}
341
343 m_frame_sp = frame_sp;
344 if (frame_sp) {
345 m_thread_sp = frame_sp->CalculateThread();
346 if (m_thread_sp) {
347 m_process_sp = m_thread_sp->GetProcess();
348 if (m_process_sp)
349 m_target_sp = m_process_sp->GetTarget().shared_from_this();
350 else
351 m_target_sp.reset();
352 } else {
353 m_target_sp.reset();
354 m_process_sp.reset();
355 }
356 } else {
357 m_target_sp.reset();
358 m_process_sp.reset();
359 m_thread_sp.reset();
360 }
361}
362
364 if (this != &rhs) {
369 }
370 return *this;
371}
372
374 // Check that the frame shared pointers match, or both are valid and their
375 // stack IDs match since sometimes we get new objects that represent the same
376 // frame within a thread.
377 if ((m_frame_sp == rhs.m_frame_sp) ||
378 (m_frame_sp && rhs.m_frame_sp &&
379 m_frame_sp->GetStackID() == rhs.m_frame_sp->GetStackID())) {
380 // Check that the thread shared pointers match, or both are valid and their
381 // thread IDs match since sometimes we get new objects that represent the
382 // same thread within a process.
383 if ((m_thread_sp == rhs.m_thread_sp) ||
384 (m_thread_sp && rhs.m_thread_sp &&
385 m_thread_sp->GetID() == rhs.m_thread_sp->GetID())) {
386 // Processes and targets don't change much
387 return m_process_sp == rhs.m_process_sp && m_target_sp == rhs.m_target_sp;
388 }
389 }
390 return false;
391}
392
394 return !(*this == rhs);
395}
396
398 return ((bool)m_target_sp && m_target_sp->IsValid());
399}
400
402 return (HasTargetScope() && ((bool)m_process_sp && m_process_sp->IsValid()));
403}
404
406 return (HasProcessScope() && ((bool)m_thread_sp && m_thread_sp->IsValid()));
407}
408
410 return HasThreadScope() && m_frame_sp;
411}
412
415
418 if (exe_ctx)
419 *this = *exe_ctx;
420}
421
426
429 SetTargetPtr(target, adopt_selected);
430}
431
434 SetProcessPtr(process, adopt_selected);
435}
436
439 SetThreadPtr(thread, adopt_selected);
440}
441
443
444 = default;
445
447operator=(const ExecutionContextRef &rhs) {
448 if (this != &rhs) {
452 m_tid = rhs.m_tid;
454 }
455 return *this;
456}
457
459operator=(const ExecutionContext &exe_ctx) {
460 m_target_wp = exe_ctx.GetTargetSP();
461 m_process_wp = exe_ctx.GetProcessSP();
462 lldb::ThreadSP thread_sp(exe_ctx.GetThreadSP());
463 m_thread_wp = thread_sp;
464 if (thread_sp)
465 m_tid = thread_sp->GetID();
466 else
468 lldb::StackFrameSP frame_sp(exe_ctx.GetFrameSP());
469 if (frame_sp)
470 m_stack_id = frame_sp->GetStackID();
471 else
472 m_stack_id.Clear();
473 return *this;
474}
475
477 m_target_wp.reset();
478 m_process_wp.reset();
479 ClearThread();
480 ClearFrame();
481}
482
484
486 m_target_wp = target_sp;
487}
488
490 if (process_sp) {
491 m_process_wp = process_sp;
492 SetTargetSP(process_sp->GetTarget().shared_from_this());
493 } else {
494 m_process_wp.reset();
495 m_target_wp.reset();
496 }
497}
498
500 if (thread_sp) {
501 m_thread_wp = thread_sp;
502 m_tid = thread_sp->GetID();
503 SetProcessSP(thread_sp->GetProcess());
504 } else {
505 ClearThread();
506 m_process_wp.reset();
507 m_target_wp.reset();
508 }
509}
510
512 if (frame_sp) {
513 m_stack_id = frame_sp->GetStackID();
514 SetThreadSP(frame_sp->GetThread());
515 } else {
516 ClearFrame();
517 ClearThread();
518 m_process_wp.reset();
519 m_target_wp.reset();
520 }
521}
522
523void ExecutionContextRef::SetTargetPtr(Target *target, bool adopt_selected) {
524 Clear();
525 if (target) {
526 lldb::TargetSP target_sp = target->shared_from_this();
527 SetTargetSP(target_sp);
528 if (adopt_selected) {
529 if (lldb::ProcessSP process_sp = target_sp->GetProcessSP())
530 SetProcessPtr(process_sp.get(), adopt_selected);
531 }
532 }
533}
534
535void ExecutionContextRef::SetProcessPtr(Process *process, bool adopt_selected) {
536 if (process) {
537 lldb::ProcessSP process_sp = process->shared_from_this();
538 SetProcessSP(process_sp);
539 if (adopt_selected) {
540 // Only fill in the thread if our process is stopped.
541 // Don't just check the state, since we might be in the middle of
542 // resuming.
543 Process::StopLocker stop_locker;
544 if (stop_locker.TryLock(&process_sp->GetRunLock()) &&
545 StateIsStoppedState(process_sp->GetState(), true)) {
546 lldb::ThreadSP thread_sp(
547 process_sp->GetThreadList().GetSelectedThread());
548 if (!thread_sp)
549 thread_sp = process_sp->GetThreadList().GetThreadAtIndex(0);
550 if (thread_sp) {
551 SetThreadSP(thread_sp);
552 lldb::StackFrameSP frame_sp =
553 thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);
554 if (!frame_sp)
555 frame_sp = thread_sp->GetStackFrameAtIndex(0);
556 if (frame_sp)
557 SetFrameSP(frame_sp);
558 }
559 }
560 }
561 } else {
562 m_process_wp.reset();
563 m_target_wp.reset();
564 }
565}
566
567void ExecutionContextRef::SetThreadPtr(Thread *thread, bool adopt_selected) {
568 if (thread) {
569 lldb::ThreadSP thread_sp = thread->shared_from_this();
570 SetThreadSP(thread_sp);
571 if (adopt_selected) {
572 // Only fill in the frame if our process is stopped.
573 // Don't just check the state, since we might be in the middle of
574 // resuming.
575 Process::StopLocker stop_locker;
576 if (stop_locker.TryLock(&thread->GetProcess()->GetRunLock()) &&
577 StateIsStoppedState(thread->GetProcess()->GetState(), true)) {
578 lldb::StackFrameSP frame_sp =
579 thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);
580 if (!frame_sp)
581 frame_sp = thread_sp->GetStackFrameAtIndex(0);
582 if (frame_sp)
583 SetFrameSP(frame_sp);
584 }
585 }
586 } else {
587 ClearThread();
588 m_process_wp.reset();
589 m_target_wp.reset();
590 }
591}
592
594 if (frame)
595 SetFrameSP(frame->shared_from_this());
596 else
597 Clear();
598}
599
601 lldb::TargetSP target_sp(m_target_wp.lock());
602 if (target_sp && !target_sp->IsValid())
603 target_sp.reset();
604 return target_sp;
605}
606
608 lldb::ProcessSP process_sp(m_process_wp.lock());
609 if (process_sp && !process_sp->IsValid())
610 process_sp.reset();
611 return process_sp;
612}
613
615 lldb::ThreadSP thread_sp(m_thread_wp.lock());
616
618 // We check if the thread has been destroyed in cases where clients might
619 // still have shared pointer to a thread, but the thread is not valid
620 // anymore (not part of the process)
621 if (!thread_sp || !thread_sp->IsValid()) {
622 lldb::ProcessSP process_sp(GetProcessSP());
623 if (process_sp && process_sp->IsValid()) {
624 thread_sp = process_sp->GetThreadList().FindThreadByID(m_tid);
625 m_thread_wp = thread_sp;
626 }
627 }
628 }
629
630 // Check that we aren't about to return an invalid thread sp. We might
631 // return a nullptr thread_sp, but don't return an invalid one.
632
633 if (thread_sp && !thread_sp->IsValid())
634 thread_sp.reset();
635
636 return thread_sp;
637}
638
640 if (m_stack_id.IsValid()) {
641 lldb::ThreadSP thread_sp(GetThreadSP());
642 if (thread_sp)
643 return thread_sp->GetFrameWithStackID(m_stack_id);
644 }
645 return lldb::StackFrameSP();
646}
647
649ExecutionContextRef::Lock(bool thread_and_frame_only_if_stopped) const {
650 return ExecutionContext(this, thread_and_frame_only_if_stopped);
651}
Execution context objects refer to objects in the execution of the program that is being debugged.
StackID m_stack_id
The stack ID that this object refers to in case the backing object changes.
ExecutionContext Lock(bool thread_and_frame_only_if_stopped) const
Create an ExecutionContext object from this object.
void SetThreadSP(const lldb::ThreadSP &thread_sp)
Set accessor that creates a weak reference to the thread referenced in thread_sp.
void Clear()
Clear the object's state.
lldb::StackFrameSP GetFrameSP() const
Get accessor that creates a strong reference from the weak frame reference contained in this object.
lldb::ProcessWP m_process_wp
A weak reference to a process.
lldb::ThreadSP GetThreadSP() const
Get accessor that creates a strong reference from the weak thread reference contained in this object.
void SetFrameSP(const lldb::StackFrameSP &frame_sp)
Set accessor that creates a weak reference to the frame referenced in frame_sp.
lldb::tid_t m_tid
The thread ID that this object refers to in case the backing object changes.
lldb::TargetSP GetTargetSP() const
Get accessor that creates a strong reference from the weak target reference contained in this object.
void SetTargetPtr(Target *target, bool adopt_selected)
lldb::ProcessSP GetProcessSP() const
Get accessor that creates a strong reference from the weak process reference contained in this object...
void SetThreadPtr(Thread *thread, bool adopt_selected=false)
ExecutionContextRef & operator=(const ExecutionContextRef &rhs)
Assignment operator.
ExecutionContextRef()
Default Constructor.
void SetTargetSP(const lldb::TargetSP &target_sp)
Set accessor that creates a weak reference to the target referenced in target_sp.
void SetProcessPtr(Process *process, bool adopt_selected=false)
lldb::TargetWP m_target_wp
A weak reference to a target.
void SetProcessSP(const lldb::ProcessSP &process_sp)
Set accessor that creates a weak reference to the process referenced in process_sp.
lldb::ThreadWP m_thread_wp
A weak reference to a thread.
"lldb/Target/ExecutionContextScope.h" Inherit from this if your object can reconstruct its execution ...
virtual void CalculateExecutionContext(ExecutionContext &exe_ctx)=0
Reconstruct the object's execution context into sc.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
void SetFrameSP(const lldb::StackFrameSP &frame_sp)
Set accessor to set only the frame shared pointer.
bool HasThreadScope() const
Returns true the ExecutionContext object contains a valid target, process, and thread.
void SetProcessPtr(Process *process)
Set accessor to set only the process shared pointer from a process pointer.
bool HasProcessScope() const
Returns true the ExecutionContext object contains a valid target and process.
ExecutionContextScope * GetBestExecutionContextScope() const
const lldb::TargetSP & GetTargetSP() const
Get accessor to get the target shared pointer.
void Clear()
Clear the object's state.
ExecutionContext()
Default Constructor.
const lldb::ProcessSP & GetProcessSP() const
Get accessor to get the process shared pointer.
void SetProcessSP(const lldb::ProcessSP &process_sp)
Set accessor to set only the process shared pointer.
lldb::StackFrameSP m_frame_sp
The stack frame in thread.
bool operator==(const ExecutionContext &rhs) const
void SetThreadPtr(Thread *thread)
Set accessor to set only the thread shared pointer from a thread pointer.
lldb::ByteOrder GetByteOrder() const
void SetTargetPtr(Target *target)
Set accessor to set only the target shared pointer from a target pointer.
lldb::TargetSP m_target_sp
The target that owns the process/thread/frame.
const lldb::StackFrameSP & GetFrameSP() const
Get accessor to get the frame shared pointer.
Process & GetProcessRef() const
Returns a reference to the process object.
void SetContext(const lldb::TargetSP &target_sp, bool get_process)
void SetTargetSP(const lldb::TargetSP &target_sp)
Set accessor to set only the target shared pointer.
Target * GetTargetPtr() const
Returns a pointer to the target object.
const lldb::ThreadSP & GetThreadSP() const
Get accessor to get the thread shared pointer.
void SetThreadSP(const lldb::ThreadSP &thread_sp)
Set accessor to set only the thread shared pointer.
bool HasTargetScope() const
Returns true the ExecutionContext object contains a valid target.
StackFrame & GetFrameRef() const
Returns a reference to the thread object.
bool HasFrameScope() const
Returns true the ExecutionContext object contains a valid target, process, thread and frame.
lldb::ThreadSP m_thread_sp
The thread that owns the frame.
lldb::ProcessSP m_process_sp
The process that owns the thread/frame.
bool operator!=(const ExecutionContext &rhs) const
Target & GetTargetRef() const
Returns a reference to the target object.
void SetFramePtr(StackFrame *frame)
Set accessor to set only the frame shared pointer from a frame pointer.
ExecutionContext & operator=(const ExecutionContext &rhs)
Process * GetProcessPtr() const
Returns a pointer to the process object.
Thread & GetThreadRef() const
Returns a reference to the thread object.
RegisterContext * GetRegisterContext() const
A plug-in interface definition class for debugging a process.
Definition Process.h:357
ProcessRunLock::ProcessRunLocker StopLocker
Definition Process.h:396
Target & GetTarget()
Get the target object pointer for this module.
Definition Process.h:1270
This base class provides an interface to stack frames.
Definition StackFrame.h:44
const lldb::ProcessSP & GetProcessSP() const
Definition Target.cpp:309
#define LLDB_INVALID_THREAD_ID
@ DoNoSelectMostRelevantFrame
lldb::ByteOrder InlHostByteOrder()
Definition Endian.h:25
A class that represents a running process on the host machine.
bool StateIsStoppedState(lldb::StateType state, bool must_exist)
Check if a state represents a state where the process or thread is stopped.
Definition State.cpp:89
llvm::Expected< StoppedExecutionContext > GetStoppedExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr)
std::weak_ptr< lldb_private::StackFrame > StackFrameWP
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
std::shared_ptr< lldb_private::Thread > ThreadSP
std::shared_ptr< lldb_private::Process > ProcessSP
ByteOrder
Byte ordering definitions.
std::weak_ptr< lldb_private::Process > ProcessWP
std::weak_ptr< lldb_private::Target > TargetWP
std::shared_ptr< lldb_private::Target > TargetSP
std::weak_ptr< lldb_private::Thread > ThreadWP
std::shared_ptr< lldb_private::ExecutionContextRef > ExecutionContextRefSP
A wrapper class representing an execution context with non-null Target and Process pointers,...
ProcessRunLock::ProcessRunLocker m_stop_locker
std::unique_lock< std::recursive_mutex > m_api_lock
std::unique_lock< std::recursive_mutex > AllowResume()
Clears this context, unlocking the ProcessRunLock and returning the locked API lock,...