brintos

brintos / llvm-project-archived public Read only

0
0
Text · 19.3 KiB · a795913 Raw
652 lines · cpp
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-exception6//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/LLDBLog.h"16#include "lldb/Utility/State.h"17#include <mutex>18 19using namespace lldb_private;20 21ExecutionContext::ExecutionContext()22    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {}23 24ExecutionContext::ExecutionContext(const ExecutionContext &rhs) = default;25 26ExecutionContext::ExecutionContext(const lldb::TargetSP &target_sp,27                                   bool get_process)28    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {29  if (target_sp)30    SetContext(target_sp, get_process);31}32 33ExecutionContext::ExecutionContext(const lldb::ProcessSP &process_sp)34    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {35  if (process_sp)36    SetContext(process_sp);37}38 39ExecutionContext::ExecutionContext(const lldb::ThreadSP &thread_sp)40    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {41  if (thread_sp)42    SetContext(thread_sp);43}44 45ExecutionContext::ExecutionContext(const lldb::StackFrameSP &frame_sp)46    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {47  if (frame_sp)48    SetContext(frame_sp);49}50 51ExecutionContext::ExecutionContext(const lldb::TargetWP &target_wp,52                                   bool get_process)53    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {54  lldb::TargetSP target_sp(target_wp.lock());55  if (target_sp)56    SetContext(target_sp, get_process);57}58 59ExecutionContext::ExecutionContext(const lldb::ProcessWP &process_wp)60    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {61  lldb::ProcessSP process_sp(process_wp.lock());62  if (process_sp)63    SetContext(process_sp);64}65 66ExecutionContext::ExecutionContext(const lldb::ThreadWP &thread_wp)67    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {68  lldb::ThreadSP thread_sp(thread_wp.lock());69  if (thread_sp)70    SetContext(thread_sp);71}72 73ExecutionContext::ExecutionContext(const lldb::StackFrameWP &frame_wp)74    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {75  lldb::StackFrameSP frame_sp(frame_wp.lock());76  if (frame_sp)77    SetContext(frame_sp);78}79 80ExecutionContext::ExecutionContext(Target *t,81                                   bool fill_current_process_thread_frame)82    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {83  if (t) {84    m_target_sp = t->shared_from_this();85    if (fill_current_process_thread_frame) {86      m_process_sp = t->GetProcessSP();87      if (m_process_sp) {88        m_thread_sp = m_process_sp->GetThreadList().GetSelectedThread();89        if (m_thread_sp)90          m_frame_sp =91              m_thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);92      }93    }94  }95}96 97ExecutionContext::ExecutionContext(Process *process, Thread *thread,98                                   StackFrame *frame)99    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {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 110ExecutionContext::ExecutionContext(const ExecutionContextRef &exe_ctx_ref)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 116ExecutionContext::ExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr,117                                   bool thread_and_frame_only_if_stopped)118    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {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>131lldb_private::GetStoppedExecutionContext(132    const lldb::ExecutionContextRefSP &exe_ctx_ref_ptr) {133  return GetStoppedExecutionContext(exe_ctx_ref_ptr.get());134}135 136llvm::Expected<StoppedExecutionContext>137lldb_private::GetStoppedExecutionContext(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 156  ProcessRunLock::ProcessRunLocker stop_locker;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();169  m_stop_locker = ProcessRunLock::ProcessRunLocker();170  return std::move(m_api_lock);171}172 173ExecutionContext::ExecutionContext(ExecutionContextScope *exe_scope_ptr)174    : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() {175  if (exe_scope_ptr)176    exe_scope_ptr->CalculateExecutionContext(*this);177}178 179ExecutionContext::ExecutionContext(ExecutionContextScope &exe_scope_ref) {180  exe_scope_ref.CalculateExecutionContext(*this);181}182 183void ExecutionContext::Clear() {184  m_target_sp.reset();185  m_process_sp.reset();186  m_thread_sp.reset();187  m_frame_sp.reset();188}189 190ExecutionContext::~ExecutionContext() = default;191 192uint32_t ExecutionContext::GetAddressByteSize() const {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 200lldb::ByteOrder ExecutionContext::GetByteOrder() const {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();205  return endian::InlHostByteOrder();206}207 208RegisterContext *ExecutionContext::GetRegisterContext() const {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 216Target *ExecutionContext::GetTargetPtr() const {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 224Process *ExecutionContext::GetProcessPtr() const {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 232ExecutionContextScope *ExecutionContext::GetBestExecutionContextScope() const {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 242Target &ExecutionContext::GetTargetRef() const {243  assert(m_target_sp);244  return *m_target_sp;245}246 247Process &ExecutionContext::GetProcessRef() const {248  assert(m_process_sp);249  return *m_process_sp;250}251 252Thread &ExecutionContext::GetThreadRef() const {253  assert(m_thread_sp);254  return *m_thread_sp;255}256 257StackFrame &ExecutionContext::GetFrameRef() const {258  assert(m_frame_sp);259  return *m_frame_sp;260}261 262void ExecutionContext::SetTargetSP(const lldb::TargetSP &target_sp) {263  m_target_sp = target_sp;264}265 266void ExecutionContext::SetProcessSP(const lldb::ProcessSP &process_sp) {267  m_process_sp = process_sp;268}269 270void ExecutionContext::SetThreadSP(const lldb::ThreadSP &thread_sp) {271  m_thread_sp = thread_sp;272}273 274void ExecutionContext::SetFrameSP(const lldb::StackFrameSP &frame_sp) {275  m_frame_sp = frame_sp;276}277 278void ExecutionContext::SetTargetPtr(Target *target) {279  if (target)280    m_target_sp = target->shared_from_this();281  else282    m_target_sp.reset();283}284 285void ExecutionContext::SetProcessPtr(Process *process) {286  if (process)287    m_process_sp = process->shared_from_this();288  else289    m_process_sp.reset();290}291 292void ExecutionContext::SetThreadPtr(Thread *thread) {293  if (thread)294    m_thread_sp = thread->shared_from_this();295  else296    m_thread_sp.reset();297}298 299void ExecutionContext::SetFramePtr(StackFrame *frame) {300  if (frame)301    m_frame_sp = frame->shared_from_this();302  else303    m_frame_sp.reset();304}305 306void ExecutionContext::SetContext(const lldb::TargetSP &target_sp,307                                  bool get_process) {308  m_target_sp = target_sp;309  if (get_process && target_sp)310    m_process_sp = target_sp->GetProcessSP();311  else312    m_process_sp.reset();313  m_thread_sp.reset();314  m_frame_sp.reset();315}316 317void ExecutionContext::SetContext(const lldb::ProcessSP &process_sp) {318  m_process_sp = process_sp;319  if (process_sp)320    m_target_sp = process_sp->GetTarget().shared_from_this();321  else322    m_target_sp.reset();323  m_thread_sp.reset();324  m_frame_sp.reset();325}326 327void ExecutionContext::SetContext(const lldb::ThreadSP &thread_sp) {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    else335      m_target_sp.reset();336  } else {337    m_target_sp.reset();338    m_process_sp.reset();339  }340}341 342void ExecutionContext::SetContext(const lldb::StackFrameSP &frame_sp) {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      else351        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 363ExecutionContext &ExecutionContext::operator=(const ExecutionContext &rhs) {364  if (this != &rhs) {365    m_target_sp = rhs.m_target_sp;366    m_process_sp = rhs.m_process_sp;367    m_thread_sp = rhs.m_thread_sp;368    m_frame_sp = rhs.m_frame_sp;369  }370  return *this;371}372 373bool ExecutionContext::operator==(const ExecutionContext &rhs) const {374  // Check that the frame shared pointers match, or both are valid and their375  // stack IDs match since sometimes we get new objects that represent the same376  // 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 their381    // thread IDs match since sometimes we get new objects that represent the382    // 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 much387      return m_process_sp == rhs.m_process_sp && m_target_sp == rhs.m_target_sp;388    }389  }390  return false;391}392 393bool ExecutionContext::operator!=(const ExecutionContext &rhs) const {394  return !(*this == rhs);395}396 397bool ExecutionContext::HasTargetScope() const {398  return ((bool)m_target_sp && m_target_sp->IsValid());399}400 401bool ExecutionContext::HasProcessScope() const {402  return (HasTargetScope() && ((bool)m_process_sp && m_process_sp->IsValid()));403}404 405bool ExecutionContext::HasThreadScope() const {406  return (HasProcessScope() && ((bool)m_thread_sp && m_thread_sp->IsValid()));407}408 409bool ExecutionContext::HasFrameScope() const {410  return HasThreadScope() && m_frame_sp;411}412 413ExecutionContextRef::ExecutionContextRef()414    : m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() {}415 416ExecutionContextRef::ExecutionContextRef(const ExecutionContext *exe_ctx)417    : m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() {418  if (exe_ctx)419    *this = *exe_ctx;420}421 422ExecutionContextRef::ExecutionContextRef(const ExecutionContext &exe_ctx)423    : m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() {424  *this = exe_ctx;425}426 427ExecutionContextRef::ExecutionContextRef(Target *target, bool adopt_selected)428    : m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() {429  SetTargetPtr(target, adopt_selected);430}431 432ExecutionContextRef::ExecutionContextRef(Process *process, bool adopt_selected)433    : m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() {434  SetProcessPtr(process, adopt_selected);435}436 437ExecutionContextRef::ExecutionContextRef(Thread *thread, bool adopt_selected)438    : m_target_wp(), m_process_wp(), m_thread_wp(), m_stack_id() {439  SetThreadPtr(thread, adopt_selected);440}441 442ExecutionContextRef::ExecutionContextRef(const ExecutionContextRef &rhs)443 444    = default;445 446ExecutionContextRef &ExecutionContextRef::447operator=(const ExecutionContextRef &rhs) {448  if (this != &rhs) {449    m_target_wp = rhs.m_target_wp;450    m_process_wp = rhs.m_process_wp;451    m_thread_wp = rhs.m_thread_wp;452    m_tid = rhs.m_tid;453    m_stack_id = rhs.m_stack_id;454  }455  return *this;456}457 458ExecutionContextRef &ExecutionContextRef::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  else467    m_tid = LLDB_INVALID_THREAD_ID;468  lldb::StackFrameSP frame_sp(exe_ctx.GetFrameSP());469  if (frame_sp)470    m_stack_id = frame_sp->GetStackID();471  else472    m_stack_id.Clear();473  return *this;474}475 476void ExecutionContextRef::Clear() {477  m_target_wp.reset();478  m_process_wp.reset();479  ClearThread();480  ClearFrame();481}482 483ExecutionContextRef::~ExecutionContextRef() = default;484 485void ExecutionContextRef::SetTargetSP(const lldb::TargetSP &target_sp) {486  m_target_wp = target_sp;487}488 489void ExecutionContextRef::SetProcessSP(const lldb::ProcessSP &process_sp) {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 499void ExecutionContextRef::SetThreadSP(const lldb::ThreadSP &thread_sp) {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 511void ExecutionContextRef::SetFrameSP(const lldb::StackFrameSP &frame_sp) {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 of542      // 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 of574      // 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 593void ExecutionContextRef::SetFramePtr(StackFrame *frame) {594  if (frame)595    SetFrameSP(frame->shared_from_this());596  else597    Clear();598}599 600lldb::TargetSP ExecutionContextRef::GetTargetSP() const {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 607lldb::ProcessSP ExecutionContextRef::GetProcessSP() const {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 614lldb::ThreadSP ExecutionContextRef::GetThreadSP() const {615  lldb::ThreadSP thread_sp(m_thread_wp.lock());616 617  if (m_tid != LLDB_INVALID_THREAD_ID) {618    // We check if the thread has been destroyed in cases where clients might619    // still have shared pointer to a thread, but the thread is not valid620    // 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 might631  // 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 639lldb::StackFrameSP ExecutionContextRef::GetFrameSP() const {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 648ExecutionContext649ExecutionContextRef::Lock(bool thread_and_frame_only_if_stopped) const {650  return ExecutionContext(this, thread_and_frame_only_if_stopped);651}652