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, 550 LLDB_OPT_SET_1 | LLDB_OPT_SET_2, 551 LLDB_OPT_SET_1); 552 } 553 m_all_options.Append(&m_options); 554 m_all_options.Finalize(); 555 } 556 557 ~CommandObjectThreadStepWithTypeAndScope() override = default; 558 559 Options *GetOptions() override { 560 return &m_all_options; 561 } 562 563 protected: 564 bool DoExecute(Args &command, CommandReturnObject &result) override { 565 Process *process = m_exe_ctx.GetProcessPtr(); 566 bool synchronous_execution = m_interpreter.GetSynchronous(); 567 568 const uint32_t num_threads = process->GetThreadList().GetSize(); 569 Thread *thread = nullptr; 570 571 if (command.GetArgumentCount() == 0) { 572 thread = GetDefaultThread(); 573 574 if (thread == nullptr) { 575 result.AppendError("no selected thread in process"); 576 result.SetStatus(eReturnStatusFailed); 577 return false; 578 } 579 } else { 580 const char *thread_idx_cstr = command.GetArgumentAtIndex(0); 581 uint32_t step_thread_idx = 582 StringConvert::ToUInt32(thread_idx_cstr, LLDB_INVALID_INDEX32); 583 if (step_thread_idx == LLDB_INVALID_INDEX32) { 584 result.AppendErrorWithFormat("invalid thread index '%s'.\n", 585 thread_idx_cstr); 586 result.SetStatus(eReturnStatusFailed); 587 return false; 588 } 589 thread = 590 process->GetThreadList().FindThreadByIndexID(step_thread_idx).get(); 591 if (thread == nullptr) { 592 result.AppendErrorWithFormat( 593 "Thread index %u is out of range (valid values are 0 - %u).\n", 594 step_thread_idx, num_threads); 595 result.SetStatus(eReturnStatusFailed); 596 return false; 597 } 598 } 599 600 if (m_step_type == eStepTypeScripted) { 601 if (m_class_options.GetName().empty()) { 602 result.AppendErrorWithFormat("empty class name for scripted step."); 603 result.SetStatus(eReturnStatusFailed); 604 return false; 605 } else if (!GetDebugger().GetScriptInterpreter()->CheckObjectExists( 606 m_class_options.GetName().c_str())) { 607 result.AppendErrorWithFormat( 608 "class for scripted step: \"%s\" does not exist.", 609 m_class_options.GetName().c_str()); 610 result.SetStatus(eReturnStatusFailed); 611 return false; 612 } 613 } 614 615 if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER && 616 m_step_type != eStepTypeInto) { 617 result.AppendErrorWithFormat( 618 "end line option is only valid for step into"); 619 result.SetStatus(eReturnStatusFailed); 620 return false; 621 } 622 623 const bool abort_other_plans = false; 624 const lldb::RunMode stop_other_threads = m_options.m_run_mode; 625 626 // This is a bit unfortunate, but not all the commands in this command 627 // object support only while stepping, so I use the bool for them. 628 bool bool_stop_other_threads; 629 if (m_options.m_run_mode == eAllThreads) 630 bool_stop_other_threads = false; 631 else if (m_options.m_run_mode == eOnlyDuringStepping) 632 bool_stop_other_threads = 633 (m_step_type != eStepTypeOut && m_step_type != eStepTypeScripted); 634 else 635 bool_stop_other_threads = true; 636 637 ThreadPlanSP new_plan_sp; 638 Status new_plan_status; 639 640 if (m_step_type == eStepTypeInto) { 641 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 642 assert(frame != nullptr); 643 644 if (frame->HasDebugInformation()) { 645 AddressRange range; 646 SymbolContext sc = frame->GetSymbolContext(eSymbolContextEverything); 647 if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER) { 648 Status error; 649 if (!sc.GetAddressRangeFromHereToEndLine(m_options.m_end_line, range, 650 error)) { 651 result.AppendErrorWithFormat("invalid end-line option: %s.", 652 error.AsCString()); 653 result.SetStatus(eReturnStatusFailed); 654 return false; 655 } 656 } else if (m_options.m_end_line_is_block_end) { 657 Status error; 658 Block *block = frame->GetSymbolContext(eSymbolContextBlock).block; 659 if (!block) { 660 result.AppendErrorWithFormat("Could not find the current block."); 661 result.SetStatus(eReturnStatusFailed); 662 return false; 663 } 664 665 AddressRange block_range; 666 Address pc_address = frame->GetFrameCodeAddress(); 667 block->GetRangeContainingAddress(pc_address, block_range); 668 if (!block_range.GetBaseAddress().IsValid()) { 669 result.AppendErrorWithFormat( 670 "Could not find the current block address."); 671 result.SetStatus(eReturnStatusFailed); 672 return false; 673 } 674 lldb::addr_t pc_offset_in_block = 675 pc_address.GetFileAddress() - 676 block_range.GetBaseAddress().GetFileAddress(); 677 lldb::addr_t range_length = 678 block_range.GetByteSize() - pc_offset_in_block; 679 range = AddressRange(pc_address, range_length); 680 } else { 681 range = sc.line_entry.range; 682 } 683 684 new_plan_sp = thread->QueueThreadPlanForStepInRange( 685 abort_other_plans, range, 686 frame->GetSymbolContext(eSymbolContextEverything), 687 m_options.m_step_in_target.c_str(), stop_other_threads, 688 new_plan_status, m_options.m_step_in_avoid_no_debug, 689 m_options.m_step_out_avoid_no_debug); 690 691 if (new_plan_sp && !m_options.m_avoid_regexp.empty()) { 692 ThreadPlanStepInRange *step_in_range_plan = 693 static_cast<ThreadPlanStepInRange *>(new_plan_sp.get()); 694 step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str()); 695 } 696 } else 697 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( 698 false, abort_other_plans, bool_stop_other_threads, new_plan_status); 699 } else if (m_step_type == eStepTypeOver) { 700 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 701 702 if (frame->HasDebugInformation()) 703 new_plan_sp = thread->QueueThreadPlanForStepOverRange( 704 abort_other_plans, 705 frame->GetSymbolContext(eSymbolContextEverything).line_entry, 706 frame->GetSymbolContext(eSymbolContextEverything), 707 stop_other_threads, new_plan_status, 708 m_options.m_step_out_avoid_no_debug); 709 else 710 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( 711 true, abort_other_plans, bool_stop_other_threads, new_plan_status); 712 } else if (m_step_type == eStepTypeTrace) { 713 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( 714 false, abort_other_plans, bool_stop_other_threads, new_plan_status); 715 } else if (m_step_type == eStepTypeTraceOver) { 716 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( 717 true, abort_other_plans, bool_stop_other_threads, new_plan_status); 718 } else if (m_step_type == eStepTypeOut) { 719 new_plan_sp = thread->QueueThreadPlanForStepOut( 720 abort_other_plans, nullptr, false, bool_stop_other_threads, eVoteYes, 721 eVoteNoOpinion, thread->GetSelectedFrameIndex(), new_plan_status, 722 m_options.m_step_out_avoid_no_debug); 723 } else if (m_step_type == eStepTypeScripted) { 724 new_plan_sp = thread->QueueThreadPlanForStepScripted( 725 abort_other_plans, m_class_options.GetName().c_str(), 726 m_class_options.GetStructuredData(), 727 bool_stop_other_threads, new_plan_status); 728 } else { 729 result.AppendError("step type is not supported"); 730 result.SetStatus(eReturnStatusFailed); 731 return false; 732 } 733 734 // If we got a new plan, then set it to be a master plan (User level Plans 735 // should be master plans so that they can be interruptible). Then resume 736 // the process. 737 738 if (new_plan_sp) { 739 new_plan_sp->SetIsMasterPlan(true); 740 new_plan_sp->SetOkayToDiscard(false); 741 742 if (m_options.m_step_count > 1) { 743 if (!new_plan_sp->SetIterationCount(m_options.m_step_count)) { 744 result.AppendWarning( 745 "step operation does not support iteration count."); 746 } 747 } 748 749 process->GetThreadList().SetSelectedThreadByID(thread->GetID()); 750 751 const uint32_t iohandler_id = process->GetIOHandlerID(); 752 753 StreamString stream; 754 Status error; 755 if (synchronous_execution) 756 error = process->ResumeSynchronous(&stream); 757 else 758 error = process->Resume(); 759 760 if (!error.Success()) { 761 result.AppendMessage(error.AsCString()); 762 result.SetStatus(eReturnStatusFailed); 763 return false; 764 } 765 766 // There is a race condition where this thread will return up the call 767 // stack to the main command handler and show an (lldb) prompt before 768 // HandlePrivateEvent (from PrivateStateThread) has a chance to call 769 // PushProcessIOHandler(). 770 process->SyncIOHandler(iohandler_id, std::chrono::seconds(2)); 771 772 if (synchronous_execution) { 773 // If any state changed events had anything to say, add that to the 774 // result 775 if (stream.GetSize() > 0) 776 result.AppendMessage(stream.GetString()); 777 778 process->GetThreadList().SetSelectedThreadByID(thread->GetID()); 779 result.SetDidChangeProcessState(true); 780 result.SetStatus(eReturnStatusSuccessFinishNoResult); 781 } else { 782 result.SetStatus(eReturnStatusSuccessContinuingNoResult); 783 } 784 } else { 785 result.SetError(new_plan_status); 786 result.SetStatus(eReturnStatusFailed); 787 } 788 return result.Succeeded(); 789 } 790 791 protected: 792 StepType m_step_type; 793 StepScope m_step_scope; 794 ThreadStepScopeOptionGroup m_options; 795 OptionGroupPythonClassWithDict m_class_options; 796 OptionGroupOptions m_all_options; 797 }; 798 799 // CommandObjectThreadContinue 800 801 class CommandObjectThreadContinue : public CommandObjectParsed { 802 public: 803 CommandObjectThreadContinue(CommandInterpreter &interpreter) 804 : CommandObjectParsed( 805 interpreter, "thread continue", 806 "Continue execution of the current target process. One " 807 "or more threads may be specified, by default all " 808 "threads continue.", 809 nullptr, 810 eCommandRequiresThread | eCommandTryTargetAPILock | 811 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { 812 CommandArgumentEntry arg; 813 CommandArgumentData thread_idx_arg; 814 815 // Define the first (and only) variant of this arg. 816 thread_idx_arg.arg_type = eArgTypeThreadIndex; 817 thread_idx_arg.arg_repetition = eArgRepeatPlus; 818 819 // There is only one variant this argument could be; put it into the 820 // argument entry. 821 arg.push_back(thread_idx_arg); 822 823 // Push the data for the first argument into the m_arguments vector. 824 m_arguments.push_back(arg); 825 } 826 827 ~CommandObjectThreadContinue() override = default; 828 829 bool DoExecute(Args &command, CommandReturnObject &result) override { 830 bool synchronous_execution = m_interpreter.GetSynchronous(); 831 832 Process *process = m_exe_ctx.GetProcessPtr(); 833 if (process == nullptr) { 834 result.AppendError("no process exists. Cannot continue"); 835 result.SetStatus(eReturnStatusFailed); 836 return false; 837 } 838 839 StateType state = process->GetState(); 840 if ((state == eStateCrashed) || (state == eStateStopped) || 841 (state == eStateSuspended)) { 842 const size_t argc = command.GetArgumentCount(); 843 if (argc > 0) { 844 // These two lines appear at the beginning of both blocks in this 845 // if..else, but that is because we need to release the lock before 846 // calling process->Resume below. 847 std::lock_guard<std::recursive_mutex> guard( 848 process->GetThreadList().GetMutex()); 849 const uint32_t num_threads = process->GetThreadList().GetSize(); 850 std::vector<Thread *> resume_threads; 851 for (auto &entry : command.entries()) { 852 uint32_t thread_idx; 853 if (entry.ref().getAsInteger(0, thread_idx)) { 854 result.AppendErrorWithFormat( 855 "invalid thread index argument: \"%s\".\n", entry.c_str()); 856 result.SetStatus(eReturnStatusFailed); 857 return false; 858 } 859 Thread *thread = 860 process->GetThreadList().FindThreadByIndexID(thread_idx).get(); 861 862 if (thread) { 863 resume_threads.push_back(thread); 864 } else { 865 result.AppendErrorWithFormat("invalid thread index %u.\n", 866 thread_idx); 867 result.SetStatus(eReturnStatusFailed); 868 return false; 869 } 870 } 871 872 if (resume_threads.empty()) { 873 result.AppendError("no valid thread indexes were specified"); 874 result.SetStatus(eReturnStatusFailed); 875 return false; 876 } else { 877 if (resume_threads.size() == 1) 878 result.AppendMessageWithFormat("Resuming thread: "); 879 else 880 result.AppendMessageWithFormat("Resuming threads: "); 881 882 for (uint32_t idx = 0; idx < num_threads; ++idx) { 883 Thread *thread = 884 process->GetThreadList().GetThreadAtIndex(idx).get(); 885 std::vector<Thread *>::iterator this_thread_pos = 886 find(resume_threads.begin(), resume_threads.end(), thread); 887 888 if (this_thread_pos != resume_threads.end()) { 889 resume_threads.erase(this_thread_pos); 890 if (!resume_threads.empty()) 891 result.AppendMessageWithFormat("%u, ", thread->GetIndexID()); 892 else 893 result.AppendMessageWithFormat("%u ", thread->GetIndexID()); 894 895 const bool override_suspend = true; 896 thread->SetResumeState(eStateRunning, override_suspend); 897 } else { 898 thread->SetResumeState(eStateSuspended); 899 } 900 } 901 result.AppendMessageWithFormat("in process %" PRIu64 "\n", 902 process->GetID()); 903 } 904 } else { 905 // These two lines appear at the beginning of both blocks in this 906 // if..else, but that is because we need to release the lock before 907 // calling process->Resume below. 908 std::lock_guard<std::recursive_mutex> guard( 909 process->GetThreadList().GetMutex()); 910 const uint32_t num_threads = process->GetThreadList().GetSize(); 911 Thread *current_thread = GetDefaultThread(); 912 if (current_thread == nullptr) { 913 result.AppendError("the process doesn't have a current thread"); 914 result.SetStatus(eReturnStatusFailed); 915 return false; 916 } 917 // Set the actions that the threads should each take when resuming 918 for (uint32_t idx = 0; idx < num_threads; ++idx) { 919 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 920 if (thread == current_thread) { 921 result.AppendMessageWithFormat("Resuming thread 0x%4.4" PRIx64 922 " in process %" PRIu64 "\n", 923 thread->GetID(), process->GetID()); 924 const bool override_suspend = true; 925 thread->SetResumeState(eStateRunning, override_suspend); 926 } else { 927 thread->SetResumeState(eStateSuspended); 928 } 929 } 930 } 931 932 StreamString stream; 933 Status error; 934 if (synchronous_execution) 935 error = process->ResumeSynchronous(&stream); 936 else 937 error = process->Resume(); 938 939 // We should not be holding the thread list lock when we do this. 940 if (error.Success()) { 941 result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", 942 process->GetID()); 943 if (synchronous_execution) { 944 // If any state changed events had anything to say, add that to the 945 // result 946 if (stream.GetSize() > 0) 947 result.AppendMessage(stream.GetString()); 948 949 result.SetDidChangeProcessState(true); 950 result.SetStatus(eReturnStatusSuccessFinishNoResult); 951 } else { 952 result.SetStatus(eReturnStatusSuccessContinuingNoResult); 953 } 954 } else { 955 result.AppendErrorWithFormat("Failed to resume process: %s\n", 956 error.AsCString()); 957 result.SetStatus(eReturnStatusFailed); 958 } 959 } else { 960 result.AppendErrorWithFormat( 961 "Process cannot be continued from its current state (%s).\n", 962 StateAsCString(state)); 963 result.SetStatus(eReturnStatusFailed); 964 } 965 966 return result.Succeeded(); 967 } 968 }; 969 970 // CommandObjectThreadUntil 971 972 static constexpr OptionEnumValueElement g_duo_running_mode[] = { 973 {eOnlyThisThread, "this-thread", "Run only this thread"}, 974 {eAllThreads, "all-threads", "Run all threads"} }; 975 976 static constexpr OptionEnumValues DuoRunningModes() { 977 return OptionEnumValues(g_duo_running_mode); 978 } 979 980 #define LLDB_OPTIONS_thread_until 981 #include "CommandOptions.inc" 982 983 class CommandObjectThreadUntil : public CommandObjectParsed { 984 public: 985 class CommandOptions : public Options { 986 public: 987 uint32_t m_thread_idx; 988 uint32_t m_frame_idx; 989 990 CommandOptions() 991 : Options(), m_thread_idx(LLDB_INVALID_THREAD_ID), 992 m_frame_idx(LLDB_INVALID_FRAME_ID) { 993 // Keep default values of all options in one place: OptionParsingStarting 994 // () 995 OptionParsingStarting(nullptr); 996 } 997 998 ~CommandOptions() override = default; 999 1000 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1001 ExecutionContext *execution_context) override { 1002 Status error; 1003 const int short_option = m_getopt_table[option_idx].val; 1004 1005 switch (short_option) { 1006 case 'a': { 1007 lldb::addr_t tmp_addr = OptionArgParser::ToAddress( 1008 execution_context, option_arg, LLDB_INVALID_ADDRESS, &error); 1009 if (error.Success()) 1010 m_until_addrs.push_back(tmp_addr); 1011 } break; 1012 case 't': 1013 if (option_arg.getAsInteger(0, m_thread_idx)) { 1014 m_thread_idx = LLDB_INVALID_INDEX32; 1015 error.SetErrorStringWithFormat("invalid thread index '%s'", 1016 option_arg.str().c_str()); 1017 } 1018 break; 1019 case 'f': 1020 if (option_arg.getAsInteger(0, m_frame_idx)) { 1021 m_frame_idx = LLDB_INVALID_FRAME_ID; 1022 error.SetErrorStringWithFormat("invalid frame index '%s'", 1023 option_arg.str().c_str()); 1024 } 1025 break; 1026 case 'm': { 1027 auto enum_values = GetDefinitions()[option_idx].enum_values; 1028 lldb::RunMode run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum( 1029 option_arg, enum_values, eOnlyDuringStepping, error); 1030 1031 if (error.Success()) { 1032 if (run_mode == eAllThreads) 1033 m_stop_others = false; 1034 else 1035 m_stop_others = true; 1036 } 1037 } break; 1038 default: 1039 llvm_unreachable("Unimplemented option"); 1040 } 1041 return error; 1042 } 1043 1044 void OptionParsingStarting(ExecutionContext *execution_context) override { 1045 m_thread_idx = LLDB_INVALID_THREAD_ID; 1046 m_frame_idx = 0; 1047 m_stop_others = false; 1048 m_until_addrs.clear(); 1049 } 1050 1051 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1052 return llvm::makeArrayRef(g_thread_until_options); 1053 } 1054 1055 uint32_t m_step_thread_idx; 1056 bool m_stop_others; 1057 std::vector<lldb::addr_t> m_until_addrs; 1058 1059 // Instance variables to hold the values for command options. 1060 }; 1061 1062 CommandObjectThreadUntil(CommandInterpreter &interpreter) 1063 : CommandObjectParsed( 1064 interpreter, "thread until", 1065 "Continue until a line number or address is reached by the " 1066 "current or specified thread. Stops when returning from " 1067 "the current function as a safety measure. " 1068 "The target line number(s) are given as arguments, and if more than one" 1069 " is provided, stepping will stop when the first one is hit.", 1070 nullptr, 1071 eCommandRequiresThread | eCommandTryTargetAPILock | 1072 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 1073 m_options() { 1074 CommandArgumentEntry arg; 1075 CommandArgumentData line_num_arg; 1076 1077 // Define the first (and only) variant of this arg. 1078 line_num_arg.arg_type = eArgTypeLineNum; 1079 line_num_arg.arg_repetition = eArgRepeatPlain; 1080 1081 // There is only one variant this argument could be; put it into the 1082 // argument entry. 1083 arg.push_back(line_num_arg); 1084 1085 // Push the data for the first argument into the m_arguments vector. 1086 m_arguments.push_back(arg); 1087 } 1088 1089 ~CommandObjectThreadUntil() override = default; 1090 1091 Options *GetOptions() override { return &m_options; } 1092 1093 protected: 1094 bool DoExecute(Args &command, CommandReturnObject &result) override { 1095 bool synchronous_execution = m_interpreter.GetSynchronous(); 1096 1097 Target *target = &GetSelectedTarget(); 1098 1099 Process *process = m_exe_ctx.GetProcessPtr(); 1100 if (process == nullptr) { 1101 result.AppendError("need a valid process to step"); 1102 result.SetStatus(eReturnStatusFailed); 1103 } else { 1104 Thread *thread = nullptr; 1105 std::vector<uint32_t> line_numbers; 1106 1107 if (command.GetArgumentCount() >= 1) { 1108 size_t num_args = command.GetArgumentCount(); 1109 for (size_t i = 0; i < num_args; i++) { 1110 uint32_t line_number; 1111 line_number = StringConvert::ToUInt32(command.GetArgumentAtIndex(i), 1112 UINT32_MAX); 1113 if (line_number == UINT32_MAX) { 1114 result.AppendErrorWithFormat("invalid line number: '%s'.\n", 1115 command.GetArgumentAtIndex(i)); 1116 result.SetStatus(eReturnStatusFailed); 1117 return false; 1118 } else 1119 line_numbers.push_back(line_number); 1120 } 1121 } else if (m_options.m_until_addrs.empty()) { 1122 result.AppendErrorWithFormat("No line number or address provided:\n%s", 1123 GetSyntax().str().c_str()); 1124 result.SetStatus(eReturnStatusFailed); 1125 return false; 1126 } 1127 1128 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) { 1129 thread = GetDefaultThread(); 1130 } else { 1131 thread = process->GetThreadList() 1132 .FindThreadByIndexID(m_options.m_thread_idx) 1133 .get(); 1134 } 1135 1136 if (thread == nullptr) { 1137 const uint32_t num_threads = process->GetThreadList().GetSize(); 1138 result.AppendErrorWithFormat( 1139 "Thread index %u is out of range (valid values are 0 - %u).\n", 1140 m_options.m_thread_idx, num_threads); 1141 result.SetStatus(eReturnStatusFailed); 1142 return false; 1143 } 1144 1145 const bool abort_other_plans = false; 1146 1147 StackFrame *frame = 1148 thread->GetStackFrameAtIndex(m_options.m_frame_idx).get(); 1149 if (frame == nullptr) { 1150 result.AppendErrorWithFormat( 1151 "Frame index %u is out of range for thread %u.\n", 1152 m_options.m_frame_idx, m_options.m_thread_idx); 1153 result.SetStatus(eReturnStatusFailed); 1154 return false; 1155 } 1156 1157 ThreadPlanSP new_plan_sp; 1158 Status new_plan_status; 1159 1160 if (frame->HasDebugInformation()) { 1161 // Finally we got here... Translate the given line number to a bunch 1162 // of addresses: 1163 SymbolContext sc(frame->GetSymbolContext(eSymbolContextCompUnit)); 1164 LineTable *line_table = nullptr; 1165 if (sc.comp_unit) 1166 line_table = sc.comp_unit->GetLineTable(); 1167 1168 if (line_table == nullptr) { 1169 result.AppendErrorWithFormat("Failed to resolve the line table for " 1170 "frame %u of thread index %u.\n", 1171 m_options.m_frame_idx, 1172 m_options.m_thread_idx); 1173 result.SetStatus(eReturnStatusFailed); 1174 return false; 1175 } 1176 1177 LineEntry function_start; 1178 uint32_t index_ptr = 0, end_ptr; 1179 std::vector<addr_t> address_list; 1180 1181 // Find the beginning & end index of the 1182 AddressRange fun_addr_range = sc.function->GetAddressRange(); 1183 Address fun_start_addr = fun_addr_range.GetBaseAddress(); 1184 line_table->FindLineEntryByAddress(fun_start_addr, function_start, 1185 &index_ptr); 1186 1187 Address fun_end_addr(fun_start_addr.GetSection(), 1188 fun_start_addr.GetOffset() + 1189 fun_addr_range.GetByteSize()); 1190 1191 bool all_in_function = true; 1192 1193 line_table->FindLineEntryByAddress(fun_end_addr, function_start, 1194 &end_ptr); 1195 1196 for (uint32_t line_number : line_numbers) { 1197 uint32_t start_idx_ptr = index_ptr; 1198 while (start_idx_ptr <= end_ptr) { 1199 LineEntry line_entry; 1200 const bool exact = false; 1201 start_idx_ptr = sc.comp_unit->FindLineEntry( 1202 start_idx_ptr, line_number, sc.comp_unit, exact, &line_entry); 1203 if (start_idx_ptr == UINT32_MAX) 1204 break; 1205 1206 addr_t address = 1207 line_entry.range.GetBaseAddress().GetLoadAddress(target); 1208 if (address != LLDB_INVALID_ADDRESS) { 1209 if (fun_addr_range.ContainsLoadAddress(address, target)) 1210 address_list.push_back(address); 1211 else 1212 all_in_function = false; 1213 } 1214 start_idx_ptr++; 1215 } 1216 } 1217 1218 for (lldb::addr_t address : m_options.m_until_addrs) { 1219 if (fun_addr_range.ContainsLoadAddress(address, target)) 1220 address_list.push_back(address); 1221 else 1222 all_in_function = false; 1223 } 1224 1225 if (address_list.empty()) { 1226 if (all_in_function) 1227 result.AppendErrorWithFormat( 1228 "No line entries matching until target.\n"); 1229 else 1230 result.AppendErrorWithFormat( 1231 "Until target outside of the current function.\n"); 1232 1233 result.SetStatus(eReturnStatusFailed); 1234 return false; 1235 } 1236 1237 new_plan_sp = thread->QueueThreadPlanForStepUntil( 1238 abort_other_plans, &address_list.front(), address_list.size(), 1239 m_options.m_stop_others, m_options.m_frame_idx, new_plan_status); 1240 if (new_plan_sp) { 1241 // User level plans should be master plans so they can be interrupted 1242 // (e.g. by hitting a breakpoint) and other plans executed by the 1243 // user (stepping around the breakpoint) and then a "continue" will 1244 // resume the original plan. 1245 new_plan_sp->SetIsMasterPlan(true); 1246 new_plan_sp->SetOkayToDiscard(false); 1247 } else { 1248 result.SetError(new_plan_status); 1249 result.SetStatus(eReturnStatusFailed); 1250 return false; 1251 } 1252 } else { 1253 result.AppendErrorWithFormat( 1254 "Frame index %u of thread %u has no debug information.\n", 1255 m_options.m_frame_idx, m_options.m_thread_idx); 1256 result.SetStatus(eReturnStatusFailed); 1257 return false; 1258 } 1259 1260 process->GetThreadList().SetSelectedThreadByID(m_options.m_thread_idx); 1261 1262 StreamString stream; 1263 Status error; 1264 if (synchronous_execution) 1265 error = process->ResumeSynchronous(&stream); 1266 else 1267 error = process->Resume(); 1268 1269 if (error.Success()) { 1270 result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", 1271 process->GetID()); 1272 if (synchronous_execution) { 1273 // If any state changed events had anything to say, add that to the 1274 // result 1275 if (stream.GetSize() > 0) 1276 result.AppendMessage(stream.GetString()); 1277 1278 result.SetDidChangeProcessState(true); 1279 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1280 } else { 1281 result.SetStatus(eReturnStatusSuccessContinuingNoResult); 1282 } 1283 } else { 1284 result.AppendErrorWithFormat("Failed to resume process: %s.\n", 1285 error.AsCString()); 1286 result.SetStatus(eReturnStatusFailed); 1287 } 1288 } 1289 return result.Succeeded(); 1290 } 1291 1292 CommandOptions m_options; 1293 }; 1294 1295 // CommandObjectThreadSelect 1296 1297 class CommandObjectThreadSelect : public CommandObjectParsed { 1298 public: 1299 CommandObjectThreadSelect(CommandInterpreter &interpreter) 1300 : CommandObjectParsed(interpreter, "thread select", 1301 "Change the currently selected thread.", nullptr, 1302 eCommandRequiresProcess | eCommandTryTargetAPILock | 1303 eCommandProcessMustBeLaunched | 1304 eCommandProcessMustBePaused) { 1305 CommandArgumentEntry arg; 1306 CommandArgumentData thread_idx_arg; 1307 1308 // Define the first (and only) variant of this arg. 1309 thread_idx_arg.arg_type = eArgTypeThreadIndex; 1310 thread_idx_arg.arg_repetition = eArgRepeatPlain; 1311 1312 // There is only one variant this argument could be; put it into the 1313 // argument entry. 1314 arg.push_back(thread_idx_arg); 1315 1316 // Push the data for the first argument into the m_arguments vector. 1317 m_arguments.push_back(arg); 1318 } 1319 1320 ~CommandObjectThreadSelect() override = default; 1321 1322 protected: 1323 bool DoExecute(Args &command, CommandReturnObject &result) override { 1324 Process *process = m_exe_ctx.GetProcessPtr(); 1325 if (process == nullptr) { 1326 result.AppendError("no process"); 1327 result.SetStatus(eReturnStatusFailed); 1328 return false; 1329 } else if (command.GetArgumentCount() != 1) { 1330 result.AppendErrorWithFormat( 1331 "'%s' takes exactly one thread index argument:\nUsage: %s\n", 1332 m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1333 result.SetStatus(eReturnStatusFailed); 1334 return false; 1335 } 1336 1337 uint32_t index_id = 1338 StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0); 1339 1340 Thread *new_thread = 1341 process->GetThreadList().FindThreadByIndexID(index_id).get(); 1342 if (new_thread == nullptr) { 1343 result.AppendErrorWithFormat("invalid thread #%s.\n", 1344 command.GetArgumentAtIndex(0)); 1345 result.SetStatus(eReturnStatusFailed); 1346 return false; 1347 } 1348 1349 process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true); 1350 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1351 1352 return result.Succeeded(); 1353 } 1354 }; 1355 1356 // CommandObjectThreadList 1357 1358 class CommandObjectThreadList : public CommandObjectParsed { 1359 public: 1360 CommandObjectThreadList(CommandInterpreter &interpreter) 1361 : CommandObjectParsed( 1362 interpreter, "thread list", 1363 "Show a summary of each thread in the current target process. " 1364 "Use 'settings set thread-format' to customize the individual " 1365 "thread listings.", 1366 "thread list", 1367 eCommandRequiresProcess | eCommandTryTargetAPILock | 1368 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 1369 1370 ~CommandObjectThreadList() override = default; 1371 1372 protected: 1373 bool DoExecute(Args &command, CommandReturnObject &result) override { 1374 Stream &strm = result.GetOutputStream(); 1375 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1376 Process *process = m_exe_ctx.GetProcessPtr(); 1377 const bool only_threads_with_stop_reason = false; 1378 const uint32_t start_frame = 0; 1379 const uint32_t num_frames = 0; 1380 const uint32_t num_frames_with_source = 0; 1381 process->GetStatus(strm); 1382 process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, 1383 num_frames, num_frames_with_source, false); 1384 return result.Succeeded(); 1385 } 1386 }; 1387 1388 // CommandObjectThreadInfo 1389 #define LLDB_OPTIONS_thread_info 1390 #include "CommandOptions.inc" 1391 1392 class CommandObjectThreadInfo : public CommandObjectIterateOverThreads { 1393 public: 1394 class CommandOptions : public Options { 1395 public: 1396 CommandOptions() : Options() { OptionParsingStarting(nullptr); } 1397 1398 ~CommandOptions() override = default; 1399 1400 void OptionParsingStarting(ExecutionContext *execution_context) override { 1401 m_json_thread = false; 1402 m_json_stopinfo = false; 1403 } 1404 1405 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1406 ExecutionContext *execution_context) override { 1407 const int short_option = m_getopt_table[option_idx].val; 1408 Status error; 1409 1410 switch (short_option) { 1411 case 'j': 1412 m_json_thread = true; 1413 break; 1414 1415 case 's': 1416 m_json_stopinfo = true; 1417 break; 1418 1419 default: 1420 llvm_unreachable("Unimplemented option"); 1421 } 1422 return error; 1423 } 1424 1425 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1426 return llvm::makeArrayRef(g_thread_info_options); 1427 } 1428 1429 bool m_json_thread; 1430 bool m_json_stopinfo; 1431 }; 1432 1433 CommandObjectThreadInfo(CommandInterpreter &interpreter) 1434 : CommandObjectIterateOverThreads( 1435 interpreter, "thread info", "Show an extended summary of one or " 1436 "more threads. Defaults to the " 1437 "current thread.", 1438 "thread info", 1439 eCommandRequiresProcess | eCommandTryTargetAPILock | 1440 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 1441 m_options() { 1442 m_add_return = false; 1443 } 1444 1445 ~CommandObjectThreadInfo() override = default; 1446 1447 Options *GetOptions() override { return &m_options; } 1448 1449 bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { 1450 ThreadSP thread_sp = 1451 m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); 1452 if (!thread_sp) { 1453 result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n", 1454 tid); 1455 result.SetStatus(eReturnStatusFailed); 1456 return false; 1457 } 1458 1459 Thread *thread = thread_sp.get(); 1460 1461 Stream &strm = result.GetOutputStream(); 1462 if (!thread->GetDescription(strm, eDescriptionLevelFull, 1463 m_options.m_json_thread, 1464 m_options.m_json_stopinfo)) { 1465 result.AppendErrorWithFormat("error displaying info for thread: \"%d\"\n", 1466 thread->GetIndexID()); 1467 result.SetStatus(eReturnStatusFailed); 1468 return false; 1469 } 1470 return true; 1471 } 1472 1473 CommandOptions m_options; 1474 }; 1475 1476 // CommandObjectThreadException 1477 1478 class CommandObjectThreadException : public CommandObjectIterateOverThreads { 1479 public: 1480 CommandObjectThreadException(CommandInterpreter &interpreter) 1481 : CommandObjectIterateOverThreads( 1482 interpreter, "thread exception", 1483 "Display the current exception object for a thread. Defaults to " 1484 "the current thread.", 1485 "thread exception", 1486 eCommandRequiresProcess | eCommandTryTargetAPILock | 1487 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 1488 1489 ~CommandObjectThreadException() override = default; 1490 1491 bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { 1492 ThreadSP thread_sp = 1493 m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); 1494 if (!thread_sp) { 1495 result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n", 1496 tid); 1497 result.SetStatus(eReturnStatusFailed); 1498 return false; 1499 } 1500 1501 Stream &strm = result.GetOutputStream(); 1502 ValueObjectSP exception_object_sp = thread_sp->GetCurrentException(); 1503 if (exception_object_sp) { 1504 exception_object_sp->Dump(strm); 1505 } 1506 1507 ThreadSP exception_thread_sp = thread_sp->GetCurrentExceptionBacktrace(); 1508 if (exception_thread_sp && exception_thread_sp->IsValid()) { 1509 const uint32_t num_frames_with_source = 0; 1510 const bool stop_format = false; 1511 exception_thread_sp->GetStatus(strm, 0, UINT32_MAX, 1512 num_frames_with_source, stop_format); 1513 } 1514 1515 return true; 1516 } 1517 }; 1518 1519 // CommandObjectThreadReturn 1520 #define LLDB_OPTIONS_thread_return 1521 #include "CommandOptions.inc" 1522 1523 class CommandObjectThreadReturn : public CommandObjectRaw { 1524 public: 1525 class CommandOptions : public Options { 1526 public: 1527 CommandOptions() : Options(), m_from_expression(false) { 1528 // Keep default values of all options in one place: OptionParsingStarting 1529 // () 1530 OptionParsingStarting(nullptr); 1531 } 1532 1533 ~CommandOptions() override = default; 1534 1535 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1536 ExecutionContext *execution_context) override { 1537 Status error; 1538 const int short_option = m_getopt_table[option_idx].val; 1539 1540 switch (short_option) { 1541 case 'x': { 1542 bool success; 1543 bool tmp_value = 1544 OptionArgParser::ToBoolean(option_arg, false, &success); 1545 if (success) 1546 m_from_expression = tmp_value; 1547 else { 1548 error.SetErrorStringWithFormat( 1549 "invalid boolean value '%s' for 'x' option", 1550 option_arg.str().c_str()); 1551 } 1552 } break; 1553 default: 1554 llvm_unreachable("Unimplemented option"); 1555 } 1556 return error; 1557 } 1558 1559 void OptionParsingStarting(ExecutionContext *execution_context) override { 1560 m_from_expression = false; 1561 } 1562 1563 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1564 return llvm::makeArrayRef(g_thread_return_options); 1565 } 1566 1567 bool m_from_expression; 1568 1569 // Instance variables to hold the values for command options. 1570 }; 1571 1572 CommandObjectThreadReturn(CommandInterpreter &interpreter) 1573 : CommandObjectRaw(interpreter, "thread return", 1574 "Prematurely return from a stack frame, " 1575 "short-circuiting execution of newer frames " 1576 "and optionally yielding a specified value. Defaults " 1577 "to the exiting the current stack " 1578 "frame.", 1579 "thread return", 1580 eCommandRequiresFrame | eCommandTryTargetAPILock | 1581 eCommandProcessMustBeLaunched | 1582 eCommandProcessMustBePaused), 1583 m_options() { 1584 CommandArgumentEntry arg; 1585 CommandArgumentData expression_arg; 1586 1587 // Define the first (and only) variant of this arg. 1588 expression_arg.arg_type = eArgTypeExpression; 1589 expression_arg.arg_repetition = eArgRepeatOptional; 1590 1591 // There is only one variant this argument could be; put it into the 1592 // argument entry. 1593 arg.push_back(expression_arg); 1594 1595 // Push the data for the first argument into the m_arguments vector. 1596 m_arguments.push_back(arg); 1597 } 1598 1599 ~CommandObjectThreadReturn() override = default; 1600 1601 Options *GetOptions() override { return &m_options; } 1602 1603 protected: 1604 bool DoExecute(llvm::StringRef command, 1605 CommandReturnObject &result) override { 1606 // I am going to handle this by hand, because I don't want you to have to 1607 // say: 1608 // "thread return -- -5". 1609 if (command.startswith("-x")) { 1610 if (command.size() != 2U) 1611 result.AppendWarning("Return values ignored when returning from user " 1612 "called expressions"); 1613 1614 Thread *thread = m_exe_ctx.GetThreadPtr(); 1615 Status error; 1616 error = thread->UnwindInnermostExpression(); 1617 if (!error.Success()) { 1618 result.AppendErrorWithFormat("Unwinding expression failed - %s.", 1619 error.AsCString()); 1620 result.SetStatus(eReturnStatusFailed); 1621 } else { 1622 bool success = 1623 thread->SetSelectedFrameByIndexNoisily(0, result.GetOutputStream()); 1624 if (success) { 1625 m_exe_ctx.SetFrameSP(thread->GetSelectedFrame()); 1626 result.SetStatus(eReturnStatusSuccessFinishResult); 1627 } else { 1628 result.AppendErrorWithFormat( 1629 "Could not select 0th frame after unwinding expression."); 1630 result.SetStatus(eReturnStatusFailed); 1631 } 1632 } 1633 return result.Succeeded(); 1634 } 1635 1636 ValueObjectSP return_valobj_sp; 1637 1638 StackFrameSP frame_sp = m_exe_ctx.GetFrameSP(); 1639 uint32_t frame_idx = frame_sp->GetFrameIndex(); 1640 1641 if (frame_sp->IsInlined()) { 1642 result.AppendError("Don't know how to return from inlined frames."); 1643 result.SetStatus(eReturnStatusFailed); 1644 return false; 1645 } 1646 1647 if (!command.empty()) { 1648 Target *target = m_exe_ctx.GetTargetPtr(); 1649 EvaluateExpressionOptions options; 1650 1651 options.SetUnwindOnError(true); 1652 options.SetUseDynamic(eNoDynamicValues); 1653 1654 ExpressionResults exe_results = eExpressionSetupError; 1655 exe_results = target->EvaluateExpression(command, frame_sp.get(), 1656 return_valobj_sp, options); 1657 if (exe_results != eExpressionCompleted) { 1658 if (return_valobj_sp) 1659 result.AppendErrorWithFormat( 1660 "Error evaluating result expression: %s", 1661 return_valobj_sp->GetError().AsCString()); 1662 else 1663 result.AppendErrorWithFormat( 1664 "Unknown error evaluating result expression."); 1665 result.SetStatus(eReturnStatusFailed); 1666 return false; 1667 } 1668 } 1669 1670 Status error; 1671 ThreadSP thread_sp = m_exe_ctx.GetThreadSP(); 1672 const bool broadcast = true; 1673 error = thread_sp->ReturnFromFrame(frame_sp, return_valobj_sp, broadcast); 1674 if (!error.Success()) { 1675 result.AppendErrorWithFormat( 1676 "Error returning from frame %d of thread %d: %s.", frame_idx, 1677 thread_sp->GetIndexID(), error.AsCString()); 1678 result.SetStatus(eReturnStatusFailed); 1679 return false; 1680 } 1681 1682 result.SetStatus(eReturnStatusSuccessFinishResult); 1683 return true; 1684 } 1685 1686 CommandOptions m_options; 1687 }; 1688 1689 // CommandObjectThreadJump 1690 #define LLDB_OPTIONS_thread_jump 1691 #include "CommandOptions.inc" 1692 1693 class CommandObjectThreadJump : public CommandObjectParsed { 1694 public: 1695 class CommandOptions : public Options { 1696 public: 1697 CommandOptions() : Options() { OptionParsingStarting(nullptr); } 1698 1699 ~CommandOptions() override = default; 1700 1701 void OptionParsingStarting(ExecutionContext *execution_context) override { 1702 m_filenames.Clear(); 1703 m_line_num = 0; 1704 m_line_offset = 0; 1705 m_load_addr = LLDB_INVALID_ADDRESS; 1706 m_force = false; 1707 } 1708 1709 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1710 ExecutionContext *execution_context) override { 1711 const int short_option = m_getopt_table[option_idx].val; 1712 Status error; 1713 1714 switch (short_option) { 1715 case 'f': 1716 m_filenames.AppendIfUnique(FileSpec(option_arg)); 1717 if (m_filenames.GetSize() > 1) 1718 return Status("only one source file expected."); 1719 break; 1720 case 'l': 1721 if (option_arg.getAsInteger(0, m_line_num)) 1722 return Status("invalid line number: '%s'.", option_arg.str().c_str()); 1723 break; 1724 case 'b': 1725 if (option_arg.getAsInteger(0, m_line_offset)) 1726 return Status("invalid line offset: '%s'.", option_arg.str().c_str()); 1727 break; 1728 case 'a': 1729 m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg, 1730 LLDB_INVALID_ADDRESS, &error); 1731 break; 1732 case 'r': 1733 m_force = true; 1734 break; 1735 default: 1736 llvm_unreachable("Unimplemented option"); 1737 } 1738 return error; 1739 } 1740 1741 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1742 return llvm::makeArrayRef(g_thread_jump_options); 1743 } 1744 1745 FileSpecList m_filenames; 1746 uint32_t m_line_num; 1747 int32_t m_line_offset; 1748 lldb::addr_t m_load_addr; 1749 bool m_force; 1750 }; 1751 1752 CommandObjectThreadJump(CommandInterpreter &interpreter) 1753 : CommandObjectParsed( 1754 interpreter, "thread jump", 1755 "Sets the program counter to a new address.", "thread jump", 1756 eCommandRequiresFrame | eCommandTryTargetAPILock | 1757 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), 1758 m_options() {} 1759 1760 ~CommandObjectThreadJump() override = default; 1761 1762 Options *GetOptions() override { return &m_options; } 1763 1764 protected: 1765 bool DoExecute(Args &args, CommandReturnObject &result) override { 1766 RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); 1767 StackFrame *frame = m_exe_ctx.GetFramePtr(); 1768 Thread *thread = m_exe_ctx.GetThreadPtr(); 1769 Target *target = m_exe_ctx.GetTargetPtr(); 1770 const SymbolContext &sym_ctx = 1771 frame->GetSymbolContext(eSymbolContextLineEntry); 1772 1773 if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) { 1774 // Use this address directly. 1775 Address dest = Address(m_options.m_load_addr); 1776 1777 lldb::addr_t callAddr = dest.GetCallableLoadAddress(target); 1778 if (callAddr == LLDB_INVALID_ADDRESS) { 1779 result.AppendErrorWithFormat("Invalid destination address."); 1780 result.SetStatus(eReturnStatusFailed); 1781 return false; 1782 } 1783 1784 if (!reg_ctx->SetPC(callAddr)) { 1785 result.AppendErrorWithFormat("Error changing PC value for thread %d.", 1786 thread->GetIndexID()); 1787 result.SetStatus(eReturnStatusFailed); 1788 return false; 1789 } 1790 } else { 1791 // Pick either the absolute line, or work out a relative one. 1792 int32_t line = (int32_t)m_options.m_line_num; 1793 if (line == 0) 1794 line = sym_ctx.line_entry.line + m_options.m_line_offset; 1795 1796 // Try the current file, but override if asked. 1797 FileSpec file = sym_ctx.line_entry.file; 1798 if (m_options.m_filenames.GetSize() == 1) 1799 file = m_options.m_filenames.GetFileSpecAtIndex(0); 1800 1801 if (!file) { 1802 result.AppendErrorWithFormat( 1803 "No source file available for the current location."); 1804 result.SetStatus(eReturnStatusFailed); 1805 return false; 1806 } 1807 1808 std::string warnings; 1809 Status err = thread->JumpToLine(file, line, m_options.m_force, &warnings); 1810 1811 if (err.Fail()) { 1812 result.SetError(err); 1813 return false; 1814 } 1815 1816 if (!warnings.empty()) 1817 result.AppendWarning(warnings.c_str()); 1818 } 1819 1820 result.SetStatus(eReturnStatusSuccessFinishResult); 1821 return true; 1822 } 1823 1824 CommandOptions m_options; 1825 }; 1826 1827 // Next are the subcommands of CommandObjectMultiwordThreadPlan 1828 1829 // CommandObjectThreadPlanList 1830 #define LLDB_OPTIONS_thread_plan_list 1831 #include "CommandOptions.inc" 1832 1833 class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads { 1834 public: 1835 class CommandOptions : public Options { 1836 public: 1837 CommandOptions() : Options() { 1838 // Keep default values of all options in one place: OptionParsingStarting 1839 // () 1840 OptionParsingStarting(nullptr); 1841 } 1842 1843 ~CommandOptions() override = default; 1844 1845 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1846 ExecutionContext *execution_context) override { 1847 Status error; 1848 const int short_option = m_getopt_table[option_idx].val; 1849 1850 switch (short_option) { 1851 case 'i': 1852 m_internal = true; 1853 break; 1854 case 'v': 1855 m_verbose = true; 1856 break; 1857 default: 1858 llvm_unreachable("Unimplemented option"); 1859 } 1860 return error; 1861 } 1862 1863 void OptionParsingStarting(ExecutionContext *execution_context) override { 1864 m_verbose = false; 1865 m_internal = false; 1866 } 1867 1868 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1869 return llvm::makeArrayRef(g_thread_plan_list_options); 1870 } 1871 1872 // Instance variables to hold the values for command options. 1873 bool m_verbose; 1874 bool m_internal; 1875 }; 1876 1877 CommandObjectThreadPlanList(CommandInterpreter &interpreter) 1878 : CommandObjectIterateOverThreads( 1879 interpreter, "thread plan list", 1880 "Show thread plans for one or more threads. If no threads are " 1881 "specified, show the " 1882 "current thread. Use the thread-index \"all\" to see all threads.", 1883 nullptr, 1884 eCommandRequiresProcess | eCommandRequiresThread | 1885 eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | 1886 eCommandProcessMustBePaused), 1887 m_options() {} 1888 1889 ~CommandObjectThreadPlanList() override = default; 1890 1891 Options *GetOptions() override { return &m_options; } 1892 1893 protected: 1894 bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { 1895 ThreadSP thread_sp = 1896 m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); 1897 if (!thread_sp) { 1898 result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n", 1899 tid); 1900 result.SetStatus(eReturnStatusFailed); 1901 return false; 1902 } 1903 1904 Thread *thread = thread_sp.get(); 1905 1906 Stream &strm = result.GetOutputStream(); 1907 DescriptionLevel desc_level = eDescriptionLevelFull; 1908 if (m_options.m_verbose) 1909 desc_level = eDescriptionLevelVerbose; 1910 1911 thread->DumpThreadPlans(&strm, desc_level, m_options.m_internal, true); 1912 return true; 1913 } 1914 1915 CommandOptions m_options; 1916 }; 1917 1918 class CommandObjectThreadPlanDiscard : public CommandObjectParsed { 1919 public: 1920 CommandObjectThreadPlanDiscard(CommandInterpreter &interpreter) 1921 : CommandObjectParsed(interpreter, "thread plan discard", 1922 "Discards thread plans up to and including the " 1923 "specified index (see 'thread plan list'.) " 1924 "Only user visible plans can be discarded.", 1925 nullptr, 1926 eCommandRequiresProcess | eCommandRequiresThread | 1927 eCommandTryTargetAPILock | 1928 eCommandProcessMustBeLaunched | 1929 eCommandProcessMustBePaused) { 1930 CommandArgumentEntry arg; 1931 CommandArgumentData plan_index_arg; 1932 1933 // Define the first (and only) variant of this arg. 1934 plan_index_arg.arg_type = eArgTypeUnsignedInteger; 1935 plan_index_arg.arg_repetition = eArgRepeatPlain; 1936 1937 // There is only one variant this argument could be; put it into the 1938 // argument entry. 1939 arg.push_back(plan_index_arg); 1940 1941 // Push the data for the first argument into the m_arguments vector. 1942 m_arguments.push_back(arg); 1943 } 1944 1945 ~CommandObjectThreadPlanDiscard() override = default; 1946 1947 bool DoExecute(Args &args, CommandReturnObject &result) override { 1948 Thread *thread = m_exe_ctx.GetThreadPtr(); 1949 if (args.GetArgumentCount() != 1) { 1950 result.AppendErrorWithFormat("Too many arguments, expected one - the " 1951 "thread plan index - but got %zu.", 1952 args.GetArgumentCount()); 1953 result.SetStatus(eReturnStatusFailed); 1954 return false; 1955 } 1956 1957 bool success; 1958 uint32_t thread_plan_idx = 1959 StringConvert::ToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success); 1960 if (!success) { 1961 result.AppendErrorWithFormat( 1962 "Invalid thread index: \"%s\" - should be unsigned int.", 1963 args.GetArgumentAtIndex(0)); 1964 result.SetStatus(eReturnStatusFailed); 1965 return false; 1966 } 1967 1968 if (thread_plan_idx == 0) { 1969 result.AppendErrorWithFormat( 1970 "You wouldn't really want me to discard the base thread plan."); 1971 result.SetStatus(eReturnStatusFailed); 1972 return false; 1973 } 1974 1975 if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx)) { 1976 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1977 return true; 1978 } else { 1979 result.AppendErrorWithFormat( 1980 "Could not find User thread plan with index %s.", 1981 args.GetArgumentAtIndex(0)); 1982 result.SetStatus(eReturnStatusFailed); 1983 return false; 1984 } 1985 } 1986 }; 1987 1988 // CommandObjectMultiwordThreadPlan 1989 1990 class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword { 1991 public: 1992 CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) 1993 : CommandObjectMultiword( 1994 interpreter, "plan", 1995 "Commands for managing thread plans that control execution.", 1996 "thread plan <subcommand> [<subcommand objects]") { 1997 LoadSubCommand( 1998 "list", CommandObjectSP(new CommandObjectThreadPlanList(interpreter))); 1999 LoadSubCommand( 2000 "discard", 2001 CommandObjectSP(new CommandObjectThreadPlanDiscard(interpreter))); 2002 } 2003 2004 ~CommandObjectMultiwordThreadPlan() override = default; 2005 }; 2006 2007 // CommandObjectMultiwordThread 2008 2009 CommandObjectMultiwordThread::CommandObjectMultiwordThread( 2010 CommandInterpreter &interpreter) 2011 : CommandObjectMultiword(interpreter, "thread", "Commands for operating on " 2012 "one or more threads in " 2013 "the current process.", 2014 "thread <subcommand> [<subcommand-options>]") { 2015 LoadSubCommand("backtrace", CommandObjectSP(new CommandObjectThreadBacktrace( 2016 interpreter))); 2017 LoadSubCommand("continue", 2018 CommandObjectSP(new CommandObjectThreadContinue(interpreter))); 2019 LoadSubCommand("list", 2020 CommandObjectSP(new CommandObjectThreadList(interpreter))); 2021 LoadSubCommand("return", 2022 CommandObjectSP(new CommandObjectThreadReturn(interpreter))); 2023 LoadSubCommand("jump", 2024 CommandObjectSP(new CommandObjectThreadJump(interpreter))); 2025 LoadSubCommand("select", 2026 CommandObjectSP(new CommandObjectThreadSelect(interpreter))); 2027 LoadSubCommand("until", 2028 CommandObjectSP(new CommandObjectThreadUntil(interpreter))); 2029 LoadSubCommand("info", 2030 CommandObjectSP(new CommandObjectThreadInfo(interpreter))); 2031 LoadSubCommand( 2032 "exception", 2033 CommandObjectSP(new CommandObjectThreadException(interpreter))); 2034 LoadSubCommand("step-in", 2035 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2036 interpreter, "thread step-in", 2037 "Source level single step, stepping into calls. Defaults " 2038 "to current thread unless specified.", 2039 nullptr, eStepTypeInto, eStepScopeSource))); 2040 2041 LoadSubCommand("step-out", 2042 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2043 interpreter, "thread step-out", 2044 "Finish executing the current stack frame and stop after " 2045 "returning. Defaults to current thread unless specified.", 2046 nullptr, eStepTypeOut, eStepScopeSource))); 2047 2048 LoadSubCommand("step-over", 2049 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2050 interpreter, "thread step-over", 2051 "Source level single step, stepping over calls. Defaults " 2052 "to current thread unless specified.", 2053 nullptr, eStepTypeOver, eStepScopeSource))); 2054 2055 LoadSubCommand("step-inst", 2056 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2057 interpreter, "thread step-inst", 2058 "Instruction level single step, stepping into calls. " 2059 "Defaults to current thread unless specified.", 2060 nullptr, eStepTypeTrace, eStepScopeInstruction))); 2061 2062 LoadSubCommand("step-inst-over", 2063 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2064 interpreter, "thread step-inst-over", 2065 "Instruction level single step, stepping over calls. " 2066 "Defaults to current thread unless specified.", 2067 nullptr, eStepTypeTraceOver, eStepScopeInstruction))); 2068 2069 LoadSubCommand( 2070 "step-scripted", 2071 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2072 interpreter, "thread step-scripted", 2073 "Step as instructed by the script class passed in the -C option. " 2074 "You can also specify a dictionary of key (-k) and value (-v) pairs " 2075 "that will be used to populate an SBStructuredData Dictionary, which " 2076 "will be passed to the constructor of the class implementing the " 2077 "scripted step. See the Python Reference for more details.", 2078 nullptr, eStepTypeScripted, eStepScopeSource))); 2079 2080 LoadSubCommand("plan", CommandObjectSP(new CommandObjectMultiwordThreadPlan( 2081 interpreter))); 2082 } 2083 2084 CommandObjectMultiwordThread::~CommandObjectMultiwordThread() = default; 2085