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