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