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