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