diff options
Diffstat (limited to 'lldb/source/API/SBThreadPlan.cpp')
| -rw-r--r-- | lldb/source/API/SBThreadPlan.cpp | 486 | 
1 files changed, 486 insertions, 0 deletions
| diff --git a/lldb/source/API/SBThreadPlan.cpp b/lldb/source/API/SBThreadPlan.cpp new file mode 100644 index 000000000000..eed4d1bfb9c4 --- /dev/null +++ b/lldb/source/API/SBThreadPlan.cpp @@ -0,0 +1,486 @@ +//===-- SBThreadPlan.cpp ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "SBReproducerPrivate.h" +#include "lldb/API/SBThread.h" + +#include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBStream.h" +#include "lldb/API/SBStructuredData.h" +#include "lldb/API/SBSymbolContext.h" +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/StructuredDataImpl.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Queue.h" +#include "lldb/Target/StopInfo.h" +#include "lldb/Target/SystemRuntime.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanPython.h" +#include "lldb/Target/ThreadPlanStepInRange.h" +#include "lldb/Target/ThreadPlanStepInstruction.h" +#include "lldb/Target/ThreadPlanStepOut.h" +#include "lldb/Target/ThreadPlanStepRange.h" +#include "lldb/Utility/State.h" +#include "lldb/Utility/Stream.h" +#include "lldb/Utility/StructuredData.h" + +#include "lldb/API/SBAddress.h" +#include "lldb/API/SBDebugger.h" +#include "lldb/API/SBEvent.h" +#include "lldb/API/SBFrame.h" +#include "lldb/API/SBProcess.h" +#include "lldb/API/SBThreadPlan.h" +#include "lldb/API/SBValue.h" + +#include <memory> + +using namespace lldb; +using namespace lldb_private; + +// Constructors +SBThreadPlan::SBThreadPlan() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBThreadPlan); } + +SBThreadPlan::SBThreadPlan(const ThreadPlanSP &lldb_object_sp) +    : m_opaque_sp(lldb_object_sp) { +  LLDB_RECORD_CONSTRUCTOR(SBThreadPlan, (const lldb::ThreadPlanSP &), +                          lldb_object_sp); +} + +SBThreadPlan::SBThreadPlan(const SBThreadPlan &rhs) +    : m_opaque_sp(rhs.m_opaque_sp) { +  LLDB_RECORD_CONSTRUCTOR(SBThreadPlan, (const lldb::SBThreadPlan &), rhs); +} + +SBThreadPlan::SBThreadPlan(lldb::SBThread &sb_thread, const char *class_name) { +  LLDB_RECORD_CONSTRUCTOR(SBThreadPlan, (lldb::SBThread &, const char *), +                          sb_thread, class_name); + +  Thread *thread = sb_thread.get(); +  if (thread) +    m_opaque_sp = std::make_shared<ThreadPlanPython>(*thread, class_name,  +                                                     nullptr); +} + +SBThreadPlan::SBThreadPlan(lldb::SBThread &sb_thread, const char *class_name, +                           lldb::SBStructuredData &args_data) { +  LLDB_RECORD_CONSTRUCTOR(SBThreadPlan, (lldb::SBThread &, const char *, +                                         SBStructuredData &), +                          sb_thread, class_name, args_data); + +  Thread *thread = sb_thread.get(); +  if (thread) +    m_opaque_sp = std::make_shared<ThreadPlanPython>(*thread, class_name,  +                                                     args_data.m_impl_up.get()); +} + +// Assignment operator + +const lldb::SBThreadPlan &SBThreadPlan::operator=(const SBThreadPlan &rhs) { +  LLDB_RECORD_METHOD(const lldb::SBThreadPlan &, +                     SBThreadPlan, operator=,(const lldb::SBThreadPlan &), rhs); + +  if (this != &rhs) +    m_opaque_sp = rhs.m_opaque_sp; +  return LLDB_RECORD_RESULT(*this); +} +// Destructor +SBThreadPlan::~SBThreadPlan() {} + +lldb_private::ThreadPlan *SBThreadPlan::get() { return m_opaque_sp.get(); } + +bool SBThreadPlan::IsValid() const { +  LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBThreadPlan, IsValid); +  return this->operator bool(); +} +SBThreadPlan::operator bool() const { +  LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBThreadPlan, operator bool); + +  return m_opaque_sp.get() != nullptr; +} + +void SBThreadPlan::Clear() { +  LLDB_RECORD_METHOD_NO_ARGS(void, SBThreadPlan, Clear); + +  m_opaque_sp.reset(); +} + +lldb::StopReason SBThreadPlan::GetStopReason() { +  LLDB_RECORD_METHOD_NO_ARGS(lldb::StopReason, SBThreadPlan, GetStopReason); + +  return eStopReasonNone; +} + +size_t SBThreadPlan::GetStopReasonDataCount() { +  LLDB_RECORD_METHOD_NO_ARGS(size_t, SBThreadPlan, GetStopReasonDataCount); + +  return 0; +} + +uint64_t SBThreadPlan::GetStopReasonDataAtIndex(uint32_t idx) { +  LLDB_RECORD_METHOD(uint64_t, SBThreadPlan, GetStopReasonDataAtIndex, +                     (uint32_t), idx); + +  return 0; +} + +SBThread SBThreadPlan::GetThread() const { +  LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBThread, SBThreadPlan, GetThread); + +  if (m_opaque_sp) { +    return LLDB_RECORD_RESULT( +        SBThread(m_opaque_sp->GetThread().shared_from_this())); +  } else +    return LLDB_RECORD_RESULT(SBThread()); +} + +bool SBThreadPlan::GetDescription(lldb::SBStream &description) const { +  LLDB_RECORD_METHOD_CONST(bool, SBThreadPlan, GetDescription, +                           (lldb::SBStream &), description); + +  if (m_opaque_sp) { +    m_opaque_sp->GetDescription(description.get(), eDescriptionLevelFull); +  } else { +    description.Printf("Empty SBThreadPlan"); +  } +  return true; +} + +void SBThreadPlan::SetThreadPlan(const ThreadPlanSP &lldb_object_sp) { +  m_opaque_sp = lldb_object_sp; +} + +void SBThreadPlan::SetPlanComplete(bool success) { +  LLDB_RECORD_METHOD(void, SBThreadPlan, SetPlanComplete, (bool), success); + +  if (m_opaque_sp) +    m_opaque_sp->SetPlanComplete(success); +} + +bool SBThreadPlan::IsPlanComplete() { +  LLDB_RECORD_METHOD_NO_ARGS(bool, SBThreadPlan, IsPlanComplete); + +  if (m_opaque_sp) +    return m_opaque_sp->IsPlanComplete(); +  else +    return true; +} + +bool SBThreadPlan::IsPlanStale() { +  LLDB_RECORD_METHOD_NO_ARGS(bool, SBThreadPlan, IsPlanStale); + +  if (m_opaque_sp) +    return m_opaque_sp->IsPlanStale(); +  else +    return true; +} + +bool SBThreadPlan::IsValid() { +  LLDB_RECORD_METHOD_NO_ARGS(bool, SBThreadPlan, IsValid); + +  if (m_opaque_sp) +    return m_opaque_sp->ValidatePlan(nullptr); +  else +    return false; +} + +// This section allows an SBThreadPlan to push another of the common types of +// plans... +// +// FIXME, you should only be able to queue thread plans from inside the methods +// of a Scripted Thread Plan.  Need a way to enforce that. + +SBThreadPlan +SBThreadPlan::QueueThreadPlanForStepOverRange(SBAddress &sb_start_address, +                                              lldb::addr_t size) { +  LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                     QueueThreadPlanForStepOverRange, +                     (lldb::SBAddress &, lldb::addr_t), sb_start_address, size); + +  SBError error; +  return LLDB_RECORD_RESULT( +      QueueThreadPlanForStepOverRange(sb_start_address, size, error)); +} + +SBThreadPlan SBThreadPlan::QueueThreadPlanForStepOverRange( +    SBAddress &sb_start_address, lldb::addr_t size, SBError &error) { +  LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                     QueueThreadPlanForStepOverRange, +                     (lldb::SBAddress &, lldb::addr_t, lldb::SBError &), +                     sb_start_address, size, error); + +  if (m_opaque_sp) { +    Address *start_address = sb_start_address.get(); +    if (!start_address) { +      return LLDB_RECORD_RESULT(SBThreadPlan()); +    } + +    AddressRange range(*start_address, size); +    SymbolContext sc; +    start_address->CalculateSymbolContext(&sc); +    Status plan_status; + +    SBThreadPlan plan = +        SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepOverRange( +            false, range, sc, eAllThreads, plan_status)); + +    if (plan_status.Fail()) +      error.SetErrorString(plan_status.AsCString()); + +    return LLDB_RECORD_RESULT(plan); +  } else { +    return LLDB_RECORD_RESULT(SBThreadPlan()); +  } +} + +SBThreadPlan +SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address, +                                            lldb::addr_t size) { +  LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                     QueueThreadPlanForStepInRange, +                     (lldb::SBAddress &, lldb::addr_t), sb_start_address, size); + +  SBError error; +  return LLDB_RECORD_RESULT( +      QueueThreadPlanForStepInRange(sb_start_address, size, error)); +} + +SBThreadPlan +SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address, +                                            lldb::addr_t size, SBError &error) { +  LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                     QueueThreadPlanForStepInRange, +                     (lldb::SBAddress &, lldb::addr_t, lldb::SBError &), +                     sb_start_address, size, error); + +  if (m_opaque_sp) { +    Address *start_address = sb_start_address.get(); +    if (!start_address) { +      return LLDB_RECORD_RESULT(SBThreadPlan()); +    } + +    AddressRange range(*start_address, size); +    SymbolContext sc; +    start_address->CalculateSymbolContext(&sc); + +    Status plan_status; +    SBThreadPlan plan = +        SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepInRange( +            false, range, sc, nullptr, eAllThreads, plan_status)); + +    if (plan_status.Fail()) +      error.SetErrorString(plan_status.AsCString()); + +    return LLDB_RECORD_RESULT(plan); +  } else { +    return LLDB_RECORD_RESULT(SBThreadPlan()); +  } +} + +SBThreadPlan +SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to, +                                        bool first_insn) { +  LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                     QueueThreadPlanForStepOut, (uint32_t, bool), +                     frame_idx_to_step_to, first_insn); + +  SBError error; +  return LLDB_RECORD_RESULT( +      QueueThreadPlanForStepOut(frame_idx_to_step_to, first_insn, error)); +} + +SBThreadPlan +SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to, +                                        bool first_insn, SBError &error) { +  LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                     QueueThreadPlanForStepOut, +                     (uint32_t, bool, lldb::SBError &), frame_idx_to_step_to, +                     first_insn, error); + +  if (m_opaque_sp) { +    SymbolContext sc; +    sc = m_opaque_sp->GetThread().GetStackFrameAtIndex(0)->GetSymbolContext( +        lldb::eSymbolContextEverything); + +    Status plan_status; +    SBThreadPlan plan = +        SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepOut( +            false, &sc, first_insn, false, eVoteYes, eVoteNoOpinion, +            frame_idx_to_step_to, plan_status)); + +    if (plan_status.Fail()) +      error.SetErrorString(plan_status.AsCString()); + +    return LLDB_RECORD_RESULT(plan); +  } else { +    return LLDB_RECORD_RESULT(SBThreadPlan()); +  } +} + +SBThreadPlan +SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address) { +  LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                     QueueThreadPlanForRunToAddress, (lldb::SBAddress), +                     sb_address); + +  SBError error; +  return LLDB_RECORD_RESULT(QueueThreadPlanForRunToAddress(sb_address, error)); +} + +SBThreadPlan SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address, +                                                          SBError &error) { +  LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                     QueueThreadPlanForRunToAddress, +                     (lldb::SBAddress, lldb::SBError &), sb_address, error); + +  if (m_opaque_sp) { +    Address *address = sb_address.get(); +    if (!address) +      return LLDB_RECORD_RESULT(SBThreadPlan()); + +    Status plan_status; +    SBThreadPlan plan = +        SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForRunToAddress( +            false, *address, false, plan_status)); + +    if (plan_status.Fail()) +      error.SetErrorString(plan_status.AsCString()); + +    return LLDB_RECORD_RESULT(plan); +  } else { +    return LLDB_RECORD_RESULT(SBThreadPlan()); +  } +} + +SBThreadPlan +SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name) { +  LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                     QueueThreadPlanForStepScripted, (const char *), +                     script_class_name); + +  SBError error; +  return LLDB_RECORD_RESULT( +      QueueThreadPlanForStepScripted(script_class_name, error)); +} + +SBThreadPlan +SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name, +                                             SBError &error) { +  LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                     QueueThreadPlanForStepScripted, +                     (const char *, lldb::SBError &), script_class_name, error); + +  if (m_opaque_sp) { +    Status plan_status; +    StructuredData::ObjectSP empty_args; +    SBThreadPlan plan = +        SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepScripted( +            false, script_class_name, empty_args, false, plan_status)); + +    if (plan_status.Fail()) +      error.SetErrorString(plan_status.AsCString()); + +    return LLDB_RECORD_RESULT(plan); +  } else { +    return LLDB_RECORD_RESULT(SBThreadPlan()); +  } +} + +SBThreadPlan +SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name, +                                             lldb::SBStructuredData &args_data, +                                             SBError &error) { +  LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                     QueueThreadPlanForStepScripted, +                     (const char *, lldb::SBStructuredData &, lldb::SBError &),  +                     script_class_name, args_data, error); + +  if (m_opaque_sp) { +    Status plan_status; +    StructuredData::ObjectSP args_obj = args_data.m_impl_up->GetObjectSP(); +    SBThreadPlan plan = +        SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepScripted( +            false, script_class_name, args_obj, false, plan_status)); + +    if (plan_status.Fail()) +      error.SetErrorString(plan_status.AsCString()); + +    return LLDB_RECORD_RESULT(plan); +  } else { +    return LLDB_RECORD_RESULT(SBThreadPlan()); +  } +} + +namespace lldb_private { +namespace repro { + +template <> +void RegisterMethods<SBThreadPlan>(Registry &R) { +  LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, ()); +  LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (const lldb::ThreadPlanSP &)); +  LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (const lldb::SBThreadPlan &)); +  LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (lldb::SBThread &, const char *)); +  LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (lldb::SBThread &, const char *, +                       lldb::SBStructuredData &)); +  LLDB_REGISTER_METHOD(const lldb::SBThreadPlan &, +                       SBThreadPlan, operator=,(const lldb::SBThreadPlan &)); +  LLDB_REGISTER_METHOD_CONST(bool, SBThreadPlan, IsValid, ()); +  LLDB_REGISTER_METHOD_CONST(bool, SBThreadPlan, operator bool, ()); +  LLDB_REGISTER_METHOD(void, SBThreadPlan, Clear, ()); +  LLDB_REGISTER_METHOD(lldb::StopReason, SBThreadPlan, GetStopReason, ()); +  LLDB_REGISTER_METHOD(size_t, SBThreadPlan, GetStopReasonDataCount, ()); +  LLDB_REGISTER_METHOD(uint64_t, SBThreadPlan, GetStopReasonDataAtIndex, +                       (uint32_t)); +  LLDB_REGISTER_METHOD_CONST(lldb::SBThread, SBThreadPlan, GetThread, ()); +  LLDB_REGISTER_METHOD_CONST(bool, SBThreadPlan, GetDescription, +                             (lldb::SBStream &)); +  LLDB_REGISTER_METHOD(void, SBThreadPlan, SetPlanComplete, (bool)); +  LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsPlanComplete, ()); +  LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsPlanStale, ()); +  LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsValid, ()); +  LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                       QueueThreadPlanForStepOverRange, +                       (lldb::SBAddress &, lldb::addr_t)); +  LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                       QueueThreadPlanForStepOverRange, +                       (lldb::SBAddress &, lldb::addr_t, lldb::SBError &)); +  LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                       QueueThreadPlanForStepInRange, +                       (lldb::SBAddress &, lldb::addr_t)); +  LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                       QueueThreadPlanForStepInRange, +                       (lldb::SBAddress &, lldb::addr_t, lldb::SBError &)); +  LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                       QueueThreadPlanForStepOut, (uint32_t, bool)); +  LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                       QueueThreadPlanForStepOut, +                       (uint32_t, bool, lldb::SBError &)); +  LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                       QueueThreadPlanForRunToAddress, (lldb::SBAddress)); +  LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                       QueueThreadPlanForRunToAddress, +                       (lldb::SBAddress, lldb::SBError &)); +  LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                       QueueThreadPlanForStepScripted, (const char *)); +  LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                       QueueThreadPlanForStepScripted, +                       (const char *, lldb::SBError &)); +  LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, +                       QueueThreadPlanForStepScripted, +                       (const char *, lldb::SBStructuredData &, +                       lldb::SBError &)); +} + +} +} | 
