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