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