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