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 "lldb/Utility/ReproducerInstrumentation.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 = std::make_shared<ThreadPlanPython>(*thread, class_name, 73 StructuredDataImpl()); 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); 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 *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 SBThread(thread_plan_sp->GetThread().shared_from_this()); 142 } else 143 return SBThread(); 144 } 145 146 bool SBThreadPlan::GetDescription(lldb::SBStream &description) const { 147 LLDB_RECORD_METHOD_CONST(bool, SBThreadPlan, GetDescription, 148 (lldb::SBStream &), description); 149 150 ThreadPlanSP thread_plan_sp(GetSP()); 151 if (thread_plan_sp) { 152 thread_plan_sp->GetDescription(description.get(), eDescriptionLevelFull); 153 } else { 154 description.Printf("Empty SBThreadPlan"); 155 } 156 return true; 157 } 158 159 void SBThreadPlan::SetThreadPlan(const ThreadPlanSP &lldb_object_wp) { 160 m_opaque_wp = lldb_object_wp; 161 } 162 163 void SBThreadPlan::SetPlanComplete(bool success) { 164 LLDB_RECORD_METHOD(void, SBThreadPlan, SetPlanComplete, (bool), success); 165 166 ThreadPlanSP thread_plan_sp(GetSP()); 167 if (thread_plan_sp) 168 thread_plan_sp->SetPlanComplete(success); 169 } 170 171 bool SBThreadPlan::IsPlanComplete() { 172 LLDB_RECORD_METHOD_NO_ARGS(bool, SBThreadPlan, IsPlanComplete); 173 174 ThreadPlanSP thread_plan_sp(GetSP()); 175 if (thread_plan_sp) 176 return thread_plan_sp->IsPlanComplete(); 177 return true; 178 } 179 180 bool SBThreadPlan::IsPlanStale() { 181 LLDB_RECORD_METHOD_NO_ARGS(bool, SBThreadPlan, IsPlanStale); 182 183 ThreadPlanSP thread_plan_sp(GetSP()); 184 if (thread_plan_sp) 185 return thread_plan_sp->IsPlanStale(); 186 return true; 187 } 188 189 bool SBThreadPlan::IsValid() { 190 LLDB_RECORD_METHOD_NO_ARGS(bool, SBThreadPlan, IsValid); 191 192 ThreadPlanSP thread_plan_sp(GetSP()); 193 if (thread_plan_sp) 194 return thread_plan_sp->ValidatePlan(nullptr); 195 return false; 196 } 197 198 bool SBThreadPlan::GetStopOthers() { 199 LLDB_RECORD_METHOD_NO_ARGS(bool, SBThreadPlan, GetStopOthers); 200 201 ThreadPlanSP thread_plan_sp(GetSP()); 202 if (thread_plan_sp) 203 return thread_plan_sp->StopOthers(); 204 return false; 205 } 206 207 void SBThreadPlan::SetStopOthers(bool stop_others) { 208 LLDB_RECORD_METHOD(void, SBThreadPlan, SetStopOthers, (bool), stop_others); 209 210 ThreadPlanSP thread_plan_sp(GetSP()); 211 if (thread_plan_sp) 212 thread_plan_sp->SetStopOthers(stop_others); 213 } 214 215 // This section allows an SBThreadPlan to push another of the common types of 216 // plans... 217 // 218 // FIXME, you should only be able to queue thread plans from inside the methods 219 // of a Scripted Thread Plan. Need a way to enforce that. 220 221 SBThreadPlan 222 SBThreadPlan::QueueThreadPlanForStepOverRange(SBAddress &sb_start_address, 223 lldb::addr_t size) { 224 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 225 QueueThreadPlanForStepOverRange, 226 (lldb::SBAddress &, lldb::addr_t), sb_start_address, size); 227 228 SBError error; 229 return QueueThreadPlanForStepOverRange(sb_start_address, size, error); 230 } 231 232 SBThreadPlan SBThreadPlan::QueueThreadPlanForStepOverRange( 233 SBAddress &sb_start_address, lldb::addr_t size, SBError &error) { 234 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 235 QueueThreadPlanForStepOverRange, 236 (lldb::SBAddress &, lldb::addr_t, lldb::SBError &), 237 sb_start_address, size, error); 238 239 ThreadPlanSP thread_plan_sp(GetSP()); 240 if (thread_plan_sp) { 241 Address *start_address = sb_start_address.get(); 242 if (!start_address) { 243 return SBThreadPlan(); 244 } 245 246 AddressRange range(*start_address, size); 247 SymbolContext sc; 248 start_address->CalculateSymbolContext(&sc); 249 Status plan_status; 250 251 SBThreadPlan plan = SBThreadPlan( 252 thread_plan_sp->GetThread().QueueThreadPlanForStepOverRange( 253 false, range, sc, eAllThreads, plan_status)); 254 255 if (plan_status.Fail()) 256 error.SetErrorString(plan_status.AsCString()); 257 else 258 plan.GetSP()->SetPrivate(true); 259 260 return plan; 261 } 262 return SBThreadPlan(); 263 } 264 265 SBThreadPlan 266 SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address, 267 lldb::addr_t size) { 268 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 269 QueueThreadPlanForStepInRange, 270 (lldb::SBAddress &, lldb::addr_t), sb_start_address, size); 271 272 SBError error; 273 return QueueThreadPlanForStepInRange(sb_start_address, size, error); 274 } 275 276 SBThreadPlan 277 SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address, 278 lldb::addr_t size, SBError &error) { 279 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 280 QueueThreadPlanForStepInRange, 281 (lldb::SBAddress &, lldb::addr_t, lldb::SBError &), 282 sb_start_address, size, error); 283 284 ThreadPlanSP thread_plan_sp(GetSP()); 285 if (thread_plan_sp) { 286 Address *start_address = sb_start_address.get(); 287 if (!start_address) { 288 return SBThreadPlan(); 289 } 290 291 AddressRange range(*start_address, size); 292 SymbolContext sc; 293 start_address->CalculateSymbolContext(&sc); 294 295 Status plan_status; 296 SBThreadPlan plan = 297 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepInRange( 298 false, range, sc, nullptr, eAllThreads, plan_status)); 299 300 if (plan_status.Fail()) 301 error.SetErrorString(plan_status.AsCString()); 302 else 303 plan.GetSP()->SetPrivate(true); 304 305 return plan; 306 } 307 return SBThreadPlan(); 308 } 309 310 SBThreadPlan 311 SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to, 312 bool first_insn) { 313 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 314 QueueThreadPlanForStepOut, (uint32_t, bool), 315 frame_idx_to_step_to, first_insn); 316 317 SBError error; 318 return QueueThreadPlanForStepOut(frame_idx_to_step_to, first_insn, error); 319 } 320 321 SBThreadPlan 322 SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to, 323 bool first_insn, SBError &error) { 324 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 325 QueueThreadPlanForStepOut, 326 (uint32_t, bool, lldb::SBError &), frame_idx_to_step_to, 327 first_insn, error); 328 329 ThreadPlanSP thread_plan_sp(GetSP()); 330 if (thread_plan_sp) { 331 SymbolContext sc; 332 sc = thread_plan_sp->GetThread().GetStackFrameAtIndex(0)->GetSymbolContext( 333 lldb::eSymbolContextEverything); 334 335 Status plan_status; 336 SBThreadPlan plan = 337 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepOut( 338 false, &sc, first_insn, false, eVoteYes, eVoteNoOpinion, 339 frame_idx_to_step_to, plan_status)); 340 341 if (plan_status.Fail()) 342 error.SetErrorString(plan_status.AsCString()); 343 else 344 plan.GetSP()->SetPrivate(true); 345 346 return plan; 347 } 348 return SBThreadPlan(); 349 } 350 351 SBThreadPlan 352 SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address) { 353 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 354 QueueThreadPlanForRunToAddress, (lldb::SBAddress), 355 sb_address); 356 357 SBError error; 358 return QueueThreadPlanForRunToAddress(sb_address, error); 359 } 360 361 SBThreadPlan SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address, 362 SBError &error) { 363 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 364 QueueThreadPlanForRunToAddress, 365 (lldb::SBAddress, lldb::SBError &), sb_address, error); 366 367 ThreadPlanSP thread_plan_sp(GetSP()); 368 if (thread_plan_sp) { 369 Address *address = sb_address.get(); 370 if (!address) 371 return SBThreadPlan(); 372 373 Status plan_status; 374 SBThreadPlan plan = 375 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForRunToAddress( 376 false, *address, false, plan_status)); 377 378 if (plan_status.Fail()) 379 error.SetErrorString(plan_status.AsCString()); 380 else 381 plan.GetSP()->SetPrivate(true); 382 383 return plan; 384 } 385 return SBThreadPlan(); 386 } 387 388 SBThreadPlan 389 SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name) { 390 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 391 QueueThreadPlanForStepScripted, (const char *), 392 script_class_name); 393 394 SBError error; 395 return QueueThreadPlanForStepScripted(script_class_name, error); 396 } 397 398 SBThreadPlan 399 SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name, 400 SBError &error) { 401 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 402 QueueThreadPlanForStepScripted, 403 (const char *, lldb::SBError &), script_class_name, error); 404 405 ThreadPlanSP thread_plan_sp(GetSP()); 406 if (thread_plan_sp) { 407 Status plan_status; 408 StructuredData::ObjectSP empty_args; 409 SBThreadPlan plan = 410 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepScripted( 411 false, script_class_name, empty_args, false, plan_status)); 412 413 if (plan_status.Fail()) 414 error.SetErrorString(plan_status.AsCString()); 415 else 416 plan.GetSP()->SetPrivate(true); 417 418 return plan; 419 } 420 return SBThreadPlan(); 421 } 422 423 SBThreadPlan 424 SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name, 425 lldb::SBStructuredData &args_data, 426 SBError &error) { 427 LLDB_RECORD_METHOD(lldb::SBThreadPlan, SBThreadPlan, 428 QueueThreadPlanForStepScripted, 429 (const char *, lldb::SBStructuredData &, lldb::SBError &), 430 script_class_name, args_data, error); 431 432 ThreadPlanSP thread_plan_sp(GetSP()); 433 if (thread_plan_sp) { 434 Status plan_status; 435 StructuredData::ObjectSP args_obj = args_data.m_impl_up->GetObjectSP(); 436 SBThreadPlan plan = 437 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepScripted( 438 false, script_class_name, args_obj, false, plan_status)); 439 440 if (plan_status.Fail()) 441 error.SetErrorString(plan_status.AsCString()); 442 else 443 plan.GetSP()->SetPrivate(true); 444 445 return plan; 446 } else { 447 return SBThreadPlan(); 448 } 449 } 450