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 // This section allows an SBThreadPlan to push another of the common types of 200 // plans... 201 // 202 // FIXME, you should only be able to queue thread plans from inside the methods 203 // of a Scripted Thread Plan. Need a way to enforce that. 204 205 SBThreadPlan 206 SBThreadPlan::QueueThreadPlanForStepOverRange(SBAddress &sb_start_address, 207 lldb::addr_t size) { 208 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 209 QueueThreadPlanForStepOverRange, 210 (lldb::SBAddress &, lldb::addr_t), sb_start_address, size); 211 212 SBError error; 213 return LLDB_RECORD_RESULT( 214 QueueThreadPlanForStepOverRange(sb_start_address, size, error)); 215 } 216 217 SBThreadPlan SBThreadPlan::QueueThreadPlanForStepOverRange( 218 SBAddress &sb_start_address, lldb::addr_t size, SBError &error) { 219 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 220 QueueThreadPlanForStepOverRange, 221 (lldb::SBAddress &, lldb::addr_t, lldb::SBError &), 222 sb_start_address, size, error); 223 224 ThreadPlanSP thread_plan_sp(GetSP()); 225 if (thread_plan_sp) { 226 Address *start_address = sb_start_address.get(); 227 if (!start_address) { 228 return LLDB_RECORD_RESULT(SBThreadPlan()); 229 } 230 231 AddressRange range(*start_address, size); 232 SymbolContext sc; 233 start_address->CalculateSymbolContext(&sc); 234 Status plan_status; 235 236 SBThreadPlan plan = SBThreadPlan( 237 thread_plan_sp->GetThread().QueueThreadPlanForStepOverRange( 238 false, range, sc, eAllThreads, plan_status)); 239 240 if (plan_status.Fail()) 241 error.SetErrorString(plan_status.AsCString()); 242 else 243 plan.GetSP()->SetPrivate(true); 244 245 return LLDB_RECORD_RESULT(plan); 246 } 247 return LLDB_RECORD_RESULT(SBThreadPlan()); 248 } 249 250 SBThreadPlan 251 SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address, 252 lldb::addr_t size) { 253 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 254 QueueThreadPlanForStepInRange, 255 (lldb::SBAddress &, lldb::addr_t), sb_start_address, size); 256 257 SBError error; 258 return LLDB_RECORD_RESULT( 259 QueueThreadPlanForStepInRange(sb_start_address, size, error)); 260 } 261 262 SBThreadPlan 263 SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address, 264 lldb::addr_t size, SBError &error) { 265 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 266 QueueThreadPlanForStepInRange, 267 (lldb::SBAddress &, lldb::addr_t, lldb::SBError &), 268 sb_start_address, size, error); 269 270 ThreadPlanSP thread_plan_sp(GetSP()); 271 if (thread_plan_sp) { 272 Address *start_address = sb_start_address.get(); 273 if (!start_address) { 274 return LLDB_RECORD_RESULT(SBThreadPlan()); 275 } 276 277 AddressRange range(*start_address, size); 278 SymbolContext sc; 279 start_address->CalculateSymbolContext(&sc); 280 281 Status plan_status; 282 SBThreadPlan plan = 283 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepInRange( 284 false, range, sc, nullptr, eAllThreads, plan_status)); 285 286 if (plan_status.Fail()) 287 error.SetErrorString(plan_status.AsCString()); 288 else 289 plan.GetSP()->SetPrivate(true); 290 291 return LLDB_RECORD_RESULT(plan); 292 } 293 return LLDB_RECORD_RESULT(SBThreadPlan()); 294 } 295 296 SBThreadPlan 297 SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to, 298 bool first_insn) { 299 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 300 QueueThreadPlanForStepOut, (uint32_t, bool), 301 frame_idx_to_step_to, first_insn); 302 303 SBError error; 304 return LLDB_RECORD_RESULT( 305 QueueThreadPlanForStepOut(frame_idx_to_step_to, first_insn, error)); 306 } 307 308 SBThreadPlan 309 SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to, 310 bool first_insn, SBError &error) { 311 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 312 QueueThreadPlanForStepOut, 313 (uint32_t, bool, lldb::SBError &), frame_idx_to_step_to, 314 first_insn, error); 315 316 ThreadPlanSP thread_plan_sp(GetSP()); 317 if (thread_plan_sp) { 318 SymbolContext sc; 319 sc = thread_plan_sp->GetThread().GetStackFrameAtIndex(0)->GetSymbolContext( 320 lldb::eSymbolContextEverything); 321 322 Status plan_status; 323 SBThreadPlan plan = 324 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepOut( 325 false, &sc, first_insn, false, eVoteYes, eVoteNoOpinion, 326 frame_idx_to_step_to, plan_status)); 327 328 if (plan_status.Fail()) 329 error.SetErrorString(plan_status.AsCString()); 330 else 331 plan.GetSP()->SetPrivate(true); 332 333 return LLDB_RECORD_RESULT(plan); 334 } 335 return LLDB_RECORD_RESULT(SBThreadPlan()); 336 } 337 338 SBThreadPlan 339 SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address) { 340 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 341 QueueThreadPlanForRunToAddress, (lldb::SBAddress), 342 sb_address); 343 344 SBError error; 345 return LLDB_RECORD_RESULT(QueueThreadPlanForRunToAddress(sb_address, error)); 346 } 347 348 SBThreadPlan SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address, 349 SBError &error) { 350 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 351 QueueThreadPlanForRunToAddress, 352 (lldb::SBAddress, lldb::SBError &), sb_address, error); 353 354 ThreadPlanSP thread_plan_sp(GetSP()); 355 if (thread_plan_sp) { 356 Address *address = sb_address.get(); 357 if (!address) 358 return LLDB_RECORD_RESULT(SBThreadPlan()); 359 360 Status plan_status; 361 SBThreadPlan plan = 362 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForRunToAddress( 363 false, *address, false, plan_status)); 364 365 if (plan_status.Fail()) 366 error.SetErrorString(plan_status.AsCString()); 367 else 368 plan.GetSP()->SetPrivate(true); 369 370 return LLDB_RECORD_RESULT(plan); 371 } 372 return LLDB_RECORD_RESULT(SBThreadPlan()); 373 } 374 375 SBThreadPlan 376 SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name) { 377 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 378 QueueThreadPlanForStepScripted, (const char *), 379 script_class_name); 380 381 SBError error; 382 return LLDB_RECORD_RESULT( 383 QueueThreadPlanForStepScripted(script_class_name, error)); 384 } 385 386 SBThreadPlan 387 SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name, 388 SBError &error) { 389 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 390 QueueThreadPlanForStepScripted, 391 (const char *, lldb::SBError &), script_class_name, error); 392 393 ThreadPlanSP thread_plan_sp(GetSP()); 394 if (thread_plan_sp) { 395 Status plan_status; 396 StructuredData::ObjectSP empty_args; 397 SBThreadPlan plan = 398 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepScripted( 399 false, script_class_name, empty_args, false, plan_status)); 400 401 if (plan_status.Fail()) 402 error.SetErrorString(plan_status.AsCString()); 403 else 404 plan.GetSP()->SetPrivate(true); 405 406 return LLDB_RECORD_RESULT(plan); 407 } 408 return LLDB_RECORD_RESULT(SBThreadPlan()); 409 } 410 411 SBThreadPlan 412 SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name, 413 lldb::SBStructuredData &args_data, 414 SBError &error) { 415 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 416 QueueThreadPlanForStepScripted, 417 (const char *, lldb::SBStructuredData &, lldb::SBError &), 418 script_class_name, args_data, error); 419 420 ThreadPlanSP thread_plan_sp(GetSP()); 421 if (thread_plan_sp) { 422 Status plan_status; 423 StructuredData::ObjectSP args_obj = args_data.m_impl_up->GetObjectSP(); 424 SBThreadPlan plan = 425 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepScripted( 426 false, script_class_name, args_obj, false, plan_status)); 427 428 if (plan_status.Fail()) 429 error.SetErrorString(plan_status.AsCString()); 430 else 431 plan.GetSP()->SetPrivate(true); 432 433 return LLDB_RECORD_RESULT(plan); 434 } else { 435 return LLDB_RECORD_RESULT(SBThreadPlan()); 436 } 437 } 438 439 namespace lldb_private { 440 namespace repro { 441 442 template <> 443 void RegisterMethods<SBThreadPlan>(Registry &R) { 444 LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, ()); 445 LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (const lldb::ThreadPlanSP &)); 446 LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (const lldb::SBThreadPlan &)); 447 LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (lldb::SBThread &, const char *)); 448 LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (lldb::SBThread &, const char *, 449 lldb::SBStructuredData &)); 450 LLDB_REGISTER_METHOD(const lldb::SBThreadPlan &, 451 SBThreadPlan, operator=,(const lldb::SBThreadPlan &)); 452 LLDB_REGISTER_METHOD_CONST(bool, SBThreadPlan, IsValid, ()); 453 LLDB_REGISTER_METHOD_CONST(bool, SBThreadPlan, operator bool, ()); 454 LLDB_REGISTER_METHOD(void, SBThreadPlan, Clear, ()); 455 LLDB_REGISTER_METHOD(lldb::StopReason, SBThreadPlan, GetStopReason, ()); 456 LLDB_REGISTER_METHOD(size_t, SBThreadPlan, GetStopReasonDataCount, ()); 457 LLDB_REGISTER_METHOD(uint64_t, SBThreadPlan, GetStopReasonDataAtIndex, 458 (uint32_t)); 459 LLDB_REGISTER_METHOD_CONST(lldb::SBThread, SBThreadPlan, GetThread, ()); 460 LLDB_REGISTER_METHOD_CONST(bool, SBThreadPlan, GetDescription, 461 (lldb::SBStream &)); 462 LLDB_REGISTER_METHOD(void, SBThreadPlan, SetPlanComplete, (bool)); 463 LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsPlanComplete, ()); 464 LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsPlanStale, ()); 465 LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsValid, ()); 466 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 467 QueueThreadPlanForStepOverRange, 468 (lldb::SBAddress &, lldb::addr_t)); 469 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 470 QueueThreadPlanForStepOverRange, 471 (lldb::SBAddress &, lldb::addr_t, lldb::SBError &)); 472 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 473 QueueThreadPlanForStepInRange, 474 (lldb::SBAddress &, lldb::addr_t)); 475 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 476 QueueThreadPlanForStepInRange, 477 (lldb::SBAddress &, lldb::addr_t, lldb::SBError &)); 478 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 479 QueueThreadPlanForStepOut, (uint32_t, bool)); 480 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 481 QueueThreadPlanForStepOut, 482 (uint32_t, bool, lldb::SBError &)); 483 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 484 QueueThreadPlanForRunToAddress, (lldb::SBAddress)); 485 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 486 QueueThreadPlanForRunToAddress, 487 (lldb::SBAddress, lldb::SBError &)); 488 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 489 QueueThreadPlanForStepScripted, (const char *)); 490 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 491 QueueThreadPlanForStepScripted, 492 (const char *, lldb::SBError &)); 493 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 494 QueueThreadPlanForStepScripted, 495 (const char *, lldb::SBStructuredData &, 496 lldb::SBError &)); 497 } 498 499 } 500 } 501