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
433
434 = default;
435
437operator=(const ExecutionContextRef &rhs) {
438 if (this != &rhs) {
442 m_tid = rhs.m_tid;
444 }
445 return *this;
446}
447
449operator=(const ExecutionContext &exe_ctx) {
450 m_target_wp = exe_ctx.GetTargetSP();
451 m_process_wp = exe_ctx.GetProcessSP();
452 lldb::ThreadSP thread_sp(exe_ctx.GetThreadSP());
453 m_thread_wp = thread_sp;
454 if (thread_sp)
455 m_tid = thread_sp->GetID();
456 else
458 lldb::StackFrameSP frame_sp(exe_ctx.GetFrameSP());
459 if (frame_sp)
460 m_stack_id = frame_sp->GetStackID();
461 else
462 m_stack_id.Clear();
463 return *this;
464}
465
467 m_target_wp.reset();
468 m_process_wp.reset();
469 ClearThread();
470 ClearFrame();
471}
472
474
476 m_target_wp = target_sp;
477}
478
480 if (process_sp) {
481 m_process_wp = process_sp;
482 SetTargetSP(process_sp->GetTarget().shared_from_this());
483 } else {
484 m_process_wp.reset();
485 m_target_wp.reset();
486 }
487}
488
490 if (thread_sp) {
491 m_thread_wp = thread_sp;
492 m_tid = thread_sp->GetID();
493 SetProcessSP(thread_sp->GetProcess());
494 } else {
495 ClearThread();
496 m_process_wp.reset();
497 m_target_wp.reset();
498 }
499}
500
502 if (frame_sp) {
503 m_stack_id = frame_sp->GetStackID();
504 SetThreadSP(frame_sp->GetThread());
505 } else {
506 ClearFrame();
507 ClearThread();
508 m_process_wp.reset();
509 m_target_wp.reset();
510 }
511}
512
513void ExecutionContextRef::SetTargetPtr(Target *target, bool adopt_selected) {
514 Clear();
515 if (target) {
516 lldb::TargetSP target_sp(target->shared_from_this());
517 if (target_sp) {
518 m_target_wp = target_sp;
519 if (adopt_selected) {
520 lldb::ProcessSP process_sp(target_sp->GetProcessSP());
521 if (process_sp) {
522 m_process_wp = process_sp;
523 if (process_sp) {
524 // Only fill in the thread and frame if our process is stopped
525 // Don't just check the state, since we might be in the middle of
526 // resuming.
527 Process::StopLocker stop_locker;
528
529 if (stop_locker.TryLock(&process_sp->GetRunLock()) &&
530 StateIsStoppedState(process_sp->GetState(), true)) {
531 lldb::ThreadSP thread_sp(
532 process_sp->GetThreadList().GetSelectedThread());
533 if (!thread_sp)
534 thread_sp = process_sp->GetThreadList().GetThreadAtIndex(0);
535
536 if (thread_sp) {
537 SetThreadSP(thread_sp);
538 lldb::StackFrameSP frame_sp(
539 thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame));
540 if (!frame_sp)
541 frame_sp = thread_sp->GetStackFrameAtIndex(0);
542 if (frame_sp)
543 SetFrameSP(frame_sp);
544 }
545 }
546 }
547 }
548 }
549 }
550 }
551}
552
554 if (process) {
555 SetProcessSP(process->shared_from_this());
556 } else {
557 m_process_wp.reset();
558 m_target_wp.reset();
559 }
560}
561
563 if (thread) {
564 SetThreadSP(thread->shared_from_this());
565 } else {
566 ClearThread();
567 m_process_wp.reset();
568 m_target_wp.reset();
569 }
570}
571
573 if (frame)
574 SetFrameSP(frame->shared_from_this());
575 else
576 Clear();
577}
578
580 lldb::TargetSP target_sp(m_target_wp.lock());
581 if (target_sp && !target_sp->IsValid())
582 target_sp.reset();
583 return target_sp;
584}
585
587 lldb::ProcessSP process_sp(m_process_wp.lock());
588 if (process_sp && !process_sp->IsValid())
589 process_sp.reset();
590 return process_sp;
591}
592
594 lldb::ThreadSP thread_sp(m_thread_wp.lock());
595
597 // We check if the thread has been destroyed in cases where clients might
598 // still have shared pointer to a thread, but the thread is not valid
599 // anymore (not part of the process)
600 if (!thread_sp || !thread_sp->IsValid()) {
601 lldb::ProcessSP process_sp(GetProcessSP());
602 if (process_sp && process_sp->IsValid()) {
603 thread_sp = process_sp->GetThreadList().FindThreadByID(m_tid);
604 m_thread_wp = thread_sp;
605 }
606 }
607 }
608
609 // Check that we aren't about to return an invalid thread sp. We might
610 // return a nullptr thread_sp, but don't return an invalid one.
611
612 if (thread_sp && !thread_sp->IsValid())
613 thread_sp.reset();
614
615 return thread_sp;
616}
617
619 if (m_stack_id.IsValid()) {
620 lldb::ThreadSP thread_sp(GetThreadSP());
621 if (thread_sp)
622 return thread_sp->GetFrameWithStackID(m_stack_id);
623 }
624 return lldb::StackFrameSP();
625}
626
628ExecutionContextRef::Lock(bool thread_and_frame_only_if_stopped) const {
629 return ExecutionContext(this, thread_and_frame_only_if_stopped);
630}
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...
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.
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:306
#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,...