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