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/Interpreter/Options.h" 17 #include "lldb/Core/State.h" 18 #include "lldb/Core/SourceManager.h" 19 20 #include "lldb/Interpreter/CommandInterpreter.h" 21 #include "lldb/Interpreter/CommandReturnObject.h" 22 23 #include "lldb/Target/Process.h" 24 #include "lldb/Target/RegisterContext.h" 25 #include "lldb/Target/Target.h" 26 #include "lldb/Target/Thread.h" 27 #include "lldb/Target/ThreadPlan.h" 28 #include "lldb/Target/ThreadPlanStepInstruction.h" 29 #include "lldb/Target/ThreadPlanStepOut.h" 30 #include "lldb/Target/ThreadPlanStepRange.h" 31 #include "lldb/Target/ThreadPlanStepInRange.h" 32 #include "lldb/Symbol/LineTable.h" 33 #include "lldb/Symbol/LineEntry.h" 34 35 using namespace lldb; 36 using namespace lldb_private; 37 38 39 bool 40 lldb_private::DisplayThreadInfo 41 ( 42 CommandInterpreter &interpreter, 43 Stream &strm, 44 Thread *thread, 45 bool only_threads_with_stop_reason, 46 bool show_source 47 ) 48 { 49 if (thread) 50 { 51 if (only_threads_with_stop_reason) 52 { 53 if (thread->GetStopInfo() == NULL) 54 return false; 55 } 56 57 strm.Indent(); 58 strm.Printf("%c ", thread->GetProcess().GetThreadList().GetSelectedThread().get() == thread ? '*' : ' '); 59 60 // Show one frame with only the first showing source 61 if (show_source) 62 { 63 bool already_shown = false; 64 StackFrameSP frame_sp = thread->GetStackFrameAtIndex(0); 65 SymbolContext frame_sc(frame_sp->GetSymbolContext (eSymbolContextLineEntry)); 66 if (interpreter.GetDebugger().GetUseExternalEditor() && frame_sc.line_entry.file && frame_sc.line_entry.line != 0) 67 { 68 already_shown = Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line); 69 } 70 71 DisplayFramesForExecutionContext (thread, 72 interpreter, 73 strm, 74 0, // Start at first frame 75 1, // Number of frames to show 76 false,// Don't show the frame info since we already displayed most of it above... 77 !already_shown, // Show source for the first frame 78 3, // lines of source context before 79 3); // lines of source context after 80 } 81 else 82 { 83 thread->DumpUsingSettingsFormat (strm, 0); 84 } 85 86 return true; 87 } 88 return false; 89 } 90 91 size_t 92 lldb_private::DisplayThreadsInfo 93 ( 94 CommandInterpreter &interpreter, 95 ExecutionContext *exe_ctx, 96 CommandReturnObject &result, 97 bool only_threads_with_stop_reason, 98 bool show_source 99 ) 100 { 101 StreamString strm; 102 103 size_t num_thread_infos_dumped = 0; 104 105 if (!exe_ctx->process) 106 return 0; 107 108 const size_t num_threads = exe_ctx->process->GetThreadList().GetSize(); 109 if (num_threads > 0) 110 { 111 112 for (uint32_t i = 0; i < num_threads; i++) 113 { 114 Thread *thread = exe_ctx->process->GetThreadList().GetThreadAtIndex(i).get(); 115 if (thread) 116 { 117 if (DisplayThreadInfo (interpreter, 118 strm, 119 thread, 120 only_threads_with_stop_reason, 121 show_source)) 122 ++num_thread_infos_dumped; 123 } 124 } 125 } 126 127 if (num_thread_infos_dumped > 0) 128 { 129 if (num_thread_infos_dumped < num_threads) 130 result.GetOutputStream().Printf("%u of %u threads stopped with reasons:\n", num_thread_infos_dumped, num_threads); 131 132 result.GetOutputStream().GetString().append(strm.GetString()); 133 result.SetStatus (eReturnStatusSuccessFinishNoResult); 134 } 135 return num_thread_infos_dumped; 136 } 137 138 139 size_t 140 lldb_private::DisplayFramesForExecutionContext 141 ( 142 Thread *thread, 143 CommandInterpreter &interpreter, 144 Stream& strm, 145 uint32_t first_frame, 146 uint32_t num_frames, 147 bool show_frame_info, 148 uint32_t num_frames_with_source, 149 uint32_t source_lines_before, 150 uint32_t source_lines_after 151 ) 152 { 153 if (thread == NULL) 154 return 0; 155 156 size_t num_frames_displayed = 0; 157 158 if (num_frames == 0) 159 return 0; 160 161 thread->DumpUsingSettingsFormat (strm, num_frames > 1 ? UINT32_MAX : first_frame); 162 strm.IndentMore(); 163 164 StackFrameSP frame_sp; 165 uint32_t frame_idx = 0; 166 uint32_t last_frame; 167 168 // Don't let the last frame wrap around... 169 if (num_frames == UINT32_MAX) 170 last_frame = UINT32_MAX; 171 else 172 last_frame = first_frame + num_frames; 173 174 for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx) 175 { 176 frame_sp = thread->GetStackFrameAtIndex (frame_idx); 177 if (frame_sp.get() == NULL) 178 break; 179 180 if (DisplayFrameForExecutionContext (thread, 181 frame_sp.get(), 182 interpreter, 183 strm, 184 show_frame_info, 185 num_frames_with_source > first_frame - frame_idx, 186 source_lines_before, 187 source_lines_after) == false) 188 break; 189 190 ++num_frames_displayed; 191 } 192 193 strm.IndentLess(); 194 return num_frames_displayed; 195 } 196 197 bool 198 lldb_private::DisplayFrameForExecutionContext 199 ( 200 Thread *thread, 201 StackFrame *frame, 202 CommandInterpreter &interpreter, 203 Stream& strm, 204 bool show_frame_info, 205 bool show_source, 206 uint32_t source_lines_before, 207 uint32_t source_lines_after 208 ) 209 { 210 // thread and frame must be filled in prior to calling this function 211 if (thread && frame) 212 { 213 if (show_frame_info) 214 { 215 strm.Indent(); 216 frame->DumpUsingSettingsFormat (&strm); 217 } 218 219 SymbolContext sc (frame->GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry)); 220 221 if (show_source && sc.comp_unit && sc.line_entry.IsValid()) 222 { 223 interpreter.GetDebugger().GetSourceManager().DisplaySourceLinesWithLineNumbers ( 224 sc.line_entry.file, 225 sc.line_entry.line, 226 3, 227 3, 228 "->", 229 &strm); 230 231 } 232 return true; 233 } 234 return false; 235 } 236 237 238 //------------------------------------------------------------------------- 239 // CommandObjectThreadBacktrace 240 //------------------------------------------------------------------------- 241 242 class CommandObjectThreadBacktrace : public CommandObject 243 { 244 public: 245 246 class CommandOptions : public Options 247 { 248 public: 249 250 CommandOptions () : 251 Options() 252 { 253 // Keep default values of all options in one place: ResetOptionValues () 254 ResetOptionValues (); 255 } 256 257 virtual 258 ~CommandOptions () 259 { 260 } 261 262 virtual Error 263 SetOptionValue (int option_idx, const char *option_arg) 264 { 265 Error error; 266 char short_option = (char) m_getopt_table[option_idx].val; 267 268 switch (short_option) 269 { 270 case 'c': 271 { 272 bool success; 273 int32_t input_count = Args::StringToSInt32 (option_arg, -1, 0, &success); 274 if (!success) 275 error.SetErrorStringWithFormat("Invalid integer value for option '%c'.\n", short_option); 276 if (input_count < -1) 277 m_count = UINT32_MAX; 278 else 279 m_count = input_count; 280 } 281 break; 282 case 's': 283 { 284 bool success; 285 m_start = Args::StringToUInt32 (option_arg, 0, 0, &success); 286 if (!success) 287 error.SetErrorStringWithFormat("Invalid integer value for option '%c'.\n", short_option); 288 } 289 break; 290 default: 291 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 292 break; 293 294 } 295 return error; 296 } 297 298 void 299 ResetOptionValues () 300 { 301 Options::ResetOptionValues(); 302 m_count = -1; 303 m_start = 0; 304 } 305 306 const lldb::OptionDefinition* 307 GetDefinitions () 308 { 309 return g_option_table; 310 } 311 312 // Options table: Required for subclasses of Options. 313 314 static lldb::OptionDefinition g_option_table[]; 315 316 // Instance variables to hold the values for command options. 317 uint32_t m_count; 318 uint32_t m_start; 319 }; 320 321 CommandObjectThreadBacktrace (CommandInterpreter &interpreter) : 322 CommandObject (interpreter, 323 "thread backtrace", 324 "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.", 325 NULL, 326 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), 327 m_options() 328 { 329 CommandArgumentEntry arg; 330 CommandArgumentData thread_idx_arg; 331 332 // Define the first (and only) variant of this arg. 333 thread_idx_arg.arg_type = eArgTypeThreadIndex; 334 thread_idx_arg.arg_repetition = eArgRepeatStar; 335 336 // There is only one variant this argument could be; put it into the argument entry. 337 arg.push_back (thread_idx_arg); 338 339 // Push the data for the first argument into the m_arguments vector. 340 m_arguments.push_back (arg); 341 } 342 343 ~CommandObjectThreadBacktrace() 344 { 345 } 346 347 virtual Options * 348 GetOptions () 349 { 350 return &m_options; 351 } 352 353 virtual bool 354 Execute (Args& command, CommandReturnObject &result) 355 { 356 357 bool show_frame_info = true; 358 uint32_t num_frames_with_source = 0; // Don't show any frames with source when backtracing 359 360 result.SetStatus (eReturnStatusSuccessFinishResult); 361 362 if (command.GetArgumentCount() == 0) 363 { 364 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext()); 365 if (exe_ctx.thread) 366 { 367 if (DisplayFramesForExecutionContext (exe_ctx.thread, 368 m_interpreter, 369 result.GetOutputStream(), 370 m_options.m_start, 371 m_options.m_count, 372 show_frame_info, 373 num_frames_with_source, 374 3, 375 3)) 376 { 377 result.SetStatus (eReturnStatusSuccessFinishResult); 378 } 379 } 380 else 381 { 382 result.AppendError ("invalid thread"); 383 result.SetStatus (eReturnStatusFailed); 384 } 385 } 386 else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0) 387 { 388 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 389 uint32_t num_threads = process->GetThreadList().GetSize(); 390 for (uint32_t i = 0; i < num_threads; i++) 391 { 392 ThreadSP thread_sp = process->GetThreadList().GetThreadAtIndex(i); 393 if (!DisplayFramesForExecutionContext (thread_sp.get(), 394 m_interpreter, 395 result.GetOutputStream(), 396 m_options.m_start, 397 m_options.m_count, 398 show_frame_info, 399 num_frames_with_source, 400 3, 401 3)) 402 { 403 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", i); 404 result.SetStatus (eReturnStatusFailed); 405 return false; 406 } 407 if (i < num_threads - 1) 408 result.AppendMessage(""); 409 } 410 } 411 else 412 { 413 uint32_t num_args = command.GetArgumentCount(); 414 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 415 std::vector<ThreadSP> thread_sps; 416 417 for (uint32_t i = 0; i < num_args; i++) 418 { 419 bool success; 420 421 uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success); 422 if (!success) 423 { 424 result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i)); 425 result.SetStatus (eReturnStatusFailed); 426 return false; 427 } 428 429 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx)); 430 431 if (!thread_sps[i]) 432 { 433 result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i)); 434 result.SetStatus (eReturnStatusFailed); 435 return false; 436 } 437 438 } 439 440 for (uint32_t i = 0; i < num_args; i++) 441 { 442 if (!DisplayFramesForExecutionContext (thread_sps[i].get(), 443 m_interpreter, 444 result.GetOutputStream(), 445 m_options.m_start, 446 m_options.m_count, 447 show_frame_info, 448 num_frames_with_source, 449 3, 450 3)) 451 { 452 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"%s\"\n", command.GetArgumentAtIndex(i)); 453 result.SetStatus (eReturnStatusFailed); 454 return false; 455 } 456 457 if (i < num_args - 1) 458 result.AppendMessage(""); 459 } 460 } 461 return result.Succeeded(); 462 } 463 protected: 464 CommandOptions m_options; 465 }; 466 467 lldb::OptionDefinition 468 CommandObjectThreadBacktrace::CommandOptions::g_option_table[] = 469 { 470 { LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"}, 471 { LLDB_OPT_SET_1, false, "start", 's', required_argument, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"}, 472 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 473 }; 474 475 enum StepScope 476 { 477 eStepScopeSource, 478 eStepScopeInstruction 479 }; 480 481 class CommandObjectThreadStepWithTypeAndScope : public CommandObject 482 { 483 public: 484 485 class CommandOptions : public Options 486 { 487 public: 488 489 CommandOptions () : 490 Options() 491 { 492 // Keep default values of all options in one place: ResetOptionValues () 493 ResetOptionValues (); 494 } 495 496 virtual 497 ~CommandOptions () 498 { 499 } 500 501 virtual Error 502 SetOptionValue (int option_idx, const char *option_arg) 503 { 504 Error error; 505 char short_option = (char) m_getopt_table[option_idx].val; 506 507 switch (short_option) 508 { 509 case 'a': 510 { 511 bool success; 512 m_avoid_no_debug = Args::StringToBoolean (option_arg, true, &success); 513 if (!success) 514 error.SetErrorStringWithFormat("Invalid boolean value for option '%c'.\n", short_option); 515 } 516 break; 517 518 case 'm': 519 { 520 bool found_one = false; 521 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 522 m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one); 523 if (!found_one) 524 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option); 525 } 526 break; 527 528 case 'r': 529 { 530 m_avoid_regexp.clear(); 531 m_avoid_regexp.assign(option_arg); 532 } 533 break; 534 535 default: 536 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 537 break; 538 539 } 540 return error; 541 } 542 543 void 544 ResetOptionValues () 545 { 546 Options::ResetOptionValues(); 547 m_avoid_no_debug = true; 548 m_run_mode = eOnlyDuringStepping; 549 m_avoid_regexp.clear(); 550 } 551 552 const lldb::OptionDefinition* 553 GetDefinitions () 554 { 555 return g_option_table; 556 } 557 558 // Options table: Required for subclasses of Options. 559 560 static lldb::OptionDefinition g_option_table[]; 561 562 // Instance variables to hold the values for command options. 563 bool m_avoid_no_debug; 564 RunMode m_run_mode; 565 std::string m_avoid_regexp; 566 }; 567 568 CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter, 569 const char *name, 570 const char *help, 571 const char *syntax, 572 uint32_t flags, 573 StepType step_type, 574 StepScope step_scope) : 575 CommandObject (interpreter, name, help, syntax, flags), 576 m_step_type (step_type), 577 m_step_scope (step_scope), 578 m_options () 579 { 580 CommandArgumentEntry arg; 581 CommandArgumentData thread_id_arg; 582 583 // Define the first (and only) variant of this arg. 584 thread_id_arg.arg_type = eArgTypeThreadID; 585 thread_id_arg.arg_repetition = eArgRepeatOptional; 586 587 // There is only one variant this argument could be; put it into the argument entry. 588 arg.push_back (thread_id_arg); 589 590 // Push the data for the first argument into the m_arguments vector. 591 m_arguments.push_back (arg); 592 } 593 594 virtual 595 ~CommandObjectThreadStepWithTypeAndScope () 596 { 597 } 598 599 virtual 600 Options * 601 GetOptions () 602 { 603 return &m_options; 604 } 605 606 virtual bool 607 Execute 608 ( 609 Args& command, 610 CommandReturnObject &result 611 ) 612 { 613 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 614 bool synchronous_execution = m_interpreter.GetSynchronous(); 615 616 if (process == NULL) 617 { 618 result.AppendError ("need a valid process to step"); 619 result.SetStatus (eReturnStatusFailed); 620 621 } 622 else 623 { 624 const uint32_t num_threads = process->GetThreadList().GetSize(); 625 Thread *thread = NULL; 626 627 if (command.GetArgumentCount() == 0) 628 { 629 thread = process->GetThreadList().GetSelectedThread().get(); 630 if (thread == NULL) 631 { 632 result.AppendError ("no selected thread in process"); 633 result.SetStatus (eReturnStatusFailed); 634 return false; 635 } 636 } 637 else 638 { 639 const char *thread_idx_cstr = command.GetArgumentAtIndex(0); 640 uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32); 641 if (step_thread_idx == LLDB_INVALID_INDEX32) 642 { 643 result.AppendErrorWithFormat ("Invalid thread index '%s'.\n", thread_idx_cstr); 644 result.SetStatus (eReturnStatusFailed); 645 return false; 646 } 647 thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get(); 648 if (thread == NULL) 649 { 650 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", 651 step_thread_idx, 0, num_threads); 652 result.SetStatus (eReturnStatusFailed); 653 return false; 654 } 655 } 656 657 const bool abort_other_plans = false; 658 const lldb::RunMode stop_other_threads = m_options.m_run_mode; 659 660 // This is a bit unfortunate, but not all the commands in this command object support 661 // only while stepping, so I use the bool for them. 662 bool bool_stop_other_threads; 663 if (m_options.m_run_mode == eAllThreads) 664 bool_stop_other_threads = false; 665 else 666 bool_stop_other_threads = true; 667 668 if (m_step_type == eStepTypeInto) 669 { 670 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 671 ThreadPlan *new_plan; 672 673 if (frame->HasDebugInformation ()) 674 { 675 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type, 676 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 677 frame->GetSymbolContext(eSymbolContextEverything), 678 stop_other_threads, 679 m_options.m_avoid_no_debug); 680 if (new_plan && !m_options.m_avoid_regexp.empty()) 681 { 682 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan); 683 step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str()); 684 } 685 } 686 else 687 new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads); 688 689 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 690 process->Resume (); 691 } 692 else if (m_step_type == eStepTypeOver) 693 { 694 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 695 ThreadPlan *new_plan; 696 697 if (frame->HasDebugInformation()) 698 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, 699 m_step_type, 700 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 701 frame->GetSymbolContext(eSymbolContextEverything), 702 stop_other_threads, 703 false); 704 else 705 new_plan = thread->QueueThreadPlanForStepSingleInstruction (true, 706 abort_other_plans, 707 bool_stop_other_threads); 708 709 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over. 710 // Maybe there should be a parameter to control this. 711 new_plan->SetOkayToDiscard(false); 712 713 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 714 process->Resume (); 715 } 716 else if (m_step_type == eStepTypeTrace) 717 { 718 thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads); 719 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 720 process->Resume (); 721 } 722 else if (m_step_type == eStepTypeTraceOver) 723 { 724 thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads); 725 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 726 process->Resume (); 727 } 728 else if (m_step_type == eStepTypeOut) 729 { 730 ThreadPlan *new_plan; 731 732 new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, bool_stop_other_threads, eVoteYes, eVoteNoOpinion); 733 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over. 734 // Maybe there should be a parameter to control this. 735 new_plan->SetOkayToDiscard(false); 736 737 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 738 process->Resume (); 739 } 740 else 741 { 742 result.AppendError ("step type is not supported"); 743 result.SetStatus (eReturnStatusFailed); 744 } 745 if (synchronous_execution) 746 { 747 StateType state = process->WaitForProcessToStop (NULL); 748 749 //EventSP event_sp; 750 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp); 751 //while (! StateIsStoppedState (state)) 752 // { 753 // state = process->WaitForStateChangedEvents (NULL, event_sp); 754 // } 755 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 756 result.SetDidChangeProcessState (true); 757 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 758 result.SetStatus (eReturnStatusSuccessFinishNoResult); 759 } 760 } 761 return result.Succeeded(); 762 } 763 764 protected: 765 StepType m_step_type; 766 StepScope m_step_scope; 767 CommandOptions m_options; 768 }; 769 770 static lldb::OptionEnumValueElement 771 g_tri_running_mode[] = 772 { 773 { eOnlyThisThread, "this-thread", "Run only this thread"}, 774 { eAllThreads, "all-threads", "Run all threads"}, 775 { eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"}, 776 { 0, NULL, NULL } 777 }; 778 779 static lldb::OptionEnumValueElement 780 g_duo_running_mode[] = 781 { 782 { eOnlyThisThread, "this-thread", "Run only this thread"}, 783 { eAllThreads, "all-threads", "Run all threads"}, 784 { 0, NULL, NULL } 785 }; 786 787 lldb::OptionDefinition 788 CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] = 789 { 790 { LLDB_OPT_SET_1, false, "avoid-no-debug", 'a', required_argument, NULL, 0, eArgTypeBoolean, "A boolean value that sets whether step-in will step over functions with no debug information."}, 791 { LLDB_OPT_SET_1, false, "run-mode", 'm', required_argument, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."}, 792 { LLDB_OPT_SET_1, false, "step-over-regexp",'r', required_argument, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to step over."}, 793 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 794 }; 795 796 797 //------------------------------------------------------------------------- 798 // CommandObjectThreadContinue 799 //------------------------------------------------------------------------- 800 801 class CommandObjectThreadContinue : public CommandObject 802 { 803 public: 804 805 CommandObjectThreadContinue (CommandInterpreter &interpreter) : 806 CommandObject (interpreter, 807 "thread continue", 808 "Continue execution of one or more threads in an active process.", 809 NULL, 810 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 811 { 812 CommandArgumentEntry arg; 813 CommandArgumentData thread_idx_arg; 814 815 // Define the first (and only) variant of this arg. 816 thread_idx_arg.arg_type = eArgTypeThreadIndex; 817 thread_idx_arg.arg_repetition = eArgRepeatPlus; 818 819 // There is only one variant this argument could be; put it into the argument entry. 820 arg.push_back (thread_idx_arg); 821 822 // Push the data for the first argument into the m_arguments vector. 823 m_arguments.push_back (arg); 824 } 825 826 827 virtual 828 ~CommandObjectThreadContinue () 829 { 830 } 831 832 virtual bool 833 Execute 834 ( 835 Args& command, 836 CommandReturnObject &result 837 ) 838 { 839 bool synchronous_execution = m_interpreter.GetSynchronous (); 840 841 if (!m_interpreter.GetDebugger().GetSelectedTarget().get()) 842 { 843 result.AppendError ("invalid target, set executable file using 'file' command"); 844 result.SetStatus (eReturnStatusFailed); 845 return false; 846 } 847 848 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 849 if (process == NULL) 850 { 851 result.AppendError ("no process exists. Cannot continue"); 852 result.SetStatus (eReturnStatusFailed); 853 return false; 854 } 855 856 StateType state = process->GetState(); 857 if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended)) 858 { 859 const uint32_t num_threads = process->GetThreadList().GetSize(); 860 uint32_t idx; 861 const size_t argc = command.GetArgumentCount(); 862 if (argc > 0) 863 { 864 std::vector<uint32_t> resume_thread_indexes; 865 for (uint32_t i=0; i<argc; ++i) 866 { 867 idx = Args::StringToUInt32 (command.GetArgumentAtIndex(0), LLDB_INVALID_INDEX32); 868 if (idx < num_threads) 869 resume_thread_indexes.push_back(idx); 870 else 871 result.AppendWarningWithFormat("Thread index %u out of range.\n", idx); 872 } 873 874 if (resume_thread_indexes.empty()) 875 { 876 result.AppendError ("no valid thread indexes were specified"); 877 result.SetStatus (eReturnStatusFailed); 878 return false; 879 } 880 else 881 { 882 result.AppendMessage ("Resuming thread "); 883 for (idx=0; idx<num_threads; ++idx) 884 { 885 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 886 if (find(resume_thread_indexes.begin(), resume_thread_indexes.end(), idx) != resume_thread_indexes.end()) 887 { 888 result.AppendMessageWithFormat ("%u ", idx); 889 thread->SetResumeState (eStateRunning); 890 } 891 else 892 { 893 thread->SetResumeState (eStateSuspended); 894 } 895 } 896 result.AppendMessageWithFormat ("in process %i\n", process->GetID()); 897 } 898 } 899 else 900 { 901 Thread *current_thread = process->GetThreadList().GetSelectedThread().get(); 902 if (current_thread == NULL) 903 { 904 result.AppendError ("the process doesn't have a current thread"); 905 result.SetStatus (eReturnStatusFailed); 906 return false; 907 } 908 // Set the actions that the threads should each take when resuming 909 for (idx=0; idx<num_threads; ++idx) 910 { 911 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 912 if (thread == current_thread) 913 { 914 result.AppendMessageWithFormat ("Resuming thread 0x%4.4x in process %i\n", thread->GetID(), process->GetID()); 915 thread->SetResumeState (eStateRunning); 916 } 917 else 918 { 919 thread->SetResumeState (eStateSuspended); 920 } 921 } 922 } 923 924 Error error (process->Resume()); 925 if (error.Success()) 926 { 927 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID()); 928 if (synchronous_execution) 929 { 930 state = process->WaitForProcessToStop (NULL); 931 932 result.SetDidChangeProcessState (true); 933 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 934 result.SetStatus (eReturnStatusSuccessFinishNoResult); 935 } 936 else 937 { 938 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 939 } 940 } 941 else 942 { 943 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString()); 944 result.SetStatus (eReturnStatusFailed); 945 } 946 } 947 else 948 { 949 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 950 StateAsCString(state)); 951 result.SetStatus (eReturnStatusFailed); 952 } 953 954 return result.Succeeded(); 955 } 956 957 }; 958 959 //------------------------------------------------------------------------- 960 // CommandObjectThreadUntil 961 //------------------------------------------------------------------------- 962 963 class CommandObjectThreadUntil : public CommandObject 964 { 965 public: 966 967 class CommandOptions : public Options 968 { 969 public: 970 uint32_t m_thread_idx; 971 uint32_t m_frame_idx; 972 973 CommandOptions () : 974 Options(), 975 m_thread_idx(LLDB_INVALID_THREAD_ID), 976 m_frame_idx(LLDB_INVALID_FRAME_ID) 977 { 978 // Keep default values of all options in one place: ResetOptionValues () 979 ResetOptionValues (); 980 } 981 982 virtual 983 ~CommandOptions () 984 { 985 } 986 987 virtual Error 988 SetOptionValue (int option_idx, const char *option_arg) 989 { 990 Error error; 991 char short_option = (char) m_getopt_table[option_idx].val; 992 993 switch (short_option) 994 { 995 case 't': 996 { 997 m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32); 998 if (m_thread_idx == LLDB_INVALID_INDEX32) 999 { 1000 error.SetErrorStringWithFormat ("Invalid thread index '%s'.\n", option_arg); 1001 } 1002 } 1003 break; 1004 case 'f': 1005 { 1006 m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID); 1007 if (m_frame_idx == LLDB_INVALID_FRAME_ID) 1008 { 1009 error.SetErrorStringWithFormat ("Invalid frame index '%s'.\n", option_arg); 1010 } 1011 } 1012 break; 1013 case 'm': 1014 { 1015 bool found_one = false; 1016 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 1017 lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one); 1018 1019 if (!found_one) 1020 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option); 1021 else if (run_mode == eAllThreads) 1022 m_stop_others = false; 1023 else 1024 m_stop_others = true; 1025 1026 } 1027 break; 1028 default: 1029 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 1030 break; 1031 1032 } 1033 return error; 1034 } 1035 1036 void 1037 ResetOptionValues () 1038 { 1039 Options::ResetOptionValues(); 1040 m_thread_idx = LLDB_INVALID_THREAD_ID; 1041 m_frame_idx = 0; 1042 m_stop_others = false; 1043 } 1044 1045 const lldb::OptionDefinition* 1046 GetDefinitions () 1047 { 1048 return g_option_table; 1049 } 1050 1051 uint32_t m_step_thread_idx; 1052 bool m_stop_others; 1053 1054 // Options table: Required for subclasses of Options. 1055 1056 static lldb::OptionDefinition g_option_table[]; 1057 1058 // Instance variables to hold the values for command options. 1059 }; 1060 1061 CommandObjectThreadUntil (CommandInterpreter &interpreter) : 1062 CommandObject (interpreter, 1063 "thread until", 1064 "Run the current or specified thread until it reaches a given line number or leaves the current function.", 1065 NULL, 1066 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), 1067 m_options () 1068 { 1069 CommandArgumentEntry arg; 1070 CommandArgumentData line_num_arg; 1071 1072 // Define the first (and only) variant of this arg. 1073 line_num_arg.arg_type = eArgTypeLineNum; 1074 line_num_arg.arg_repetition = eArgRepeatPlain; 1075 1076 // There is only one variant this argument could be; put it into the argument entry. 1077 arg.push_back (line_num_arg); 1078 1079 // Push the data for the first argument into the m_arguments vector. 1080 m_arguments.push_back (arg); 1081 } 1082 1083 1084 virtual 1085 ~CommandObjectThreadUntil () 1086 { 1087 } 1088 1089 virtual 1090 Options * 1091 GetOptions () 1092 { 1093 return &m_options; 1094 } 1095 1096 virtual bool 1097 Execute 1098 ( 1099 Args& command, 1100 CommandReturnObject &result 1101 ) 1102 { 1103 bool synchronous_execution = m_interpreter.GetSynchronous (); 1104 1105 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1106 if (target == NULL) 1107 { 1108 result.AppendError ("invalid target, set executable file using 'file' command"); 1109 result.SetStatus (eReturnStatusFailed); 1110 return false; 1111 } 1112 1113 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 1114 if (process == NULL) 1115 { 1116 result.AppendError ("need a valid process to step"); 1117 result.SetStatus (eReturnStatusFailed); 1118 1119 } 1120 else 1121 { 1122 Thread *thread = NULL; 1123 uint32_t line_number; 1124 1125 if (command.GetArgumentCount() != 1) 1126 { 1127 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax()); 1128 result.SetStatus (eReturnStatusFailed); 1129 return false; 1130 } 1131 1132 line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX); 1133 if (line_number == UINT32_MAX) 1134 { 1135 result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0)); 1136 result.SetStatus (eReturnStatusFailed); 1137 return false; 1138 } 1139 1140 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) 1141 { 1142 thread = process->GetThreadList().GetSelectedThread().get(); 1143 } 1144 else 1145 { 1146 thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get(); 1147 } 1148 1149 if (thread == NULL) 1150 { 1151 const uint32_t num_threads = process->GetThreadList().GetSize(); 1152 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads); 1153 result.SetStatus (eReturnStatusFailed); 1154 return false; 1155 } 1156 1157 const bool abort_other_plans = true; 1158 1159 StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get(); 1160 if (frame == NULL) 1161 { 1162 1163 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx); 1164 result.SetStatus (eReturnStatusFailed); 1165 return false; 1166 } 1167 1168 ThreadPlan *new_plan; 1169 1170 if (frame->HasDebugInformation ()) 1171 { 1172 // Finally we got here... Translate the given line number to a bunch of addresses: 1173 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit)); 1174 LineTable *line_table = NULL; 1175 if (sc.comp_unit) 1176 line_table = sc.comp_unit->GetLineTable(); 1177 1178 if (line_table == NULL) 1179 { 1180 result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n", 1181 m_options.m_frame_idx, m_options.m_thread_idx); 1182 result.SetStatus (eReturnStatusFailed); 1183 return false; 1184 } 1185 1186 LineEntry function_start; 1187 uint32_t index_ptr = 0, end_ptr; 1188 std::vector<addr_t> address_list; 1189 1190 // Find the beginning & end index of the 1191 AddressRange fun_addr_range = sc.function->GetAddressRange(); 1192 Address fun_start_addr = fun_addr_range.GetBaseAddress(); 1193 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr); 1194 1195 Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize()); 1196 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr); 1197 1198 while (index_ptr <= end_ptr) 1199 { 1200 LineEntry line_entry; 1201 index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry); 1202 if (index_ptr == UINT32_MAX) 1203 break; 1204 1205 addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target); 1206 if (address != LLDB_INVALID_ADDRESS) 1207 address_list.push_back (address); 1208 index_ptr++; 1209 } 1210 1211 new_plan = thread->QueueThreadPlanForStepUntil (abort_other_plans, &address_list.front(), address_list.size(), m_options.m_stop_others); 1212 new_plan->SetOkayToDiscard(false); 1213 } 1214 else 1215 { 1216 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx); 1217 result.SetStatus (eReturnStatusFailed); 1218 return false; 1219 1220 } 1221 1222 process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx); 1223 Error error (process->Resume ()); 1224 if (error.Success()) 1225 { 1226 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID()); 1227 if (synchronous_execution) 1228 { 1229 StateType state = process->WaitForProcessToStop (NULL); 1230 1231 result.SetDidChangeProcessState (true); 1232 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 1233 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1234 } 1235 else 1236 { 1237 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 1238 } 1239 } 1240 else 1241 { 1242 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 1243 result.SetStatus (eReturnStatusFailed); 1244 } 1245 1246 } 1247 return result.Succeeded(); 1248 } 1249 protected: 1250 CommandOptions m_options; 1251 1252 }; 1253 1254 lldb::OptionDefinition 1255 CommandObjectThreadUntil::CommandOptions::g_option_table[] = 1256 { 1257 { LLDB_OPT_SET_1, false, "frame", 'f', required_argument, NULL, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"}, 1258 { LLDB_OPT_SET_1, false, "thread", 't', required_argument, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"}, 1259 { LLDB_OPT_SET_1, false, "run-mode",'m', required_argument, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"}, 1260 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1261 }; 1262 1263 1264 //------------------------------------------------------------------------- 1265 // CommandObjectThreadSelect 1266 //------------------------------------------------------------------------- 1267 1268 class CommandObjectThreadSelect : public CommandObject 1269 { 1270 public: 1271 1272 CommandObjectThreadSelect (CommandInterpreter &interpreter) : 1273 CommandObject (interpreter, 1274 "thread select", 1275 "Select a thread as the currently active thread.", 1276 NULL, 1277 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 1278 { 1279 CommandArgumentEntry arg; 1280 CommandArgumentData thread_idx_arg; 1281 1282 // Define the first (and only) variant of this arg. 1283 thread_idx_arg.arg_type = eArgTypeThreadIndex; 1284 thread_idx_arg.arg_repetition = eArgRepeatPlain; 1285 1286 // There is only one variant this argument could be; put it into the argument entry. 1287 arg.push_back (thread_idx_arg); 1288 1289 // Push the data for the first argument into the m_arguments vector. 1290 m_arguments.push_back (arg); 1291 } 1292 1293 1294 virtual 1295 ~CommandObjectThreadSelect () 1296 { 1297 } 1298 1299 virtual bool 1300 Execute 1301 ( 1302 Args& command, 1303 CommandReturnObject &result 1304 ) 1305 { 1306 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 1307 if (process == NULL) 1308 { 1309 result.AppendError ("no process"); 1310 result.SetStatus (eReturnStatusFailed); 1311 return false; 1312 } 1313 else if (command.GetArgumentCount() != 1) 1314 { 1315 result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1316 result.SetStatus (eReturnStatusFailed); 1317 return false; 1318 } 1319 1320 uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0); 1321 1322 Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get(); 1323 if (new_thread == NULL) 1324 { 1325 result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0)); 1326 result.SetStatus (eReturnStatusFailed); 1327 return false; 1328 } 1329 1330 process->GetThreadList().SetSelectedThreadByID(new_thread->GetID()); 1331 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1332 1333 DisplayThreadInfo (m_interpreter, 1334 result.GetOutputStream(), 1335 new_thread, 1336 false, 1337 true); 1338 1339 return result.Succeeded(); 1340 } 1341 1342 }; 1343 1344 1345 //------------------------------------------------------------------------- 1346 // CommandObjectThreadList 1347 //------------------------------------------------------------------------- 1348 1349 class CommandObjectThreadList : public CommandObject 1350 { 1351 public: 1352 1353 1354 CommandObjectThreadList (CommandInterpreter &interpreter): 1355 CommandObject (interpreter, 1356 "thread list", 1357 "Show a summary of all current threads in a process.", 1358 "thread list", 1359 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 1360 { 1361 } 1362 1363 ~CommandObjectThreadList() 1364 { 1365 } 1366 1367 bool 1368 Execute 1369 ( 1370 Args& command, 1371 CommandReturnObject &result 1372 ) 1373 { 1374 StreamString &strm = result.GetOutputStream(); 1375 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1376 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext()); 1377 if (exe_ctx.process) 1378 { 1379 const StateType state = exe_ctx.process->GetState(); 1380 1381 if (StateIsStoppedState(state)) 1382 { 1383 if (state == eStateExited) 1384 { 1385 int exit_status = exe_ctx.process->GetExitStatus(); 1386 const char *exit_description = exe_ctx.process->GetExitDescription(); 1387 strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n", 1388 exe_ctx.process->GetID(), 1389 exit_status, 1390 exit_status, 1391 exit_description ? exit_description : ""); 1392 } 1393 else 1394 { 1395 strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state)); 1396 if (exe_ctx.thread == NULL) 1397 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get(); 1398 if (exe_ctx.thread != NULL) 1399 { 1400 DisplayThreadsInfo (m_interpreter, &exe_ctx, result, false, false); 1401 } 1402 else 1403 { 1404 result.AppendError ("no valid thread found in current process"); 1405 result.SetStatus (eReturnStatusFailed); 1406 } 1407 } 1408 } 1409 else 1410 { 1411 result.AppendError ("process is currently running"); 1412 result.SetStatus (eReturnStatusFailed); 1413 } 1414 } 1415 else 1416 { 1417 result.AppendError ("no current location or status available"); 1418 result.SetStatus (eReturnStatusFailed); 1419 } 1420 return result.Succeeded(); 1421 } 1422 }; 1423 1424 //------------------------------------------------------------------------- 1425 // CommandObjectMultiwordThread 1426 //------------------------------------------------------------------------- 1427 1428 CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) : 1429 CommandObjectMultiword (interpreter, 1430 "thread", 1431 "A set of commands for operating on one or more threads within a running process.", 1432 "thread <subcommand> [<subcommand-options>]") 1433 { 1434 LoadSubCommand ("backtrace", CommandObjectSP (new CommandObjectThreadBacktrace (interpreter))); 1435 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectThreadContinue (interpreter))); 1436 LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadList (interpreter))); 1437 LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter))); 1438 LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter))); 1439 LoadSubCommand ("step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 1440 interpreter, 1441 "thread step-in", 1442 "Source level single step in specified thread (current thread, if none specified).", 1443 NULL, 1444 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused, 1445 eStepTypeInto, 1446 eStepScopeSource))); 1447 1448 LoadSubCommand ("step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 1449 interpreter, 1450 "thread step-out", 1451 "Finish executing the current fucntion and return to its call site in specified thread (current thread, if none specified).", 1452 NULL, 1453 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused, 1454 eStepTypeOut, 1455 eStepScopeSource))); 1456 1457 LoadSubCommand ("step-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 1458 interpreter, 1459 "thread step-over", 1460 "Source level single step in specified thread (current thread, if none specified), stepping over calls.", 1461 NULL, 1462 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused, 1463 eStepTypeOver, 1464 eStepScopeSource))); 1465 1466 LoadSubCommand ("step-inst", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 1467 interpreter, 1468 "thread step-inst", 1469 "Single step one instruction in specified thread (current thread, if none specified).", 1470 NULL, 1471 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused, 1472 eStepTypeTrace, 1473 eStepScopeInstruction))); 1474 1475 LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 1476 interpreter, 1477 "thread step-inst-over", 1478 "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.", 1479 NULL, 1480 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused, 1481 eStepTypeTraceOver, 1482 eStepScopeInstruction))); 1483 } 1484 1485 CommandObjectMultiwordThread::~CommandObjectMultiwordThread () 1486 { 1487 } 1488 1489 1490