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