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