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