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