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