1 //===-- CommandObjectThread.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 "CommandObjectThread.h" 10 11 #include "lldb/Core/SourceManager.h" 12 #include "lldb/Core/ValueObject.h" 13 #include "lldb/Host/Host.h" 14 #include "lldb/Host/OptionParser.h" 15 #include "lldb/Host/StringConvert.h" 16 #include "lldb/Interpreter/CommandInterpreter.h" 17 #include "lldb/Interpreter/CommandReturnObject.h" 18 #include "lldb/Interpreter/OptionArgParser.h" 19 #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" 20 #include "lldb/Interpreter/Options.h" 21 #include "lldb/Symbol/CompileUnit.h" 22 #include "lldb/Symbol/Function.h" 23 #include "lldb/Symbol/LineEntry.h" 24 #include "lldb/Symbol/LineTable.h" 25 #include "lldb/Target/Process.h" 26 #include "lldb/Target/RegisterContext.h" 27 #include "lldb/Target/SystemRuntime.h" 28 #include "lldb/Target/Target.h" 29 #include "lldb/Target/Thread.h" 30 #include "lldb/Target/ThreadPlan.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/lldb-private.h" 37 38 using namespace lldb; 39 using namespace lldb_private; 40 41 // CommandObjectIterateOverThreads 42 43 class CommandObjectIterateOverThreads : public CommandObjectParsed { 44 45 class UniqueStack { 46 47 public: 48 UniqueStack(std::stack<lldb::addr_t> stack_frames, uint32_t thread_index_id) 49 : m_stack_frames(stack_frames) { 50 m_thread_index_ids.push_back(thread_index_id); 51 } 52 53 void AddThread(uint32_t thread_index_id) const { 54 m_thread_index_ids.push_back(thread_index_id); 55 } 56 57 const std::vector<uint32_t> &GetUniqueThreadIndexIDs() const { 58 return m_thread_index_ids; 59 } 60 61 lldb::tid_t GetRepresentativeThread() const { 62 return m_thread_index_ids.front(); 63 } 64 65 friend bool inline operator<(const UniqueStack &lhs, 66 const UniqueStack &rhs) { 67 return lhs.m_stack_frames < rhs.m_stack_frames; 68 } 69 70 protected: 71 // Mark the thread index as mutable, as we don't care about it from a const 72 // perspective, we only care about m_stack_frames so we keep our std::set 73 // sorted. 74 mutable std::vector<uint32_t> m_thread_index_ids; 75 std::stack<lldb::addr_t> m_stack_frames; 76 }; 77 78 public: 79 CommandObjectIterateOverThreads(CommandInterpreter &interpreter, 80 const char *name, const char *help, 81 const char *syntax, uint32_t flags) 82 : CommandObjectParsed(interpreter, name, help, syntax, flags) {} 83 84 ~CommandObjectIterateOverThreads() override = default; 85 86 bool DoExecute(Args &command, CommandReturnObject &result) override { 87 result.SetStatus(m_success_return); 88 89 bool all_threads = false; 90 if (command.GetArgumentCount() == 0) { 91 Thread *thread = m_exe_ctx.GetThreadPtr(); 92 if (!thread || !HandleOneThread(thread->GetID(), result)) 93 return false; 94 return result.Succeeded(); 95 } else if (command.GetArgumentCount() == 1) { 96 all_threads = ::strcmp(command.GetArgumentAtIndex(0), "all") == 0; 97 m_unique_stacks = ::strcmp(command.GetArgumentAtIndex(0), "unique") == 0; 98 } 99 100 // Use tids instead of ThreadSPs to prevent deadlocking problems which 101 // result from JIT-ing code while iterating over the (locked) ThreadSP 102 // list. 103 std::vector<lldb::tid_t> tids; 104 105 if (all_threads || m_unique_stacks) { 106 Process *process = m_exe_ctx.GetProcessPtr(); 107 108 for (ThreadSP thread_sp : process->Threads()) 109 tids.push_back(thread_sp->GetID()); 110 } else { 111 const size_t num_args = command.GetArgumentCount(); 112 Process *process = m_exe_ctx.GetProcessPtr(); 113 114 std::lock_guard<std::recursive_mutex> guard( 115 process->GetThreadList().GetMutex()); 116 117 for (size_t i = 0; i < num_args; i++) { 118 bool success; 119 120 uint32_t thread_idx = StringConvert::ToUInt32( 121 command.GetArgumentAtIndex(i), 0, 0, &success); 122 if (!success) { 123 result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n", 124 command.GetArgumentAtIndex(i)); 125 result.SetStatus(eReturnStatusFailed); 126 return false; 127 } 128 129 ThreadSP thread = 130 process->GetThreadList().FindThreadByIndexID(thread_idx); 131 132 if (!thread) { 133 result.AppendErrorWithFormat("no thread with index: \"%s\"\n", 134 command.GetArgumentAtIndex(i)); 135 result.SetStatus(eReturnStatusFailed); 136 return false; 137 } 138 139 tids.push_back(thread->GetID()); 140 } 141 } 142 143 if (m_unique_stacks) { 144 // Iterate over threads, finding unique stack buckets. 145 std::set<UniqueStack> unique_stacks; 146 for (const lldb::tid_t &tid : tids) { 147 if (!BucketThread(tid, unique_stacks, result)) { 148 return false; 149 } 150 } 151 152 // Write the thread id's and unique call stacks to the output stream 153 Stream &strm = result.GetOutputStream(); 154 Process *process = m_exe_ctx.GetProcessPtr(); 155 for (const UniqueStack &stack : unique_stacks) { 156 // List the common thread ID's 157 const std::vector<uint32_t> &thread_index_ids = 158 stack.GetUniqueThreadIndexIDs(); 159 strm.Format("{0} thread(s) ", thread_index_ids.size()); 160 for (const uint32_t &thread_index_id : thread_index_ids) { 161 strm.Format("#{0} ", thread_index_id); 162 } 163 strm.EOL(); 164 165 // List the shared call stack for this set of threads 166 uint32_t representative_thread_id = stack.GetRepresentativeThread(); 167 ThreadSP thread = process->GetThreadList().FindThreadByIndexID( 168 representative_thread_id); 169 if (!HandleOneThread(thread->GetID(), result)) { 170 return false; 171 } 172 } 173 } else { 174 uint32_t idx = 0; 175 for (const lldb::tid_t &tid : tids) { 176 if (idx != 0 && m_add_return) 177 result.AppendMessage(""); 178 179 if (!HandleOneThread(tid, result)) 180 return false; 181 182 ++idx; 183 } 184 } 185 return result.Succeeded(); 186 } 187 188 protected: 189 // Override this to do whatever you need to do for one thread. 190 // 191 // If you return false, the iteration will stop, otherwise it will proceed. 192 // The result is set to m_success_return (defaults to 193 // eReturnStatusSuccessFinishResult) before the iteration, so you only need 194 // to set the return status in HandleOneThread if you want to indicate an 195 // error. If m_add_return is true, a blank line will be inserted between each 196 // of the listings (except the last one.) 197 198 virtual bool HandleOneThread(lldb::tid_t, CommandReturnObject &result) = 0; 199 200 bool BucketThread(lldb::tid_t tid, std::set<UniqueStack> &unique_stacks, 201 CommandReturnObject &result) { 202 // Grab the corresponding thread for the given thread id. 203 Process *process = m_exe_ctx.GetProcessPtr(); 204 Thread *thread = process->GetThreadList().FindThreadByID(tid).get(); 205 if (thread == nullptr) { 206 result.AppendErrorWithFormatv("Failed to process thread #{0}.\n", tid); 207 result.SetStatus(eReturnStatusFailed); 208 return false; 209 } 210 211 // Collect the each frame's address for this call-stack 212 std::stack<lldb::addr_t> stack_frames; 213 const uint32_t frame_count = thread->GetStackFrameCount(); 214 for (uint32_t frame_index = 0; frame_index < frame_count; frame_index++) { 215 const lldb::StackFrameSP frame_sp = 216 thread->GetStackFrameAtIndex(frame_index); 217 const lldb::addr_t pc = frame_sp->GetStackID().GetPC(); 218 stack_frames.push(pc); 219 } 220 221 uint32_t thread_index_id = thread->GetIndexID(); 222 UniqueStack new_unique_stack(stack_frames, thread_index_id); 223 224 // Try to match the threads stack to and existing entry. 225 std::set<UniqueStack>::iterator matching_stack = 226 unique_stacks.find(new_unique_stack); 227 if (matching_stack != unique_stacks.end()) { 228 matching_stack->AddThread(thread_index_id); 229 } else { 230 unique_stacks.insert(new_unique_stack); 231 } 232 return true; 233 } 234 235 ReturnStatus m_success_return = eReturnStatusSuccessFinishResult; 236 bool m_unique_stacks = false; 237 bool m_add_return = true; 238 }; 239 240 // CommandObjectThreadBacktrace 241 #define LLDB_OPTIONS_thread_backtrace 242 #include "CommandOptions.inc" 243 244 class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads { 245 public: 246 class CommandOptions : public Options { 247 public: 248 CommandOptions() : Options() { 249 // Keep default values of all options in one place: OptionParsingStarting 250 // () 251 OptionParsingStarting(nullptr); 252 } 253 254 ~CommandOptions() override = default; 255 256 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 257 ExecutionContext *execution_context) override { 258 Status error; 259 const int short_option = m_getopt_table[option_idx].val; 260 261 switch (short_option) { 262 case 'c': { 263 int32_t input_count = 0; 264 if (option_arg.getAsInteger(0, m_count)) { 265 m_count = UINT32_MAX; 266 error.SetErrorStringWithFormat( 267 "invalid integer value for option '%c'", short_option); 268 } else if (input_count < 0) 269 m_count = UINT32_MAX; 270 } break; 271 case 's': 272 if (option_arg.getAsInteger(0, m_start)) 273 error.SetErrorStringWithFormat( 274 "invalid integer value for option '%c'", short_option); 275 break; 276 case 'e': { 277 bool success; 278 m_extended_backtrace = 279 OptionArgParser::ToBoolean(option_arg, false, &success); 280 if (!success) 281 error.SetErrorStringWithFormat( 282 "invalid boolean value for option '%c'", short_option); 283 } break; 284 default: 285 llvm_unreachable("Unimplemented option"); 286 } 287 return error; 288 } 289 290 void OptionParsingStarting(ExecutionContext *execution_context) override { 291 m_count = UINT32_MAX; 292 m_start = 0; 293 m_extended_backtrace = false; 294 } 295 296 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 297 return llvm::makeArrayRef(g_thread_backtrace_options); 298 } 299 300 // Instance variables to hold the values for command options. 301 uint32_t m_count; 302 uint32_t m_start; 303 bool m_extended_backtrace; 304 }; 305 306 CommandObjectThreadBacktrace(CommandInterpreter &interpreter) 307 : CommandObjectIterateOverThreads( 308 interpreter, "thread backtrace", 309 "Show thread call stacks. Defaults to the current thread, thread " 310 "indexes can be specified as arguments.\n" 311 "Use the thread-index \"all\" to see all threads.\n" 312 "Use the thread-index \"unique\" to see threads grouped by unique " 313 "call stacks.\n" 314 "Use 'settings set frame-format' to customize the printing of " 315 "frames in the backtrace and 'settings set thread-format' to " 316 "customize the thread header.", 317 nullptr, 318 eCommandRequiresProcess | eCommandRequiresThread | 319 eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | 320 eCommandProcessMustBePaused), 321 m_options() {} 322 323 ~CommandObjectThreadBacktrace() override = default; 324 325 Options *GetOptions() override { return &m_options; } 326 327 protected: 328 void DoExtendedBacktrace(Thread *thread, CommandReturnObject &result) { 329 SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime(); 330 if (runtime) { 331 Stream &strm = result.GetOutputStream(); 332 const std::vector<ConstString> &types = 333 runtime->GetExtendedBacktraceTypes(); 334 for (auto type : types) { 335 ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread( 336 thread->shared_from_this(), type); 337 if (ext_thread_sp && ext_thread_sp->IsValid()) { 338 const uint32_t num_frames_with_source = 0; 339 const bool stop_format = false; 340 if (ext_thread_sp->GetStatus(strm, m_options.m_start, 341 m_options.m_count, 342 num_frames_with_source, 343 stop_format)) { 344 DoExtendedBacktrace(ext_thread_sp.get(), result); 345 } 346 } 347 } 348 } 349 } 350 351 bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { 352 ThreadSP thread_sp = 353 m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); 354 if (!thread_sp) { 355 result.AppendErrorWithFormat( 356 "thread disappeared while computing backtraces: 0x%" PRIx64 "\n", 357 tid); 358 result.SetStatus(eReturnStatusFailed); 359 return false; 360 } 361 362 Thread *thread = thread_sp.get(); 363 364 Stream &strm = result.GetOutputStream(); 365 366 // Only dump stack info if we processing unique stacks. 367 const bool only_stacks = m_unique_stacks; 368 369 // Don't show source context when doing backtraces. 370 const uint32_t num_frames_with_source = 0; 371 const bool stop_format = true; 372 if (!thread->GetStatus(strm, m_options.m_start, m_options.m_count, 373 num_frames_with_source, stop_format, only_stacks)) { 374 result.AppendErrorWithFormat( 375 "error displaying backtrace for thread: \"0x%4.4x\"\n", 376 thread->GetIndexID()); 377 result.SetStatus(eReturnStatusFailed); 378 return false; 379 } 380 if (m_options.m_extended_backtrace) { 381 DoExtendedBacktrace(thread, result); 382 } 383 384 return true; 385 } 386 387 CommandOptions m_options; 388 }; 389 390 enum StepScope { eStepScopeSource, eStepScopeInstruction }; 391 392 static constexpr OptionEnumValueElement g_tri_running_mode[] = { 393 {eOnlyThisThread, "this-thread", "Run only this thread"}, 394 {eAllThreads, "all-threads", "Run all threads"}, 395 {eOnlyDuringStepping, "while-stepping", 396 "Run only this thread while stepping"} }; 397 398 static constexpr OptionEnumValues TriRunningModes() { 399 return OptionEnumValues(g_tri_running_mode); 400 } 401 402 #define LLDB_OPTIONS_thread_step_scope 403 #include "CommandOptions.inc" 404 405 class ThreadStepScopeOptionGroup : public OptionGroup { 406 public: 407 ThreadStepScopeOptionGroup() : OptionGroup() { 408 // Keep default values of all options in one place: OptionParsingStarting 409 // () 410 OptionParsingStarting(nullptr); 411 } 412 413 ~ThreadStepScopeOptionGroup() override = default; 414 415 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 416 return llvm::makeArrayRef(g_thread_step_scope_options); 417 } 418 419 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 420 ExecutionContext *execution_context) override { 421 Status error; 422 const int short_option 423 = g_thread_step_scope_options[option_idx].short_option; 424 425 switch (short_option) { 426 case 'a': { 427 bool success; 428 bool avoid_no_debug = 429 OptionArgParser::ToBoolean(option_arg, true, &success); 430 if (!success) 431 error.SetErrorStringWithFormat( 432 "invalid boolean value for option '%c'", short_option); 433 else { 434 m_step_in_avoid_no_debug = 435 avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; 436 } 437 } break; 438 439 case 'A': { 440 bool success; 441 bool avoid_no_debug = 442 OptionArgParser::ToBoolean(option_arg, true, &success); 443 if (!success) 444 error.SetErrorStringWithFormat( 445 "invalid boolean value for option '%c'", short_option); 446 else { 447 m_step_out_avoid_no_debug = 448 avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; 449 } 450 } break; 451 452 case 'c': 453 if (option_arg.getAsInteger(0, m_step_count)) 454 error.SetErrorStringWithFormat("invalid step count '%s'", 455 option_arg.str().c_str()); 456 break; 457 458 case 'm': { 459 auto enum_values = GetDefinitions()[option_idx].enum_values; 460 m_run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum( 461 option_arg, enum_values, eOnlyDuringStepping, error); 462 } break; 463 464 case 'e': 465 if (option_arg == "block") { 466 m_end_line_is_block_end = true; 467 break; 468 } 469 if (option_arg.getAsInteger(0, m_end_line)) 470 error.SetErrorStringWithFormat("invalid end line number '%s'", 471 option_arg.str().c_str()); 472 break; 473 474 case 'r': 475 m_avoid_regexp.clear(); 476 m_avoid_regexp.assign(option_arg); 477 break; 478 479 case 't': 480 m_step_in_target.clear(); 481 m_step_in_target.assign(option_arg); 482 break; 483 484 default: 485 llvm_unreachable("Unimplemented option"); 486 } 487 return error; 488 } 489 490 void OptionParsingStarting(ExecutionContext *execution_context) override { 491 m_step_in_avoid_no_debug = eLazyBoolCalculate; 492 m_step_out_avoid_no_debug = eLazyBoolCalculate; 493 m_run_mode = eOnlyDuringStepping; 494 495 // Check if we are in Non-Stop mode 496 TargetSP target_sp = 497 execution_context ? execution_context->GetTargetSP() : TargetSP(); 498 if (target_sp && target_sp->GetNonStopModeEnabled()) 499 m_run_mode = eOnlyThisThread; 500 501 m_avoid_regexp.clear(); 502 m_step_in_target.clear(); 503 m_step_count = 1; 504 m_end_line = LLDB_INVALID_LINE_NUMBER; 505 m_end_line_is_block_end = false; 506 } 507 508 // Instance variables to hold the values for command options. 509 LazyBool m_step_in_avoid_no_debug; 510 LazyBool m_step_out_avoid_no_debug; 511 RunMode m_run_mode; 512 std::string m_avoid_regexp; 513 std::string m_step_in_target; 514 uint32_t m_step_count; 515 uint32_t m_end_line; 516 bool m_end_line_is_block_end; 517 }; 518 519 class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed { 520 public: 521 522 CommandObjectThreadStepWithTypeAndScope(CommandInterpreter &interpreter, 523 const char *name, const char *help, 524 const char *syntax, 525 StepType step_type, 526 StepScope step_scope) 527 : CommandObjectParsed(interpreter, name, help, syntax, 528 eCommandRequiresProcess | eCommandRequiresThread | 529 eCommandTryTargetAPILock | 530 eCommandProcessMustBeLaunched | 531 eCommandProcessMustBePaused), 532 m_step_type(step_type), m_step_scope(step_scope), m_options(), 533 m_class_options("scripted step", 'C') { 534 CommandArgumentEntry arg; 535 CommandArgumentData thread_id_arg; 536 537 // Define the first (and only) variant of this arg. 538 thread_id_arg.arg_type = eArgTypeThreadID; 539 thread_id_arg.arg_repetition = eArgRepeatOptional; 540 541 // There is only one variant this argument could be; put it into the 542 // argument entry. 543 arg.push_back(thread_id_arg); 544 545 // Push the data for the first argument into the m_arguments vector. 546 m_arguments.push_back(arg); 547 548 if (step_type == eStepTypeScripted) { 549 m_all_options.Append(&m_class_options, LLDB_OPT_SET_1, LLDB_OPT_SET_1); 550 } 551 m_all_options.Append(&m_options); 552 m_all_options.Finalize(); 553 } 554 555 ~CommandObjectThreadStepWithTypeAndScope() override = default; 556 557 Options *GetOptions() override { 558 return &m_all_options; 559 } 560 561 protected: 562 bool DoExecute(Args &command, CommandReturnObject &result) override { 563 Process *process = m_exe_ctx.GetProcessPtr(); 564 bool synchronous_execution = m_interpreter.GetSynchronous(); 565 566 const uint32_t num_threads = process->GetThreadList().GetSize(); 567 Thread *thread = nullptr; 568 569 if (command.GetArgumentCount() == 0) { 570 thread = GetDefaultThread(); 571 572 if (thread == nullptr) { 573 result.AppendError("no selected thread in process"); 574 result.SetStatus(eReturnStatusFailed); 575 return false; 576 } 577 } else { 578 const char *thread_idx_cstr = command.GetArgumentAtIndex(0); 579 uint32_t step_thread_idx = 580 StringConvert::ToUInt32(thread_idx_cstr, LLDB_INVALID_INDEX32); 581 if (step_thread_idx == LLDB_INVALID_INDEX32) { 582 result.AppendErrorWithFormat("invalid thread index '%s'.\n", 583 thread_idx_cstr); 584 result.SetStatus(eReturnStatusFailed); 585 return false; 586 } 587 thread = 588 process->GetThreadList().FindThreadByIndexID(step_thread_idx).get(); 589 if (thread == nullptr) { 590 result.AppendErrorWithFormat( 591 "Thread index %u is out of range (valid values are 0 - %u).\n", 592 step_thread_idx, num_threads); 593 result.SetStatus(eReturnStatusFailed); 594 return false; 595 } 596 } 597 598 if (m_step_type == eStepTypeScripted) { 599 if (m_class_options.GetClassName().empty()) { 600 result.AppendErrorWithFormat("empty class name for scripted step."); 601 result.SetStatus(eReturnStatusFailed); 602 return false; 603 } else if (!GetDebugger().GetScriptInterpreter()->CheckObjectExists( 604 m_class_options.GetClassName().c_str())) { 605 result.AppendErrorWithFormat( 606 "class for scripted step: \"%s\" does not exist.", 607 m_class_options.GetClassName().c_str()); 608 result.SetStatus(eReturnStatusFailed); 609 return false; 610 } 611 } 612 613 if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER && 614 m_step_type != eStepTypeInto) { 615 result.AppendErrorWithFormat( 616 "end line option is only valid for step into"); 617 result.SetStatus(eReturnStatusFailed); 618 return false; 619 } 620 621 const bool abort_other_plans = false; 622 const lldb::RunMode stop_other_threads = m_options.m_run_mode; 623 624 // This is a bit unfortunate, but not all the commands in this command 625 // object support only while stepping, so I use the bool for them. 626 bool bool_stop_other_threads; 627 if (m_options.m_run_mode == eAllThreads) 628 bool_stop_other_threads = false; 629 else if (m_options.m_run_mode == eOnlyDuringStepping) 630 bool_stop_other_threads = 631 (m_step_type != eStepTypeOut && m_step_type != eStepTypeScripted); 632 else 633 bool_stop_other_threads = true; 634 635 ThreadPlanSP new_plan_sp; 636 Status new_plan_status; 637 638 if (m_step_type == eStepTypeInto) { 639 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 640 assert(frame != nullptr); 641 642 if (frame->HasDebugInformation()) { 643 AddressRange range; 644 SymbolContext sc = frame->GetSymbolContext(eSymbolContextEverything); 645 if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER) { 646 Status error; 647 if (!sc.GetAddressRangeFromHereToEndLine(m_options.m_end_line, range, 648 error)) { 649 result.AppendErrorWithFormat("invalid end-line option: %s.", 650 error.AsCString()); 651 result.SetStatus(eReturnStatusFailed); 652 return false; 653 } 654 } else if (m_options.m_end_line_is_block_end) { 655 Status error; 656 Block *block = frame->GetSymbolContext(eSymbolContextBlock).block; 657 if (!block) { 658 result.AppendErrorWithFormat("Could not find the current block."); 659 result.SetStatus(eReturnStatusFailed); 660 return false; 661 } 662 663 AddressRange block_range; 664 Address pc_address = frame->GetFrameCodeAddress(); 665 block->GetRangeContainingAddress(pc_address, block_range); 666 if (!block_range.GetBaseAddress().IsValid()) { 667 result.AppendErrorWithFormat( 668 "Could not find the current block address."); 669 result.SetStatus(eReturnStatusFailed); 670 return false; 671 } 672 lldb::addr_t pc_offset_in_block = 673 pc_address.GetFileAddress() - 674 block_range.GetBaseAddress().GetFileAddress(); 675 lldb::addr_t range_length = 676 block_range.GetByteSize() - pc_offset_in_block; 677 range = AddressRange(pc_address, range_length); 678 } else { 679 range = sc.line_entry.range; 680 } 681 682 new_plan_sp = thread->QueueThreadPlanForStepInRange( 683 abort_other_plans, range, 684 frame->GetSymbolContext(eSymbolContextEverything), 685 m_options.m_step_in_target.c_str(), stop_other_threads, 686 new_plan_status, m_options.m_step_in_avoid_no_debug, 687 m_options.m_step_out_avoid_no_debug); 688 689 if (new_plan_sp && !m_options.m_avoid_regexp.empty()) { 690 ThreadPlanStepInRange *step_in_range_plan = 691 static_cast<ThreadPlanStepInRange *>(new_plan_sp.get()); 692 step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str()); 693 } 694 } else 695 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( 696 false, abort_other_plans, bool_stop_other_threads, new_plan_status); 697 } else if (m_step_type == eStepTypeOver) { 698 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 699 700 if (frame->HasDebugInformation()) 701 new_plan_sp = thread->QueueThreadPlanForStepOverRange( 702 abort_other_plans, 703 frame->GetSymbolContext(eSymbolContextEverything).line_entry, 704 frame->GetSymbolContext(eSymbolContextEverything), 705 stop_other_threads, new_plan_status, 706 m_options.m_step_out_avoid_no_debug); 707 else 708 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( 709 true, abort_other_plans, bool_stop_other_threads, new_plan_status); 710 } else if (m_step_type == eStepTypeTrace) { 711 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( 712 false, abort_other_plans, bool_stop_other_threads, new_plan_status); 713 } else if (m_step_type == eStepTypeTraceOver) { 714 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( 715 true, abort_other_plans, bool_stop_other_threads, new_plan_status); 716 } else if (m_step_type == eStepTypeOut) { 717 new_plan_sp = thread->QueueThreadPlanForStepOut( 718 abort_other_plans, nullptr, false, bool_stop_other_threads, eVoteYes, 719 eVoteNoOpinion, thread->GetSelectedFrameIndex(), new_plan_status, 720 m_options.m_step_out_avoid_no_debug); 721 } else if (m_step_type == eStepTypeScripted) { 722 new_plan_sp = thread->QueueThreadPlanForStepScripted( 723 abort_other_plans, m_class_options.GetClassName().c_str(), 724 m_class_options.GetStructuredData(), 725 bool_stop_other_threads, new_plan_status); 726 } else { 727 result.AppendError("step type is not supported"); 728 result.SetStatus(eReturnStatusFailed); 729 return false; 730 } 731 732 // If we got a new plan, then set it to be a master plan (User level Plans 733 // should be master plans so that they can be interruptible). Then resume 734 // the process. 735 736 if (new_plan_sp) { 737 new_plan_sp->SetIsMasterPlan(true); 738 new_plan_sp->SetOkayToDiscard(false); 739 740 if (m_options.m_step_count > 1) { 741 if (!new_plan_sp->SetIterationCount(m_options.m_step_count)) { 742 result.AppendWarning( 743 "step operation does not support iteration count."); 744 } 745 } 746 747 process->GetThreadList().SetSelectedThreadByID(thread->GetID()); 748 749 const uint32_t iohandler_id = process->GetIOHandlerID(); 750 751 StreamString stream; 752 Status error; 753 if (synchronous_execution) 754 error = process->ResumeSynchronous(&stream); 755 else 756 error = process->Resume(); 757 758 if (!error.Success()) { 759 result.AppendMessage(error.AsCString()); 760 result.SetStatus(eReturnStatusFailed); 761 return false; 762 } 763 764 // There is a race condition where this thread will return up the call 765 // stack to the main command handler and show an (lldb) prompt before 766 // HandlePrivateEvent (from PrivateStateThread) has a chance to call 767 // PushProcessIOHandler(). 768 process->SyncIOHandler(iohandler_id, std::chrono::seconds(2)); 769 770 if (synchronous_execution) { 771 // If any state changed events had anything to say, add that to the 772 // result 773 if (stream.GetSize() > 0) 774 result.AppendMessage(stream.GetString()); 775 776 process->GetThreadList().SetSelectedThreadByID(thread->GetID()); 777 result.SetDidChangeProcessState(true); 778 result.SetStatus(eReturnStatusSuccessFinishNoResult); 779 } else { 780 result.SetStatus(eReturnStatusSuccessContinuingNoResult); 781 } 782 } else { 783 result.SetError(new_plan_status); 784 result.SetStatus(eReturnStatusFailed); 785 } 786 return result.Succeeded(); 787 } 788 789 protected: 790 StepType m_step_type; 791 StepScope m_step_scope; 792 ThreadStepScopeOptionGroup m_options; 793 OptionGroupPythonClassWithDict m_class_options; 794 OptionGroupOptions m_all_options; 795 }; 796 797 // CommandObjectThreadContinue 798 799 class CommandObjectThreadContinue : public CommandObjectParsed { 800 public: 801 CommandObjectThreadContinue(CommandInterpreter &interpreter) 802 : CommandObjectParsed( 803 interpreter, "thread continue", 804 "Continue execution of the current target process. One " 805 "or more threads may be specified, by default all " 806 "threads continue.", 807 nullptr, 808 eCommandRequiresThread | eCommandTryTargetAPILock | 809 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { 810 CommandArgumentEntry arg; 811 CommandArgumentData thread_idx_arg; 812 813 // Define the first (and only) variant of this arg. 814 thread_idx_arg.arg_type = eArgTypeThreadIndex; 815 thread_idx_arg.arg_repetition = eArgRepeatPlus; 816 817 // There is only one variant this argument could be; put it into the 818 // argument entry. 819 arg.push_back(thread_idx_arg); 820 821 // Push the data for the first argument into the m_arguments vector. 822 m_arguments.push_back(arg); 823 } 824 825 ~CommandObjectThreadContinue() override = default; 826 827 bool DoExecute(Args &command, CommandReturnObject &result) override { 828 bool synchronous_execution = m_interpreter.GetSynchronous(); 829 830 Process *process = m_exe_ctx.GetProcessPtr(); 831 if (process == nullptr) { 832 result.AppendError("no process exists. Cannot continue"); 833 result.SetStatus(eReturnStatusFailed); 834 return false; 835 } 836 837 StateType state = process->GetState(); 838 if ((state == eStateCrashed) || (state == eStateStopped) || 839 (state == eStateSuspended)) { 840 const size_t argc = command.GetArgumentCount(); 841 if (argc > 0) { 842 // These two lines appear at the beginning of both blocks in this 843 // if..else, but that is because we need to release the lock before 844 // calling process->Resume below. 845 std::lock_guard<std::recursive_mutex> guard( 846 process->GetThreadList().GetMutex()); 847 const uint32_t num_threads = process->GetThreadList().GetSize(); 848 std::vector<Thread *> resume_threads; 849 for (auto &entry : command.entries()) { 850 uint32_t thread_idx; 851 if (entry.ref().getAsInteger(0, thread_idx)) { 852 result.AppendErrorWithFormat( 853 "invalid thread index argument: \"%s\".\n", entry.c_str()); 854 result.SetStatus(eReturnStatusFailed); 855 return false; 856 } 857 Thread *thread = 858 process->GetThreadList().FindThreadByIndexID(thread_idx).get(); 859 860 if (thread) { 861 resume_threads.push_back(thread); 862 } else { 863 result.AppendErrorWithFormat("invalid thread index %u.\n", 864 thread_idx); 865 result.SetStatus(eReturnStatusFailed); 866 return false; 867 } 868 } 869 870 if (resume_threads.empty()) { 871 result.AppendError("no valid thread indexes were specified"); 872 result.SetStatus(eReturnStatusFailed); 873 return false; 874 } else { 875 if (resume_threads.size() == 1) 876 result.AppendMessageWithFormat("Resuming thread: "); 877 else 878 result.AppendMessageWithFormat("Resuming threads: "); 879 880 for (uint32_t idx = 0; idx < num_threads; ++idx) { 881 Thread *thread = 882 process->GetThreadList().GetThreadAtIndex(idx).get(); 883 std::vector<Thread *>::iterator this_thread_pos = 884 find(resume_threads.begin(), resume_threads.end(), thread); 885 886 if (this_thread_pos != resume_threads.end()) { 887 resume_threads.erase(this_thread_pos); 888 if (!resume_threads.empty()) 889 result.AppendMessageWithFormat("%u, ", thread->GetIndexID()); 890 else 891 result.AppendMessageWithFormat("%u ", thread->GetIndexID()); 892 893 const bool override_suspend = true; 894 thread->SetResumeState(eStateRunning, override_suspend); 895 } else { 896 thread->SetResumeState(eStateSuspended); 897 } 898 } 899 result.AppendMessageWithFormat("in process %" PRIu64 "\n", 900 process->GetID()); 901 } 902 } else { 903 // These two lines appear at the beginning of both blocks in this 904 // if..else, but that is because we need to release the lock before 905 // calling process->Resume below. 906 std::lock_guard<std::recursive_mutex> guard( 907 process->GetThreadList().GetMutex()); 908 const uint32_t num_threads = process->GetThreadList().GetSize(); 909 Thread *current_thread = GetDefaultThread(); 910 if (current_thread == nullptr) { 911 result.AppendError("the process doesn't have a current thread"); 912 result.SetStatus(eReturnStatusFailed); 913 return false; 914 } 915 // Set the actions that the threads should each take when resuming 916 for (uint32_t idx = 0; idx < num_threads; ++idx) { 917 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 918 if (thread == current_thread) { 919 result.AppendMessageWithFormat("Resuming thread 0x%4.4" PRIx64 920 " in process %" PRIu64 "\n", 921 thread->GetID(), process->GetID()); 922 const bool override_suspend = true; 923 thread->SetResumeState(eStateRunning, override_suspend); 924 } else { 925 thread->SetResumeState(eStateSuspended); 926 } 927 } 928 } 929 930 StreamString stream; 931 Status error; 932 if (synchronous_execution) 933 error = process->ResumeSynchronous(&stream); 934 else 935 error = process->Resume(); 936 937 // We should not be holding the thread list lock when we do this. 938 if (error.Success()) { 939 result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", 940 process->GetID()); 941 if (synchronous_execution) { 942 // If any state changed events had anything to say, add that to the 943 // result 944 if (stream.GetSize() > 0) 945 result.AppendMessage(stream.GetString()); 946 947 result.SetDidChangeProcessState(true); 948 result.SetStatus(eReturnStatusSuccessFinishNoResult); 949 } else { 950 result.SetStatus(eReturnStatusSuccessContinuingNoResult); 951 } 952 } else { 953 result.AppendErrorWithFormat("Failed to resume process: %s\n", 954 error.AsCString()); 955 result.SetStatus(eReturnStatusFailed); 956 } 957 } else { 958 result.AppendErrorWithFormat( 959 "Process cannot be continued from its current state (%s).\n", 960 StateAsCString(state)); 961 result.SetStatus(eReturnStatusFailed); 962 } 963 964 return result.Succeeded(); 965 } 966 }; 967 968 // CommandObjectThreadUntil 969 970 static constexpr OptionEnumValueElement g_duo_running_mode[] = { 971 {eOnlyThisThread, "this-thread", "Run only this thread"}, 972 {eAllThreads, "all-threads", "Run all threads"} }; 973 974 static constexpr OptionEnumValues DuoRunningModes() { 975 return OptionEnumValues(g_duo_running_mode); 976 } 977 978 #define LLDB_OPTIONS_thread_until 979 #include "CommandOptions.inc" 980 981 class CommandObjectThreadUntil : public CommandObjectParsed { 982 public: 983 class CommandOptions : public Options { 984 public: 985 uint32_t m_thread_idx; 986 uint32_t m_frame_idx; 987 988 CommandOptions() 989 : Options(), m_thread_idx(LLDB_INVALID_THREAD_ID), 990 m_frame_idx(LLDB_INVALID_FRAME_ID) { 991 // Keep default values of all options in one place: OptionParsingStarting 992 // () 993 OptionParsingStarting(nullptr); 994 } 995 996 ~CommandOptions() override = default; 997 998 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 999 ExecutionContext *execution_context) override { 1000 Status error; 1001 const int short_option = m_getopt_table[option_idx].val; 1002 1003 switch (short_option) { 1004 case 'a': { 1005 lldb::addr_t tmp_addr = OptionArgParser::ToAddress( 1006 execution_context, option_arg, LLDB_INVALID_ADDRESS, &error); 1007 if (error.Success()) 1008 m_until_addrs.push_back(tmp_addr); 1009 } break; 1010 case 't': 1011 if (option_arg.getAsInteger(0, m_thread_idx)) { 1012 m_thread_idx = LLDB_INVALID_INDEX32; 1013 error.SetErrorStringWithFormat("invalid thread index '%s'", 1014 option_arg.str().c_str()); 1015 } 1016 break; 1017 case 'f': 1018 if (option_arg.getAsInteger(0, m_frame_idx)) { 1019 m_frame_idx = LLDB_INVALID_FRAME_ID; 1020 error.SetErrorStringWithFormat("invalid frame index '%s'", 1021 option_arg.str().c_str()); 1022 } 1023 break; 1024 case 'm': { 1025 auto enum_values = GetDefinitions()[option_idx].enum_values; 1026 lldb::RunMode run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum( 1027 option_arg, enum_values, eOnlyDuringStepping, error); 1028 1029 if (error.Success()) { 1030 if (run_mode == eAllThreads) 1031 m_stop_others = false; 1032 else 1033 m_stop_others = true; 1034 } 1035 } break; 1036 default: 1037 llvm_unreachable("Unimplemented option"); 1038 } 1039 return error; 1040 } 1041 1042 void OptionParsingStarting(ExecutionContext *execution_context) override { 1043 m_thread_idx = LLDB_INVALID_THREAD_ID; 1044 m_frame_idx = 0; 1045 m_stop_others = false; 1046 m_until_addrs.clear(); 1047 } 1048 1049 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1050 return llvm::makeArrayRef(g_thread_until_options); 1051 } 1052 1053 uint32_t m_step_thread_idx; 1054 bool m_stop_others; 1055 std::vector<lldb::addr_t> m_until_addrs; 1056 1057 // Instance variables to hold the values for command options. 1058 }; 1059 1060 CommandObjectThreadUntil(CommandInterpreter &interpreter) 1061 : CommandObjectParsed( 1062 interpreter, "thread until", 1063 "Continue until a line number or address is reached by the " 1064 "current or specified thread. Stops when returning from " 1065 "the current function as a safety measure. " 1066 "The target line number(s) are given as arguments, and if more than one" 1067 " is provided, stepping will stop when the first one is hit.", 1068 nullptr, 1069 eCommandRequiresThread | eCommandTryTargetAPILock | 1070 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 1071 m_options() { 1072 CommandArgumentEntry arg; 1073 CommandArgumentData line_num_arg; 1074 1075 // Define the first (and only) variant of this arg. 1076 line_num_arg.arg_type = eArgTypeLineNum; 1077 line_num_arg.arg_repetition = eArgRepeatPlain; 1078 1079 // There is only one variant this argument could be; put it into the 1080 // argument entry. 1081 arg.push_back(line_num_arg); 1082 1083 // Push the data for the first argument into the m_arguments vector. 1084 m_arguments.push_back(arg); 1085 } 1086 1087 ~CommandObjectThreadUntil() override = default; 1088 1089 Options *GetOptions() override { return &m_options; } 1090 1091 protected: 1092 bool DoExecute(Args &command, CommandReturnObject &result) override { 1093 bool synchronous_execution = m_interpreter.GetSynchronous(); 1094 1095 Target *target = &GetSelectedTarget(); 1096 1097 Process *process = m_exe_ctx.GetProcessPtr(); 1098 if (process == nullptr) { 1099 result.AppendError("need a valid process to step"); 1100 result.SetStatus(eReturnStatusFailed); 1101 } else { 1102 Thread *thread = nullptr; 1103 std::vector<uint32_t> line_numbers; 1104 1105 if (command.GetArgumentCount() >= 1) { 1106 size_t num_args = command.GetArgumentCount(); 1107 for (size_t i = 0; i < num_args; i++) { 1108 uint32_t line_number; 1109 line_number = StringConvert::ToUInt32(command.GetArgumentAtIndex(i), 1110 UINT32_MAX); 1111 if (line_number == UINT32_MAX) { 1112 result.AppendErrorWithFormat("invalid line number: '%s'.\n", 1113 command.GetArgumentAtIndex(i)); 1114 result.SetStatus(eReturnStatusFailed); 1115 return false; 1116 } else 1117 line_numbers.push_back(line_number); 1118 } 1119 } else if (m_options.m_until_addrs.empty()) { 1120 result.AppendErrorWithFormat("No line number or address provided:\n%s", 1121 GetSyntax().str().c_str()); 1122 result.SetStatus(eReturnStatusFailed); 1123 return false; 1124 } 1125 1126 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) { 1127 thread = GetDefaultThread(); 1128 } else { 1129 thread = process->GetThreadList() 1130 .FindThreadByIndexID(m_options.m_thread_idx) 1131 .get(); 1132 } 1133 1134 if (thread == nullptr) { 1135 const uint32_t num_threads = process->GetThreadList().GetSize(); 1136 result.AppendErrorWithFormat( 1137 "Thread index %u is out of range (valid values are 0 - %u).\n", 1138 m_options.m_thread_idx, num_threads); 1139 result.SetStatus(eReturnStatusFailed); 1140 return false; 1141 } 1142 1143 const bool abort_other_plans = false; 1144 1145 StackFrame *frame = 1146 thread->GetStackFrameAtIndex(m_options.m_frame_idx).get(); 1147 if (frame == nullptr) { 1148 result.AppendErrorWithFormat( 1149 "Frame index %u is out of range for thread %u.\n", 1150 m_options.m_frame_idx, m_options.m_thread_idx); 1151 result.SetStatus(eReturnStatusFailed); 1152 return false; 1153 } 1154 1155 ThreadPlanSP new_plan_sp; 1156 Status new_plan_status; 1157 1158 if (frame->HasDebugInformation()) { 1159 // Finally we got here... Translate the given line number to a bunch 1160 // of addresses: 1161 SymbolContext sc(frame->GetSymbolContext(eSymbolContextCompUnit)); 1162 LineTable *line_table = nullptr; 1163 if (sc.comp_unit) 1164 line_table = sc.comp_unit->GetLineTable(); 1165 1166 if (line_table == nullptr) { 1167 result.AppendErrorWithFormat("Failed to resolve the line table for " 1168 "frame %u of thread index %u.\n", 1169 m_options.m_frame_idx, 1170 m_options.m_thread_idx); 1171 result.SetStatus(eReturnStatusFailed); 1172 return false; 1173 } 1174 1175 LineEntry function_start; 1176 uint32_t index_ptr = 0, end_ptr; 1177 std::vector<addr_t> address_list; 1178 1179 // Find the beginning & end index of the 1180 AddressRange fun_addr_range = sc.function->GetAddressRange(); 1181 Address fun_start_addr = fun_addr_range.GetBaseAddress(); 1182 line_table->FindLineEntryByAddress(fun_start_addr, function_start, 1183 &index_ptr); 1184 1185 Address fun_end_addr(fun_start_addr.GetSection(), 1186 fun_start_addr.GetOffset() + 1187 fun_addr_range.GetByteSize()); 1188 1189 bool all_in_function = true; 1190 1191 line_table->FindLineEntryByAddress(fun_end_addr, function_start, 1192 &end_ptr); 1193 1194 for (uint32_t line_number : line_numbers) { 1195 uint32_t start_idx_ptr = index_ptr; 1196 while (start_idx_ptr <= end_ptr) { 1197 LineEntry line_entry; 1198 const bool exact = false; 1199 start_idx_ptr = sc.comp_unit->FindLineEntry( 1200 start_idx_ptr, line_number, sc.comp_unit, exact, &line_entry); 1201 if (start_idx_ptr == UINT32_MAX) 1202 break; 1203 1204 addr_t address = 1205 line_entry.range.GetBaseAddress().GetLoadAddress(target); 1206 if (address != LLDB_INVALID_ADDRESS) { 1207 if (fun_addr_range.ContainsLoadAddress(address, target)) 1208 address_list.push_back(address); 1209 else 1210 all_in_function = false; 1211 } 1212 start_idx_ptr++; 1213 } 1214 } 1215 1216 for (lldb::addr_t address : m_options.m_until_addrs) { 1217 if (fun_addr_range.ContainsLoadAddress(address, target)) 1218 address_list.push_back(address); 1219 else 1220 all_in_function = false; 1221 } 1222 1223 if (address_list.empty()) { 1224 if (all_in_function) 1225 result.AppendErrorWithFormat( 1226 "No line entries matching until target.\n"); 1227 else 1228 result.AppendErrorWithFormat( 1229 "Until target outside of the current function.\n"); 1230 1231 result.SetStatus(eReturnStatusFailed); 1232 return false; 1233 } 1234 1235 new_plan_sp = thread->QueueThreadPlanForStepUntil( 1236 abort_other_plans, &address_list.front(), address_list.size(), 1237 m_options.m_stop_others, m_options.m_frame_idx, new_plan_status); 1238 if (new_plan_sp) { 1239 // User level plans should be master plans so they can be interrupted 1240 // (e.g. by hitting a breakpoint) and other plans executed by the 1241 // user (stepping around the breakpoint) and then a "continue" will 1242 // resume the original plan. 1243 new_plan_sp->SetIsMasterPlan(true); 1244 new_plan_sp->SetOkayToDiscard(false); 1245 } else { 1246 result.SetError(new_plan_status); 1247 result.SetStatus(eReturnStatusFailed); 1248 return false; 1249 } 1250 } else { 1251 result.AppendErrorWithFormat( 1252 "Frame index %u of thread %u has no debug information.\n", 1253 m_options.m_frame_idx, m_options.m_thread_idx); 1254 result.SetStatus(eReturnStatusFailed); 1255 return false; 1256 } 1257 1258 process->GetThreadList().SetSelectedThreadByID(m_options.m_thread_idx); 1259 1260 StreamString stream; 1261 Status error; 1262 if (synchronous_execution) 1263 error = process->ResumeSynchronous(&stream); 1264 else 1265 error = process->Resume(); 1266 1267 if (error.Success()) { 1268 result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", 1269 process->GetID()); 1270 if (synchronous_execution) { 1271 // If any state changed events had anything to say, add that to the 1272 // result 1273 if (stream.GetSize() > 0) 1274 result.AppendMessage(stream.GetString()); 1275 1276 result.SetDidChangeProcessState(true); 1277 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1278 } else { 1279 result.SetStatus(eReturnStatusSuccessContinuingNoResult); 1280 } 1281 } else { 1282 result.AppendErrorWithFormat("Failed to resume process: %s.\n", 1283 error.AsCString()); 1284 result.SetStatus(eReturnStatusFailed); 1285 } 1286 } 1287 return result.Succeeded(); 1288 } 1289 1290 CommandOptions m_options; 1291 }; 1292 1293 // CommandObjectThreadSelect 1294 1295 class CommandObjectThreadSelect : public CommandObjectParsed { 1296 public: 1297 CommandObjectThreadSelect(CommandInterpreter &interpreter) 1298 : CommandObjectParsed(interpreter, "thread select", 1299 "Change the currently selected thread.", nullptr, 1300 eCommandRequiresProcess | eCommandTryTargetAPILock | 1301 eCommandProcessMustBeLaunched | 1302 eCommandProcessMustBePaused) { 1303 CommandArgumentEntry arg; 1304 CommandArgumentData thread_idx_arg; 1305 1306 // Define the first (and only) variant of this arg. 1307 thread_idx_arg.arg_type = eArgTypeThreadIndex; 1308 thread_idx_arg.arg_repetition = eArgRepeatPlain; 1309 1310 // There is only one variant this argument could be; put it into the 1311 // argument entry. 1312 arg.push_back(thread_idx_arg); 1313 1314 // Push the data for the first argument into the m_arguments vector. 1315 m_arguments.push_back(arg); 1316 } 1317 1318 ~CommandObjectThreadSelect() override = default; 1319 1320 protected: 1321 bool DoExecute(Args &command, CommandReturnObject &result) override { 1322 Process *process = m_exe_ctx.GetProcessPtr(); 1323 if (process == nullptr) { 1324 result.AppendError("no process"); 1325 result.SetStatus(eReturnStatusFailed); 1326 return false; 1327 } else if (command.GetArgumentCount() != 1) { 1328 result.AppendErrorWithFormat( 1329 "'%s' takes exactly one thread index argument:\nUsage: %s\n", 1330 m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1331 result.SetStatus(eReturnStatusFailed); 1332 return false; 1333 } 1334 1335 uint32_t index_id = 1336 StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0); 1337 1338 Thread *new_thread = 1339 process->GetThreadList().FindThreadByIndexID(index_id).get(); 1340 if (new_thread == nullptr) { 1341 result.AppendErrorWithFormat("invalid thread #%s.\n", 1342 command.GetArgumentAtIndex(0)); 1343 result.SetStatus(eReturnStatusFailed); 1344 return false; 1345 } 1346 1347 process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true); 1348 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1349 1350 return result.Succeeded(); 1351 } 1352 }; 1353 1354 // CommandObjectThreadList 1355 1356 class CommandObjectThreadList : public CommandObjectParsed { 1357 public: 1358 CommandObjectThreadList(CommandInterpreter &interpreter) 1359 : CommandObjectParsed( 1360 interpreter, "thread list", 1361 "Show a summary of each thread in the current target process. " 1362 "Use 'settings set thread-format' to customize the individual " 1363 "thread listings.", 1364 "thread list", 1365 eCommandRequiresProcess | eCommandTryTargetAPILock | 1366 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 1367 1368 ~CommandObjectThreadList() override = default; 1369 1370 protected: 1371 bool DoExecute(Args &command, CommandReturnObject &result) override { 1372 Stream &strm = result.GetOutputStream(); 1373 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1374 Process *process = m_exe_ctx.GetProcessPtr(); 1375 const bool only_threads_with_stop_reason = false; 1376 const uint32_t start_frame = 0; 1377 const uint32_t num_frames = 0; 1378 const uint32_t num_frames_with_source = 0; 1379 process->GetStatus(strm); 1380 process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, 1381 num_frames, num_frames_with_source, false); 1382 return result.Succeeded(); 1383 } 1384 }; 1385 1386 // CommandObjectThreadInfo 1387 #define LLDB_OPTIONS_thread_info 1388 #include "CommandOptions.inc" 1389 1390 class CommandObjectThreadInfo : public CommandObjectIterateOverThreads { 1391 public: 1392 class CommandOptions : public Options { 1393 public: 1394 CommandOptions() : Options() { OptionParsingStarting(nullptr); } 1395 1396 ~CommandOptions() override = default; 1397 1398 void OptionParsingStarting(ExecutionContext *execution_context) override { 1399 m_json_thread = false; 1400 m_json_stopinfo = false; 1401 } 1402 1403 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1404 ExecutionContext *execution_context) override { 1405 const int short_option = m_getopt_table[option_idx].val; 1406 Status error; 1407 1408 switch (short_option) { 1409 case 'j': 1410 m_json_thread = true; 1411 break; 1412 1413 case 's': 1414 m_json_stopinfo = true; 1415 break; 1416 1417 default: 1418 llvm_unreachable("Unimplemented option"); 1419 } 1420 return error; 1421 } 1422 1423 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1424 return llvm::makeArrayRef(g_thread_info_options); 1425 } 1426 1427 bool m_json_thread; 1428 bool m_json_stopinfo; 1429 }; 1430 1431 CommandObjectThreadInfo(CommandInterpreter &interpreter) 1432 : CommandObjectIterateOverThreads( 1433 interpreter, "thread info", "Show an extended summary of one or " 1434 "more threads. Defaults to the " 1435 "current thread.", 1436 "thread info", 1437 eCommandRequiresProcess | eCommandTryTargetAPILock | 1438 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 1439 m_options() { 1440 m_add_return = false; 1441 } 1442 1443 ~CommandObjectThreadInfo() override = default; 1444 1445 Options *GetOptions() override { return &m_options; } 1446 1447 bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { 1448 ThreadSP thread_sp = 1449 m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); 1450 if (!thread_sp) { 1451 result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n", 1452 tid); 1453 result.SetStatus(eReturnStatusFailed); 1454 return false; 1455 } 1456 1457 Thread *thread = thread_sp.get(); 1458 1459 Stream &strm = result.GetOutputStream(); 1460 if (!thread->GetDescription(strm, eDescriptionLevelFull, 1461 m_options.m_json_thread, 1462 m_options.m_json_stopinfo)) { 1463 result.AppendErrorWithFormat("error displaying info for thread: \"%d\"\n", 1464 thread->GetIndexID()); 1465 result.SetStatus(eReturnStatusFailed); 1466 return false; 1467 } 1468 return true; 1469 } 1470 1471 CommandOptions m_options; 1472 }; 1473 1474 // CommandObjectThreadException 1475 1476 class CommandObjectThreadException : public CommandObjectIterateOverThreads { 1477 public: 1478 CommandObjectThreadException(CommandInterpreter &interpreter) 1479 : CommandObjectIterateOverThreads( 1480 interpreter, "thread exception", 1481 "Display the current exception object for a thread. Defaults to " 1482 "the current thread.", 1483 "thread exception", 1484 eCommandRequiresProcess | eCommandTryTargetAPILock | 1485 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 1486 1487 ~CommandObjectThreadException() override = default; 1488 1489 bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { 1490 ThreadSP thread_sp = 1491 m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); 1492 if (!thread_sp) { 1493 result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n", 1494 tid); 1495 result.SetStatus(eReturnStatusFailed); 1496 return false; 1497 } 1498 1499 Stream &strm = result.GetOutputStream(); 1500 ValueObjectSP exception_object_sp = thread_sp->GetCurrentException(); 1501 if (exception_object_sp) { 1502 exception_object_sp->Dump(strm); 1503 } 1504 1505 ThreadSP exception_thread_sp = thread_sp->GetCurrentExceptionBacktrace(); 1506 if (exception_thread_sp && exception_thread_sp->IsValid()) { 1507 const uint32_t num_frames_with_source = 0; 1508 const bool stop_format = false; 1509 exception_thread_sp->GetStatus(strm, 0, UINT32_MAX, 1510 num_frames_with_source, stop_format); 1511 } 1512 1513 return true; 1514 } 1515 }; 1516 1517 // CommandObjectThreadReturn 1518 #define LLDB_OPTIONS_thread_return 1519 #include "CommandOptions.inc" 1520 1521 class CommandObjectThreadReturn : public CommandObjectRaw { 1522 public: 1523 class CommandOptions : public Options { 1524 public: 1525 CommandOptions() : Options(), m_from_expression(false) { 1526 // Keep default values of all options in one place: OptionParsingStarting 1527 // () 1528 OptionParsingStarting(nullptr); 1529 } 1530 1531 ~CommandOptions() override = default; 1532 1533 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1534 ExecutionContext *execution_context) override { 1535 Status error; 1536 const int short_option = m_getopt_table[option_idx].val; 1537 1538 switch (short_option) { 1539 case 'x': { 1540 bool success; 1541 bool tmp_value = 1542 OptionArgParser::ToBoolean(option_arg, false, &success); 1543 if (success) 1544 m_from_expression = tmp_value; 1545 else { 1546 error.SetErrorStringWithFormat( 1547 "invalid boolean value '%s' for 'x' option", 1548 option_arg.str().c_str()); 1549 } 1550 } break; 1551 default: 1552 llvm_unreachable("Unimplemented option"); 1553 } 1554 return error; 1555 } 1556 1557 void OptionParsingStarting(ExecutionContext *execution_context) override { 1558 m_from_expression = false; 1559 } 1560 1561 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1562 return llvm::makeArrayRef(g_thread_return_options); 1563 } 1564 1565 bool m_from_expression; 1566 1567 // Instance variables to hold the values for command options. 1568 }; 1569 1570 CommandObjectThreadReturn(CommandInterpreter &interpreter) 1571 : CommandObjectRaw(interpreter, "thread return", 1572 "Prematurely return from a stack frame, " 1573 "short-circuiting execution of newer frames " 1574 "and optionally yielding a specified value. Defaults " 1575 "to the exiting the current stack " 1576 "frame.", 1577 "thread return", 1578 eCommandRequiresFrame | eCommandTryTargetAPILock | 1579 eCommandProcessMustBeLaunched | 1580 eCommandProcessMustBePaused), 1581 m_options() { 1582 CommandArgumentEntry arg; 1583 CommandArgumentData expression_arg; 1584 1585 // Define the first (and only) variant of this arg. 1586 expression_arg.arg_type = eArgTypeExpression; 1587 expression_arg.arg_repetition = eArgRepeatOptional; 1588 1589 // There is only one variant this argument could be; put it into the 1590 // argument entry. 1591 arg.push_back(expression_arg); 1592 1593 // Push the data for the first argument into the m_arguments vector. 1594 m_arguments.push_back(arg); 1595 } 1596 1597 ~CommandObjectThreadReturn() override = default; 1598 1599 Options *GetOptions() override { return &m_options; } 1600 1601 protected: 1602 bool DoExecute(llvm::StringRef command, 1603 CommandReturnObject &result) override { 1604 // I am going to handle this by hand, because I don't want you to have to 1605 // say: 1606 // "thread return -- -5". 1607 if (command.startswith("-x")) { 1608 if (command.size() != 2U) 1609 result.AppendWarning("Return values ignored when returning from user " 1610 "called expressions"); 1611 1612 Thread *thread = m_exe_ctx.GetThreadPtr(); 1613 Status error; 1614 error = thread->UnwindInnermostExpression(); 1615 if (!error.Success()) { 1616 result.AppendErrorWithFormat("Unwinding expression failed - %s.", 1617 error.AsCString()); 1618 result.SetStatus(eReturnStatusFailed); 1619 } else { 1620 bool success = 1621 thread->SetSelectedFrameByIndexNoisily(0, result.GetOutputStream()); 1622 if (success) { 1623 m_exe_ctx.SetFrameSP(thread->GetSelectedFrame()); 1624 result.SetStatus(eReturnStatusSuccessFinishResult); 1625 } else { 1626 result.AppendErrorWithFormat( 1627 "Could not select 0th frame after unwinding expression."); 1628 result.SetStatus(eReturnStatusFailed); 1629 } 1630 } 1631 return result.Succeeded(); 1632 } 1633 1634 ValueObjectSP return_valobj_sp; 1635 1636 StackFrameSP frame_sp = m_exe_ctx.GetFrameSP(); 1637 uint32_t frame_idx = frame_sp->GetFrameIndex(); 1638 1639 if (frame_sp->IsInlined()) { 1640 result.AppendError("Don't know how to return from inlined frames."); 1641 result.SetStatus(eReturnStatusFailed); 1642 return false; 1643 } 1644 1645 if (!command.empty()) { 1646 Target *target = m_exe_ctx.GetTargetPtr(); 1647 EvaluateExpressionOptions options; 1648 1649 options.SetUnwindOnError(true); 1650 options.SetUseDynamic(eNoDynamicValues); 1651 1652 ExpressionResults exe_results = eExpressionSetupError; 1653 exe_results = target->EvaluateExpression(command, frame_sp.get(), 1654 return_valobj_sp, options); 1655 if (exe_results != eExpressionCompleted) { 1656 if (return_valobj_sp) 1657 result.AppendErrorWithFormat( 1658 "Error evaluating result expression: %s", 1659 return_valobj_sp->GetError().AsCString()); 1660 else 1661 result.AppendErrorWithFormat( 1662 "Unknown error evaluating result expression."); 1663 result.SetStatus(eReturnStatusFailed); 1664 return false; 1665 } 1666 } 1667 1668 Status error; 1669 ThreadSP thread_sp = m_exe_ctx.GetThreadSP(); 1670 const bool broadcast = true; 1671 error = thread_sp->ReturnFromFrame(frame_sp, return_valobj_sp, broadcast); 1672 if (!error.Success()) { 1673 result.AppendErrorWithFormat( 1674 "Error returning from frame %d of thread %d: %s.", frame_idx, 1675 thread_sp->GetIndexID(), error.AsCString()); 1676 result.SetStatus(eReturnStatusFailed); 1677 return false; 1678 } 1679 1680 result.SetStatus(eReturnStatusSuccessFinishResult); 1681 return true; 1682 } 1683 1684 CommandOptions m_options; 1685 }; 1686 1687 // CommandObjectThreadJump 1688 #define LLDB_OPTIONS_thread_jump 1689 #include "CommandOptions.inc" 1690 1691 class CommandObjectThreadJump : public CommandObjectParsed { 1692 public: 1693 class CommandOptions : public Options { 1694 public: 1695 CommandOptions() : Options() { OptionParsingStarting(nullptr); } 1696 1697 ~CommandOptions() override = default; 1698 1699 void OptionParsingStarting(ExecutionContext *execution_context) override { 1700 m_filenames.Clear(); 1701 m_line_num = 0; 1702 m_line_offset = 0; 1703 m_load_addr = LLDB_INVALID_ADDRESS; 1704 m_force = false; 1705 } 1706 1707 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1708 ExecutionContext *execution_context) override { 1709 const int short_option = m_getopt_table[option_idx].val; 1710 Status error; 1711 1712 switch (short_option) { 1713 case 'f': 1714 m_filenames.AppendIfUnique(FileSpec(option_arg)); 1715 if (m_filenames.GetSize() > 1) 1716 return Status("only one source file expected."); 1717 break; 1718 case 'l': 1719 if (option_arg.getAsInteger(0, m_line_num)) 1720 return Status("invalid line number: '%s'.", option_arg.str().c_str()); 1721 break; 1722 case 'b': 1723 if (option_arg.getAsInteger(0, m_line_offset)) 1724 return Status("invalid line offset: '%s'.", option_arg.str().c_str()); 1725 break; 1726 case 'a': 1727 m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg, 1728 LLDB_INVALID_ADDRESS, &error); 1729 break; 1730 case 'r': 1731 m_force = true; 1732 break; 1733 default: 1734 llvm_unreachable("Unimplemented option"); 1735 } 1736 return error; 1737 } 1738 1739 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1740 return llvm::makeArrayRef(g_thread_jump_options); 1741 } 1742 1743 FileSpecList m_filenames; 1744 uint32_t m_line_num; 1745 int32_t m_line_offset; 1746 lldb::addr_t m_load_addr; 1747 bool m_force; 1748 }; 1749 1750 CommandObjectThreadJump(CommandInterpreter &interpreter) 1751 : CommandObjectParsed( 1752 interpreter, "thread jump", 1753 "Sets the program counter to a new address.", "thread jump", 1754 eCommandRequiresFrame | eCommandTryTargetAPILock | 1755 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 1756 m_options() {} 1757 1758 ~CommandObjectThreadJump() override = default; 1759 1760 Options *GetOptions() override { return &m_options; } 1761 1762 protected: 1763 bool DoExecute(Args &args, CommandReturnObject &result) override { 1764 RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); 1765 StackFrame *frame = m_exe_ctx.GetFramePtr(); 1766 Thread *thread = m_exe_ctx.GetThreadPtr(); 1767 Target *target = m_exe_ctx.GetTargetPtr(); 1768 const SymbolContext &sym_ctx = 1769 frame->GetSymbolContext(eSymbolContextLineEntry); 1770 1771 if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) { 1772 // Use this address directly. 1773 Address dest = Address(m_options.m_load_addr); 1774 1775 lldb::addr_t callAddr = dest.GetCallableLoadAddress(target); 1776 if (callAddr == LLDB_INVALID_ADDRESS) { 1777 result.AppendErrorWithFormat("Invalid destination address."); 1778 result.SetStatus(eReturnStatusFailed); 1779 return false; 1780 } 1781 1782 if (!reg_ctx->SetPC(callAddr)) { 1783 result.AppendErrorWithFormat("Error changing PC value for thread %d.", 1784 thread->GetIndexID()); 1785 result.SetStatus(eReturnStatusFailed); 1786 return false; 1787 } 1788 } else { 1789 // Pick either the absolute line, or work out a relative one. 1790 int32_t line = (int32_t)m_options.m_line_num; 1791 if (line == 0) 1792 line = sym_ctx.line_entry.line + m_options.m_line_offset; 1793 1794 // Try the current file, but override if asked. 1795 FileSpec file = sym_ctx.line_entry.file; 1796 if (m_options.m_filenames.GetSize() == 1) 1797 file = m_options.m_filenames.GetFileSpecAtIndex(0); 1798 1799 if (!file) { 1800 result.AppendErrorWithFormat( 1801 "No source file available for the current location."); 1802 result.SetStatus(eReturnStatusFailed); 1803 return false; 1804 } 1805 1806 std::string warnings; 1807 Status err = thread->JumpToLine(file, line, m_options.m_force, &warnings); 1808 1809 if (err.Fail()) { 1810 result.SetError(err); 1811 return false; 1812 } 1813 1814 if (!warnings.empty()) 1815 result.AppendWarning(warnings.c_str()); 1816 } 1817 1818 result.SetStatus(eReturnStatusSuccessFinishResult); 1819 return true; 1820 } 1821 1822 CommandOptions m_options; 1823 }; 1824 1825 // Next are the subcommands of CommandObjectMultiwordThreadPlan 1826 1827 // CommandObjectThreadPlanList 1828 #define LLDB_OPTIONS_thread_plan_list 1829 #include "CommandOptions.inc" 1830 1831 class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads { 1832 public: 1833 class CommandOptions : public Options { 1834 public: 1835 CommandOptions() : Options() { 1836 // Keep default values of all options in one place: OptionParsingStarting 1837 // () 1838 OptionParsingStarting(nullptr); 1839 } 1840 1841 ~CommandOptions() override = default; 1842 1843 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1844 ExecutionContext *execution_context) override { 1845 Status error; 1846 const int short_option = m_getopt_table[option_idx].val; 1847 1848 switch (short_option) { 1849 case 'i': 1850 m_internal = true; 1851 break; 1852 case 'v': 1853 m_verbose = true; 1854 break; 1855 default: 1856 llvm_unreachable("Unimplemented option"); 1857 } 1858 return error; 1859 } 1860 1861 void OptionParsingStarting(ExecutionContext *execution_context) override { 1862 m_verbose = false; 1863 m_internal = false; 1864 } 1865 1866 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1867 return llvm::makeArrayRef(g_thread_plan_list_options); 1868 } 1869 1870 // Instance variables to hold the values for command options. 1871 bool m_verbose; 1872 bool m_internal; 1873 }; 1874 1875 CommandObjectThreadPlanList(CommandInterpreter &interpreter) 1876 : CommandObjectIterateOverThreads( 1877 interpreter, "thread plan list", 1878 "Show thread plans for one or more threads. If no threads are " 1879 "specified, show the " 1880 "current thread. Use the thread-index \"all\" to see all threads.", 1881 nullptr, 1882 eCommandRequiresProcess | eCommandRequiresThread | 1883 eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | 1884 eCommandProcessMustBePaused), 1885 m_options() {} 1886 1887 ~CommandObjectThreadPlanList() override = default; 1888 1889 Options *GetOptions() override { return &m_options; } 1890 1891 protected: 1892 bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { 1893 ThreadSP thread_sp = 1894 m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); 1895 if (!thread_sp) { 1896 result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n", 1897 tid); 1898 result.SetStatus(eReturnStatusFailed); 1899 return false; 1900 } 1901 1902 Thread *thread = thread_sp.get(); 1903 1904 Stream &strm = result.GetOutputStream(); 1905 DescriptionLevel desc_level = eDescriptionLevelFull; 1906 if (m_options.m_verbose) 1907 desc_level = eDescriptionLevelVerbose; 1908 1909 thread->DumpThreadPlans(&strm, desc_level, m_options.m_internal, true); 1910 return true; 1911 } 1912 1913 CommandOptions m_options; 1914 }; 1915 1916 class CommandObjectThreadPlanDiscard : public CommandObjectParsed { 1917 public: 1918 CommandObjectThreadPlanDiscard(CommandInterpreter &interpreter) 1919 : CommandObjectParsed(interpreter, "thread plan discard", 1920 "Discards thread plans up to and including the " 1921 "specified index (see 'thread plan list'.) " 1922 "Only user visible plans can be discarded.", 1923 nullptr, 1924 eCommandRequiresProcess | eCommandRequiresThread | 1925 eCommandTryTargetAPILock | 1926 eCommandProcessMustBeLaunched | 1927 eCommandProcessMustBePaused) { 1928 CommandArgumentEntry arg; 1929 CommandArgumentData plan_index_arg; 1930 1931 // Define the first (and only) variant of this arg. 1932 plan_index_arg.arg_type = eArgTypeUnsignedInteger; 1933 plan_index_arg.arg_repetition = eArgRepeatPlain; 1934 1935 // There is only one variant this argument could be; put it into the 1936 // argument entry. 1937 arg.push_back(plan_index_arg); 1938 1939 // Push the data for the first argument into the m_arguments vector. 1940 m_arguments.push_back(arg); 1941 } 1942 1943 ~CommandObjectThreadPlanDiscard() override = default; 1944 1945 bool DoExecute(Args &args, CommandReturnObject &result) override { 1946 Thread *thread = m_exe_ctx.GetThreadPtr(); 1947 if (args.GetArgumentCount() != 1) { 1948 result.AppendErrorWithFormat("Too many arguments, expected one - the " 1949 "thread plan index - but got %zu.", 1950 args.GetArgumentCount()); 1951 result.SetStatus(eReturnStatusFailed); 1952 return false; 1953 } 1954 1955 bool success; 1956 uint32_t thread_plan_idx = 1957 StringConvert::ToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success); 1958 if (!success) { 1959 result.AppendErrorWithFormat( 1960 "Invalid thread index: \"%s\" - should be unsigned int.", 1961 args.GetArgumentAtIndex(0)); 1962 result.SetStatus(eReturnStatusFailed); 1963 return false; 1964 } 1965 1966 if (thread_plan_idx == 0) { 1967 result.AppendErrorWithFormat( 1968 "You wouldn't really want me to discard the base thread plan."); 1969 result.SetStatus(eReturnStatusFailed); 1970 return false; 1971 } 1972 1973 if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx)) { 1974 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1975 return true; 1976 } else { 1977 result.AppendErrorWithFormat( 1978 "Could not find User thread plan with index %s.", 1979 args.GetArgumentAtIndex(0)); 1980 result.SetStatus(eReturnStatusFailed); 1981 return false; 1982 } 1983 } 1984 }; 1985 1986 // CommandObjectMultiwordThreadPlan 1987 1988 class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword { 1989 public: 1990 CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) 1991 : CommandObjectMultiword( 1992 interpreter, "plan", 1993 "Commands for managing thread plans that control execution.", 1994 "thread plan <subcommand> [<subcommand objects]") { 1995 LoadSubCommand( 1996 "list", CommandObjectSP(new CommandObjectThreadPlanList(interpreter))); 1997 LoadSubCommand( 1998 "discard", 1999 CommandObjectSP(new CommandObjectThreadPlanDiscard(interpreter))); 2000 } 2001 2002 ~CommandObjectMultiwordThreadPlan() override = default; 2003 }; 2004 2005 // CommandObjectMultiwordThread 2006 2007 CommandObjectMultiwordThread::CommandObjectMultiwordThread( 2008 CommandInterpreter &interpreter) 2009 : CommandObjectMultiword(interpreter, "thread", "Commands for operating on " 2010 "one or more threads in " 2011 "the current process.", 2012 "thread <subcommand> [<subcommand-options>]") { 2013 LoadSubCommand("backtrace", CommandObjectSP(new CommandObjectThreadBacktrace( 2014 interpreter))); 2015 LoadSubCommand("continue", 2016 CommandObjectSP(new CommandObjectThreadContinue(interpreter))); 2017 LoadSubCommand("list", 2018 CommandObjectSP(new CommandObjectThreadList(interpreter))); 2019 LoadSubCommand("return", 2020 CommandObjectSP(new CommandObjectThreadReturn(interpreter))); 2021 LoadSubCommand("jump", 2022 CommandObjectSP(new CommandObjectThreadJump(interpreter))); 2023 LoadSubCommand("select", 2024 CommandObjectSP(new CommandObjectThreadSelect(interpreter))); 2025 LoadSubCommand("until", 2026 CommandObjectSP(new CommandObjectThreadUntil(interpreter))); 2027 LoadSubCommand("info", 2028 CommandObjectSP(new CommandObjectThreadInfo(interpreter))); 2029 LoadSubCommand( 2030 "exception", 2031 CommandObjectSP(new CommandObjectThreadException(interpreter))); 2032 LoadSubCommand("step-in", 2033 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2034 interpreter, "thread step-in", 2035 "Source level single step, stepping into calls. Defaults " 2036 "to current thread unless specified.", 2037 nullptr, eStepTypeInto, eStepScopeSource))); 2038 2039 LoadSubCommand("step-out", 2040 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2041 interpreter, "thread step-out", 2042 "Finish executing the current stack frame and stop after " 2043 "returning. Defaults to current thread unless specified.", 2044 nullptr, eStepTypeOut, eStepScopeSource))); 2045 2046 LoadSubCommand("step-over", 2047 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2048 interpreter, "thread step-over", 2049 "Source level single step, stepping over calls. Defaults " 2050 "to current thread unless specified.", 2051 nullptr, eStepTypeOver, eStepScopeSource))); 2052 2053 LoadSubCommand("step-inst", 2054 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2055 interpreter, "thread step-inst", 2056 "Instruction level single step, stepping into calls. " 2057 "Defaults to current thread unless specified.", 2058 nullptr, eStepTypeTrace, eStepScopeInstruction))); 2059 2060 LoadSubCommand("step-inst-over", 2061 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2062 interpreter, "thread step-inst-over", 2063 "Instruction level single step, stepping over calls. " 2064 "Defaults to current thread unless specified.", 2065 nullptr, eStepTypeTraceOver, eStepScopeInstruction))); 2066 2067 LoadSubCommand( 2068 "step-scripted", 2069 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2070 interpreter, "thread step-scripted", 2071 "Step as instructed by the script class passed in the -C option. " 2072 "You can also specify a dictionary of key (-k) and value (-v) pairs " 2073 "that will be used to populate an SBStructuredData Dictionary, which " 2074 "will be passed to the constructor of the class implementing the " 2075 "scripted step. See the Python Reference for more details.", 2076 nullptr, eStepTypeScripted, eStepScopeSource))); 2077 2078 LoadSubCommand("plan", CommandObjectSP(new CommandObjectMultiwordThreadPlan( 2079 interpreter))); 2080 } 2081 2082 CommandObjectMultiwordThread::~CommandObjectMultiwordThread() = default; 2083