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