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