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