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