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