439 lines · cpp
1//===-- SBThreadPlan.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/API/SBThread.h"10#include "lldb/Utility/Instrumentation.h"11 12#include "lldb/API/SBFileSpec.h"13#include "lldb/API/SBStream.h"14#include "lldb/API/SBStructuredData.h"15#include "lldb/API/SBSymbolContext.h"16#include "lldb/Breakpoint/BreakpointLocation.h"17#include "lldb/Core/Debugger.h"18#include "lldb/Core/StructuredDataImpl.h"19#include "lldb/Interpreter/CommandInterpreter.h"20#include "lldb/Symbol/CompileUnit.h"21#include "lldb/Symbol/SymbolContext.h"22#include "lldb/Target/Process.h"23#include "lldb/Target/Queue.h"24#include "lldb/Target/ScriptedThreadPlan.h"25#include "lldb/Target/StopInfo.h"26#include "lldb/Target/SystemRuntime.h"27#include "lldb/Target/Target.h"28#include "lldb/Target/Thread.h"29#include "lldb/Target/ThreadPlan.h"30#include "lldb/Target/ThreadPlanStepInRange.h"31#include "lldb/Target/ThreadPlanStepInstruction.h"32#include "lldb/Target/ThreadPlanStepOut.h"33#include "lldb/Target/ThreadPlanStepRange.h"34#include "lldb/Utility/State.h"35#include "lldb/Utility/Stream.h"36#include "lldb/Utility/StructuredData.h"37 38#include "lldb/API/SBAddress.h"39#include "lldb/API/SBDebugger.h"40#include "lldb/API/SBEvent.h"41#include "lldb/API/SBFrame.h"42#include "lldb/API/SBProcess.h"43#include "lldb/API/SBThreadPlan.h"44#include "lldb/API/SBValue.h"45 46#include <memory>47 48using namespace lldb;49using namespace lldb_private;50 51// Constructors52SBThreadPlan::SBThreadPlan() { LLDB_INSTRUMENT_VA(this); }53 54SBThreadPlan::SBThreadPlan(const ThreadPlanSP &lldb_object_sp)55 : m_opaque_wp(lldb_object_sp) {56 LLDB_INSTRUMENT_VA(this, lldb_object_sp);57}58 59SBThreadPlan::SBThreadPlan(const SBThreadPlan &rhs)60 : m_opaque_wp(rhs.m_opaque_wp) {61 LLDB_INSTRUMENT_VA(this, rhs);62}63 64SBThreadPlan::SBThreadPlan(lldb::SBThread &sb_thread, const char *class_name) {65 LLDB_INSTRUMENT_VA(this, sb_thread, class_name);66 67 Thread *thread = sb_thread.get();68 if (thread)69 m_opaque_wp = std::make_shared<ScriptedThreadPlan>(*thread, class_name,70 StructuredDataImpl());71}72 73SBThreadPlan::SBThreadPlan(lldb::SBThread &sb_thread, const char *class_name,74 lldb::SBStructuredData &args_data) {75 LLDB_INSTRUMENT_VA(this, sb_thread, class_name, args_data);76 77 Thread *thread = sb_thread.get();78 if (thread)79 m_opaque_wp = std::make_shared<ScriptedThreadPlan>(*thread, class_name,80 *args_data.m_impl_up);81}82 83// Assignment operator84 85const lldb::SBThreadPlan &SBThreadPlan::operator=(const SBThreadPlan &rhs) {86 LLDB_INSTRUMENT_VA(this, rhs);87 88 if (this != &rhs)89 m_opaque_wp = rhs.m_opaque_wp;90 return *this;91}92// Destructor93SBThreadPlan::~SBThreadPlan() = default;94 95bool SBThreadPlan::IsValid() const {96 LLDB_INSTRUMENT_VA(this);97 return this->operator bool();98}99SBThreadPlan::operator bool() const {100 LLDB_INSTRUMENT_VA(this);101 102 return static_cast<bool>(GetSP());103}104 105void SBThreadPlan::Clear() {106 LLDB_INSTRUMENT_VA(this);107 108 m_opaque_wp.reset();109}110 111lldb::StopReason SBThreadPlan::GetStopReason() {112 LLDB_INSTRUMENT_VA(this);113 114 return eStopReasonNone;115}116 117size_t SBThreadPlan::GetStopReasonDataCount() {118 LLDB_INSTRUMENT_VA(this);119 120 return 0;121}122 123uint64_t SBThreadPlan::GetStopReasonDataAtIndex(uint32_t idx) {124 LLDB_INSTRUMENT_VA(this, idx);125 126 return 0;127}128 129SBThread SBThreadPlan::GetThread() const {130 LLDB_INSTRUMENT_VA(this);131 132 ThreadPlanSP thread_plan_sp(GetSP());133 if (thread_plan_sp) {134 return SBThread(thread_plan_sp->GetThread().shared_from_this());135 } else136 return SBThread();137}138 139bool SBThreadPlan::GetDescription(lldb::SBStream &description) const {140 LLDB_INSTRUMENT_VA(this, description);141 142 ThreadPlanSP thread_plan_sp(GetSP());143 if (thread_plan_sp) {144 thread_plan_sp->GetDescription(description.get(), eDescriptionLevelFull);145 } else {146 description.Printf("Empty SBThreadPlan");147 }148 return true;149}150 151void SBThreadPlan::SetThreadPlan(const ThreadPlanSP &lldb_object_wp) {152 m_opaque_wp = lldb_object_wp;153}154 155void SBThreadPlan::SetPlanComplete(bool success) {156 LLDB_INSTRUMENT_VA(this, success);157 158 ThreadPlanSP thread_plan_sp(GetSP());159 if (thread_plan_sp)160 thread_plan_sp->SetPlanComplete(success);161}162 163bool SBThreadPlan::IsPlanComplete() {164 LLDB_INSTRUMENT_VA(this);165 166 ThreadPlanSP thread_plan_sp(GetSP());167 if (thread_plan_sp)168 return thread_plan_sp->IsPlanComplete();169 return true;170}171 172bool SBThreadPlan::IsPlanStale() {173 LLDB_INSTRUMENT_VA(this);174 175 ThreadPlanSP thread_plan_sp(GetSP());176 if (thread_plan_sp)177 return thread_plan_sp->IsPlanStale();178 return true;179}180 181bool SBThreadPlan::IsValid() {182 LLDB_INSTRUMENT_VA(this);183 184 ThreadPlanSP thread_plan_sp(GetSP());185 if (thread_plan_sp)186 return thread_plan_sp->ValidatePlan(nullptr);187 return false;188}189 190bool SBThreadPlan::GetStopOthers() {191 LLDB_INSTRUMENT_VA(this);192 193 ThreadPlanSP thread_plan_sp(GetSP());194 if (thread_plan_sp)195 return thread_plan_sp->StopOthers();196 return false;197}198 199void SBThreadPlan::SetStopOthers(bool stop_others) {200 LLDB_INSTRUMENT_VA(this, stop_others);201 202 ThreadPlanSP thread_plan_sp(GetSP());203 if (thread_plan_sp)204 thread_plan_sp->SetStopOthers(stop_others);205}206 207// This section allows an SBThreadPlan to push another of the common types of208// plans...209//210// FIXME, you should only be able to queue thread plans from inside the methods211// of a Scripted Thread Plan. Need a way to enforce that.212 213SBThreadPlan214SBThreadPlan::QueueThreadPlanForStepOverRange(SBAddress &sb_start_address,215 lldb::addr_t size) {216 LLDB_INSTRUMENT_VA(this, sb_start_address, size);217 218 SBError error;219 return QueueThreadPlanForStepOverRange(sb_start_address, size, error);220}221 222SBThreadPlan SBThreadPlan::QueueThreadPlanForStepOverRange(223 SBAddress &sb_start_address, lldb::addr_t size, SBError &error) {224 LLDB_INSTRUMENT_VA(this, sb_start_address, size, error);225 226 ThreadPlanSP thread_plan_sp(GetSP());227 if (thread_plan_sp) {228 Address *start_address = sb_start_address.get();229 if (!start_address) {230 return SBThreadPlan();231 }232 233 AddressRange range(*start_address, size);234 SymbolContext sc;235 start_address->CalculateSymbolContext(&sc);236 Status plan_status;237 238 SBThreadPlan plan = SBThreadPlan(239 thread_plan_sp->GetThread().QueueThreadPlanForStepOverRange(240 false, range, sc, eAllThreads, plan_status));241 242 if (plan_status.Fail())243 error.SetErrorString(plan_status.AsCString());244 else245 plan.GetSP()->SetPrivate(true);246 247 return plan;248 }249 return SBThreadPlan();250}251 252SBThreadPlan253SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address,254 lldb::addr_t size) {255 LLDB_INSTRUMENT_VA(this, sb_start_address, size);256 257 SBError error;258 return QueueThreadPlanForStepInRange(sb_start_address, size, error);259}260 261SBThreadPlan262SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address,263 lldb::addr_t size, SBError &error) {264 LLDB_INSTRUMENT_VA(this, sb_start_address, size, error);265 266 ThreadPlanSP thread_plan_sp(GetSP());267 if (thread_plan_sp) {268 Address *start_address = sb_start_address.get();269 if (!start_address) {270 return SBThreadPlan();271 }272 273 AddressRange range(*start_address, size);274 SymbolContext sc;275 start_address->CalculateSymbolContext(&sc);276 277 Status plan_status;278 SBThreadPlan plan =279 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepInRange(280 false, range, sc, nullptr, eAllThreads, plan_status));281 282 if (plan_status.Fail())283 error.SetErrorString(plan_status.AsCString());284 else285 plan.GetSP()->SetPrivate(true);286 287 return plan;288 }289 return SBThreadPlan();290}291 292SBThreadPlan293SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,294 bool first_insn) {295 LLDB_INSTRUMENT_VA(this, frame_idx_to_step_to, first_insn);296 297 SBError error;298 return QueueThreadPlanForStepOut(frame_idx_to_step_to, first_insn, error);299}300 301SBThreadPlan302SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,303 bool first_insn, SBError &error) {304 LLDB_INSTRUMENT_VA(this, frame_idx_to_step_to, first_insn, error);305 306 ThreadPlanSP thread_plan_sp(GetSP());307 if (thread_plan_sp) {308 SymbolContext sc;309 sc = thread_plan_sp->GetThread().GetStackFrameAtIndex(0)->GetSymbolContext(310 lldb::eSymbolContextEverything);311 312 Status plan_status;313 SBThreadPlan plan =314 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepOut(315 false, &sc, first_insn, false, eVoteYes, eVoteNoOpinion,316 frame_idx_to_step_to, plan_status));317 318 if (plan_status.Fail())319 error.SetErrorString(plan_status.AsCString());320 else321 plan.GetSP()->SetPrivate(true);322 323 return plan;324 }325 return SBThreadPlan();326}327 328SBThreadPlan329SBThreadPlan::QueueThreadPlanForStepSingleInstruction(bool step_over,330 SBError &error) {331 LLDB_INSTRUMENT_VA(this, step_over, error);332 333 ThreadPlanSP thread_plan_sp(GetSP());334 if (thread_plan_sp) {335 Status plan_status;336 SBThreadPlan plan(337 thread_plan_sp->GetThread().QueueThreadPlanForStepSingleInstruction(338 step_over, false, false, plan_status));339 340 if (plan_status.Fail())341 error.SetErrorString(plan_status.AsCString());342 else343 plan.GetSP()->SetPrivate(true);344 345 return plan;346 }347 348 return SBThreadPlan();349}350 351SBThreadPlan352SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address) {353 LLDB_INSTRUMENT_VA(this, sb_address);354 355 SBError error;356 return QueueThreadPlanForRunToAddress(sb_address, error);357}358 359SBThreadPlan SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address,360 SBError &error) {361 LLDB_INSTRUMENT_VA(this, sb_address, error);362 363 ThreadPlanSP thread_plan_sp(GetSP());364 if (thread_plan_sp) {365 Address *address = sb_address.get();366 if (!address)367 return SBThreadPlan();368 369 Status plan_status;370 SBThreadPlan plan =371 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForRunToAddress(372 false, *address, false, plan_status));373 374 if (plan_status.Fail())375 error.SetErrorString(plan_status.AsCString());376 else377 plan.GetSP()->SetPrivate(true);378 379 return plan;380 }381 return SBThreadPlan();382}383 384SBThreadPlan385SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name) {386 LLDB_INSTRUMENT_VA(this, script_class_name);387 388 SBError error;389 return QueueThreadPlanForStepScripted(script_class_name, error);390}391 392SBThreadPlan393SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name,394 SBError &error) {395 LLDB_INSTRUMENT_VA(this, script_class_name, error);396 397 ThreadPlanSP thread_plan_sp(GetSP());398 if (thread_plan_sp) {399 Status plan_status;400 StructuredData::ObjectSP empty_args;401 SBThreadPlan plan =402 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepScripted(403 false, script_class_name, empty_args, false, plan_status));404 405 if (plan_status.Fail())406 error.SetErrorString(plan_status.AsCString());407 else408 plan.GetSP()->SetPrivate(true);409 410 return plan;411 }412 return SBThreadPlan();413}414 415SBThreadPlan416SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name,417 lldb::SBStructuredData &args_data,418 SBError &error) {419 LLDB_INSTRUMENT_VA(this, script_class_name, args_data, error);420 421 ThreadPlanSP thread_plan_sp(GetSP());422 if (thread_plan_sp) {423 Status plan_status;424 StructuredData::ObjectSP args_obj = args_data.m_impl_up->GetObjectSP();425 SBThreadPlan plan =426 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepScripted(427 false, script_class_name, args_obj, false, plan_status));428 429 if (plan_status.Fail())430 error.SetErrorString(plan_status.AsCString());431 else432 plan.GetSP()->SetPrivate(true);433 434 return plan;435 } else {436 return SBThreadPlan();437 }438}439