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