xref: /llvm-project/lldb/source/Commands/CommandObjectThread.cpp (revision 2bdbfd50d2c9a80c6132a3f83d1c097b0b0c6ca5)
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 "lldb/lldb-python.h"
11 
12 #include "CommandObjectThread.h"
13 
14 // C Includes
15 // C++ Includes
16 // Other libraries and framework includes
17 // Project includes
18 #include "lldb/lldb-private.h"
19 #include "lldb/Core/State.h"
20 #include "lldb/Core/SourceManager.h"
21 #include "lldb/Host/Host.h"
22 #include "lldb/Interpreter/CommandInterpreter.h"
23 #include "lldb/Interpreter/CommandReturnObject.h"
24 #include "lldb/Interpreter/Options.h"
25 #include "lldb/Symbol/CompileUnit.h"
26 #include "lldb/Symbol/Function.h"
27 #include "lldb/Symbol/LineTable.h"
28 #include "lldb/Symbol/LineEntry.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/RegisterContext.h"
31 #include "lldb/Target/SystemRuntime.h"
32 #include "lldb/Target/Target.h"
33 #include "lldb/Target/Thread.h"
34 #include "lldb/Target/ThreadPlan.h"
35 #include "lldb/Target/ThreadPlanStepInstruction.h"
36 #include "lldb/Target/ThreadPlanStepOut.h"
37 #include "lldb/Target/ThreadPlanStepRange.h"
38 #include "lldb/Target/ThreadPlanStepInRange.h"
39 
40 
41 using namespace lldb;
42 using namespace lldb_private;
43 
44 
45 //-------------------------------------------------------------------------
46 // CommandObjectThreadBacktrace
47 //-------------------------------------------------------------------------
48 
49 class CommandObjectIterateOverThreads : public CommandObjectParsed
50 {
51 public:
52     CommandObjectIterateOverThreads (CommandInterpreter &interpreter,
53                          const char *name,
54                          const char *help,
55                          const char *syntax,
56                          uint32_t flags) :
57         CommandObjectParsed (interpreter, name, help, syntax, flags)
58     {
59     }
60 
61     virtual ~CommandObjectIterateOverThreads() {}
62     virtual bool
63     DoExecute (Args& command, CommandReturnObject &result)
64     {
65         result.SetStatus (m_success_return);
66 
67         if (command.GetArgumentCount() == 0)
68         {
69             Thread *thread = m_exe_ctx.GetThreadPtr();
70             if (!HandleOneThread (*thread, result))
71                 return false;
72         }
73         else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
74         {
75             Process *process = m_exe_ctx.GetProcessPtr();
76             uint32_t idx = 0;
77             for (ThreadSP thread_sp : process->Threads())
78             {
79                 if (idx != 0 && m_add_return)
80                     result.AppendMessage("");
81 
82                 if (!HandleOneThread(*(thread_sp.get()), result))
83                     return false;
84                 ++idx;
85             }
86         }
87         else
88         {
89             const size_t num_args = command.GetArgumentCount();
90             Process *process = m_exe_ctx.GetProcessPtr();
91             Mutex::Locker locker (process->GetThreadList().GetMutex());
92             std::vector<ThreadSP> thread_sps;
93 
94             for (size_t i = 0; i < num_args; i++)
95             {
96                 bool success;
97 
98                 uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
99                 if (!success)
100                 {
101                     result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
102                     result.SetStatus (eReturnStatusFailed);
103                     return false;
104                 }
105 
106                 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
107 
108                 if (!thread_sps[i])
109                 {
110                     result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
111                     result.SetStatus (eReturnStatusFailed);
112                     return false;
113                 }
114 
115             }
116 
117             for (uint32_t i = 0; i < num_args; i++)
118             {
119                 if (!HandleOneThread (*(thread_sps[i].get()), result))
120                     return false;
121 
122                 if (i < num_args - 1 && m_add_return)
123                     result.AppendMessage("");
124             }
125         }
126         return result.Succeeded();
127     }
128 
129 protected:
130 
131     // Override this to do whatever you need to do for one thread.
132     //
133     // If you return false, the iteration will stop, otherwise it will proceed.
134     // The result is set to m_success_return (defaults to eReturnStatusSuccessFinishResult) before the iteration,
135     // so you only need to set the return status in HandleOneThread if you want to indicate an error.
136     // If m_add_return is true, a blank line will be inserted between each of the listings (except the last one.)
137 
138     virtual bool
139     HandleOneThread (Thread &thread, CommandReturnObject &result) = 0;
140 
141     ReturnStatus m_success_return = eReturnStatusSuccessFinishResult;
142     bool m_add_return = true;
143 
144 };
145 
146 //-------------------------------------------------------------------------
147 // CommandObjectThreadBacktrace
148 //-------------------------------------------------------------------------
149 
150 class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads
151 {
152 public:
153 
154     class CommandOptions : public Options
155     {
156     public:
157 
158         CommandOptions (CommandInterpreter &interpreter) :
159             Options(interpreter)
160         {
161             // Keep default values of all options in one place: OptionParsingStarting ()
162             OptionParsingStarting ();
163         }
164 
165         virtual
166         ~CommandOptions ()
167         {
168         }
169 
170         virtual Error
171         SetOptionValue (uint32_t option_idx, const char *option_arg)
172         {
173             Error error;
174             const int short_option = m_getopt_table[option_idx].val;
175 
176             switch (short_option)
177             {
178                 case 'c':
179                 {
180                     bool success;
181                     int32_t input_count =  Args::StringToSInt32 (option_arg, -1, 0, &success);
182                     if (!success)
183                         error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option);
184                     if (input_count < -1)
185                         m_count = UINT32_MAX;
186                     else
187                         m_count = input_count;
188                 }
189                 break;
190                 case 's':
191                 {
192                     bool success;
193                     m_start =  Args::StringToUInt32 (option_arg, 0, 0, &success);
194                     if (!success)
195                         error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option);
196                 }
197                 case 'e':
198                 {
199                     bool success;
200                     m_extended_backtrace =  Args::StringToBoolean (option_arg, false, &success);
201                     if (!success)
202                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
203                 }
204                 break;
205                 default:
206                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
207                     break;
208 
209             }
210             return error;
211         }
212 
213         void
214         OptionParsingStarting ()
215         {
216             m_count = UINT32_MAX;
217             m_start = 0;
218             m_extended_backtrace = false;
219         }
220 
221         const OptionDefinition*
222         GetDefinitions ()
223         {
224             return g_option_table;
225         }
226 
227         // Options table: Required for subclasses of Options.
228 
229         static OptionDefinition g_option_table[];
230 
231         // Instance variables to hold the values for command options.
232         uint32_t m_count;
233         uint32_t m_start;
234         bool     m_extended_backtrace;
235     };
236 
237     CommandObjectThreadBacktrace (CommandInterpreter &interpreter) :
238         CommandObjectIterateOverThreads (interpreter,
239                              "thread backtrace",
240                              "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.",
241                              NULL,
242                              eFlagRequiresProcess       |
243                              eFlagRequiresThread        |
244                              eFlagTryTargetAPILock      |
245                              eFlagProcessMustBeLaunched |
246                              eFlagProcessMustBePaused   ),
247         m_options(interpreter)
248     {
249     }
250 
251     ~CommandObjectThreadBacktrace()
252     {
253     }
254 
255     virtual Options *
256     GetOptions ()
257     {
258         return &m_options;
259     }
260 
261 protected:
262     void
263     DoExtendedBacktrace (Thread *thread, CommandReturnObject &result)
264     {
265         SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime();
266         if (runtime)
267         {
268             Stream &strm = result.GetOutputStream();
269             const std::vector<ConstString> &types = runtime->GetExtendedBacktraceTypes();
270             for (auto type : types)
271             {
272                 ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread (thread->shared_from_this(), type);
273                 if (ext_thread_sp && ext_thread_sp->IsValid ())
274                 {
275                     const uint32_t num_frames_with_source = 0;
276                     if (ext_thread_sp->GetStatus (strm,
277                         m_options.m_start,
278                         m_options.m_count,
279                         num_frames_with_source))
280                     {
281                         DoExtendedBacktrace (ext_thread_sp.get(), result);
282                     }
283                 }
284             }
285         }
286     }
287 
288     virtual bool
289     HandleOneThread (Thread &thread, CommandReturnObject &result)
290     {
291         Stream &strm = result.GetOutputStream();
292 
293         // Don't show source context when doing backtraces.
294         const uint32_t num_frames_with_source = 0;
295 
296         if (!thread.GetStatus (strm,
297                                    m_options.m_start,
298                                    m_options.m_count,
299                                    num_frames_with_source))
300         {
301             result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", thread.GetIndexID());
302             result.SetStatus (eReturnStatusFailed);
303             return false;
304         }
305         if (m_options.m_extended_backtrace)
306         {
307             DoExtendedBacktrace (&thread, result);
308         }
309 
310         return true;
311     }
312 
313     CommandOptions m_options;
314 };
315 
316 OptionDefinition
317 CommandObjectThreadBacktrace::CommandOptions::g_option_table[] =
318 {
319 { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"},
320 { LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"},
321 { LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Show the extended backtrace, if available"},
322 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
323 };
324 
325 enum StepScope
326 {
327     eStepScopeSource,
328     eStepScopeInstruction
329 };
330 
331 class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed
332 {
333 public:
334 
335     class CommandOptions : public Options
336     {
337     public:
338 
339         CommandOptions (CommandInterpreter &interpreter) :
340             Options (interpreter)
341         {
342             // Keep default values of all options in one place: OptionParsingStarting ()
343             OptionParsingStarting ();
344         }
345 
346         virtual
347         ~CommandOptions ()
348         {
349         }
350 
351         virtual Error
352         SetOptionValue (uint32_t option_idx, const char *option_arg)
353         {
354             Error error;
355             const int short_option = m_getopt_table[option_idx].val;
356 
357             switch (short_option)
358             {
359             case 'a':
360                 {
361                     bool success;
362                     bool avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
363                     if (!success)
364                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
365                     else
366                     {
367                         m_step_in_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
368                     }
369                 }
370                 break;
371 
372             case 'A':
373                 {
374                     bool success;
375                     bool avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
376                     if (!success)
377                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
378                     else
379                     {
380                         m_step_out_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
381                     }
382                 }
383                 break;
384 
385             case 'c':
386                 {
387                     m_step_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
388                     if (m_step_count == UINT32_MAX)
389                        error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
390                     break;
391                 }
392                 break;
393             case 'C':
394                 {
395                     m_class_name.clear();
396                     m_class_name.assign(option_arg);
397                 }
398                 break;
399             case 'm':
400                 {
401                     OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
402                     m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error);
403                 }
404                 break;
405 
406             case 'r':
407                 {
408                     m_avoid_regexp.clear();
409                     m_avoid_regexp.assign(option_arg);
410                 }
411                 break;
412 
413             case 't':
414                 {
415                     m_step_in_target.clear();
416                     m_step_in_target.assign(option_arg);
417 
418                 }
419                 break;
420             default:
421                 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
422                 break;
423 
424             }
425             return error;
426         }
427 
428         void
429         OptionParsingStarting ()
430         {
431             m_step_in_avoid_no_debug = eLazyBoolCalculate;
432             m_step_out_avoid_no_debug = eLazyBoolCalculate;
433             m_run_mode = eOnlyDuringStepping;
434             m_avoid_regexp.clear();
435             m_step_in_target.clear();
436             m_class_name.clear();
437             m_step_count = 1;
438         }
439 
440         const OptionDefinition*
441         GetDefinitions ()
442         {
443             return g_option_table;
444         }
445 
446         // Options table: Required for subclasses of Options.
447 
448         static OptionDefinition g_option_table[];
449 
450         // Instance variables to hold the values for command options.
451         LazyBool m_step_in_avoid_no_debug;
452         LazyBool m_step_out_avoid_no_debug;
453         RunMode m_run_mode;
454         std::string m_avoid_regexp;
455         std::string m_step_in_target;
456         std::string m_class_name;
457         int32_t m_step_count;
458     };
459 
460     CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
461                                              const char *name,
462                                              const char *help,
463                                              const char *syntax,
464                                              StepType step_type,
465                                              StepScope step_scope) :
466         CommandObjectParsed (interpreter, name, help, syntax,
467                              eFlagRequiresProcess       |
468                              eFlagRequiresThread        |
469                              eFlagTryTargetAPILock      |
470                              eFlagProcessMustBeLaunched |
471                              eFlagProcessMustBePaused   ),
472         m_step_type (step_type),
473         m_step_scope (step_scope),
474         m_options (interpreter)
475     {
476         CommandArgumentEntry arg;
477         CommandArgumentData thread_id_arg;
478 
479         // Define the first (and only) variant of this arg.
480         thread_id_arg.arg_type = eArgTypeThreadID;
481         thread_id_arg.arg_repetition = eArgRepeatOptional;
482 
483         // There is only one variant this argument could be; put it into the argument entry.
484         arg.push_back (thread_id_arg);
485 
486         // Push the data for the first argument into the m_arguments vector.
487         m_arguments.push_back (arg);
488     }
489 
490     virtual
491     ~CommandObjectThreadStepWithTypeAndScope ()
492     {
493     }
494 
495     virtual
496     Options *
497     GetOptions ()
498     {
499         return &m_options;
500     }
501 
502 protected:
503     virtual bool
504     DoExecute (Args& command, CommandReturnObject &result)
505     {
506         Process *process = m_exe_ctx.GetProcessPtr();
507         bool synchronous_execution = m_interpreter.GetSynchronous();
508 
509         const uint32_t num_threads = process->GetThreadList().GetSize();
510         Thread *thread = NULL;
511 
512         if (command.GetArgumentCount() == 0)
513         {
514             thread = process->GetThreadList().GetSelectedThread().get();
515             if (thread == NULL)
516             {
517                 result.AppendError ("no selected thread in process");
518                 result.SetStatus (eReturnStatusFailed);
519                 return false;
520             }
521         }
522         else
523         {
524             const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
525             uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
526             if (step_thread_idx == LLDB_INVALID_INDEX32)
527             {
528                 result.AppendErrorWithFormat ("invalid thread index '%s'.\n", thread_idx_cstr);
529                 result.SetStatus (eReturnStatusFailed);
530                 return false;
531             }
532             thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
533             if (thread == NULL)
534             {
535                 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
536                                               step_thread_idx, num_threads);
537                 result.SetStatus (eReturnStatusFailed);
538                 return false;
539             }
540         }
541 
542         if (m_step_type == eStepTypeScripted)
543         {
544             if (m_options.m_class_name.empty())
545             {
546                 result.AppendErrorWithFormat ("empty class name for scripted step.");
547                 result.SetStatus(eReturnStatusFailed);
548                 return false;
549             }
550             else if (!m_interpreter.GetScriptInterpreter()->CheckObjectExists(m_options.m_class_name.c_str()))
551             {
552                 result.AppendErrorWithFormat ("class for scripted step: \"%s\" does not exist.", m_options.m_class_name.c_str());
553                 result.SetStatus(eReturnStatusFailed);
554                 return false;
555             }
556         }
557 
558         const bool abort_other_plans = false;
559         const lldb::RunMode stop_other_threads = m_options.m_run_mode;
560 
561         // This is a bit unfortunate, but not all the commands in this command object support
562         // only while stepping, so I use the bool for them.
563         bool bool_stop_other_threads;
564         if (m_options.m_run_mode == eAllThreads)
565             bool_stop_other_threads = false;
566         else if (m_options.m_run_mode == eOnlyDuringStepping)
567         {
568             if (m_step_type == eStepTypeOut || m_step_type == eStepTypeScripted)
569                 bool_stop_other_threads = false;
570             else
571                 bool_stop_other_threads = true;
572         }
573         else
574             bool_stop_other_threads = true;
575 
576         ThreadPlanSP new_plan_sp;
577 
578         if (m_step_type == eStepTypeInto)
579         {
580             StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
581 
582             if (frame->HasDebugInformation ())
583             {
584                 new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans,
585                                                                 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
586                                                                 frame->GetSymbolContext(eSymbolContextEverything),
587                                                                 m_options.m_step_in_target.c_str(),
588                                                                 stop_other_threads,
589                                                                 m_options.m_step_in_avoid_no_debug,
590                                                                 m_options.m_step_out_avoid_no_debug);
591 
592                 if (new_plan_sp && !m_options.m_avoid_regexp.empty())
593                 {
594                     ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan_sp.get());
595                     step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
596                 }
597             }
598             else
599                 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
600 
601         }
602         else if (m_step_type == eStepTypeOver)
603         {
604             StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
605 
606             if (frame->HasDebugInformation())
607                 new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
608                                                                     frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
609                                                                     frame->GetSymbolContext(eSymbolContextEverything),
610                                                                     stop_other_threads,
611                                                                     m_options.m_step_out_avoid_no_debug);
612             else
613                 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true,
614                                                                             abort_other_plans,
615                                                                             bool_stop_other_threads);
616 
617         }
618         else if (m_step_type == eStepTypeTrace)
619         {
620             new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
621         }
622         else if (m_step_type == eStepTypeTraceOver)
623         {
624             new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
625         }
626         else if (m_step_type == eStepTypeOut)
627         {
628             new_plan_sp = thread->QueueThreadPlanForStepOut (abort_other_plans,
629                                                           NULL,
630                                                           false,
631                                                           bool_stop_other_threads,
632                                                           eVoteYes,
633                                                           eVoteNoOpinion,
634                                                           thread->GetSelectedFrameIndex(),
635                                                           m_options.m_step_out_avoid_no_debug);
636         }
637         else if (m_step_type == eStepTypeScripted)
638         {
639             new_plan_sp = thread->QueueThreadPlanForStepScripted (abort_other_plans,
640                                                                   m_options.m_class_name.c_str(),
641                                                                   bool_stop_other_threads);
642         }
643         else
644         {
645             result.AppendError ("step type is not supported");
646             result.SetStatus (eReturnStatusFailed);
647             return false;
648         }
649 
650         // If we got a new plan, then set it to be a master plan (User level Plans should be master plans
651         // so that they can be interruptible).  Then resume the process.
652 
653         if (new_plan_sp)
654         {
655             new_plan_sp->SetIsMasterPlan (true);
656             new_plan_sp->SetOkayToDiscard (false);
657 
658             if (m_options.m_step_count > 1)
659             {
660                 if (new_plan_sp->SetIterationCount(m_options.m_step_count))
661                 {
662                     result.AppendWarning ("step operation does not support iteration count.");
663                 }
664             }
665 
666             process->GetThreadList().SetSelectedThreadByID (thread->GetID());
667             process->Resume ();
668 
669             // There is a race condition where this thread will return up the call stack to the main command handler
670             // and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has
671             // a chance to call PushProcessIOHandler().
672             process->SyncIOHandler(2000);
673 
674             if (synchronous_execution)
675             {
676                 StateType state = process->WaitForProcessToStop (NULL);
677 
678                 //EventSP event_sp;
679                 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
680                 //while (! StateIsStoppedState (state))
681                 //  {
682                 //    state = process->WaitForStateChangedEvents (NULL, event_sp);
683                 //  }
684                 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
685                 result.SetDidChangeProcessState (true);
686                 result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
687                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
688             }
689             else
690             {
691                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
692             }
693         }
694         else
695         {
696             result.AppendError ("Couldn't find thread plan to implement step type.");
697             result.SetStatus (eReturnStatusFailed);
698         }
699         return result.Succeeded();
700     }
701 
702 protected:
703     StepType m_step_type;
704     StepScope m_step_scope;
705     CommandOptions m_options;
706 };
707 
708 static OptionEnumValueElement
709 g_tri_running_mode[] =
710 {
711 { eOnlyThisThread,     "this-thread",    "Run only this thread"},
712 { eAllThreads,         "all-threads",    "Run all threads"},
713 { eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"},
714 { 0, NULL, NULL }
715 };
716 
717 static OptionEnumValueElement
718 g_duo_running_mode[] =
719 {
720 { eOnlyThisThread,     "this-thread",    "Run only this thread"},
721 { eAllThreads,         "all-threads",    "Run all threads"},
722 { 0, NULL, NULL }
723 };
724 
725 OptionDefinition
726 CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
727 {
728 { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug",   'a', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeBoolean,     "A boolean value that sets whether stepping into functions will step over functions with no debug information."},
729 { LLDB_OPT_SET_1, false, "step-out-avoids-no-debug",  'A', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeBoolean,     "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information."},
730 { LLDB_OPT_SET_1, false, "count",                     'c', OptionParser::eRequiredArgument, NULL, NULL,               1, eArgTypeCount,     "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."},
731 { LLDB_OPT_SET_1, false, "run-mode",                  'm', OptionParser::eRequiredArgument, NULL, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."},
732 { LLDB_OPT_SET_1, false, "step-over-regexp",          'r', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeRegularExpression,   "A regular expression that defines function names to not to stop at when stepping in."},
733 { LLDB_OPT_SET_1, false, "step-in-target",            't', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeFunctionName,   "The name of the directly called function step in should stop at when stepping into."},
734 { LLDB_OPT_SET_2, false, "python-class",              'C', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypePythonClass, "The name of the class that will manage this step - only supported for Scripted Step."},
735 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
736 };
737 
738 
739 //-------------------------------------------------------------------------
740 // CommandObjectThreadContinue
741 //-------------------------------------------------------------------------
742 
743 class CommandObjectThreadContinue : public CommandObjectParsed
744 {
745 public:
746 
747     CommandObjectThreadContinue (CommandInterpreter &interpreter) :
748         CommandObjectParsed (interpreter,
749                              "thread continue",
750                              "Continue execution of one or more threads in an active process.",
751                              NULL,
752                              eFlagRequiresThread        |
753                              eFlagTryTargetAPILock      |
754                              eFlagProcessMustBeLaunched |
755                              eFlagProcessMustBePaused)
756     {
757         CommandArgumentEntry arg;
758         CommandArgumentData thread_idx_arg;
759 
760         // Define the first (and only) variant of this arg.
761         thread_idx_arg.arg_type = eArgTypeThreadIndex;
762         thread_idx_arg.arg_repetition = eArgRepeatPlus;
763 
764         // There is only one variant this argument could be; put it into the argument entry.
765         arg.push_back (thread_idx_arg);
766 
767         // Push the data for the first argument into the m_arguments vector.
768         m_arguments.push_back (arg);
769     }
770 
771 
772     virtual
773     ~CommandObjectThreadContinue ()
774     {
775     }
776 
777     virtual bool
778     DoExecute (Args& command, CommandReturnObject &result)
779     {
780         bool synchronous_execution = m_interpreter.GetSynchronous ();
781 
782         if (!m_interpreter.GetDebugger().GetSelectedTarget().get())
783         {
784             result.AppendError ("invalid target, create a debug target using the 'target create' command");
785             result.SetStatus (eReturnStatusFailed);
786             return false;
787         }
788 
789         Process *process = m_exe_ctx.GetProcessPtr();
790         if (process == NULL)
791         {
792             result.AppendError ("no process exists. Cannot continue");
793             result.SetStatus (eReturnStatusFailed);
794             return false;
795         }
796 
797         StateType state = process->GetState();
798         if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
799         {
800             const size_t argc = command.GetArgumentCount();
801             if (argc > 0)
802             {
803                 // These two lines appear at the beginning of both blocks in
804                 // this if..else, but that is because we need to release the
805                 // lock before calling process->Resume below.
806                 Mutex::Locker locker (process->GetThreadList().GetMutex());
807                 const uint32_t num_threads = process->GetThreadList().GetSize();
808                 std::vector<Thread *> resume_threads;
809                 for (uint32_t i=0; i<argc; ++i)
810                 {
811                     bool success;
812                     const int base = 0;
813                     uint32_t thread_idx = Args::StringToUInt32 (command.GetArgumentAtIndex(i), LLDB_INVALID_INDEX32, base, &success);
814                     if (success)
815                     {
816                         Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get();
817 
818                         if (thread)
819                         {
820                             resume_threads.push_back(thread);
821                         }
822                         else
823                         {
824                             result.AppendErrorWithFormat("invalid thread index %u.\n", thread_idx);
825                             result.SetStatus (eReturnStatusFailed);
826                             return false;
827                         }
828                     }
829                     else
830                     {
831                         result.AppendErrorWithFormat ("invalid thread index argument: \"%s\".\n", command.GetArgumentAtIndex(i));
832                         result.SetStatus (eReturnStatusFailed);
833                         return false;
834                     }
835                 }
836 
837                 if (resume_threads.empty())
838                 {
839                     result.AppendError ("no valid thread indexes were specified");
840                     result.SetStatus (eReturnStatusFailed);
841                     return false;
842                 }
843                 else
844                 {
845                     if (resume_threads.size() == 1)
846                         result.AppendMessageWithFormat ("Resuming thread: ");
847                     else
848                         result.AppendMessageWithFormat ("Resuming threads: ");
849 
850                     for (uint32_t idx=0; idx<num_threads; ++idx)
851                     {
852                         Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
853                         std::vector<Thread *>::iterator this_thread_pos = find(resume_threads.begin(), resume_threads.end(), thread);
854 
855                         if (this_thread_pos != resume_threads.end())
856                         {
857                             resume_threads.erase(this_thread_pos);
858                             if (resume_threads.size() > 0)
859                                 result.AppendMessageWithFormat ("%u, ", thread->GetIndexID());
860                             else
861                                 result.AppendMessageWithFormat ("%u ", thread->GetIndexID());
862 
863                             const bool override_suspend = true;
864                             thread->SetResumeState (eStateRunning, override_suspend);
865                         }
866                         else
867                         {
868                             thread->SetResumeState (eStateSuspended);
869                         }
870                     }
871                     result.AppendMessageWithFormat ("in process %" PRIu64 "\n", process->GetID());
872                 }
873             }
874             else
875             {
876                 // These two lines appear at the beginning of both blocks in
877                 // this if..else, but that is because we need to release the
878                 // lock before calling process->Resume below.
879                 Mutex::Locker locker (process->GetThreadList().GetMutex());
880                 const uint32_t num_threads = process->GetThreadList().GetSize();
881                 Thread *current_thread = process->GetThreadList().GetSelectedThread().get();
882                 if (current_thread == NULL)
883                 {
884                     result.AppendError ("the process doesn't have a current thread");
885                     result.SetStatus (eReturnStatusFailed);
886                     return false;
887                 }
888                 // Set the actions that the threads should each take when resuming
889                 for (uint32_t idx=0; idx<num_threads; ++idx)
890                 {
891                     Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
892                     if (thread == current_thread)
893                     {
894                         result.AppendMessageWithFormat ("Resuming thread 0x%4.4" PRIx64 " in process %" PRIu64 "\n", thread->GetID(), process->GetID());
895                         const bool override_suspend = true;
896                         thread->SetResumeState (eStateRunning, override_suspend);
897                     }
898                     else
899                     {
900                         thread->SetResumeState (eStateSuspended);
901                     }
902                 }
903             }
904 
905             // We should not be holding the thread list lock when we do this.
906             Error error (process->Resume());
907             if (error.Success())
908             {
909                 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
910                 if (synchronous_execution)
911                 {
912                     state = process->WaitForProcessToStop (NULL);
913 
914                     result.SetDidChangeProcessState (true);
915                     result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
916                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
917                 }
918                 else
919                 {
920                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
921                 }
922             }
923             else
924             {
925                 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
926                 result.SetStatus (eReturnStatusFailed);
927             }
928         }
929         else
930         {
931             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
932                                           StateAsCString(state));
933             result.SetStatus (eReturnStatusFailed);
934         }
935 
936         return result.Succeeded();
937     }
938 
939 };
940 
941 //-------------------------------------------------------------------------
942 // CommandObjectThreadUntil
943 //-------------------------------------------------------------------------
944 
945 class CommandObjectThreadUntil : public CommandObjectParsed
946 {
947 public:
948 
949     class CommandOptions : public Options
950     {
951     public:
952         uint32_t m_thread_idx;
953         uint32_t m_frame_idx;
954 
955         CommandOptions (CommandInterpreter &interpreter) :
956             Options (interpreter),
957             m_thread_idx(LLDB_INVALID_THREAD_ID),
958             m_frame_idx(LLDB_INVALID_FRAME_ID)
959         {
960             // Keep default values of all options in one place: OptionParsingStarting ()
961             OptionParsingStarting ();
962         }
963 
964         virtual
965         ~CommandOptions ()
966         {
967         }
968 
969         virtual Error
970         SetOptionValue (uint32_t option_idx, const char *option_arg)
971         {
972             Error error;
973             const int short_option = m_getopt_table[option_idx].val;
974 
975             switch (short_option)
976             {
977                 case 't':
978                 {
979                     m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
980                     if (m_thread_idx == LLDB_INVALID_INDEX32)
981                     {
982                         error.SetErrorStringWithFormat ("invalid thread index '%s'", option_arg);
983                     }
984                 }
985                 break;
986                 case 'f':
987                 {
988                     m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
989                     if (m_frame_idx == LLDB_INVALID_FRAME_ID)
990                     {
991                         error.SetErrorStringWithFormat ("invalid frame index '%s'", option_arg);
992                     }
993                 }
994                 break;
995                 case 'm':
996                 {
997                     OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
998                     lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error);
999 
1000                     if (error.Success())
1001                     {
1002                         if (run_mode == eAllThreads)
1003                             m_stop_others = false;
1004                         else
1005                             m_stop_others = true;
1006                     }
1007                 }
1008                 break;
1009                 default:
1010                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1011                     break;
1012 
1013             }
1014             return error;
1015         }
1016 
1017         void
1018         OptionParsingStarting ()
1019         {
1020             m_thread_idx = LLDB_INVALID_THREAD_ID;
1021             m_frame_idx = 0;
1022             m_stop_others = false;
1023         }
1024 
1025         const OptionDefinition*
1026         GetDefinitions ()
1027         {
1028             return g_option_table;
1029         }
1030 
1031         uint32_t m_step_thread_idx;
1032         bool m_stop_others;
1033 
1034         // Options table: Required for subclasses of Options.
1035 
1036         static OptionDefinition g_option_table[];
1037 
1038         // Instance variables to hold the values for command options.
1039     };
1040 
1041     CommandObjectThreadUntil (CommandInterpreter &interpreter) :
1042         CommandObjectParsed (interpreter,
1043                              "thread until",
1044                              "Run the current or specified thread until it reaches a given line number or leaves the current function.",
1045                              NULL,
1046                              eFlagRequiresThread        |
1047                              eFlagTryTargetAPILock      |
1048                              eFlagProcessMustBeLaunched |
1049                              eFlagProcessMustBePaused   ),
1050         m_options (interpreter)
1051     {
1052         CommandArgumentEntry arg;
1053         CommandArgumentData line_num_arg;
1054 
1055         // Define the first (and only) variant of this arg.
1056         line_num_arg.arg_type = eArgTypeLineNum;
1057         line_num_arg.arg_repetition = eArgRepeatPlain;
1058 
1059         // There is only one variant this argument could be; put it into the argument entry.
1060         arg.push_back (line_num_arg);
1061 
1062         // Push the data for the first argument into the m_arguments vector.
1063         m_arguments.push_back (arg);
1064     }
1065 
1066 
1067     virtual
1068     ~CommandObjectThreadUntil ()
1069     {
1070     }
1071 
1072     virtual
1073     Options *
1074     GetOptions ()
1075     {
1076         return &m_options;
1077     }
1078 
1079 protected:
1080     virtual bool
1081     DoExecute (Args& command, CommandReturnObject &result)
1082     {
1083         bool synchronous_execution = m_interpreter.GetSynchronous ();
1084 
1085         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1086         if (target == NULL)
1087         {
1088             result.AppendError ("invalid target, create a debug target using the 'target create' command");
1089             result.SetStatus (eReturnStatusFailed);
1090             return false;
1091         }
1092 
1093         Process *process = m_exe_ctx.GetProcessPtr();
1094         if (process == NULL)
1095         {
1096             result.AppendError ("need a valid process to step");
1097             result.SetStatus (eReturnStatusFailed);
1098 
1099         }
1100         else
1101         {
1102             Thread *thread = NULL;
1103             uint32_t line_number;
1104 
1105             if (command.GetArgumentCount() != 1)
1106             {
1107                 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
1108                 result.SetStatus (eReturnStatusFailed);
1109                 return false;
1110             }
1111 
1112             line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
1113             if (line_number == UINT32_MAX)
1114             {
1115                 result.AppendErrorWithFormat ("invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
1116                 result.SetStatus (eReturnStatusFailed);
1117                 return false;
1118             }
1119 
1120             if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
1121             {
1122                 thread = process->GetThreadList().GetSelectedThread().get();
1123             }
1124             else
1125             {
1126                 thread = process->GetThreadList().FindThreadByIndexID(m_options.m_thread_idx).get();
1127             }
1128 
1129             if (thread == NULL)
1130             {
1131                 const uint32_t num_threads = process->GetThreadList().GetSize();
1132                 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
1133                                               m_options.m_thread_idx,
1134                                               num_threads);
1135                 result.SetStatus (eReturnStatusFailed);
1136                 return false;
1137             }
1138 
1139             const bool abort_other_plans = false;
1140 
1141             StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
1142             if (frame == NULL)
1143             {
1144 
1145                 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n",
1146                                               m_options.m_frame_idx,
1147                                               m_options.m_thread_idx);
1148                 result.SetStatus (eReturnStatusFailed);
1149                 return false;
1150             }
1151 
1152             ThreadPlanSP new_plan_sp;
1153 
1154             if (frame->HasDebugInformation ())
1155             {
1156                 // Finally we got here...  Translate the given line number to a bunch of addresses:
1157                 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
1158                 LineTable *line_table = NULL;
1159                 if (sc.comp_unit)
1160                     line_table = sc.comp_unit->GetLineTable();
1161 
1162                 if (line_table == NULL)
1163                 {
1164                     result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
1165                                                  m_options.m_frame_idx, m_options.m_thread_idx);
1166                     result.SetStatus (eReturnStatusFailed);
1167                     return false;
1168                 }
1169 
1170                 LineEntry function_start;
1171                 uint32_t index_ptr = 0, end_ptr;
1172                 std::vector<addr_t> address_list;
1173 
1174                 // Find the beginning & end index of the
1175                 AddressRange fun_addr_range = sc.function->GetAddressRange();
1176                 Address fun_start_addr = fun_addr_range.GetBaseAddress();
1177                 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1178 
1179                 Address fun_end_addr(fun_start_addr.GetSection(),
1180                                      fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1181                 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
1182 
1183                 bool all_in_function = true;
1184 
1185                 while (index_ptr <= end_ptr)
1186                 {
1187                     LineEntry line_entry;
1188                     const bool exact = false;
1189                     index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, exact, &line_entry);
1190                     if (index_ptr == UINT32_MAX)
1191                         break;
1192 
1193                     addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target);
1194                     if (address != LLDB_INVALID_ADDRESS)
1195                     {
1196                         if (fun_addr_range.ContainsLoadAddress (address, target))
1197                             address_list.push_back (address);
1198                         else
1199                             all_in_function = false;
1200                     }
1201                     index_ptr++;
1202                 }
1203 
1204                 if (address_list.size() == 0)
1205                 {
1206                     if (all_in_function)
1207                         result.AppendErrorWithFormat ("No line entries matching until target.\n");
1208                     else
1209                         result.AppendErrorWithFormat ("Until target outside of the current function.\n");
1210 
1211                     result.SetStatus (eReturnStatusFailed);
1212                     return false;
1213                 }
1214 
1215                 new_plan_sp = thread->QueueThreadPlanForStepUntil (abort_other_plans,
1216                                                                 &address_list.front(),
1217                                                                 address_list.size(),
1218                                                                 m_options.m_stop_others,
1219                                                                 m_options.m_frame_idx);
1220                 // User level plans should be master plans so they can be interrupted (e.g. by hitting a breakpoint)
1221                 // and other plans executed by the user (stepping around the breakpoint) and then a "continue"
1222                 // will resume the original plan.
1223                 new_plan_sp->SetIsMasterPlan (true);
1224                 new_plan_sp->SetOkayToDiscard(false);
1225             }
1226             else
1227             {
1228                 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n",
1229                                               m_options.m_frame_idx,
1230                                               m_options.m_thread_idx);
1231                 result.SetStatus (eReturnStatusFailed);
1232                 return false;
1233 
1234             }
1235 
1236             process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx);
1237             Error error (process->Resume ());
1238             if (error.Success())
1239             {
1240                 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
1241                 if (synchronous_execution)
1242                 {
1243                     StateType state = process->WaitForProcessToStop (NULL);
1244 
1245                     result.SetDidChangeProcessState (true);
1246                     result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
1247                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1248                 }
1249                 else
1250                 {
1251                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1252                 }
1253             }
1254             else
1255             {
1256                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1257                 result.SetStatus (eReturnStatusFailed);
1258             }
1259 
1260         }
1261         return result.Succeeded();
1262     }
1263 
1264     CommandOptions m_options;
1265 
1266 };
1267 
1268 OptionDefinition
1269 CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1270 {
1271 { LLDB_OPT_SET_1, false, "frame",   'f', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeFrameIndex,   "Frame index for until operation - defaults to 0"},
1272 { LLDB_OPT_SET_1, false, "thread",  't', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeThreadIndex,  "Thread index for the thread for until operation"},
1273 { LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, NULL, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"},
1274 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1275 };
1276 
1277 
1278 //-------------------------------------------------------------------------
1279 // CommandObjectThreadSelect
1280 //-------------------------------------------------------------------------
1281 
1282 class CommandObjectThreadSelect : public CommandObjectParsed
1283 {
1284 public:
1285 
1286     CommandObjectThreadSelect (CommandInterpreter &interpreter) :
1287         CommandObjectParsed (interpreter,
1288                              "thread select",
1289                              "Select a thread as the currently active thread.",
1290                              NULL,
1291                              eFlagRequiresProcess       |
1292                              eFlagTryTargetAPILock      |
1293                              eFlagProcessMustBeLaunched |
1294                              eFlagProcessMustBePaused   )
1295     {
1296         CommandArgumentEntry arg;
1297         CommandArgumentData thread_idx_arg;
1298 
1299         // Define the first (and only) variant of this arg.
1300         thread_idx_arg.arg_type = eArgTypeThreadIndex;
1301         thread_idx_arg.arg_repetition = eArgRepeatPlain;
1302 
1303         // There is only one variant this argument could be; put it into the argument entry.
1304         arg.push_back (thread_idx_arg);
1305 
1306         // Push the data for the first argument into the m_arguments vector.
1307         m_arguments.push_back (arg);
1308     }
1309 
1310 
1311     virtual
1312     ~CommandObjectThreadSelect ()
1313     {
1314     }
1315 
1316 protected:
1317     virtual bool
1318     DoExecute (Args& command, CommandReturnObject &result)
1319     {
1320         Process *process = m_exe_ctx.GetProcessPtr();
1321         if (process == NULL)
1322         {
1323             result.AppendError ("no process");
1324             result.SetStatus (eReturnStatusFailed);
1325             return false;
1326         }
1327         else if (command.GetArgumentCount() != 1)
1328         {
1329             result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1330             result.SetStatus (eReturnStatusFailed);
1331             return false;
1332         }
1333 
1334         uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1335 
1336         Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1337         if (new_thread == NULL)
1338         {
1339             result.AppendErrorWithFormat ("invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1340             result.SetStatus (eReturnStatusFailed);
1341             return false;
1342         }
1343 
1344         process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true);
1345         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1346 
1347         return result.Succeeded();
1348     }
1349 
1350 };
1351 
1352 
1353 //-------------------------------------------------------------------------
1354 // CommandObjectThreadList
1355 //-------------------------------------------------------------------------
1356 
1357 class CommandObjectThreadList : public CommandObjectParsed
1358 {
1359 public:
1360 
1361 
1362     CommandObjectThreadList (CommandInterpreter &interpreter):
1363         CommandObjectParsed (interpreter,
1364                              "thread list",
1365                              "Show a summary of all current threads in a process.",
1366                              "thread list",
1367                              eFlagRequiresProcess       |
1368                              eFlagTryTargetAPILock      |
1369                              eFlagProcessMustBeLaunched |
1370                              eFlagProcessMustBePaused   )
1371     {
1372     }
1373 
1374     ~CommandObjectThreadList()
1375     {
1376     }
1377 
1378 protected:
1379     bool
1380     DoExecute (Args& command, CommandReturnObject &result)
1381     {
1382         Stream &strm = result.GetOutputStream();
1383         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1384         Process *process = m_exe_ctx.GetProcessPtr();
1385         const bool only_threads_with_stop_reason = false;
1386         const uint32_t start_frame = 0;
1387         const uint32_t num_frames = 0;
1388         const uint32_t num_frames_with_source = 0;
1389         process->GetStatus(strm);
1390         process->GetThreadStatus (strm,
1391                                   only_threads_with_stop_reason,
1392                                   start_frame,
1393                                   num_frames,
1394                                   num_frames_with_source);
1395         return result.Succeeded();
1396     }
1397 };
1398 
1399 //-------------------------------------------------------------------------
1400 // CommandObjectThreadInfo
1401 //-------------------------------------------------------------------------
1402 
1403 class CommandObjectThreadInfo : public CommandObjectIterateOverThreads
1404 {
1405 public:
1406 
1407     CommandObjectThreadInfo (CommandInterpreter &interpreter) :
1408         CommandObjectIterateOverThreads (interpreter,
1409                                          "thread info",
1410                                          "Show an extended summary of information about thread(s) in a process.",
1411                                          "thread info",
1412                                          eFlagRequiresProcess       |
1413                                          eFlagTryTargetAPILock      |
1414                                          eFlagProcessMustBeLaunched |
1415                                          eFlagProcessMustBePaused),
1416         m_options (interpreter)
1417     {
1418         m_add_return = false;
1419     }
1420 
1421     class CommandOptions : public Options
1422     {
1423     public:
1424 
1425         CommandOptions (CommandInterpreter &interpreter) :
1426             Options (interpreter)
1427         {
1428             OptionParsingStarting ();
1429         }
1430 
1431         void
1432         OptionParsingStarting ()
1433         {
1434             m_json = false;
1435         }
1436 
1437         virtual
1438         ~CommandOptions ()
1439         {
1440         }
1441 
1442         virtual Error
1443         SetOptionValue (uint32_t option_idx, const char *option_arg)
1444         {
1445             const int short_option = m_getopt_table[option_idx].val;
1446             Error error;
1447 
1448             switch (short_option)
1449             {
1450                 case 'j':
1451                     m_json = true;
1452                     break;
1453 
1454                  default:
1455                     return Error("invalid short option character '%c'", short_option);
1456 
1457             }
1458             return error;
1459         }
1460 
1461         const OptionDefinition*
1462         GetDefinitions ()
1463         {
1464             return g_option_table;
1465         }
1466 
1467         bool m_json;
1468 
1469         static OptionDefinition g_option_table[];
1470     };
1471 
1472     virtual
1473     Options *
1474     GetOptions ()
1475     {
1476         return &m_options;
1477     }
1478 
1479 
1480     virtual
1481     ~CommandObjectThreadInfo ()
1482     {
1483     }
1484 
1485     virtual bool
1486     HandleOneThread (Thread &thread, CommandReturnObject &result)
1487     {
1488         Stream &strm = result.GetOutputStream();
1489         if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json))
1490         {
1491             result.AppendErrorWithFormat ("error displaying info for thread: \"%d\"\n", thread.GetIndexID());
1492             result.SetStatus (eReturnStatusFailed);
1493             return false;
1494         }
1495         return true;
1496     }
1497 
1498     CommandOptions m_options;
1499 
1500 };
1501 
1502 OptionDefinition
1503 CommandObjectThreadInfo::CommandOptions::g_option_table[] =
1504 {
1505     { LLDB_OPT_SET_ALL, false, "json",'j', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the thread info in JSON format."},
1506 
1507     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1508 };
1509 
1510 
1511 //-------------------------------------------------------------------------
1512 // CommandObjectThreadReturn
1513 //-------------------------------------------------------------------------
1514 
1515 class CommandObjectThreadReturn : public CommandObjectRaw
1516 {
1517 public:
1518     class CommandOptions : public Options
1519     {
1520     public:
1521 
1522         CommandOptions (CommandInterpreter &interpreter) :
1523             Options (interpreter),
1524             m_from_expression (false)
1525         {
1526             // Keep default values of all options in one place: OptionParsingStarting ()
1527             OptionParsingStarting ();
1528         }
1529 
1530         virtual
1531         ~CommandOptions ()
1532         {
1533         }
1534 
1535         virtual Error
1536         SetOptionValue (uint32_t option_idx, const char *option_arg)
1537         {
1538             Error error;
1539             const int short_option = m_getopt_table[option_idx].val;
1540 
1541             switch (short_option)
1542             {
1543                 case 'x':
1544                 {
1545                     bool success;
1546                     bool tmp_value = Args::StringToBoolean (option_arg, false, &success);
1547                     if (success)
1548                         m_from_expression = tmp_value;
1549                     else
1550                     {
1551                         error.SetErrorStringWithFormat ("invalid boolean value '%s' for 'x' option", option_arg);
1552                     }
1553                 }
1554                 break;
1555                 default:
1556                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1557                     break;
1558 
1559             }
1560             return error;
1561         }
1562 
1563         void
1564         OptionParsingStarting ()
1565         {
1566             m_from_expression = false;
1567         }
1568 
1569         const OptionDefinition*
1570         GetDefinitions ()
1571         {
1572             return g_option_table;
1573         }
1574 
1575         bool m_from_expression;
1576 
1577         // Options table: Required for subclasses of Options.
1578 
1579         static OptionDefinition g_option_table[];
1580 
1581         // Instance variables to hold the values for command options.
1582     };
1583 
1584     virtual
1585     Options *
1586     GetOptions ()
1587     {
1588         return &m_options;
1589     }
1590 
1591     CommandObjectThreadReturn (CommandInterpreter &interpreter) :
1592         CommandObjectRaw (interpreter,
1593                           "thread return",
1594                           "Return from the currently selected frame, short-circuiting execution of the frames below it, with an optional return value,"
1595                           " or with the -x option from the innermost function evaluation.",
1596                           "thread return",
1597                           eFlagRequiresFrame         |
1598                           eFlagTryTargetAPILock      |
1599                           eFlagProcessMustBeLaunched |
1600                           eFlagProcessMustBePaused   ),
1601         m_options (interpreter)
1602     {
1603         CommandArgumentEntry arg;
1604         CommandArgumentData expression_arg;
1605 
1606         // Define the first (and only) variant of this arg.
1607         expression_arg.arg_type = eArgTypeExpression;
1608         expression_arg.arg_repetition = eArgRepeatOptional;
1609 
1610         // There is only one variant this argument could be; put it into the argument entry.
1611         arg.push_back (expression_arg);
1612 
1613         // Push the data for the first argument into the m_arguments vector.
1614         m_arguments.push_back (arg);
1615 
1616 
1617     }
1618 
1619     ~CommandObjectThreadReturn()
1620     {
1621     }
1622 
1623 protected:
1624 
1625     bool DoExecute
1626     (
1627         const char *command,
1628         CommandReturnObject &result
1629     )
1630     {
1631         // I am going to handle this by hand, because I don't want you to have to say:
1632         // "thread return -- -5".
1633         if (command[0] == '-' && command[1] == 'x')
1634         {
1635             if (command && command[2] != '\0')
1636                 result.AppendWarning("Return values ignored when returning from user called expressions");
1637 
1638             Thread *thread = m_exe_ctx.GetThreadPtr();
1639             Error error;
1640             error = thread->UnwindInnermostExpression();
1641             if (!error.Success())
1642             {
1643                 result.AppendErrorWithFormat ("Unwinding expression failed - %s.", error.AsCString());
1644                 result.SetStatus (eReturnStatusFailed);
1645             }
1646             else
1647             {
1648                 bool success = thread->SetSelectedFrameByIndexNoisily (0, result.GetOutputStream());
1649                 if (success)
1650                 {
1651                     m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ());
1652                     result.SetStatus (eReturnStatusSuccessFinishResult);
1653                 }
1654                 else
1655                 {
1656                     result.AppendErrorWithFormat ("Could not select 0th frame after unwinding expression.");
1657                     result.SetStatus (eReturnStatusFailed);
1658                 }
1659             }
1660             return result.Succeeded();
1661         }
1662 
1663         ValueObjectSP return_valobj_sp;
1664 
1665         StackFrameSP frame_sp = m_exe_ctx.GetFrameSP();
1666         uint32_t frame_idx = frame_sp->GetFrameIndex();
1667 
1668         if (frame_sp->IsInlined())
1669         {
1670             result.AppendError("Don't know how to return from inlined frames.");
1671             result.SetStatus (eReturnStatusFailed);
1672             return false;
1673         }
1674 
1675         if (command && command[0] != '\0')
1676         {
1677             Target *target = m_exe_ctx.GetTargetPtr();
1678             EvaluateExpressionOptions options;
1679 
1680             options.SetUnwindOnError(true);
1681             options.SetUseDynamic(eNoDynamicValues);
1682 
1683             ExpressionResults exe_results = eExpressionSetupError;
1684             exe_results = target->EvaluateExpression (command,
1685                                                       frame_sp.get(),
1686                                                       return_valobj_sp,
1687                                                       options);
1688             if (exe_results != eExpressionCompleted)
1689             {
1690                 if (return_valobj_sp)
1691                     result.AppendErrorWithFormat("Error evaluating result expression: %s", return_valobj_sp->GetError().AsCString());
1692                 else
1693                     result.AppendErrorWithFormat("Unknown error evaluating result expression.");
1694                 result.SetStatus (eReturnStatusFailed);
1695                 return false;
1696 
1697             }
1698         }
1699 
1700         Error error;
1701         ThreadSP thread_sp = m_exe_ctx.GetThreadSP();
1702         const bool broadcast = true;
1703         error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp, broadcast);
1704         if (!error.Success())
1705         {
1706             result.AppendErrorWithFormat("Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString());
1707             result.SetStatus (eReturnStatusFailed);
1708             return false;
1709         }
1710 
1711         result.SetStatus (eReturnStatusSuccessFinishResult);
1712         return true;
1713     }
1714 
1715     CommandOptions m_options;
1716 
1717 };
1718 OptionDefinition
1719 CommandObjectThreadReturn::CommandOptions::g_option_table[] =
1720 {
1721 { LLDB_OPT_SET_ALL, false, "from-expression",  'x', OptionParser::eNoArgument, NULL, NULL,               0, eArgTypeNone,     "Return from the innermost expression evaluation."},
1722 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1723 };
1724 
1725 //-------------------------------------------------------------------------
1726 // CommandObjectThreadJump
1727 //-------------------------------------------------------------------------
1728 
1729 class CommandObjectThreadJump : public CommandObjectParsed
1730 {
1731 public:
1732     class CommandOptions : public Options
1733     {
1734     public:
1735 
1736         CommandOptions (CommandInterpreter &interpreter) :
1737             Options (interpreter)
1738         {
1739             OptionParsingStarting ();
1740         }
1741 
1742         void
1743         OptionParsingStarting ()
1744         {
1745             m_filenames.Clear();
1746             m_line_num = 0;
1747             m_line_offset = 0;
1748             m_load_addr = LLDB_INVALID_ADDRESS;
1749             m_force = false;
1750         }
1751 
1752         virtual
1753         ~CommandOptions ()
1754         {
1755         }
1756 
1757         virtual Error
1758         SetOptionValue (uint32_t option_idx, const char *option_arg)
1759         {
1760             bool success;
1761             const int short_option = m_getopt_table[option_idx].val;
1762             Error error;
1763 
1764             switch (short_option)
1765             {
1766                 case 'f':
1767                     m_filenames.AppendIfUnique (FileSpec(option_arg, false));
1768                     if (m_filenames.GetSize() > 1)
1769                         return Error("only one source file expected.");
1770                     break;
1771                 case 'l':
1772                     m_line_num = Args::StringToUInt32 (option_arg, 0, 0, &success);
1773                     if (!success || m_line_num == 0)
1774                         return Error("invalid line number: '%s'.", option_arg);
1775                     break;
1776                 case 'b':
1777                     m_line_offset = Args::StringToSInt32 (option_arg, 0, 0, &success);
1778                     if (!success)
1779                         return Error("invalid line offset: '%s'.", option_arg);
1780                     break;
1781                 case 'a':
1782                     {
1783                         ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
1784                         m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
1785                     }
1786                     break;
1787                 case 'r':
1788                     m_force = true;
1789                     break;
1790 
1791                  default:
1792                     return Error("invalid short option character '%c'", short_option);
1793 
1794             }
1795             return error;
1796         }
1797 
1798         const OptionDefinition*
1799         GetDefinitions ()
1800         {
1801             return g_option_table;
1802         }
1803 
1804         FileSpecList m_filenames;
1805         uint32_t m_line_num;
1806         int32_t m_line_offset;
1807         lldb::addr_t m_load_addr;
1808         bool m_force;
1809 
1810         static OptionDefinition g_option_table[];
1811     };
1812 
1813     virtual
1814     Options *
1815     GetOptions ()
1816     {
1817         return &m_options;
1818     }
1819 
1820     CommandObjectThreadJump (CommandInterpreter &interpreter) :
1821         CommandObjectParsed (interpreter,
1822                           "thread jump",
1823                           "Sets the program counter to a new address.",
1824                           "thread jump",
1825                           eFlagRequiresFrame         |
1826                           eFlagTryTargetAPILock      |
1827                           eFlagProcessMustBeLaunched |
1828                           eFlagProcessMustBePaused   ),
1829         m_options (interpreter)
1830     {
1831     }
1832 
1833     ~CommandObjectThreadJump()
1834     {
1835     }
1836 
1837 protected:
1838 
1839     bool DoExecute (Args& args, CommandReturnObject &result)
1840     {
1841         RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
1842         StackFrame *frame = m_exe_ctx.GetFramePtr();
1843         Thread *thread = m_exe_ctx.GetThreadPtr();
1844         Target *target = m_exe_ctx.GetTargetPtr();
1845         const SymbolContext &sym_ctx = frame->GetSymbolContext (eSymbolContextLineEntry);
1846 
1847         if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
1848         {
1849             // Use this address directly.
1850             Address dest = Address(m_options.m_load_addr);
1851 
1852             lldb::addr_t callAddr = dest.GetCallableLoadAddress (target);
1853             if (callAddr == LLDB_INVALID_ADDRESS)
1854             {
1855                 result.AppendErrorWithFormat ("Invalid destination address.");
1856                 result.SetStatus (eReturnStatusFailed);
1857                 return false;
1858             }
1859 
1860             if (!reg_ctx->SetPC (callAddr))
1861             {
1862                 result.AppendErrorWithFormat ("Error changing PC value for thread %d.", thread->GetIndexID());
1863                 result.SetStatus (eReturnStatusFailed);
1864                 return false;
1865             }
1866         }
1867         else
1868         {
1869             // Pick either the absolute line, or work out a relative one.
1870             int32_t line = (int32_t)m_options.m_line_num;
1871             if (line == 0)
1872                 line = sym_ctx.line_entry.line + m_options.m_line_offset;
1873 
1874             // Try the current file, but override if asked.
1875             FileSpec file = sym_ctx.line_entry.file;
1876             if (m_options.m_filenames.GetSize() == 1)
1877                 file = m_options.m_filenames.GetFileSpecAtIndex(0);
1878 
1879             if (!file)
1880             {
1881                 result.AppendErrorWithFormat ("No source file available for the current location.");
1882                 result.SetStatus (eReturnStatusFailed);
1883                 return false;
1884             }
1885 
1886             std::string warnings;
1887             Error err = thread->JumpToLine (file, line, m_options.m_force, &warnings);
1888 
1889             if (err.Fail())
1890             {
1891                 result.SetError (err);
1892                 return false;
1893             }
1894 
1895             if (!warnings.empty())
1896                 result.AppendWarning (warnings.c_str());
1897         }
1898 
1899         result.SetStatus (eReturnStatusSuccessFinishResult);
1900         return true;
1901     }
1902 
1903     CommandOptions m_options;
1904 };
1905 OptionDefinition
1906 CommandObjectThreadJump::CommandOptions::g_option_table[] =
1907 {
1908     { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
1909         "Specifies the source file to jump to."},
1910 
1911     { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum,
1912         "Specifies the line number to jump to."},
1913 
1914     { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset,
1915         "Jumps by a relative line offset from the current line."},
1916 
1917     { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression,
1918         "Jumps to a specific address."},
1919 
1920     { LLDB_OPT_SET_1|
1921       LLDB_OPT_SET_2|
1922       LLDB_OPT_SET_3, false, "force",'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,"Allows the PC to leave the current function."},
1923 
1924     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1925 };
1926 
1927 //-------------------------------------------------------------------------
1928 // Next are the subcommands of CommandObjectMultiwordThreadPlan
1929 //-------------------------------------------------------------------------
1930 
1931 
1932 //-------------------------------------------------------------------------
1933 // CommandObjectThreadPlanList
1934 //-------------------------------------------------------------------------
1935 class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads
1936 {
1937 public:
1938 
1939     class CommandOptions : public Options
1940     {
1941     public:
1942 
1943         CommandOptions (CommandInterpreter &interpreter) :
1944             Options(interpreter)
1945         {
1946             // Keep default values of all options in one place: OptionParsingStarting ()
1947             OptionParsingStarting ();
1948         }
1949 
1950         virtual
1951         ~CommandOptions ()
1952         {
1953         }
1954 
1955         virtual Error
1956         SetOptionValue (uint32_t option_idx, const char *option_arg)
1957         {
1958             Error error;
1959             const int short_option = m_getopt_table[option_idx].val;
1960 
1961             switch (short_option)
1962             {
1963                 case 'i':
1964                 {
1965                     m_internal = true;
1966                 }
1967                 break;
1968                 case 'v':
1969                 {
1970                     m_verbose = true;
1971                 }
1972                 break;
1973                 default:
1974                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1975                     break;
1976 
1977             }
1978             return error;
1979         }
1980 
1981         void
1982         OptionParsingStarting ()
1983         {
1984             m_verbose = false;
1985             m_internal = false;
1986         }
1987 
1988         const OptionDefinition*
1989         GetDefinitions ()
1990         {
1991             return g_option_table;
1992         }
1993 
1994         // Options table: Required for subclasses of Options.
1995 
1996         static OptionDefinition g_option_table[];
1997 
1998         // Instance variables to hold the values for command options.
1999         bool m_verbose;
2000         bool m_internal;
2001     };
2002 
2003     CommandObjectThreadPlanList (CommandInterpreter &interpreter) :
2004         CommandObjectIterateOverThreads (interpreter,
2005                                          "thread plan list",
2006                                          "Show thread plans for one or more threads.  If no threads are specified, show the "
2007                                          "currently selected thread.  Use the thread-index \"all\" to see all threads.",
2008                                          NULL,
2009                                          eFlagRequiresProcess       |
2010                                          eFlagRequiresThread        |
2011                                          eFlagTryTargetAPILock      |
2012                                          eFlagProcessMustBeLaunched |
2013                                          eFlagProcessMustBePaused   ),
2014         m_options(interpreter)
2015     {
2016     }
2017 
2018     ~CommandObjectThreadPlanList ()
2019     {
2020     }
2021 
2022     virtual Options *
2023     GetOptions ()
2024     {
2025         return &m_options;
2026     }
2027 
2028 protected:
2029     virtual bool
2030     HandleOneThread (Thread &thread, CommandReturnObject &result)
2031     {
2032         Stream &strm = result.GetOutputStream();
2033         DescriptionLevel desc_level = eDescriptionLevelFull;
2034         if (m_options.m_verbose)
2035             desc_level = eDescriptionLevelVerbose;
2036 
2037         thread.DumpThreadPlans (&strm, desc_level, m_options.m_internal, true);
2038         return true;
2039     }
2040     CommandOptions m_options;
2041 };
2042 
2043 OptionDefinition
2044 CommandObjectThreadPlanList::CommandOptions::g_option_table[] =
2045 {
2046 { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display more information about the thread plans"},
2047 { LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display internal as well as user thread plans"},
2048 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2049 };
2050 
2051 class CommandObjectThreadPlanDiscard : public CommandObjectParsed
2052 {
2053 public:
2054     CommandObjectThreadPlanDiscard (CommandInterpreter &interpreter) :
2055         CommandObjectParsed (interpreter,
2056                              "thread plan discard",
2057                              "Discards thread plans up to and including the plan passed as the command argument."
2058                              "Only user visible plans can be discarded, use the index from \"thread plan list\""
2059                              " without the \"-i\" argument.",
2060                              NULL,
2061                              eFlagRequiresProcess       |
2062                              eFlagRequiresThread        |
2063                              eFlagTryTargetAPILock      |
2064                              eFlagProcessMustBeLaunched |
2065                              eFlagProcessMustBePaused   )
2066     {
2067         CommandArgumentEntry arg;
2068         CommandArgumentData plan_index_arg;
2069 
2070         // Define the first (and only) variant of this arg.
2071         plan_index_arg.arg_type = eArgTypeUnsignedInteger;
2072         plan_index_arg.arg_repetition = eArgRepeatPlain;
2073 
2074         // There is only one variant this argument could be; put it into the argument entry.
2075         arg.push_back (plan_index_arg);
2076 
2077         // Push the data for the first argument into the m_arguments vector.
2078         m_arguments.push_back (arg);
2079     }
2080 
2081     virtual ~CommandObjectThreadPlanDiscard () {}
2082 
2083     bool
2084     DoExecute (Args& args, CommandReturnObject &result)
2085     {
2086         Thread *thread = m_exe_ctx.GetThreadPtr();
2087         if (args.GetArgumentCount() != 1)
2088         {
2089             result.AppendErrorWithFormat("Too many arguments, expected one - the thread plan index - but got %zu.",
2090                                          args.GetArgumentCount());
2091             result.SetStatus (eReturnStatusFailed);
2092             return false;
2093         }
2094 
2095         bool success;
2096         uint32_t thread_plan_idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success);
2097         if (!success)
2098         {
2099             result.AppendErrorWithFormat("Invalid thread index: \"%s\" - should be unsigned int.",
2100                                          args.GetArgumentAtIndex(0));
2101             result.SetStatus (eReturnStatusFailed);
2102             return false;
2103         }
2104 
2105         if (thread_plan_idx == 0)
2106         {
2107             result.AppendErrorWithFormat("You wouldn't really want me to discard the base thread plan.");
2108             result.SetStatus (eReturnStatusFailed);
2109             return false;
2110         }
2111 
2112         if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx))
2113         {
2114             result.SetStatus(eReturnStatusSuccessFinishNoResult);
2115             return true;
2116         }
2117         else
2118         {
2119             result.AppendErrorWithFormat("Could not find User thread plan with index %s.",
2120                                          args.GetArgumentAtIndex(0));
2121             result.SetStatus (eReturnStatusFailed);
2122             return false;
2123         }
2124     }
2125 };
2126 
2127 //-------------------------------------------------------------------------
2128 // CommandObjectMultiwordThreadPlan
2129 //-------------------------------------------------------------------------
2130 
2131 class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword
2132 {
2133 public:
2134     CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) :
2135         CommandObjectMultiword (interpreter,
2136                                 "plan",
2137                                 "A set of subcommands for accessing the thread plans controlling execution control on one or more threads.",
2138                                 "thread plan <subcommand> [<subcommand objects]")
2139     {
2140         LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadPlanList (interpreter)));
2141         LoadSubCommand ("discard", CommandObjectSP (new CommandObjectThreadPlanDiscard (interpreter)));
2142     }
2143 
2144     virtual ~CommandObjectMultiwordThreadPlan () {}
2145 
2146 
2147 };
2148 
2149 //-------------------------------------------------------------------------
2150 // CommandObjectMultiwordThread
2151 //-------------------------------------------------------------------------
2152 
2153 CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
2154     CommandObjectMultiword (interpreter,
2155                             "thread",
2156                             "A set of commands for operating on one or more threads within a running process.",
2157                             "thread <subcommand> [<subcommand-options>]")
2158 {
2159     LoadSubCommand ("backtrace",  CommandObjectSP (new CommandObjectThreadBacktrace (interpreter)));
2160     LoadSubCommand ("continue",   CommandObjectSP (new CommandObjectThreadContinue (interpreter)));
2161     LoadSubCommand ("list",       CommandObjectSP (new CommandObjectThreadList (interpreter)));
2162     LoadSubCommand ("return",     CommandObjectSP (new CommandObjectThreadReturn (interpreter)));
2163     LoadSubCommand ("jump",       CommandObjectSP (new CommandObjectThreadJump (interpreter)));
2164     LoadSubCommand ("select",     CommandObjectSP (new CommandObjectThreadSelect (interpreter)));
2165     LoadSubCommand ("until",      CommandObjectSP (new CommandObjectThreadUntil (interpreter)));
2166     LoadSubCommand ("info",       CommandObjectSP (new CommandObjectThreadInfo (interpreter)));
2167     LoadSubCommand ("step-in",    CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2168                                                     interpreter,
2169                                                     "thread step-in",
2170                                                     "Source level single step in specified thread (current thread, if none specified).",
2171                                                     NULL,
2172                                                     eStepTypeInto,
2173                                                     eStepScopeSource)));
2174 
2175     LoadSubCommand ("step-out",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2176                                                     interpreter,
2177                                                     "thread step-out",
2178                                                     "Finish executing the function of the currently selected frame and return to its call site in specified thread (current thread, if none specified).",
2179                                                     NULL,
2180                                                     eStepTypeOut,
2181                                                     eStepScopeSource)));
2182 
2183     LoadSubCommand ("step-over",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2184                                                     interpreter,
2185                                                     "thread step-over",
2186                                                     "Source level single step in specified thread (current thread, if none specified), stepping over calls.",
2187                                                     NULL,
2188                                                     eStepTypeOver,
2189                                                     eStepScopeSource)));
2190 
2191     LoadSubCommand ("step-inst",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2192                                                     interpreter,
2193                                                     "thread step-inst",
2194                                                     "Single step one instruction in specified thread (current thread, if none specified).",
2195                                                     NULL,
2196                                                     eStepTypeTrace,
2197                                                     eStepScopeInstruction)));
2198 
2199     LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2200                                                     interpreter,
2201                                                     "thread step-inst-over",
2202                                                     "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
2203                                                     NULL,
2204                                                     eStepTypeTraceOver,
2205                                                     eStepScopeInstruction)));
2206 
2207     LoadSubCommand ("step-scripted", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2208                                                     interpreter,
2209                                                     "thread step-scripted",
2210                                                     "Step as instructed by the script class passed in the -C option.",
2211                                                     NULL,
2212                                                     eStepTypeScripted,
2213                                                     eStepScopeSource)));
2214 
2215     LoadSubCommand ("plan", CommandObjectSP (new CommandObjectMultiwordThreadPlan(interpreter)));
2216 }
2217 
2218 CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
2219 {
2220 }
2221 
2222 
2223