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