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