Path: blob/main/contrib/llvm-project/lldb/source/Target/ExecutionContext.cpp
39587 views
//===-- ExecutionContext.cpp ----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Target/ExecutionContext.h"9#include "lldb/Target/ExecutionContextScope.h"10#include "lldb/Target/Process.h"11#include "lldb/Target/StackFrame.h"12#include "lldb/Target/Target.h"13#include "lldb/Target/Thread.h"14#include "lldb/Utility/State.h"1516using namespace lldb_private;1718ExecutionContext::ExecutionContext()19: m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {}2021ExecutionContext::ExecutionContext(const ExecutionContext &rhs) = default;2223ExecutionContext::ExecutionContext(const lldb::TargetSP &target_sp,24bool get_process)25: m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {26if (target_sp)27SetContext(target_sp, get_process);28}2930ExecutionContext::ExecutionContext(const lldb::ProcessSP &process_sp)31: m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {32if (process_sp)33SetContext(process_sp);34}3536ExecutionContext::ExecutionContext(const lldb::ThreadSP &thread_sp)37: m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {38if (thread_sp)39SetContext(thread_sp);40}4142ExecutionContext::ExecutionContext(const lldb::StackFrameSP &frame_sp)43: m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {44if (frame_sp)45SetContext(frame_sp);46}4748ExecutionContext::ExecutionContext(const lldb::TargetWP &target_wp,49bool get_process)50: m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {51lldb::TargetSP target_sp(target_wp.lock());52if (target_sp)53SetContext(target_sp, get_process);54}5556ExecutionContext::ExecutionContext(const lldb::ProcessWP &process_wp)57: m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {58lldb::ProcessSP process_sp(process_wp.lock());59if (process_sp)60SetContext(process_sp);61}6263ExecutionContext::ExecutionContext(const lldb::ThreadWP &thread_wp)64: m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {65lldb::ThreadSP thread_sp(thread_wp.lock());66if (thread_sp)67SetContext(thread_sp);68}6970ExecutionContext::ExecutionContext(const lldb::StackFrameWP &frame_wp)71: m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {72lldb::StackFrameSP frame_sp(frame_wp.lock());73if (frame_sp)74SetContext(frame_sp);75}7677ExecutionContext::ExecutionContext(Target *t,78bool fill_current_process_thread_frame)79: m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {80if (t) {81m_target_sp = t->shared_from_this();82if (fill_current_process_thread_frame) {83m_process_sp = t->GetProcessSP();84if (m_process_sp) {85m_thread_sp = m_process_sp->GetThreadList().GetSelectedThread();86if (m_thread_sp)87m_frame_sp =88m_thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);89}90}91}92}9394ExecutionContext::ExecutionContext(Process *process, Thread *thread,95StackFrame *frame)96: m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {97if (process) {98m_process_sp = process->shared_from_this();99m_target_sp = process->GetTarget().shared_from_this();100}101if (thread)102m_thread_sp = thread->shared_from_this();103if (frame)104m_frame_sp = frame->shared_from_this();105}106107ExecutionContext::ExecutionContext(const ExecutionContextRef &exe_ctx_ref)108: m_target_sp(exe_ctx_ref.GetTargetSP()),109m_process_sp(exe_ctx_ref.GetProcessSP()),110m_thread_sp(exe_ctx_ref.GetThreadSP()),111m_frame_sp(exe_ctx_ref.GetFrameSP()) {}112113ExecutionContext::ExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr,114bool thread_and_frame_only_if_stopped)115: m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {116if (exe_ctx_ref_ptr) {117m_target_sp = exe_ctx_ref_ptr->GetTargetSP();118m_process_sp = exe_ctx_ref_ptr->GetProcessSP();119if (!thread_and_frame_only_if_stopped ||120(m_process_sp && StateIsStoppedState(m_process_sp->GetState(), true))) {121m_thread_sp = exe_ctx_ref_ptr->GetThreadSP();122m_frame_sp = exe_ctx_ref_ptr->GetFrameSP();123}124}125}126127ExecutionContext::ExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr,128std::unique_lock<std::recursive_mutex> &lock)129: m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {130if (exe_ctx_ref_ptr) {131m_target_sp = exe_ctx_ref_ptr->GetTargetSP();132if (m_target_sp) {133lock = std::unique_lock<std::recursive_mutex>(m_target_sp->GetAPIMutex());134135m_process_sp = exe_ctx_ref_ptr->GetProcessSP();136m_thread_sp = exe_ctx_ref_ptr->GetThreadSP();137m_frame_sp = exe_ctx_ref_ptr->GetFrameSP();138}139}140}141142ExecutionContext::ExecutionContext(const ExecutionContextRef &exe_ctx_ref,143std::unique_lock<std::recursive_mutex> &lock)144: m_target_sp(exe_ctx_ref.GetTargetSP()), m_process_sp(), m_thread_sp(),145m_frame_sp() {146if (m_target_sp) {147lock = std::unique_lock<std::recursive_mutex>(m_target_sp->GetAPIMutex());148149m_process_sp = exe_ctx_ref.GetProcessSP();150m_thread_sp = exe_ctx_ref.GetThreadSP();151m_frame_sp = exe_ctx_ref.GetFrameSP();152}153}154155ExecutionContext::ExecutionContext(ExecutionContextScope *exe_scope_ptr)156: m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {157if (exe_scope_ptr)158exe_scope_ptr->CalculateExecutionContext(*this);159}160161ExecutionContext::ExecutionContext(ExecutionContextScope &exe_scope_ref) {162exe_scope_ref.CalculateExecutionContext(*this);163}164165void ExecutionContext::Clear() {166m_target_sp.reset();167m_process_sp.reset();168m_thread_sp.reset();169m_frame_sp.reset();170}171172ExecutionContext::~ExecutionContext() = default;173174uint32_t ExecutionContext::GetAddressByteSize() const {175if (m_target_sp && m_target_sp->GetArchitecture().IsValid())176return m_target_sp->GetArchitecture().GetAddressByteSize();177if (m_process_sp)178return m_process_sp->GetAddressByteSize();179return sizeof(void *);180}181182lldb::ByteOrder ExecutionContext::GetByteOrder() const {183if (m_target_sp && m_target_sp->GetArchitecture().IsValid())184return m_target_sp->GetArchitecture().GetByteOrder();185if (m_process_sp)186return m_process_sp->GetByteOrder();187return endian::InlHostByteOrder();188}189190RegisterContext *ExecutionContext::GetRegisterContext() const {191if (m_frame_sp)192return m_frame_sp->GetRegisterContext().get();193else if (m_thread_sp)194return m_thread_sp->GetRegisterContext().get();195return nullptr;196}197198Target *ExecutionContext::GetTargetPtr() const {199if (m_target_sp)200return m_target_sp.get();201if (m_process_sp)202return &m_process_sp->GetTarget();203return nullptr;204}205206Process *ExecutionContext::GetProcessPtr() const {207if (m_process_sp)208return m_process_sp.get();209if (m_target_sp)210return m_target_sp->GetProcessSP().get();211return nullptr;212}213214ExecutionContextScope *ExecutionContext::GetBestExecutionContextScope() const {215if (m_frame_sp)216return m_frame_sp.get();217if (m_thread_sp)218return m_thread_sp.get();219if (m_process_sp)220return m_process_sp.get();221return m_target_sp.get();222}223224Target &ExecutionContext::GetTargetRef() const {225assert(m_target_sp);226return *m_target_sp;227}228229Process &ExecutionContext::GetProcessRef() const {230assert(m_process_sp);231return *m_process_sp;232}233234Thread &ExecutionContext::GetThreadRef() const {235assert(m_thread_sp);236return *m_thread_sp;237}238239StackFrame &ExecutionContext::GetFrameRef() const {240assert(m_frame_sp);241return *m_frame_sp;242}243244void ExecutionContext::SetTargetSP(const lldb::TargetSP &target_sp) {245m_target_sp = target_sp;246}247248void ExecutionContext::SetProcessSP(const lldb::ProcessSP &process_sp) {249m_process_sp = process_sp;250}251252void ExecutionContext::SetThreadSP(const lldb::ThreadSP &thread_sp) {253m_thread_sp = thread_sp;254}255256void ExecutionContext::SetFrameSP(const lldb::StackFrameSP &frame_sp) {257m_frame_sp = frame_sp;258}259260void ExecutionContext::SetTargetPtr(Target *target) {261if (target)262m_target_sp = target->shared_from_this();263else264m_target_sp.reset();265}266267void ExecutionContext::SetProcessPtr(Process *process) {268if (process)269m_process_sp = process->shared_from_this();270else271m_process_sp.reset();272}273274void ExecutionContext::SetThreadPtr(Thread *thread) {275if (thread)276m_thread_sp = thread->shared_from_this();277else278m_thread_sp.reset();279}280281void ExecutionContext::SetFramePtr(StackFrame *frame) {282if (frame)283m_frame_sp = frame->shared_from_this();284else285m_frame_sp.reset();286}287288void ExecutionContext::SetContext(const lldb::TargetSP &target_sp,289bool get_process) {290m_target_sp = target_sp;291if (get_process && target_sp)292m_process_sp = target_sp->GetProcessSP();293else294m_process_sp.reset();295m_thread_sp.reset();296m_frame_sp.reset();297}298299void ExecutionContext::SetContext(const lldb::ProcessSP &process_sp) {300m_process_sp = process_sp;301if (process_sp)302m_target_sp = process_sp->GetTarget().shared_from_this();303else304m_target_sp.reset();305m_thread_sp.reset();306m_frame_sp.reset();307}308309void ExecutionContext::SetContext(const lldb::ThreadSP &thread_sp) {310m_frame_sp.reset();311m_thread_sp = thread_sp;312if (thread_sp) {313m_process_sp = thread_sp->GetProcess();314if (m_process_sp)315m_target_sp = m_process_sp->GetTarget().shared_from_this();316else317m_target_sp.reset();318} else {319m_target_sp.reset();320m_process_sp.reset();321}322}323324void ExecutionContext::SetContext(const lldb::StackFrameSP &frame_sp) {325m_frame_sp = frame_sp;326if (frame_sp) {327m_thread_sp = frame_sp->CalculateThread();328if (m_thread_sp) {329m_process_sp = m_thread_sp->GetProcess();330if (m_process_sp)331m_target_sp = m_process_sp->GetTarget().shared_from_this();332else333m_target_sp.reset();334} else {335m_target_sp.reset();336m_process_sp.reset();337}338} else {339m_target_sp.reset();340m_process_sp.reset();341m_thread_sp.reset();342}343}344345ExecutionContext &ExecutionContext::operator=(const ExecutionContext &rhs) {346if (this != &rhs) {347m_target_sp = rhs.m_target_sp;348m_process_sp = rhs.m_process_sp;349m_thread_sp = rhs.m_thread_sp;350m_frame_sp = rhs.m_frame_sp;351}352return *this;353}354355bool ExecutionContext::operator==(const ExecutionContext &rhs) const {356// Check that the frame shared pointers match, or both are valid and their357// stack IDs match since sometimes we get new objects that represent the same358// frame within a thread.359if ((m_frame_sp == rhs.m_frame_sp) ||360(m_frame_sp && rhs.m_frame_sp &&361m_frame_sp->GetStackID() == rhs.m_frame_sp->GetStackID())) {362// Check that the thread shared pointers match, or both are valid and their363// thread IDs match since sometimes we get new objects that represent the364// same thread within a process.365if ((m_thread_sp == rhs.m_thread_sp) ||366(m_thread_sp && rhs.m_thread_sp &&367m_thread_sp->GetID() == rhs.m_thread_sp->GetID())) {368// Processes and targets don't change much369return m_process_sp == rhs.m_process_sp && m_target_sp == rhs.m_target_sp;370}371}372return false;373}374375bool ExecutionContext::operator!=(const ExecutionContext &rhs) const {376return !(*this == rhs);377}378379bool ExecutionContext::HasTargetScope() const {380return ((bool)m_target_sp && m_target_sp->IsValid());381}382383bool ExecutionContext::HasProcessScope() const {384return (HasTargetScope() && ((bool)m_process_sp && m_process_sp->IsValid()));385}386387bool ExecutionContext::HasThreadScope() const {388return (HasProcessScope() && ((bool)m_thread_sp && m_thread_sp->IsValid()));389}390391bool ExecutionContext::HasFrameScope() const {392return HasThreadScope() && m_frame_sp;393}394395ExecutionContextRef::ExecutionContextRef()396: m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() {}397398ExecutionContextRef::ExecutionContextRef(const ExecutionContext *exe_ctx)399: m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() {400if (exe_ctx)401*this = *exe_ctx;402}403404ExecutionContextRef::ExecutionContextRef(const ExecutionContext &exe_ctx)405: m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() {406*this = exe_ctx;407}408409ExecutionContextRef::ExecutionContextRef(Target *target, bool adopt_selected)410: m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() {411SetTargetPtr(target, adopt_selected);412}413414ExecutionContextRef::ExecutionContextRef(const ExecutionContextRef &rhs)415416= default;417418ExecutionContextRef &ExecutionContextRef::419operator=(const ExecutionContextRef &rhs) {420if (this != &rhs) {421m_target_wp = rhs.m_target_wp;422m_process_wp = rhs.m_process_wp;423m_thread_wp = rhs.m_thread_wp;424m_tid = rhs.m_tid;425m_stack_id = rhs.m_stack_id;426}427return *this;428}429430ExecutionContextRef &ExecutionContextRef::431operator=(const ExecutionContext &exe_ctx) {432m_target_wp = exe_ctx.GetTargetSP();433m_process_wp = exe_ctx.GetProcessSP();434lldb::ThreadSP thread_sp(exe_ctx.GetThreadSP());435m_thread_wp = thread_sp;436if (thread_sp)437m_tid = thread_sp->GetID();438else439m_tid = LLDB_INVALID_THREAD_ID;440lldb::StackFrameSP frame_sp(exe_ctx.GetFrameSP());441if (frame_sp)442m_stack_id = frame_sp->GetStackID();443else444m_stack_id.Clear();445return *this;446}447448void ExecutionContextRef::Clear() {449m_target_wp.reset();450m_process_wp.reset();451ClearThread();452ClearFrame();453}454455ExecutionContextRef::~ExecutionContextRef() = default;456457void ExecutionContextRef::SetTargetSP(const lldb::TargetSP &target_sp) {458m_target_wp = target_sp;459}460461void ExecutionContextRef::SetProcessSP(const lldb::ProcessSP &process_sp) {462if (process_sp) {463m_process_wp = process_sp;464SetTargetSP(process_sp->GetTarget().shared_from_this());465} else {466m_process_wp.reset();467m_target_wp.reset();468}469}470471void ExecutionContextRef::SetThreadSP(const lldb::ThreadSP &thread_sp) {472if (thread_sp) {473m_thread_wp = thread_sp;474m_tid = thread_sp->GetID();475SetProcessSP(thread_sp->GetProcess());476} else {477ClearThread();478m_process_wp.reset();479m_target_wp.reset();480}481}482483void ExecutionContextRef::SetFrameSP(const lldb::StackFrameSP &frame_sp) {484if (frame_sp) {485m_stack_id = frame_sp->GetStackID();486SetThreadSP(frame_sp->GetThread());487} else {488ClearFrame();489ClearThread();490m_process_wp.reset();491m_target_wp.reset();492}493}494495void ExecutionContextRef::SetTargetPtr(Target *target, bool adopt_selected) {496Clear();497if (target) {498lldb::TargetSP target_sp(target->shared_from_this());499if (target_sp) {500m_target_wp = target_sp;501if (adopt_selected) {502lldb::ProcessSP process_sp(target_sp->GetProcessSP());503if (process_sp) {504m_process_wp = process_sp;505if (process_sp) {506// Only fill in the thread and frame if our process is stopped507// Don't just check the state, since we might be in the middle of508// resuming.509Process::StopLocker stop_locker;510511if (stop_locker.TryLock(&process_sp->GetRunLock()) &&512StateIsStoppedState(process_sp->GetState(), true)) {513lldb::ThreadSP thread_sp(514process_sp->GetThreadList().GetSelectedThread());515if (!thread_sp)516thread_sp = process_sp->GetThreadList().GetThreadAtIndex(0);517518if (thread_sp) {519SetThreadSP(thread_sp);520lldb::StackFrameSP frame_sp(521thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame));522if (!frame_sp)523frame_sp = thread_sp->GetStackFrameAtIndex(0);524if (frame_sp)525SetFrameSP(frame_sp);526}527}528}529}530}531}532}533}534535void ExecutionContextRef::SetProcessPtr(Process *process) {536if (process) {537SetProcessSP(process->shared_from_this());538} else {539m_process_wp.reset();540m_target_wp.reset();541}542}543544void ExecutionContextRef::SetThreadPtr(Thread *thread) {545if (thread) {546SetThreadSP(thread->shared_from_this());547} else {548ClearThread();549m_process_wp.reset();550m_target_wp.reset();551}552}553554void ExecutionContextRef::SetFramePtr(StackFrame *frame) {555if (frame)556SetFrameSP(frame->shared_from_this());557else558Clear();559}560561lldb::TargetSP ExecutionContextRef::GetTargetSP() const {562lldb::TargetSP target_sp(m_target_wp.lock());563if (target_sp && !target_sp->IsValid())564target_sp.reset();565return target_sp;566}567568lldb::ProcessSP ExecutionContextRef::GetProcessSP() const {569lldb::ProcessSP process_sp(m_process_wp.lock());570if (process_sp && !process_sp->IsValid())571process_sp.reset();572return process_sp;573}574575lldb::ThreadSP ExecutionContextRef::GetThreadSP() const {576lldb::ThreadSP thread_sp(m_thread_wp.lock());577578if (m_tid != LLDB_INVALID_THREAD_ID) {579// We check if the thread has been destroyed in cases where clients might580// still have shared pointer to a thread, but the thread is not valid581// anymore (not part of the process)582if (!thread_sp || !thread_sp->IsValid()) {583lldb::ProcessSP process_sp(GetProcessSP());584if (process_sp && process_sp->IsValid()) {585thread_sp = process_sp->GetThreadList().FindThreadByID(m_tid);586m_thread_wp = thread_sp;587}588}589}590591// Check that we aren't about to return an invalid thread sp. We might592// return a nullptr thread_sp, but don't return an invalid one.593594if (thread_sp && !thread_sp->IsValid())595thread_sp.reset();596597return thread_sp;598}599600lldb::StackFrameSP ExecutionContextRef::GetFrameSP() const {601if (m_stack_id.IsValid()) {602lldb::ThreadSP thread_sp(GetThreadSP());603if (thread_sp)604return thread_sp->GetFrameWithStackID(m_stack_id);605}606return lldb::StackFrameSP();607}608609ExecutionContext610ExecutionContextRef::Lock(bool thread_and_frame_only_if_stopped) const {611return ExecutionContext(this, thread_and_frame_only_if_stopped);612}613614615