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_wp(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_wp(rhs.m_opaque_wp) { 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_wp = 73 std::make_shared<ThreadPlanPython>(*thread, class_name, 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_wp = 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_wp = rhs.m_opaque_wp; 96 return LLDB_RECORD_RESULT(*this); 97 } 98 // Destructor 99 SBThreadPlan::~SBThreadPlan() = default; 100 101 bool SBThreadPlan::IsValid() const { 102 LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBThreadPlan, IsValid); 103 return this->operator bool(); 104 } 105 SBThreadPlan::operator bool() const { 106 LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBThreadPlan, operator bool); 107 108 return static_cast<bool>(GetSP()); 109 } 110 111 void SBThreadPlan::Clear() { 112 LLDB_RECORD_METHOD_NO_ARGS(void, SBThreadPlan, Clear); 113 114 m_opaque_wp.reset(); 115 } 116 117 lldb::StopReason SBThreadPlan::GetStopReason() { 118 LLDB_RECORD_METHOD_NO_ARGS(lldb::StopReason, SBThreadPlan, GetStopReason); 119 120 return eStopReasonNone; 121 } 122 123 size_t SBThreadPlan::GetStopReasonDataCount() { 124 LLDB_RECORD_METHOD_NO_ARGS(size_t, SBThreadPlan, GetStopReasonDataCount); 125 126 return 0; 127 } 128 129 uint64_t SBThreadPlan::GetStopReasonDataAtIndex(uint32_t idx) { 130 LLDB_RECORD_METHOD(uint64_t, SBThreadPlan, GetStopReasonDataAtIndex, 131 (uint32_t), idx); 132 133 return 0; 134 } 135 136 SBThread SBThreadPlan::GetThread() const { 137 LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBThread, SBThreadPlan, GetThread); 138 139 ThreadPlanSP thread_plan_sp(GetSP()); 140 if (thread_plan_sp) { 141 return LLDB_RECORD_RESULT( 142 SBThread(thread_plan_sp->GetThread().shared_from_this())); 143 } else 144 return LLDB_RECORD_RESULT(SBThread()); 145 } 146 147 bool SBThreadPlan::GetDescription(lldb::SBStream &description) const { 148 LLDB_RECORD_METHOD_CONST(bool, SBThreadPlan, GetDescription, 149 (lldb::SBStream &), description); 150 151 ThreadPlanSP thread_plan_sp(GetSP()); 152 if (thread_plan_sp) { 153 thread_plan_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_wp) { 161 m_opaque_wp = lldb_object_wp; 162 } 163 164 void SBThreadPlan::SetPlanComplete(bool success) { 165 LLDB_RECORD_METHOD(void, SBThreadPlan, SetPlanComplete, (bool), success); 166 167 ThreadPlanSP thread_plan_sp(GetSP()); 168 if (thread_plan_sp) 169 thread_plan_sp->SetPlanComplete(success); 170 } 171 172 bool SBThreadPlan::IsPlanComplete() { 173 LLDB_RECORD_METHOD_NO_ARGS(bool, SBThreadPlan, IsPlanComplete); 174 175 ThreadPlanSP thread_plan_sp(GetSP()); 176 if (thread_plan_sp) 177 return thread_plan_sp->IsPlanComplete(); 178 return true; 179 } 180 181 bool SBThreadPlan::IsPlanStale() { 182 LLDB_RECORD_METHOD_NO_ARGS(bool, SBThreadPlan, IsPlanStale); 183 184 ThreadPlanSP thread_plan_sp(GetSP()); 185 if (thread_plan_sp) 186 return thread_plan_sp->IsPlanStale(); 187 return true; 188 } 189 190 bool SBThreadPlan::IsValid() { 191 LLDB_RECORD_METHOD_NO_ARGS(bool, SBThreadPlan, IsValid); 192 193 ThreadPlanSP thread_plan_sp(GetSP()); 194 if (thread_plan_sp) 195 return thread_plan_sp->ValidatePlan(nullptr); 196 return false; 197 } 198 199 bool SBThreadPlan::GetStopOthers() { 200 LLDB_RECORD_METHOD_NO_ARGS(bool, SBThreadPlan, GetStopOthers); 201 202 ThreadPlanSP thread_plan_sp(GetSP()); 203 if (thread_plan_sp) 204 return thread_plan_sp->StopOthers(); 205 return false; 206 } 207 208 void SBThreadPlan::SetStopOthers(bool stop_others) { 209 LLDB_RECORD_METHOD(void, SBThreadPlan, SetStopOthers, (bool), stop_others); 210 211 ThreadPlanSP thread_plan_sp(GetSP()); 212 if (thread_plan_sp) 213 thread_plan_sp->SetStopOthers(stop_others); 214 } 215 216 // This section allows an SBThreadPlan to push another of the common types of 217 // plans... 218 // 219 // FIXME, you should only be able to queue thread plans from inside the methods 220 // of a Scripted Thread Plan. Need a way to enforce that. 221 222 SBThreadPlan 223 SBThreadPlan::QueueThreadPlanForStepOverRange(SBAddress &sb_start_address, 224 lldb::addr_t size) { 225 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 226 QueueThreadPlanForStepOverRange, 227 (lldb::SBAddress &, lldb::addr_t), sb_start_address, size); 228 229 SBError error; 230 return LLDB_RECORD_RESULT( 231 QueueThreadPlanForStepOverRange(sb_start_address, size, error)); 232 } 233 234 SBThreadPlan SBThreadPlan::QueueThreadPlanForStepOverRange( 235 SBAddress &sb_start_address, lldb::addr_t size, SBError &error) { 236 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 237 QueueThreadPlanForStepOverRange, 238 (lldb::SBAddress &, lldb::addr_t, lldb::SBError &), 239 sb_start_address, size, error); 240 241 ThreadPlanSP thread_plan_sp(GetSP()); 242 if (thread_plan_sp) { 243 Address *start_address = sb_start_address.get(); 244 if (!start_address) { 245 return LLDB_RECORD_RESULT(SBThreadPlan()); 246 } 247 248 AddressRange range(*start_address, size); 249 SymbolContext sc; 250 start_address->CalculateSymbolContext(&sc); 251 Status plan_status; 252 253 SBThreadPlan plan = SBThreadPlan( 254 thread_plan_sp->GetThread().QueueThreadPlanForStepOverRange( 255 false, range, sc, eAllThreads, plan_status)); 256 257 if (plan_status.Fail()) 258 error.SetErrorString(plan_status.AsCString()); 259 else 260 plan.GetSP()->SetPrivate(true); 261 262 return LLDB_RECORD_RESULT(plan); 263 } 264 return LLDB_RECORD_RESULT(SBThreadPlan()); 265 } 266 267 SBThreadPlan 268 SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address, 269 lldb::addr_t size) { 270 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 271 QueueThreadPlanForStepInRange, 272 (lldb::SBAddress &, lldb::addr_t), sb_start_address, size); 273 274 SBError error; 275 return LLDB_RECORD_RESULT( 276 QueueThreadPlanForStepInRange(sb_start_address, size, error)); 277 } 278 279 SBThreadPlan 280 SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address, 281 lldb::addr_t size, SBError &error) { 282 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 283 QueueThreadPlanForStepInRange, 284 (lldb::SBAddress &, lldb::addr_t, lldb::SBError &), 285 sb_start_address, size, error); 286 287 ThreadPlanSP thread_plan_sp(GetSP()); 288 if (thread_plan_sp) { 289 Address *start_address = sb_start_address.get(); 290 if (!start_address) { 291 return LLDB_RECORD_RESULT(SBThreadPlan()); 292 } 293 294 AddressRange range(*start_address, size); 295 SymbolContext sc; 296 start_address->CalculateSymbolContext(&sc); 297 298 Status plan_status; 299 SBThreadPlan plan = 300 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepInRange( 301 false, range, sc, nullptr, eAllThreads, plan_status)); 302 303 if (plan_status.Fail()) 304 error.SetErrorString(plan_status.AsCString()); 305 else 306 plan.GetSP()->SetPrivate(true); 307 308 return LLDB_RECORD_RESULT(plan); 309 } 310 return LLDB_RECORD_RESULT(SBThreadPlan()); 311 } 312 313 SBThreadPlan 314 SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to, 315 bool first_insn) { 316 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 317 QueueThreadPlanForStepOut, (uint32_t, bool), 318 frame_idx_to_step_to, first_insn); 319 320 SBError error; 321 return LLDB_RECORD_RESULT( 322 QueueThreadPlanForStepOut(frame_idx_to_step_to, first_insn, error)); 323 } 324 325 SBThreadPlan 326 SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to, 327 bool first_insn, SBError &error) { 328 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 329 QueueThreadPlanForStepOut, 330 (uint32_t, bool, lldb::SBError &), frame_idx_to_step_to, 331 first_insn, error); 332 333 ThreadPlanSP thread_plan_sp(GetSP()); 334 if (thread_plan_sp) { 335 SymbolContext sc; 336 sc = thread_plan_sp->GetThread().GetStackFrameAtIndex(0)->GetSymbolContext( 337 lldb::eSymbolContextEverything); 338 339 Status plan_status; 340 SBThreadPlan plan = 341 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepOut( 342 false, &sc, first_insn, false, eVoteYes, eVoteNoOpinion, 343 frame_idx_to_step_to, plan_status)); 344 345 if (plan_status.Fail()) 346 error.SetErrorString(plan_status.AsCString()); 347 else 348 plan.GetSP()->SetPrivate(true); 349 350 return LLDB_RECORD_RESULT(plan); 351 } 352 return LLDB_RECORD_RESULT(SBThreadPlan()); 353 } 354 355 SBThreadPlan 356 SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address) { 357 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 358 QueueThreadPlanForRunToAddress, (lldb::SBAddress), 359 sb_address); 360 361 SBError error; 362 return LLDB_RECORD_RESULT(QueueThreadPlanForRunToAddress(sb_address, error)); 363 } 364 365 SBThreadPlan SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address, 366 SBError &error) { 367 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 368 QueueThreadPlanForRunToAddress, 369 (lldb::SBAddress, lldb::SBError &), sb_address, error); 370 371 ThreadPlanSP thread_plan_sp(GetSP()); 372 if (thread_plan_sp) { 373 Address *address = sb_address.get(); 374 if (!address) 375 return LLDB_RECORD_RESULT(SBThreadPlan()); 376 377 Status plan_status; 378 SBThreadPlan plan = 379 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForRunToAddress( 380 false, *address, false, plan_status)); 381 382 if (plan_status.Fail()) 383 error.SetErrorString(plan_status.AsCString()); 384 else 385 plan.GetSP()->SetPrivate(true); 386 387 return LLDB_RECORD_RESULT(plan); 388 } 389 return LLDB_RECORD_RESULT(SBThreadPlan()); 390 } 391 392 SBThreadPlan 393 SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name) { 394 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 395 QueueThreadPlanForStepScripted, (const char *), 396 script_class_name); 397 398 SBError error; 399 return LLDB_RECORD_RESULT( 400 QueueThreadPlanForStepScripted(script_class_name, error)); 401 } 402 403 SBThreadPlan 404 SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name, 405 SBError &error) { 406 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 407 QueueThreadPlanForStepScripted, 408 (const char *, lldb::SBError &), script_class_name, error); 409 410 ThreadPlanSP thread_plan_sp(GetSP()); 411 if (thread_plan_sp) { 412 Status plan_status; 413 StructuredData::ObjectSP empty_args; 414 SBThreadPlan plan = 415 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepScripted( 416 false, script_class_name, empty_args, false, plan_status)); 417 418 if (plan_status.Fail()) 419 error.SetErrorString(plan_status.AsCString()); 420 else 421 plan.GetSP()->SetPrivate(true); 422 423 return LLDB_RECORD_RESULT(plan); 424 } 425 return LLDB_RECORD_RESULT(SBThreadPlan()); 426 } 427 428 SBThreadPlan 429 SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name, 430 lldb::SBStructuredData &args_data, 431 SBError &error) { 432 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 433 QueueThreadPlanForStepScripted, 434 (const char *, lldb::SBStructuredData &, lldb::SBError &), 435 script_class_name, args_data, error); 436 437 ThreadPlanSP thread_plan_sp(GetSP()); 438 if (thread_plan_sp) { 439 Status plan_status; 440 StructuredData::ObjectSP args_obj = args_data.m_impl_up->GetObjectSP(); 441 SBThreadPlan plan = 442 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepScripted( 443 false, script_class_name, args_obj, false, plan_status)); 444 445 if (plan_status.Fail()) 446 error.SetErrorString(plan_status.AsCString()); 447 else 448 plan.GetSP()->SetPrivate(true); 449 450 return LLDB_RECORD_RESULT(plan); 451 } else { 452 return LLDB_RECORD_RESULT(SBThreadPlan()); 453 } 454 } 455 456 namespace lldb_private { 457 namespace repro { 458 459 template <> 460 void RegisterMethods<SBThreadPlan>(Registry &R) { 461 LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, ()); 462 LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (const lldb::ThreadPlanSP &)); 463 LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (const lldb::SBThreadPlan &)); 464 LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (lldb::SBThread &, const char *)); 465 LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (lldb::SBThread &, const char *, 466 lldb::SBStructuredData &)); 467 LLDB_REGISTER_METHOD(const lldb::SBThreadPlan &, 468 SBThreadPlan, operator=,(const lldb::SBThreadPlan &)); 469 LLDB_REGISTER_METHOD_CONST(bool, SBThreadPlan, IsValid, ()); 470 LLDB_REGISTER_METHOD_CONST(bool, SBThreadPlan, operator bool, ()); 471 LLDB_REGISTER_METHOD(void, SBThreadPlan, Clear, ()); 472 LLDB_REGISTER_METHOD(lldb::StopReason, SBThreadPlan, GetStopReason, ()); 473 LLDB_REGISTER_METHOD(size_t, SBThreadPlan, GetStopReasonDataCount, ()); 474 LLDB_REGISTER_METHOD(uint64_t, SBThreadPlan, GetStopReasonDataAtIndex, 475 (uint32_t)); 476 LLDB_REGISTER_METHOD_CONST(lldb::SBThread, SBThreadPlan, GetThread, ()); 477 LLDB_REGISTER_METHOD_CONST(bool, SBThreadPlan, GetDescription, 478 (lldb::SBStream &)); 479 LLDB_REGISTER_METHOD(void, SBThreadPlan, SetPlanComplete, (bool)); 480 LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsPlanComplete, ()); 481 LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsPlanStale, ()); 482 LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsValid, ()); 483 LLDB_REGISTER_METHOD(void, SBThreadPlan, SetStopOthers, (bool)); 484 LLDB_REGISTER_METHOD(bool, SBThreadPlan, GetStopOthers, ()); 485 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 486 QueueThreadPlanForStepOverRange, 487 (lldb::SBAddress &, lldb::addr_t)); 488 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 489 QueueThreadPlanForStepOverRange, 490 (lldb::SBAddress &, lldb::addr_t, lldb::SBError &)); 491 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 492 QueueThreadPlanForStepInRange, 493 (lldb::SBAddress &, lldb::addr_t)); 494 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 495 QueueThreadPlanForStepInRange, 496 (lldb::SBAddress &, lldb::addr_t, lldb::SBError &)); 497 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 498 QueueThreadPlanForStepOut, (uint32_t, bool)); 499 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 500 QueueThreadPlanForStepOut, 501 (uint32_t, bool, lldb::SBError &)); 502 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 503 QueueThreadPlanForRunToAddress, (lldb::SBAddress)); 504 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 505 QueueThreadPlanForRunToAddress, 506 (lldb::SBAddress, lldb::SBError &)); 507 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 508 QueueThreadPlanForStepScripted, (const char *)); 509 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 510 QueueThreadPlanForStepScripted, 511 (const char *, lldb::SBError &)); 512 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 513 QueueThreadPlanForStepScripted, 514 (const char *, lldb::SBStructuredData &, 515 lldb::SBError &)); 516 } 517 518 } 519 } 520