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