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/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() {} 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 241 return LLDB_RECORD_RESULT(plan); 242 } else { 243 return LLDB_RECORD_RESULT(SBThreadPlan()); 244 } 245 } 246 247 SBThreadPlan 248 SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address, 249 lldb::addr_t size) { 250 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 251 QueueThreadPlanForStepInRange, 252 (lldb::SBAddress &, lldb::addr_t), sb_start_address, size); 253 254 SBError error; 255 return LLDB_RECORD_RESULT( 256 QueueThreadPlanForStepInRange(sb_start_address, size, error)); 257 } 258 259 SBThreadPlan 260 SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address, 261 lldb::addr_t size, SBError &error) { 262 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 263 QueueThreadPlanForStepInRange, 264 (lldb::SBAddress &, lldb::addr_t, lldb::SBError &), 265 sb_start_address, size, error); 266 267 if (m_opaque_sp) { 268 Address *start_address = sb_start_address.get(); 269 if (!start_address) { 270 return LLDB_RECORD_RESULT(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(m_opaque_sp->GetThread().QueueThreadPlanForStepInRange( 280 false, range, sc, nullptr, eAllThreads, plan_status)); 281 282 if (plan_status.Fail()) 283 error.SetErrorString(plan_status.AsCString()); 284 285 return LLDB_RECORD_RESULT(plan); 286 } else { 287 return LLDB_RECORD_RESULT(SBThreadPlan()); 288 } 289 } 290 291 SBThreadPlan 292 SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to, 293 bool first_insn) { 294 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 295 QueueThreadPlanForStepOut, (uint32_t, bool), 296 frame_idx_to_step_to, first_insn); 297 298 SBError error; 299 return LLDB_RECORD_RESULT( 300 QueueThreadPlanForStepOut(frame_idx_to_step_to, first_insn, error)); 301 } 302 303 SBThreadPlan 304 SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to, 305 bool first_insn, SBError &error) { 306 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 307 QueueThreadPlanForStepOut, 308 (uint32_t, bool, lldb::SBError &), frame_idx_to_step_to, 309 first_insn, error); 310 311 if (m_opaque_sp) { 312 SymbolContext sc; 313 sc = m_opaque_sp->GetThread().GetStackFrameAtIndex(0)->GetSymbolContext( 314 lldb::eSymbolContextEverything); 315 316 Status plan_status; 317 SBThreadPlan plan = 318 SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepOut( 319 false, &sc, first_insn, false, eVoteYes, eVoteNoOpinion, 320 frame_idx_to_step_to, plan_status)); 321 322 if (plan_status.Fail()) 323 error.SetErrorString(plan_status.AsCString()); 324 325 return LLDB_RECORD_RESULT(plan); 326 } else { 327 return LLDB_RECORD_RESULT(SBThreadPlan()); 328 } 329 } 330 331 SBThreadPlan 332 SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address) { 333 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 334 QueueThreadPlanForRunToAddress, (lldb::SBAddress), 335 sb_address); 336 337 SBError error; 338 return LLDB_RECORD_RESULT(QueueThreadPlanForRunToAddress(sb_address, error)); 339 } 340 341 SBThreadPlan SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address, 342 SBError &error) { 343 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 344 QueueThreadPlanForRunToAddress, 345 (lldb::SBAddress, lldb::SBError &), sb_address, error); 346 347 if (m_opaque_sp) { 348 Address *address = sb_address.get(); 349 if (!address) 350 return LLDB_RECORD_RESULT(SBThreadPlan()); 351 352 Status plan_status; 353 SBThreadPlan plan = 354 SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForRunToAddress( 355 false, *address, false, plan_status)); 356 357 if (plan_status.Fail()) 358 error.SetErrorString(plan_status.AsCString()); 359 360 return LLDB_RECORD_RESULT(plan); 361 } else { 362 return LLDB_RECORD_RESULT(SBThreadPlan()); 363 } 364 } 365 366 SBThreadPlan 367 SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name) { 368 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 369 QueueThreadPlanForStepScripted, (const char *), 370 script_class_name); 371 372 SBError error; 373 return LLDB_RECORD_RESULT( 374 QueueThreadPlanForStepScripted(script_class_name, error)); 375 } 376 377 SBThreadPlan 378 SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name, 379 SBError &error) { 380 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 381 QueueThreadPlanForStepScripted, 382 (const char *, lldb::SBError &), script_class_name, error); 383 384 if (m_opaque_sp) { 385 Status plan_status; 386 StructuredData::ObjectSP empty_args; 387 SBThreadPlan plan = 388 SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepScripted( 389 false, script_class_name, empty_args, false, plan_status)); 390 391 if (plan_status.Fail()) 392 error.SetErrorString(plan_status.AsCString()); 393 394 return LLDB_RECORD_RESULT(plan); 395 } else { 396 return LLDB_RECORD_RESULT(SBThreadPlan()); 397 } 398 } 399 400 SBThreadPlan 401 SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name, 402 lldb::SBStructuredData &args_data, 403 SBError &error) { 404 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 405 QueueThreadPlanForStepScripted, 406 (const char *, lldb::SBStructuredData &, lldb::SBError &), 407 script_class_name, args_data, error); 408 409 if (m_opaque_sp) { 410 Status plan_status; 411 StructuredData::ObjectSP args_obj = args_data.m_impl_up->GetObjectSP(); 412 SBThreadPlan plan = 413 SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepScripted( 414 false, script_class_name, args_obj, false, plan_status)); 415 416 if (plan_status.Fail()) 417 error.SetErrorString(plan_status.AsCString()); 418 419 return LLDB_RECORD_RESULT(plan); 420 } else { 421 return LLDB_RECORD_RESULT(SBThreadPlan()); 422 } 423 } 424 425 namespace lldb_private { 426 namespace repro { 427 428 template <> 429 void RegisterMethods<SBThreadPlan>(Registry &R) { 430 LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, ()); 431 LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (const lldb::ThreadPlanSP &)); 432 LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (const lldb::SBThreadPlan &)); 433 LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (lldb::SBThread &, const char *)); 434 LLDB_REGISTER_CONSTRUCTOR(SBThreadPlan, (lldb::SBThread &, const char *, 435 lldb::SBStructuredData &)); 436 LLDB_REGISTER_METHOD(const lldb::SBThreadPlan &, 437 SBThreadPlan, operator=,(const lldb::SBThreadPlan &)); 438 LLDB_REGISTER_METHOD_CONST(bool, SBThreadPlan, IsValid, ()); 439 LLDB_REGISTER_METHOD_CONST(bool, SBThreadPlan, operator bool, ()); 440 LLDB_REGISTER_METHOD(void, SBThreadPlan, Clear, ()); 441 LLDB_REGISTER_METHOD(lldb::StopReason, SBThreadPlan, GetStopReason, ()); 442 LLDB_REGISTER_METHOD(size_t, SBThreadPlan, GetStopReasonDataCount, ()); 443 LLDB_REGISTER_METHOD(uint64_t, SBThreadPlan, GetStopReasonDataAtIndex, 444 (uint32_t)); 445 LLDB_REGISTER_METHOD_CONST(lldb::SBThread, SBThreadPlan, GetThread, ()); 446 LLDB_REGISTER_METHOD_CONST(bool, SBThreadPlan, GetDescription, 447 (lldb::SBStream &)); 448 LLDB_REGISTER_METHOD(void, SBThreadPlan, SetPlanComplete, (bool)); 449 LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsPlanComplete, ()); 450 LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsPlanStale, ()); 451 LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsValid, ()); 452 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 453 QueueThreadPlanForStepOverRange, 454 (lldb::SBAddress &, lldb::addr_t)); 455 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 456 QueueThreadPlanForStepOverRange, 457 (lldb::SBAddress &, lldb::addr_t, lldb::SBError &)); 458 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 459 QueueThreadPlanForStepInRange, 460 (lldb::SBAddress &, lldb::addr_t)); 461 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 462 QueueThreadPlanForStepInRange, 463 (lldb::SBAddress &, lldb::addr_t, lldb::SBError &)); 464 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 465 QueueThreadPlanForStepOut, (uint32_t, bool)); 466 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 467 QueueThreadPlanForStepOut, 468 (uint32_t, bool, lldb::SBError &)); 469 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 470 QueueThreadPlanForRunToAddress, (lldb::SBAddress)); 471 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 472 QueueThreadPlanForRunToAddress, 473 (lldb::SBAddress, lldb::SBError &)); 474 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 475 QueueThreadPlanForStepScripted, (const char *)); 476 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 477 QueueThreadPlanForStepScripted, 478 (const char *, lldb::SBError &)); 479 LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan, 480 QueueThreadPlanForStepScripted, 481 (const char *, lldb::SBStructuredData &, 482 lldb::SBError &)); 483 } 484 485 } 486 } 487