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