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