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