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