xref: /llvm-project/lldb/source/Commands/CommandObjectThread.cpp (revision 547917aebd1e79a8929b53f0ddf3b5185ee4df74)
1 //===-- CommandObjectThread.cpp -------------------------------------------===//
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 <memory>
12 #include <optional>
13 #include <sstream>
14 
15 #include "CommandObjectThreadUtil.h"
16 #include "CommandObjectTrace.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Core/ValueObject.h"
19 #include "lldb/Host/OptionParser.h"
20 #include "lldb/Interpreter/CommandInterpreter.h"
21 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
22 #include "lldb/Interpreter/CommandReturnObject.h"
23 #include "lldb/Interpreter/OptionArgParser.h"
24 #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
25 #include "lldb/Interpreter/Options.h"
26 #include "lldb/Symbol/CompileUnit.h"
27 #include "lldb/Symbol/Function.h"
28 #include "lldb/Symbol/LineEntry.h"
29 #include "lldb/Symbol/LineTable.h"
30 #include "lldb/Target/Process.h"
31 #include "lldb/Target/RegisterContext.h"
32 #include "lldb/Target/SystemRuntime.h"
33 #include "lldb/Target/Target.h"
34 #include "lldb/Target/Thread.h"
35 #include "lldb/Target/ThreadPlan.h"
36 #include "lldb/Target/ThreadPlanStepInRange.h"
37 #include "lldb/Target/Trace.h"
38 #include "lldb/Target/TraceDumper.h"
39 #include "lldb/Utility/State.h"
40 
41 using namespace lldb;
42 using namespace lldb_private;
43 
44 // CommandObjectThreadBacktrace
45 #define LLDB_OPTIONS_thread_backtrace
46 #include "CommandOptions.inc"
47 
48 class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads {
49 public:
50   class CommandOptions : public Options {
51   public:
52     CommandOptions() {
53       // Keep default values of all options in one place: OptionParsingStarting
54       // ()
55       OptionParsingStarting(nullptr);
56     }
57 
58     ~CommandOptions() override = default;
59 
60     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
61                           ExecutionContext *execution_context) override {
62       Status error;
63       const int short_option = m_getopt_table[option_idx].val;
64 
65       switch (short_option) {
66       case 'c':
67         if (option_arg.getAsInteger(0, m_count)) {
68           m_count = UINT32_MAX;
69           error.SetErrorStringWithFormat(
70               "invalid integer value for option '%c': %s", short_option,
71               option_arg.data());
72         }
73         // A count of 0 means all frames.
74         if (m_count == 0)
75           m_count = UINT32_MAX;
76         break;
77       case 's':
78         if (option_arg.getAsInteger(0, m_start))
79           error.SetErrorStringWithFormat(
80               "invalid integer value for option '%c': %s", short_option,
81               option_arg.data());
82         break;
83       case 'e': {
84         bool success;
85         m_extended_backtrace =
86             OptionArgParser::ToBoolean(option_arg, false, &success);
87         if (!success)
88           error.SetErrorStringWithFormat(
89               "invalid boolean value for option '%c': %s", short_option,
90               option_arg.data());
91       } break;
92       default:
93         llvm_unreachable("Unimplemented option");
94       }
95       return error;
96     }
97 
98     void OptionParsingStarting(ExecutionContext *execution_context) override {
99       m_count = UINT32_MAX;
100       m_start = 0;
101       m_extended_backtrace = false;
102     }
103 
104     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
105       return llvm::ArrayRef(g_thread_backtrace_options);
106     }
107 
108     // Instance variables to hold the values for command options.
109     uint32_t m_count;
110     uint32_t m_start;
111     bool m_extended_backtrace;
112   };
113 
114   CommandObjectThreadBacktrace(CommandInterpreter &interpreter)
115       : CommandObjectIterateOverThreads(
116             interpreter, "thread backtrace",
117             "Show backtraces of thread call stacks.  Defaults to the current "
118             "thread, thread indexes can be specified as arguments.\n"
119             "Use the thread-index \"all\" to see all threads.\n"
120             "Use the thread-index \"unique\" to see threads grouped by unique "
121             "call stacks.\n"
122             "Use 'settings set frame-format' to customize the printing of "
123             "frames in the backtrace and 'settings set thread-format' to "
124             "customize the thread header.",
125             nullptr,
126             eCommandRequiresProcess | eCommandRequiresThread |
127                 eCommandTryTargetAPILock | eCommandProcessMustBeLaunched |
128                 eCommandProcessMustBePaused) {}
129 
130   ~CommandObjectThreadBacktrace() override = default;
131 
132   Options *GetOptions() override { return &m_options; }
133 
134   std::optional<std::string> GetRepeatCommand(Args &current_args,
135                                               uint32_t index) override {
136     llvm::StringRef count_opt("--count");
137     llvm::StringRef start_opt("--start");
138 
139     // If no "count" was provided, we are dumping the entire backtrace, so
140     // there isn't a repeat command.  So we search for the count option in
141     // the args, and if we find it, we make a copy and insert or modify the
142     // start option's value to start count indices greater.
143 
144     Args copy_args(current_args);
145     size_t num_entries = copy_args.GetArgumentCount();
146     // These two point at the index of the option value if found.
147     size_t count_idx = 0;
148     size_t start_idx = 0;
149     size_t count_val = 0;
150     size_t start_val = 0;
151 
152     for (size_t idx = 0; idx < num_entries; idx++) {
153       llvm::StringRef arg_string = copy_args[idx].ref();
154       if (arg_string == "-c" || count_opt.starts_with(arg_string)) {
155         idx++;
156         if (idx == num_entries)
157           return std::nullopt;
158         count_idx = idx;
159         if (copy_args[idx].ref().getAsInteger(0, count_val))
160           return std::nullopt;
161       } else if (arg_string == "-s" || start_opt.starts_with(arg_string)) {
162         idx++;
163         if (idx == num_entries)
164           return std::nullopt;
165         start_idx = idx;
166         if (copy_args[idx].ref().getAsInteger(0, start_val))
167           return std::nullopt;
168       }
169     }
170     if (count_idx == 0)
171       return std::nullopt;
172 
173     std::string new_start_val = llvm::formatv("{0}", start_val + count_val);
174     if (start_idx == 0) {
175       copy_args.AppendArgument(start_opt);
176       copy_args.AppendArgument(new_start_val);
177     } else {
178       copy_args.ReplaceArgumentAtIndex(start_idx, new_start_val);
179     }
180     std::string repeat_command;
181     if (!copy_args.GetQuotedCommandString(repeat_command))
182       return std::nullopt;
183     return repeat_command;
184   }
185 
186 protected:
187   void DoExtendedBacktrace(Thread *thread, CommandReturnObject &result) {
188     SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime();
189     if (runtime) {
190       Stream &strm = result.GetOutputStream();
191       const std::vector<ConstString> &types =
192           runtime->GetExtendedBacktraceTypes();
193       for (auto type : types) {
194         ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread(
195             thread->shared_from_this(), type);
196         if (ext_thread_sp && ext_thread_sp->IsValid()) {
197           const uint32_t num_frames_with_source = 0;
198           const bool stop_format = false;
199           strm.PutChar('\n');
200           if (ext_thread_sp->GetStatus(strm, m_options.m_start,
201                                        m_options.m_count,
202                                        num_frames_with_source, stop_format)) {
203             DoExtendedBacktrace(ext_thread_sp.get(), result);
204           }
205         }
206       }
207     }
208   }
209 
210   bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
211     ThreadSP thread_sp =
212         m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
213     if (!thread_sp) {
214       result.AppendErrorWithFormat(
215           "thread disappeared while computing backtraces: 0x%" PRIx64 "\n",
216           tid);
217       return false;
218     }
219 
220     Thread *thread = thread_sp.get();
221 
222     Stream &strm = result.GetOutputStream();
223 
224     // Only dump stack info if we processing unique stacks.
225     const bool only_stacks = m_unique_stacks;
226 
227     // Don't show source context when doing backtraces.
228     const uint32_t num_frames_with_source = 0;
229     const bool stop_format = true;
230     if (!thread->GetStatus(strm, m_options.m_start, m_options.m_count,
231                            num_frames_with_source, stop_format, only_stacks)) {
232       result.AppendErrorWithFormat(
233           "error displaying backtrace for thread: \"0x%4.4x\"\n",
234           thread->GetIndexID());
235       return false;
236     }
237     if (m_options.m_extended_backtrace) {
238       if (!INTERRUPT_REQUESTED(GetDebugger(),
239                                "Interrupt skipped extended backtrace")) {
240         DoExtendedBacktrace(thread, result);
241       }
242     }
243 
244     return true;
245   }
246 
247   CommandOptions m_options;
248 };
249 
250 #define LLDB_OPTIONS_thread_step_scope
251 #include "CommandOptions.inc"
252 
253 class ThreadStepScopeOptionGroup : public OptionGroup {
254 public:
255   ThreadStepScopeOptionGroup() {
256     // Keep default values of all options in one place: OptionParsingStarting
257     // ()
258     OptionParsingStarting(nullptr);
259   }
260 
261   ~ThreadStepScopeOptionGroup() override = default;
262 
263   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
264     return llvm::ArrayRef(g_thread_step_scope_options);
265   }
266 
267   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
268                         ExecutionContext *execution_context) override {
269     Status error;
270     const int short_option =
271         g_thread_step_scope_options[option_idx].short_option;
272 
273     switch (short_option) {
274     case 'a': {
275       bool success;
276       bool avoid_no_debug =
277           OptionArgParser::ToBoolean(option_arg, true, &success);
278       if (!success)
279         error.SetErrorStringWithFormat(
280             "invalid boolean value for option '%c': %s", short_option,
281             option_arg.data());
282       else {
283         m_step_in_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
284       }
285     } break;
286 
287     case 'A': {
288       bool success;
289       bool avoid_no_debug =
290           OptionArgParser::ToBoolean(option_arg, true, &success);
291       if (!success)
292         error.SetErrorStringWithFormat(
293             "invalid boolean value for option '%c': %s", short_option,
294             option_arg.data());
295       else {
296         m_step_out_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
297       }
298     } break;
299 
300     case 'c':
301       if (option_arg.getAsInteger(0, m_step_count))
302         error.SetErrorStringWithFormat(
303             "invalid integer value for option '%c': %s", short_option,
304             option_arg.data());
305       break;
306 
307     case 'm': {
308       auto enum_values = GetDefinitions()[option_idx].enum_values;
309       m_run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum(
310           option_arg, enum_values, eOnlyDuringStepping, error);
311     } break;
312 
313     case 'e':
314       if (option_arg == "block") {
315         m_end_line_is_block_end = true;
316         break;
317       }
318       if (option_arg.getAsInteger(0, m_end_line))
319         error.SetErrorStringWithFormat("invalid end line number '%s'",
320                                        option_arg.str().c_str());
321       break;
322 
323     case 'r':
324       m_avoid_regexp.clear();
325       m_avoid_regexp.assign(std::string(option_arg));
326       break;
327 
328     case 't':
329       m_step_in_target.clear();
330       m_step_in_target.assign(std::string(option_arg));
331       break;
332 
333     default:
334       llvm_unreachable("Unimplemented option");
335     }
336     return error;
337   }
338 
339   void OptionParsingStarting(ExecutionContext *execution_context) override {
340     m_step_in_avoid_no_debug = eLazyBoolCalculate;
341     m_step_out_avoid_no_debug = eLazyBoolCalculate;
342     m_run_mode = eOnlyDuringStepping;
343 
344     // Check if we are in Non-Stop mode
345     TargetSP target_sp =
346         execution_context ? execution_context->GetTargetSP() : TargetSP();
347     ProcessSP process_sp =
348         execution_context ? execution_context->GetProcessSP() : ProcessSP();
349     if (process_sp && process_sp->GetSteppingRunsAllThreads())
350       m_run_mode = eAllThreads;
351 
352     m_avoid_regexp.clear();
353     m_step_in_target.clear();
354     m_step_count = 1;
355     m_end_line = LLDB_INVALID_LINE_NUMBER;
356     m_end_line_is_block_end = false;
357   }
358 
359   // Instance variables to hold the values for command options.
360   LazyBool m_step_in_avoid_no_debug;
361   LazyBool m_step_out_avoid_no_debug;
362   RunMode m_run_mode;
363   std::string m_avoid_regexp;
364   std::string m_step_in_target;
365   uint32_t m_step_count;
366   uint32_t m_end_line;
367   bool m_end_line_is_block_end;
368 };
369 
370 class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed {
371 public:
372   CommandObjectThreadStepWithTypeAndScope(CommandInterpreter &interpreter,
373                                           const char *name, const char *help,
374                                           const char *syntax,
375                                           StepType step_type)
376       : CommandObjectParsed(interpreter, name, help, syntax,
377                             eCommandRequiresProcess | eCommandRequiresThread |
378                                 eCommandTryTargetAPILock |
379                                 eCommandProcessMustBeLaunched |
380                                 eCommandProcessMustBePaused),
381         m_step_type(step_type), m_class_options("scripted step") {
382     AddSimpleArgumentList(eArgTypeThreadIndex, eArgRepeatOptional);
383 
384     if (step_type == eStepTypeScripted) {
385       m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
386                            LLDB_OPT_SET_1);
387     }
388     m_all_options.Append(&m_options);
389     m_all_options.Finalize();
390   }
391 
392   ~CommandObjectThreadStepWithTypeAndScope() override = default;
393 
394   void
395   HandleArgumentCompletion(CompletionRequest &request,
396                            OptionElementVector &opt_element_vector) override {
397     if (request.GetCursorIndex())
398       return;
399     CommandObject::HandleArgumentCompletion(request, opt_element_vector);
400   }
401 
402   Options *GetOptions() override { return &m_all_options; }
403 
404 protected:
405   void DoExecute(Args &command, CommandReturnObject &result) override {
406     Process *process = m_exe_ctx.GetProcessPtr();
407     bool synchronous_execution = m_interpreter.GetSynchronous();
408 
409     const uint32_t num_threads = process->GetThreadList().GetSize();
410     Thread *thread = nullptr;
411 
412     if (command.GetArgumentCount() == 0) {
413       thread = GetDefaultThread();
414 
415       if (thread == nullptr) {
416         result.AppendError("no selected thread in process");
417         return;
418       }
419     } else {
420       const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
421       uint32_t step_thread_idx;
422 
423       if (!llvm::to_integer(thread_idx_cstr, step_thread_idx)) {
424         result.AppendErrorWithFormat("invalid thread index '%s'.\n",
425                                      thread_idx_cstr);
426         return;
427       }
428       thread =
429           process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
430       if (thread == nullptr) {
431         result.AppendErrorWithFormat(
432             "Thread index %u is out of range (valid values are 0 - %u).\n",
433             step_thread_idx, num_threads);
434         return;
435       }
436     }
437 
438     if (m_step_type == eStepTypeScripted) {
439       if (m_class_options.GetName().empty()) {
440         result.AppendErrorWithFormat("empty class name for scripted step.");
441         return;
442       } else if (!GetDebugger().GetScriptInterpreter()->CheckObjectExists(
443                      m_class_options.GetName().c_str())) {
444         result.AppendErrorWithFormat(
445             "class for scripted step: \"%s\" does not exist.",
446             m_class_options.GetName().c_str());
447         return;
448       }
449     }
450 
451     if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER &&
452         m_step_type != eStepTypeInto) {
453       result.AppendErrorWithFormat(
454           "end line option is only valid for step into");
455       return;
456     }
457 
458     const bool abort_other_plans = false;
459     const lldb::RunMode stop_other_threads = m_options.m_run_mode;
460 
461     // This is a bit unfortunate, but not all the commands in this command
462     // object support only while stepping, so I use the bool for them.
463     bool bool_stop_other_threads;
464     if (m_options.m_run_mode == eAllThreads)
465       bool_stop_other_threads = false;
466     else if (m_options.m_run_mode == eOnlyDuringStepping)
467       bool_stop_other_threads = (m_step_type != eStepTypeOut);
468     else
469       bool_stop_other_threads = true;
470 
471     ThreadPlanSP new_plan_sp;
472     Status new_plan_status;
473 
474     if (m_step_type == eStepTypeInto) {
475       StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
476       assert(frame != nullptr);
477 
478       if (frame->HasDebugInformation()) {
479         AddressRange range;
480         SymbolContext sc = frame->GetSymbolContext(eSymbolContextEverything);
481         if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER) {
482           Status error;
483           if (!sc.GetAddressRangeFromHereToEndLine(m_options.m_end_line, range,
484                                                    error)) {
485             result.AppendErrorWithFormat("invalid end-line option: %s.",
486                                          error.AsCString());
487             return;
488           }
489         } else if (m_options.m_end_line_is_block_end) {
490           Status error;
491           Block *block = frame->GetSymbolContext(eSymbolContextBlock).block;
492           if (!block) {
493             result.AppendErrorWithFormat("Could not find the current block.");
494             return;
495           }
496 
497           AddressRange block_range;
498           Address pc_address = frame->GetFrameCodeAddress();
499           block->GetRangeContainingAddress(pc_address, block_range);
500           if (!block_range.GetBaseAddress().IsValid()) {
501             result.AppendErrorWithFormat(
502                 "Could not find the current block address.");
503             return;
504           }
505           lldb::addr_t pc_offset_in_block =
506               pc_address.GetFileAddress() -
507               block_range.GetBaseAddress().GetFileAddress();
508           lldb::addr_t range_length =
509               block_range.GetByteSize() - pc_offset_in_block;
510           range = AddressRange(pc_address, range_length);
511         } else {
512           range = sc.line_entry.range;
513         }
514 
515         new_plan_sp = thread->QueueThreadPlanForStepInRange(
516             abort_other_plans, range,
517             frame->GetSymbolContext(eSymbolContextEverything),
518             m_options.m_step_in_target.c_str(), stop_other_threads,
519             new_plan_status, m_options.m_step_in_avoid_no_debug,
520             m_options.m_step_out_avoid_no_debug);
521 
522         if (new_plan_sp && !m_options.m_avoid_regexp.empty()) {
523           ThreadPlanStepInRange *step_in_range_plan =
524               static_cast<ThreadPlanStepInRange *>(new_plan_sp.get());
525           step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
526         }
527       } else
528         new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
529             false, abort_other_plans, bool_stop_other_threads, new_plan_status);
530     } else if (m_step_type == eStepTypeOver) {
531       StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
532 
533       if (frame->HasDebugInformation())
534         new_plan_sp = thread->QueueThreadPlanForStepOverRange(
535             abort_other_plans,
536             frame->GetSymbolContext(eSymbolContextEverything).line_entry,
537             frame->GetSymbolContext(eSymbolContextEverything),
538             stop_other_threads, new_plan_status,
539             m_options.m_step_out_avoid_no_debug);
540       else
541         new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
542             true, abort_other_plans, bool_stop_other_threads, new_plan_status);
543     } else if (m_step_type == eStepTypeTrace) {
544       new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
545           false, abort_other_plans, bool_stop_other_threads, new_plan_status);
546     } else if (m_step_type == eStepTypeTraceOver) {
547       new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
548           true, abort_other_plans, bool_stop_other_threads, new_plan_status);
549     } else if (m_step_type == eStepTypeOut) {
550       new_plan_sp = thread->QueueThreadPlanForStepOut(
551           abort_other_plans, nullptr, false, bool_stop_other_threads, eVoteYes,
552           eVoteNoOpinion,
553           thread->GetSelectedFrameIndex(DoNoSelectMostRelevantFrame),
554           new_plan_status, m_options.m_step_out_avoid_no_debug);
555     } else if (m_step_type == eStepTypeScripted) {
556       new_plan_sp = thread->QueueThreadPlanForStepScripted(
557           abort_other_plans, m_class_options.GetName().c_str(),
558           m_class_options.GetStructuredData(), bool_stop_other_threads,
559           new_plan_status);
560     } else {
561       result.AppendError("step type is not supported");
562       return;
563     }
564 
565     // If we got a new plan, then set it to be a controlling plan (User level
566     // Plans should be controlling plans so that they can be interruptible).
567     // Then resume the process.
568 
569     if (new_plan_sp) {
570       new_plan_sp->SetIsControllingPlan(true);
571       new_plan_sp->SetOkayToDiscard(false);
572 
573       if (m_options.m_step_count > 1) {
574         if (!new_plan_sp->SetIterationCount(m_options.m_step_count)) {
575           result.AppendWarning(
576               "step operation does not support iteration count.");
577         }
578       }
579 
580       process->GetThreadList().SetSelectedThreadByID(thread->GetID());
581 
582       const uint32_t iohandler_id = process->GetIOHandlerID();
583 
584       StreamString stream;
585       Status error;
586       if (synchronous_execution)
587         error = process->ResumeSynchronous(&stream);
588       else
589         error = process->Resume();
590 
591       if (!error.Success()) {
592         result.AppendMessage(error.AsCString());
593         return;
594       }
595 
596       // There is a race condition where this thread will return up the call
597       // stack to the main command handler and show an (lldb) prompt before
598       // HandlePrivateEvent (from PrivateStateThread) has a chance to call
599       // PushProcessIOHandler().
600       process->SyncIOHandler(iohandler_id, std::chrono::seconds(2));
601 
602       if (synchronous_execution) {
603         // If any state changed events had anything to say, add that to the
604         // result
605         if (stream.GetSize() > 0)
606           result.AppendMessage(stream.GetString());
607 
608         process->GetThreadList().SetSelectedThreadByID(thread->GetID());
609         result.SetDidChangeProcessState(true);
610         result.SetStatus(eReturnStatusSuccessFinishNoResult);
611       } else {
612         result.SetStatus(eReturnStatusSuccessContinuingNoResult);
613       }
614     } else {
615       result.SetError(new_plan_status);
616     }
617   }
618 
619   StepType m_step_type;
620   ThreadStepScopeOptionGroup m_options;
621   OptionGroupPythonClassWithDict m_class_options;
622   OptionGroupOptions m_all_options;
623 };
624 
625 // CommandObjectThreadContinue
626 
627 class CommandObjectThreadContinue : public CommandObjectParsed {
628 public:
629   CommandObjectThreadContinue(CommandInterpreter &interpreter)
630       : CommandObjectParsed(
631             interpreter, "thread continue",
632             "Continue execution of the current target process.  One "
633             "or more threads may be specified, by default all "
634             "threads continue.",
635             nullptr,
636             eCommandRequiresThread | eCommandTryTargetAPILock |
637                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
638     AddSimpleArgumentList(eArgTypeThreadIndex, eArgRepeatPlus);
639   }
640 
641   ~CommandObjectThreadContinue() override = default;
642 
643   void DoExecute(Args &command, CommandReturnObject &result) override {
644     bool synchronous_execution = m_interpreter.GetSynchronous();
645 
646     Process *process = m_exe_ctx.GetProcessPtr();
647     if (process == nullptr) {
648       result.AppendError("no process exists. Cannot continue");
649       return;
650     }
651 
652     StateType state = process->GetState();
653     if ((state == eStateCrashed) || (state == eStateStopped) ||
654         (state == eStateSuspended)) {
655       const size_t argc = command.GetArgumentCount();
656       if (argc > 0) {
657         // These two lines appear at the beginning of both blocks in this
658         // if..else, but that is because we need to release the lock before
659         // calling process->Resume below.
660         std::lock_guard<std::recursive_mutex> guard(
661             process->GetThreadList().GetMutex());
662         const uint32_t num_threads = process->GetThreadList().GetSize();
663         std::vector<Thread *> resume_threads;
664         for (auto &entry : command.entries()) {
665           uint32_t thread_idx;
666           if (entry.ref().getAsInteger(0, thread_idx)) {
667             result.AppendErrorWithFormat(
668                 "invalid thread index argument: \"%s\".\n", entry.c_str());
669             return;
670           }
671           Thread *thread =
672               process->GetThreadList().FindThreadByIndexID(thread_idx).get();
673 
674           if (thread) {
675             resume_threads.push_back(thread);
676           } else {
677             result.AppendErrorWithFormat("invalid thread index %u.\n",
678                                          thread_idx);
679             return;
680           }
681         }
682 
683         if (resume_threads.empty()) {
684           result.AppendError("no valid thread indexes were specified");
685           return;
686         } else {
687           if (resume_threads.size() == 1)
688             result.AppendMessageWithFormat("Resuming thread: ");
689           else
690             result.AppendMessageWithFormat("Resuming threads: ");
691 
692           for (uint32_t idx = 0; idx < num_threads; ++idx) {
693             Thread *thread =
694                 process->GetThreadList().GetThreadAtIndex(idx).get();
695             std::vector<Thread *>::iterator this_thread_pos =
696                 find(resume_threads.begin(), resume_threads.end(), thread);
697 
698             if (this_thread_pos != resume_threads.end()) {
699               resume_threads.erase(this_thread_pos);
700               if (!resume_threads.empty())
701                 result.AppendMessageWithFormat("%u, ", thread->GetIndexID());
702               else
703                 result.AppendMessageWithFormat("%u ", thread->GetIndexID());
704 
705               const bool override_suspend = true;
706               thread->SetResumeState(eStateRunning, override_suspend);
707             } else {
708               thread->SetResumeState(eStateSuspended);
709             }
710           }
711           result.AppendMessageWithFormat("in process %" PRIu64 "\n",
712                                          process->GetID());
713         }
714       } else {
715         // These two lines appear at the beginning of both blocks in this
716         // if..else, but that is because we need to release the lock before
717         // calling process->Resume below.
718         std::lock_guard<std::recursive_mutex> guard(
719             process->GetThreadList().GetMutex());
720         const uint32_t num_threads = process->GetThreadList().GetSize();
721         Thread *current_thread = GetDefaultThread();
722         if (current_thread == nullptr) {
723           result.AppendError("the process doesn't have a current thread");
724           return;
725         }
726         // Set the actions that the threads should each take when resuming
727         for (uint32_t idx = 0; idx < num_threads; ++idx) {
728           Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
729           if (thread == current_thread) {
730             result.AppendMessageWithFormat("Resuming thread 0x%4.4" PRIx64
731                                            " in process %" PRIu64 "\n",
732                                            thread->GetID(), process->GetID());
733             const bool override_suspend = true;
734             thread->SetResumeState(eStateRunning, override_suspend);
735           } else {
736             thread->SetResumeState(eStateSuspended);
737           }
738         }
739       }
740 
741       StreamString stream;
742       Status error;
743       if (synchronous_execution)
744         error = process->ResumeSynchronous(&stream);
745       else
746         error = process->Resume();
747 
748       // We should not be holding the thread list lock when we do this.
749       if (error.Success()) {
750         result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n",
751                                        process->GetID());
752         if (synchronous_execution) {
753           // If any state changed events had anything to say, add that to the
754           // result
755           if (stream.GetSize() > 0)
756             result.AppendMessage(stream.GetString());
757 
758           result.SetDidChangeProcessState(true);
759           result.SetStatus(eReturnStatusSuccessFinishNoResult);
760         } else {
761           result.SetStatus(eReturnStatusSuccessContinuingNoResult);
762         }
763       } else {
764         result.AppendErrorWithFormat("Failed to resume process: %s\n",
765                                      error.AsCString());
766       }
767     } else {
768       result.AppendErrorWithFormat(
769           "Process cannot be continued from its current state (%s).\n",
770           StateAsCString(state));
771     }
772   }
773 };
774 
775 // CommandObjectThreadUntil
776 
777 #define LLDB_OPTIONS_thread_until
778 #include "CommandOptions.inc"
779 
780 class CommandObjectThreadUntil : public CommandObjectParsed {
781 public:
782   class CommandOptions : public Options {
783   public:
784     uint32_t m_thread_idx = LLDB_INVALID_THREAD_ID;
785     uint32_t m_frame_idx = LLDB_INVALID_FRAME_ID;
786 
787     CommandOptions() {
788       // Keep default values of all options in one place: OptionParsingStarting
789       // ()
790       OptionParsingStarting(nullptr);
791     }
792 
793     ~CommandOptions() override = default;
794 
795     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
796                           ExecutionContext *execution_context) override {
797       Status error;
798       const int short_option = m_getopt_table[option_idx].val;
799 
800       switch (short_option) {
801       case 'a': {
802         lldb::addr_t tmp_addr = OptionArgParser::ToAddress(
803             execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
804         if (error.Success())
805           m_until_addrs.push_back(tmp_addr);
806       } break;
807       case 't':
808         if (option_arg.getAsInteger(0, m_thread_idx)) {
809           m_thread_idx = LLDB_INVALID_INDEX32;
810           error.SetErrorStringWithFormat("invalid thread index '%s'",
811                                          option_arg.str().c_str());
812         }
813         break;
814       case 'f':
815         if (option_arg.getAsInteger(0, m_frame_idx)) {
816           m_frame_idx = LLDB_INVALID_FRAME_ID;
817           error.SetErrorStringWithFormat("invalid frame index '%s'",
818                                          option_arg.str().c_str());
819         }
820         break;
821       case 'm': {
822         auto enum_values = GetDefinitions()[option_idx].enum_values;
823         lldb::RunMode run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum(
824             option_arg, enum_values, eOnlyDuringStepping, error);
825 
826         if (error.Success()) {
827           if (run_mode == eAllThreads)
828             m_stop_others = false;
829           else
830             m_stop_others = true;
831         }
832       } break;
833       default:
834         llvm_unreachable("Unimplemented option");
835       }
836       return error;
837     }
838 
839     void OptionParsingStarting(ExecutionContext *execution_context) override {
840       m_thread_idx = LLDB_INVALID_THREAD_ID;
841       m_frame_idx = 0;
842       m_stop_others = false;
843       m_until_addrs.clear();
844     }
845 
846     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
847       return llvm::ArrayRef(g_thread_until_options);
848     }
849 
850     uint32_t m_step_thread_idx = LLDB_INVALID_THREAD_ID;
851     bool m_stop_others = false;
852     std::vector<lldb::addr_t> m_until_addrs;
853 
854     // Instance variables to hold the values for command options.
855   };
856 
857   CommandObjectThreadUntil(CommandInterpreter &interpreter)
858       : CommandObjectParsed(
859             interpreter, "thread until",
860             "Continue until a line number or address is reached by the "
861             "current or specified thread.  Stops when returning from "
862             "the current function as a safety measure.  "
863             "The target line number(s) are given as arguments, and if more "
864             "than one"
865             " is provided, stepping will stop when the first one is hit.",
866             nullptr,
867             eCommandRequiresThread | eCommandTryTargetAPILock |
868                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
869     AddSimpleArgumentList(eArgTypeLineNum);
870   }
871 
872   ~CommandObjectThreadUntil() override = default;
873 
874   Options *GetOptions() override { return &m_options; }
875 
876 protected:
877   void DoExecute(Args &command, CommandReturnObject &result) override {
878     bool synchronous_execution = m_interpreter.GetSynchronous();
879 
880     Target *target = &GetTarget();
881 
882     Process *process = m_exe_ctx.GetProcessPtr();
883     if (process == nullptr) {
884       result.AppendError("need a valid process to step");
885     } else {
886       Thread *thread = nullptr;
887       std::vector<uint32_t> line_numbers;
888 
889       if (command.GetArgumentCount() >= 1) {
890         size_t num_args = command.GetArgumentCount();
891         for (size_t i = 0; i < num_args; i++) {
892           uint32_t line_number;
893           if (!llvm::to_integer(command.GetArgumentAtIndex(i), line_number)) {
894             result.AppendErrorWithFormat("invalid line number: '%s'.\n",
895                                          command.GetArgumentAtIndex(i));
896             return;
897           } else
898             line_numbers.push_back(line_number);
899         }
900       } else if (m_options.m_until_addrs.empty()) {
901         result.AppendErrorWithFormat("No line number or address provided:\n%s",
902                                      GetSyntax().str().c_str());
903         return;
904       }
905 
906       if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) {
907         thread = GetDefaultThread();
908       } else {
909         thread = process->GetThreadList()
910                      .FindThreadByIndexID(m_options.m_thread_idx)
911                      .get();
912       }
913 
914       if (thread == nullptr) {
915         const uint32_t num_threads = process->GetThreadList().GetSize();
916         result.AppendErrorWithFormat(
917             "Thread index %u is out of range (valid values are 0 - %u).\n",
918             m_options.m_thread_idx, num_threads);
919         return;
920       }
921 
922       const bool abort_other_plans = false;
923 
924       StackFrame *frame =
925           thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
926       if (frame == nullptr) {
927         result.AppendErrorWithFormat(
928             "Frame index %u is out of range for thread id %" PRIu64 ".\n",
929             m_options.m_frame_idx, thread->GetID());
930         return;
931       }
932 
933       ThreadPlanSP new_plan_sp;
934       Status new_plan_status;
935 
936       if (frame->HasDebugInformation()) {
937         // Finally we got here...  Translate the given line number to a bunch
938         // of addresses:
939         SymbolContext sc(frame->GetSymbolContext(eSymbolContextCompUnit));
940         LineTable *line_table = nullptr;
941         if (sc.comp_unit)
942           line_table = sc.comp_unit->GetLineTable();
943 
944         if (line_table == nullptr) {
945           result.AppendErrorWithFormat("Failed to resolve the line table for "
946                                        "frame %u of thread id %" PRIu64 ".\n",
947                                        m_options.m_frame_idx, thread->GetID());
948           return;
949         }
950 
951         LineEntry function_start;
952         uint32_t index_ptr = 0, end_ptr = UINT32_MAX;
953         std::vector<addr_t> address_list;
954 
955         // Find the beginning & end index of the function, but first make
956         // sure it is valid:
957         if (!sc.function) {
958           result.AppendErrorWithFormat("Have debug information but no "
959                                        "function info - can't get until range.");
960           return;
961         }
962 
963         AddressRange fun_addr_range = sc.function->GetAddressRange();
964         Address fun_start_addr = fun_addr_range.GetBaseAddress();
965         line_table->FindLineEntryByAddress(fun_start_addr, function_start,
966                                            &index_ptr);
967 
968         Address fun_end_addr(fun_start_addr.GetSection(),
969                              fun_start_addr.GetOffset() +
970                                  fun_addr_range.GetByteSize());
971 
972         bool all_in_function = true;
973 
974         line_table->FindLineEntryByAddress(fun_end_addr, function_start,
975                                            &end_ptr);
976 
977         // Since not all source lines will contribute code, check if we are
978         // setting the breakpoint on the exact line number or the nearest
979         // subsequent line number and set breakpoints at all the line table
980         // entries of the chosen line number (exact or nearest subsequent).
981         for (uint32_t line_number : line_numbers) {
982           LineEntry line_entry;
983           bool exact = false;
984           uint32_t start_idx_ptr = index_ptr;
985           start_idx_ptr = sc.comp_unit->FindLineEntry(
986               index_ptr, line_number, nullptr, exact, &line_entry);
987           if (start_idx_ptr != UINT32_MAX)
988             line_number = line_entry.line;
989           exact = true;
990           start_idx_ptr = index_ptr;
991           while (start_idx_ptr <= end_ptr) {
992             start_idx_ptr = sc.comp_unit->FindLineEntry(
993                 start_idx_ptr, line_number, nullptr, exact, &line_entry);
994             if (start_idx_ptr == UINT32_MAX)
995               break;
996 
997             addr_t address =
998                 line_entry.range.GetBaseAddress().GetLoadAddress(target);
999             if (address != LLDB_INVALID_ADDRESS) {
1000               if (fun_addr_range.ContainsLoadAddress(address, target))
1001                 address_list.push_back(address);
1002               else
1003                 all_in_function = false;
1004             }
1005             start_idx_ptr++;
1006           }
1007         }
1008 
1009         for (lldb::addr_t address : m_options.m_until_addrs) {
1010           if (fun_addr_range.ContainsLoadAddress(address, target))
1011             address_list.push_back(address);
1012           else
1013             all_in_function = false;
1014         }
1015 
1016         if (address_list.empty()) {
1017           if (all_in_function)
1018             result.AppendErrorWithFormat(
1019                 "No line entries matching until target.\n");
1020           else
1021             result.AppendErrorWithFormat(
1022                 "Until target outside of the current function.\n");
1023 
1024           return;
1025         }
1026 
1027         new_plan_sp = thread->QueueThreadPlanForStepUntil(
1028             abort_other_plans, &address_list.front(), address_list.size(),
1029             m_options.m_stop_others, m_options.m_frame_idx, new_plan_status);
1030         if (new_plan_sp) {
1031           // User level plans should be controlling plans so they can be
1032           // interrupted
1033           // (e.g. by hitting a breakpoint) and other plans executed by the
1034           // user (stepping around the breakpoint) and then a "continue" will
1035           // resume the original plan.
1036           new_plan_sp->SetIsControllingPlan(true);
1037           new_plan_sp->SetOkayToDiscard(false);
1038         } else {
1039           result.SetError(new_plan_status);
1040           return;
1041         }
1042       } else {
1043         result.AppendErrorWithFormat("Frame index %u of thread id %" PRIu64
1044                                      " has no debug information.\n",
1045                                      m_options.m_frame_idx, thread->GetID());
1046         return;
1047       }
1048 
1049       if (!process->GetThreadList().SetSelectedThreadByID(thread->GetID())) {
1050         result.AppendErrorWithFormat(
1051             "Failed to set the selected thread to thread id %" PRIu64 ".\n",
1052             thread->GetID());
1053         return;
1054       }
1055 
1056       StreamString stream;
1057       Status error;
1058       if (synchronous_execution)
1059         error = process->ResumeSynchronous(&stream);
1060       else
1061         error = process->Resume();
1062 
1063       if (error.Success()) {
1064         result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n",
1065                                        process->GetID());
1066         if (synchronous_execution) {
1067           // If any state changed events had anything to say, add that to the
1068           // result
1069           if (stream.GetSize() > 0)
1070             result.AppendMessage(stream.GetString());
1071 
1072           result.SetDidChangeProcessState(true);
1073           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1074         } else {
1075           result.SetStatus(eReturnStatusSuccessContinuingNoResult);
1076         }
1077       } else {
1078         result.AppendErrorWithFormat("Failed to resume process: %s.\n",
1079                                      error.AsCString());
1080       }
1081     }
1082   }
1083 
1084   CommandOptions m_options;
1085 };
1086 
1087 // CommandObjectThreadSelect
1088 
1089 #define LLDB_OPTIONS_thread_select
1090 #include "CommandOptions.inc"
1091 
1092 class CommandObjectThreadSelect : public CommandObjectParsed {
1093 public:
1094   class OptionGroupThreadSelect : public OptionGroup {
1095   public:
1096     OptionGroupThreadSelect() { OptionParsingStarting(nullptr); }
1097 
1098     ~OptionGroupThreadSelect() override = default;
1099 
1100     void OptionParsingStarting(ExecutionContext *execution_context) override {
1101       m_thread_id = LLDB_INVALID_THREAD_ID;
1102     }
1103 
1104     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1105                           ExecutionContext *execution_context) override {
1106       const int short_option = g_thread_select_options[option_idx].short_option;
1107       switch (short_option) {
1108       case 't': {
1109         if (option_arg.getAsInteger(0, m_thread_id)) {
1110           m_thread_id = LLDB_INVALID_THREAD_ID;
1111           return Status("Invalid thread ID: '%s'.", option_arg.str().c_str());
1112         }
1113         break;
1114       }
1115 
1116       default:
1117         llvm_unreachable("Unimplemented option");
1118       }
1119 
1120       return {};
1121     }
1122 
1123     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1124       return llvm::ArrayRef(g_thread_select_options);
1125     }
1126 
1127     lldb::tid_t m_thread_id;
1128   };
1129 
1130   CommandObjectThreadSelect(CommandInterpreter &interpreter)
1131       : CommandObjectParsed(interpreter, "thread select",
1132                             "Change the currently selected thread.",
1133                             "thread select <thread-index> (or -t <thread-id>)",
1134                             eCommandRequiresProcess | eCommandTryTargetAPILock |
1135                                 eCommandProcessMustBeLaunched |
1136                                 eCommandProcessMustBePaused) {
1137     CommandArgumentEntry arg;
1138     CommandArgumentData thread_idx_arg;
1139 
1140     // Define the first (and only) variant of this arg.
1141     thread_idx_arg.arg_type = eArgTypeThreadIndex;
1142     thread_idx_arg.arg_repetition = eArgRepeatPlain;
1143     thread_idx_arg.arg_opt_set_association = LLDB_OPT_SET_1;
1144 
1145     // There is only one variant this argument could be; put it into the
1146     // argument entry.
1147     arg.push_back(thread_idx_arg);
1148 
1149     // Push the data for the first argument into the m_arguments vector.
1150     m_arguments.push_back(arg);
1151 
1152     m_option_group.Append(&m_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1153     m_option_group.Finalize();
1154   }
1155 
1156   ~CommandObjectThreadSelect() override = default;
1157 
1158   void
1159   HandleArgumentCompletion(CompletionRequest &request,
1160                            OptionElementVector &opt_element_vector) override {
1161     if (request.GetCursorIndex())
1162       return;
1163 
1164     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1165         GetCommandInterpreter(), lldb::eThreadIndexCompletion, request,
1166         nullptr);
1167   }
1168 
1169   Options *GetOptions() override { return &m_option_group; }
1170 
1171 protected:
1172   void DoExecute(Args &command, CommandReturnObject &result) override {
1173     Process *process = m_exe_ctx.GetProcessPtr();
1174     if (process == nullptr) {
1175       result.AppendError("no process");
1176       return;
1177     } else if (m_options.m_thread_id == LLDB_INVALID_THREAD_ID &&
1178                command.GetArgumentCount() != 1) {
1179       result.AppendErrorWithFormat(
1180           "'%s' takes exactly one thread index argument, or a thread ID "
1181           "option:\nUsage: %s\n",
1182           m_cmd_name.c_str(), m_cmd_syntax.c_str());
1183       return;
1184     } else if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID &&
1185                command.GetArgumentCount() != 0) {
1186       result.AppendErrorWithFormat("'%s' cannot take both a thread ID option "
1187                                    "and a thread index argument:\nUsage: %s\n",
1188                                    m_cmd_name.c_str(), m_cmd_syntax.c_str());
1189       return;
1190     }
1191 
1192     Thread *new_thread = nullptr;
1193     if (command.GetArgumentCount() == 1) {
1194       uint32_t index_id;
1195       if (!llvm::to_integer(command.GetArgumentAtIndex(0), index_id)) {
1196         result.AppendErrorWithFormat("Invalid thread index '%s'",
1197                                      command.GetArgumentAtIndex(0));
1198         return;
1199       }
1200       new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1201       if (new_thread == nullptr) {
1202         result.AppendErrorWithFormat("Invalid thread index #%s.\n",
1203                                      command.GetArgumentAtIndex(0));
1204         return;
1205       }
1206     } else {
1207       new_thread =
1208           process->GetThreadList().FindThreadByID(m_options.m_thread_id).get();
1209       if (new_thread == nullptr) {
1210         result.AppendErrorWithFormat("Invalid thread ID %" PRIu64 ".\n",
1211                                      m_options.m_thread_id);
1212         return;
1213       }
1214     }
1215 
1216     process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true);
1217     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1218   }
1219 
1220   OptionGroupThreadSelect m_options;
1221   OptionGroupOptions m_option_group;
1222 };
1223 
1224 // CommandObjectThreadList
1225 
1226 class CommandObjectThreadList : public CommandObjectParsed {
1227 public:
1228   CommandObjectThreadList(CommandInterpreter &interpreter)
1229       : CommandObjectParsed(
1230             interpreter, "thread list",
1231             "Show a summary of each thread in the current target process.  "
1232             "Use 'settings set thread-format' to customize the individual "
1233             "thread listings.",
1234             "thread list",
1235             eCommandRequiresProcess | eCommandTryTargetAPILock |
1236                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
1237 
1238   ~CommandObjectThreadList() override = default;
1239 
1240 protected:
1241   void DoExecute(Args &command, CommandReturnObject &result) override {
1242     Stream &strm = result.GetOutputStream();
1243     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1244     Process *process = m_exe_ctx.GetProcessPtr();
1245     const bool only_threads_with_stop_reason = false;
1246     const uint32_t start_frame = 0;
1247     const uint32_t num_frames = 0;
1248     const uint32_t num_frames_with_source = 0;
1249     process->GetStatus(strm);
1250     process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,
1251                              num_frames, num_frames_with_source, false);
1252   }
1253 };
1254 
1255 // CommandObjectThreadInfo
1256 #define LLDB_OPTIONS_thread_info
1257 #include "CommandOptions.inc"
1258 
1259 class CommandObjectThreadInfo : public CommandObjectIterateOverThreads {
1260 public:
1261   class CommandOptions : public Options {
1262   public:
1263     CommandOptions() { OptionParsingStarting(nullptr); }
1264 
1265     ~CommandOptions() override = default;
1266 
1267     void OptionParsingStarting(ExecutionContext *execution_context) override {
1268       m_json_thread = false;
1269       m_json_stopinfo = false;
1270     }
1271 
1272     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1273                           ExecutionContext *execution_context) override {
1274       const int short_option = m_getopt_table[option_idx].val;
1275       Status error;
1276 
1277       switch (short_option) {
1278       case 'j':
1279         m_json_thread = true;
1280         break;
1281 
1282       case 's':
1283         m_json_stopinfo = true;
1284         break;
1285 
1286       default:
1287         llvm_unreachable("Unimplemented option");
1288       }
1289       return error;
1290     }
1291 
1292     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1293       return llvm::ArrayRef(g_thread_info_options);
1294     }
1295 
1296     bool m_json_thread;
1297     bool m_json_stopinfo;
1298   };
1299 
1300   CommandObjectThreadInfo(CommandInterpreter &interpreter)
1301       : CommandObjectIterateOverThreads(
1302             interpreter, "thread info",
1303             "Show an extended summary of one or "
1304             "more threads.  Defaults to the "
1305             "current thread.",
1306             "thread info",
1307             eCommandRequiresProcess | eCommandTryTargetAPILock |
1308                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
1309     m_add_return = false;
1310   }
1311 
1312   ~CommandObjectThreadInfo() override = default;
1313 
1314   void
1315   HandleArgumentCompletion(CompletionRequest &request,
1316                            OptionElementVector &opt_element_vector) override {
1317     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1318         GetCommandInterpreter(), lldb::eThreadIndexCompletion, request,
1319         nullptr);
1320   }
1321 
1322   Options *GetOptions() override { return &m_options; }
1323 
1324   bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
1325     ThreadSP thread_sp =
1326         m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
1327     if (!thread_sp) {
1328       result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n",
1329                                    tid);
1330       return false;
1331     }
1332 
1333     Thread *thread = thread_sp.get();
1334 
1335     Stream &strm = result.GetOutputStream();
1336     if (!thread->GetDescription(strm, eDescriptionLevelFull,
1337                                 m_options.m_json_thread,
1338                                 m_options.m_json_stopinfo)) {
1339       result.AppendErrorWithFormat("error displaying info for thread: \"%d\"\n",
1340                                    thread->GetIndexID());
1341       return false;
1342     }
1343     return true;
1344   }
1345 
1346   CommandOptions m_options;
1347 };
1348 
1349 // CommandObjectThreadException
1350 
1351 class CommandObjectThreadException : public CommandObjectIterateOverThreads {
1352 public:
1353   CommandObjectThreadException(CommandInterpreter &interpreter)
1354       : CommandObjectIterateOverThreads(
1355             interpreter, "thread exception",
1356             "Display the current exception object for a thread. Defaults to "
1357             "the current thread.",
1358             "thread exception",
1359             eCommandRequiresProcess | eCommandTryTargetAPILock |
1360                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
1361 
1362   ~CommandObjectThreadException() override = default;
1363 
1364   void
1365   HandleArgumentCompletion(CompletionRequest &request,
1366                            OptionElementVector &opt_element_vector) override {
1367     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1368         GetCommandInterpreter(), lldb::eThreadIndexCompletion, request,
1369         nullptr);
1370   }
1371 
1372   bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
1373     ThreadSP thread_sp =
1374         m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
1375     if (!thread_sp) {
1376       result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n",
1377                                    tid);
1378       return false;
1379     }
1380 
1381     Stream &strm = result.GetOutputStream();
1382     ValueObjectSP exception_object_sp = thread_sp->GetCurrentException();
1383     if (exception_object_sp) {
1384       if (llvm::Error error = exception_object_sp->Dump(strm)) {
1385         result.AppendError(toString(std::move(error)));
1386         return false;
1387       }
1388     }
1389 
1390     ThreadSP exception_thread_sp = thread_sp->GetCurrentExceptionBacktrace();
1391     if (exception_thread_sp && exception_thread_sp->IsValid()) {
1392       const uint32_t num_frames_with_source = 0;
1393       const bool stop_format = false;
1394       exception_thread_sp->GetStatus(strm, 0, UINT32_MAX,
1395                                      num_frames_with_source, stop_format);
1396     }
1397 
1398     return true;
1399   }
1400 };
1401 
1402 class CommandObjectThreadSiginfo : public CommandObjectIterateOverThreads {
1403 public:
1404   CommandObjectThreadSiginfo(CommandInterpreter &interpreter)
1405       : CommandObjectIterateOverThreads(
1406             interpreter, "thread siginfo",
1407             "Display the current siginfo object for a thread. Defaults to "
1408             "the current thread.",
1409             "thread siginfo",
1410             eCommandRequiresProcess | eCommandTryTargetAPILock |
1411                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
1412 
1413   ~CommandObjectThreadSiginfo() override = default;
1414 
1415   void
1416   HandleArgumentCompletion(CompletionRequest &request,
1417                            OptionElementVector &opt_element_vector) override {
1418     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1419         GetCommandInterpreter(), lldb::eThreadIndexCompletion, request,
1420         nullptr);
1421   }
1422 
1423   bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
1424     ThreadSP thread_sp =
1425         m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
1426     if (!thread_sp) {
1427       result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n",
1428                                    tid);
1429       return false;
1430     }
1431 
1432     Stream &strm = result.GetOutputStream();
1433     if (!thread_sp->GetDescription(strm, eDescriptionLevelFull, false, false)) {
1434       result.AppendErrorWithFormat("error displaying info for thread: \"%d\"\n",
1435                                    thread_sp->GetIndexID());
1436       return false;
1437     }
1438     ValueObjectSP exception_object_sp = thread_sp->GetSiginfoValue();
1439     if (exception_object_sp) {
1440       if (llvm::Error error = exception_object_sp->Dump(strm)) {
1441         result.AppendError(toString(std::move(error)));
1442         return false;
1443       }
1444     } else
1445       strm.Printf("(no siginfo)\n");
1446     strm.PutChar('\n');
1447 
1448     return true;
1449   }
1450 };
1451 
1452 // CommandObjectThreadReturn
1453 #define LLDB_OPTIONS_thread_return
1454 #include "CommandOptions.inc"
1455 
1456 class CommandObjectThreadReturn : public CommandObjectRaw {
1457 public:
1458   class CommandOptions : public Options {
1459   public:
1460     CommandOptions() {
1461       // Keep default values of all options in one place: OptionParsingStarting
1462       // ()
1463       OptionParsingStarting(nullptr);
1464     }
1465 
1466     ~CommandOptions() override = default;
1467 
1468     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1469                           ExecutionContext *execution_context) override {
1470       Status error;
1471       const int short_option = m_getopt_table[option_idx].val;
1472 
1473       switch (short_option) {
1474       case 'x': {
1475         bool success;
1476         bool tmp_value =
1477             OptionArgParser::ToBoolean(option_arg, false, &success);
1478         if (success)
1479           m_from_expression = tmp_value;
1480         else {
1481           error.SetErrorStringWithFormat(
1482               "invalid boolean value '%s' for 'x' option",
1483               option_arg.str().c_str());
1484         }
1485       } break;
1486       default:
1487         llvm_unreachable("Unimplemented option");
1488       }
1489       return error;
1490     }
1491 
1492     void OptionParsingStarting(ExecutionContext *execution_context) override {
1493       m_from_expression = false;
1494     }
1495 
1496     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1497       return llvm::ArrayRef(g_thread_return_options);
1498     }
1499 
1500     bool m_from_expression = false;
1501 
1502     // Instance variables to hold the values for command options.
1503   };
1504 
1505   CommandObjectThreadReturn(CommandInterpreter &interpreter)
1506       : CommandObjectRaw(interpreter, "thread return",
1507                          "Prematurely return from a stack frame, "
1508                          "short-circuiting execution of newer frames "
1509                          "and optionally yielding a specified value.  Defaults "
1510                          "to the exiting the current stack "
1511                          "frame.",
1512                          "thread return",
1513                          eCommandRequiresFrame | eCommandTryTargetAPILock |
1514                              eCommandProcessMustBeLaunched |
1515                              eCommandProcessMustBePaused) {
1516     AddSimpleArgumentList(eArgTypeExpression, eArgRepeatOptional);
1517   }
1518 
1519   ~CommandObjectThreadReturn() override = default;
1520 
1521   Options *GetOptions() override { return &m_options; }
1522 
1523 protected:
1524   void DoExecute(llvm::StringRef command,
1525                  CommandReturnObject &result) override {
1526     // I am going to handle this by hand, because I don't want you to have to
1527     // say:
1528     // "thread return -- -5".
1529     if (command.starts_with("-x")) {
1530       if (command.size() != 2U)
1531         result.AppendWarning("Return values ignored when returning from user "
1532                              "called expressions");
1533 
1534       Thread *thread = m_exe_ctx.GetThreadPtr();
1535       Status error;
1536       error = thread->UnwindInnermostExpression();
1537       if (!error.Success()) {
1538         result.AppendErrorWithFormat("Unwinding expression failed - %s.",
1539                                      error.AsCString());
1540       } else {
1541         bool success =
1542             thread->SetSelectedFrameByIndexNoisily(0, result.GetOutputStream());
1543         if (success) {
1544           m_exe_ctx.SetFrameSP(
1545               thread->GetSelectedFrame(DoNoSelectMostRelevantFrame));
1546           result.SetStatus(eReturnStatusSuccessFinishResult);
1547         } else {
1548           result.AppendErrorWithFormat(
1549               "Could not select 0th frame after unwinding expression.");
1550         }
1551       }
1552       return;
1553     }
1554 
1555     ValueObjectSP return_valobj_sp;
1556 
1557     StackFrameSP frame_sp = m_exe_ctx.GetFrameSP();
1558     uint32_t frame_idx = frame_sp->GetFrameIndex();
1559 
1560     if (frame_sp->IsInlined()) {
1561       result.AppendError("Don't know how to return from inlined frames.");
1562       return;
1563     }
1564 
1565     if (!command.empty()) {
1566       Target *target = m_exe_ctx.GetTargetPtr();
1567       EvaluateExpressionOptions options;
1568 
1569       options.SetUnwindOnError(true);
1570       options.SetUseDynamic(eNoDynamicValues);
1571 
1572       ExpressionResults exe_results = eExpressionSetupError;
1573       exe_results = target->EvaluateExpression(command, frame_sp.get(),
1574                                                return_valobj_sp, options);
1575       if (exe_results != eExpressionCompleted) {
1576         if (return_valobj_sp)
1577           result.AppendErrorWithFormat(
1578               "Error evaluating result expression: %s",
1579               return_valobj_sp->GetError().AsCString());
1580         else
1581           result.AppendErrorWithFormat(
1582               "Unknown error evaluating result expression.");
1583         return;
1584       }
1585     }
1586 
1587     Status error;
1588     ThreadSP thread_sp = m_exe_ctx.GetThreadSP();
1589     const bool broadcast = true;
1590     error = thread_sp->ReturnFromFrame(frame_sp, return_valobj_sp, broadcast);
1591     if (!error.Success()) {
1592       result.AppendErrorWithFormat(
1593           "Error returning from frame %d of thread %d: %s.", frame_idx,
1594           thread_sp->GetIndexID(), error.AsCString());
1595       return;
1596     }
1597 
1598     result.SetStatus(eReturnStatusSuccessFinishResult);
1599   }
1600 
1601   CommandOptions m_options;
1602 };
1603 
1604 // CommandObjectThreadJump
1605 #define LLDB_OPTIONS_thread_jump
1606 #include "CommandOptions.inc"
1607 
1608 class CommandObjectThreadJump : public CommandObjectParsed {
1609 public:
1610   class CommandOptions : public Options {
1611   public:
1612     CommandOptions() { OptionParsingStarting(nullptr); }
1613 
1614     ~CommandOptions() override = default;
1615 
1616     void OptionParsingStarting(ExecutionContext *execution_context) override {
1617       m_filenames.Clear();
1618       m_line_num = 0;
1619       m_line_offset = 0;
1620       m_load_addr = LLDB_INVALID_ADDRESS;
1621       m_force = false;
1622     }
1623 
1624     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1625                           ExecutionContext *execution_context) override {
1626       const int short_option = m_getopt_table[option_idx].val;
1627       Status error;
1628 
1629       switch (short_option) {
1630       case 'f':
1631         m_filenames.AppendIfUnique(FileSpec(option_arg));
1632         if (m_filenames.GetSize() > 1)
1633           return Status("only one source file expected.");
1634         break;
1635       case 'l':
1636         if (option_arg.getAsInteger(0, m_line_num))
1637           return Status("invalid line number: '%s'.", option_arg.str().c_str());
1638         break;
1639       case 'b':
1640         if (option_arg.getAsInteger(0, m_line_offset))
1641           return Status("invalid line offset: '%s'.", option_arg.str().c_str());
1642         break;
1643       case 'a':
1644         m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
1645                                                  LLDB_INVALID_ADDRESS, &error);
1646         break;
1647       case 'r':
1648         m_force = true;
1649         break;
1650       default:
1651         llvm_unreachable("Unimplemented option");
1652       }
1653       return error;
1654     }
1655 
1656     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1657       return llvm::ArrayRef(g_thread_jump_options);
1658     }
1659 
1660     FileSpecList m_filenames;
1661     uint32_t m_line_num;
1662     int32_t m_line_offset;
1663     lldb::addr_t m_load_addr;
1664     bool m_force;
1665   };
1666 
1667   CommandObjectThreadJump(CommandInterpreter &interpreter)
1668       : CommandObjectParsed(
1669             interpreter, "thread jump",
1670             "Sets the program counter to a new address.", "thread jump",
1671             eCommandRequiresFrame | eCommandTryTargetAPILock |
1672                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
1673 
1674   ~CommandObjectThreadJump() override = default;
1675 
1676   Options *GetOptions() override { return &m_options; }
1677 
1678 protected:
1679   void DoExecute(Args &args, CommandReturnObject &result) override {
1680     RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
1681     StackFrame *frame = m_exe_ctx.GetFramePtr();
1682     Thread *thread = m_exe_ctx.GetThreadPtr();
1683     Target *target = m_exe_ctx.GetTargetPtr();
1684     const SymbolContext &sym_ctx =
1685         frame->GetSymbolContext(eSymbolContextLineEntry);
1686 
1687     if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) {
1688       // Use this address directly.
1689       Address dest = Address(m_options.m_load_addr);
1690 
1691       lldb::addr_t callAddr = dest.GetCallableLoadAddress(target);
1692       if (callAddr == LLDB_INVALID_ADDRESS) {
1693         result.AppendErrorWithFormat("Invalid destination address.");
1694         return;
1695       }
1696 
1697       if (!reg_ctx->SetPC(callAddr)) {
1698         result.AppendErrorWithFormat("Error changing PC value for thread %d.",
1699                                      thread->GetIndexID());
1700         return;
1701       }
1702     } else {
1703       // Pick either the absolute line, or work out a relative one.
1704       int32_t line = (int32_t)m_options.m_line_num;
1705       if (line == 0)
1706         line = sym_ctx.line_entry.line + m_options.m_line_offset;
1707 
1708       // Try the current file, but override if asked.
1709       FileSpec file = sym_ctx.line_entry.GetFile();
1710       if (m_options.m_filenames.GetSize() == 1)
1711         file = m_options.m_filenames.GetFileSpecAtIndex(0);
1712 
1713       if (!file) {
1714         result.AppendErrorWithFormat(
1715             "No source file available for the current location.");
1716         return;
1717       }
1718 
1719       std::string warnings;
1720       Status err = thread->JumpToLine(file, line, m_options.m_force, &warnings);
1721 
1722       if (err.Fail()) {
1723         result.SetError(err);
1724         return;
1725       }
1726 
1727       if (!warnings.empty())
1728         result.AppendWarning(warnings.c_str());
1729     }
1730 
1731     result.SetStatus(eReturnStatusSuccessFinishResult);
1732   }
1733 
1734   CommandOptions m_options;
1735 };
1736 
1737 // Next are the subcommands of CommandObjectMultiwordThreadPlan
1738 
1739 // CommandObjectThreadPlanList
1740 #define LLDB_OPTIONS_thread_plan_list
1741 #include "CommandOptions.inc"
1742 
1743 class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads {
1744 public:
1745   class CommandOptions : public Options {
1746   public:
1747     CommandOptions() {
1748       // Keep default values of all options in one place: OptionParsingStarting
1749       // ()
1750       OptionParsingStarting(nullptr);
1751     }
1752 
1753     ~CommandOptions() override = default;
1754 
1755     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1756                           ExecutionContext *execution_context) override {
1757       const int short_option = m_getopt_table[option_idx].val;
1758 
1759       switch (short_option) {
1760       case 'i':
1761         m_internal = true;
1762         break;
1763       case 't':
1764         lldb::tid_t tid;
1765         if (option_arg.getAsInteger(0, tid))
1766           return Status("invalid tid: '%s'.", option_arg.str().c_str());
1767         m_tids.push_back(tid);
1768         break;
1769       case 'u':
1770         m_unreported = false;
1771         break;
1772       case 'v':
1773         m_verbose = true;
1774         break;
1775       default:
1776         llvm_unreachable("Unimplemented option");
1777       }
1778       return {};
1779     }
1780 
1781     void OptionParsingStarting(ExecutionContext *execution_context) override {
1782       m_verbose = false;
1783       m_internal = false;
1784       m_unreported = true; // The variable is "skip unreported" and we want to
1785                            // skip unreported by default.
1786       m_tids.clear();
1787     }
1788 
1789     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1790       return llvm::ArrayRef(g_thread_plan_list_options);
1791     }
1792 
1793     // Instance variables to hold the values for command options.
1794     bool m_verbose;
1795     bool m_internal;
1796     bool m_unreported;
1797     std::vector<lldb::tid_t> m_tids;
1798   };
1799 
1800   CommandObjectThreadPlanList(CommandInterpreter &interpreter)
1801       : CommandObjectIterateOverThreads(
1802             interpreter, "thread plan list",
1803             "Show thread plans for one or more threads.  If no threads are "
1804             "specified, show the "
1805             "current thread.  Use the thread-index \"all\" to see all threads.",
1806             nullptr,
1807             eCommandRequiresProcess | eCommandRequiresThread |
1808                 eCommandTryTargetAPILock | eCommandProcessMustBeLaunched |
1809                 eCommandProcessMustBePaused) {}
1810 
1811   ~CommandObjectThreadPlanList() override = default;
1812 
1813   Options *GetOptions() override { return &m_options; }
1814 
1815   void DoExecute(Args &command, CommandReturnObject &result) override {
1816     // If we are reporting all threads, dispatch to the Process to do that:
1817     if (command.GetArgumentCount() == 0 && m_options.m_tids.empty()) {
1818       Stream &strm = result.GetOutputStream();
1819       DescriptionLevel desc_level = m_options.m_verbose
1820                                         ? eDescriptionLevelVerbose
1821                                         : eDescriptionLevelFull;
1822       m_exe_ctx.GetProcessPtr()->DumpThreadPlans(
1823           strm, desc_level, m_options.m_internal, true, m_options.m_unreported);
1824       result.SetStatus(eReturnStatusSuccessFinishResult);
1825       return;
1826     } else {
1827       // Do any TID's that the user may have specified as TID, then do any
1828       // Thread Indexes...
1829       if (!m_options.m_tids.empty()) {
1830         Process *process = m_exe_ctx.GetProcessPtr();
1831         StreamString tmp_strm;
1832         for (lldb::tid_t tid : m_options.m_tids) {
1833           bool success = process->DumpThreadPlansForTID(
1834               tmp_strm, tid, eDescriptionLevelFull, m_options.m_internal,
1835               true /* condense_trivial */, m_options.m_unreported);
1836           // If we didn't find a TID, stop here and return an error.
1837           if (!success) {
1838             result.AppendError("Error dumping plans:");
1839             result.AppendError(tmp_strm.GetString());
1840             return;
1841           }
1842           // Otherwise, add our data to the output:
1843           result.GetOutputStream() << tmp_strm.GetString();
1844         }
1845       }
1846       return CommandObjectIterateOverThreads::DoExecute(command, result);
1847     }
1848   }
1849 
1850 protected:
1851   bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
1852     // If we have already handled this from a -t option, skip it here.
1853     if (llvm::is_contained(m_options.m_tids, tid))
1854       return true;
1855 
1856     Process *process = m_exe_ctx.GetProcessPtr();
1857 
1858     Stream &strm = result.GetOutputStream();
1859     DescriptionLevel desc_level = eDescriptionLevelFull;
1860     if (m_options.m_verbose)
1861       desc_level = eDescriptionLevelVerbose;
1862 
1863     process->DumpThreadPlansForTID(strm, tid, desc_level, m_options.m_internal,
1864                                    true /* condense_trivial */,
1865                                    m_options.m_unreported);
1866     return true;
1867   }
1868 
1869   CommandOptions m_options;
1870 };
1871 
1872 class CommandObjectThreadPlanDiscard : public CommandObjectParsed {
1873 public:
1874   CommandObjectThreadPlanDiscard(CommandInterpreter &interpreter)
1875       : CommandObjectParsed(interpreter, "thread plan discard",
1876                             "Discards thread plans up to and including the "
1877                             "specified index (see 'thread plan list'.)  "
1878                             "Only user visible plans can be discarded.",
1879                             nullptr,
1880                             eCommandRequiresProcess | eCommandRequiresThread |
1881                                 eCommandTryTargetAPILock |
1882                                 eCommandProcessMustBeLaunched |
1883                                 eCommandProcessMustBePaused) {
1884     AddSimpleArgumentList(eArgTypeUnsignedInteger);
1885   }
1886 
1887   ~CommandObjectThreadPlanDiscard() override = default;
1888 
1889   void
1890   HandleArgumentCompletion(CompletionRequest &request,
1891                            OptionElementVector &opt_element_vector) override {
1892     if (!m_exe_ctx.HasThreadScope() || request.GetCursorIndex())
1893       return;
1894 
1895     m_exe_ctx.GetThreadPtr()->AutoCompleteThreadPlans(request);
1896   }
1897 
1898   void DoExecute(Args &args, CommandReturnObject &result) override {
1899     Thread *thread = m_exe_ctx.GetThreadPtr();
1900     if (args.GetArgumentCount() != 1) {
1901       result.AppendErrorWithFormat("Too many arguments, expected one - the "
1902                                    "thread plan index - but got %zu.",
1903                                    args.GetArgumentCount());
1904       return;
1905     }
1906 
1907     uint32_t thread_plan_idx;
1908     if (!llvm::to_integer(args.GetArgumentAtIndex(0), thread_plan_idx)) {
1909       result.AppendErrorWithFormat(
1910           "Invalid thread index: \"%s\" - should be unsigned int.",
1911           args.GetArgumentAtIndex(0));
1912       return;
1913     }
1914 
1915     if (thread_plan_idx == 0) {
1916       result.AppendErrorWithFormat(
1917           "You wouldn't really want me to discard the base thread plan.");
1918       return;
1919     }
1920 
1921     if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx)) {
1922       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1923     } else {
1924       result.AppendErrorWithFormat(
1925           "Could not find User thread plan with index %s.",
1926           args.GetArgumentAtIndex(0));
1927     }
1928   }
1929 };
1930 
1931 class CommandObjectThreadPlanPrune : public CommandObjectParsed {
1932 public:
1933   CommandObjectThreadPlanPrune(CommandInterpreter &interpreter)
1934       : CommandObjectParsed(interpreter, "thread plan prune",
1935                             "Removes any thread plans associated with "
1936                             "currently unreported threads.  "
1937                             "Specify one or more TID's to remove, or if no "
1938                             "TID's are provides, remove threads for all "
1939                             "unreported threads",
1940                             nullptr,
1941                             eCommandRequiresProcess |
1942                                 eCommandTryTargetAPILock |
1943                                 eCommandProcessMustBeLaunched |
1944                                 eCommandProcessMustBePaused) {
1945     AddSimpleArgumentList(eArgTypeThreadID, eArgRepeatStar);
1946   }
1947 
1948   ~CommandObjectThreadPlanPrune() override = default;
1949 
1950   void DoExecute(Args &args, CommandReturnObject &result) override {
1951     Process *process = m_exe_ctx.GetProcessPtr();
1952 
1953     if (args.GetArgumentCount() == 0) {
1954       process->PruneThreadPlans();
1955       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1956       return;
1957     }
1958 
1959     const size_t num_args = args.GetArgumentCount();
1960 
1961     std::lock_guard<std::recursive_mutex> guard(
1962         process->GetThreadList().GetMutex());
1963 
1964     for (size_t i = 0; i < num_args; i++) {
1965       lldb::tid_t tid;
1966       if (!llvm::to_integer(args.GetArgumentAtIndex(i), tid)) {
1967         result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n",
1968                                      args.GetArgumentAtIndex(i));
1969         return;
1970       }
1971       if (!process->PruneThreadPlansForTID(tid)) {
1972         result.AppendErrorWithFormat("Could not find unreported tid: \"%s\"\n",
1973                                      args.GetArgumentAtIndex(i));
1974         return;
1975       }
1976     }
1977     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1978   }
1979 };
1980 
1981 // CommandObjectMultiwordThreadPlan
1982 
1983 class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword {
1984 public:
1985   CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter)
1986       : CommandObjectMultiword(
1987             interpreter, "plan",
1988             "Commands for managing thread plans that control execution.",
1989             "thread plan <subcommand> [<subcommand objects]") {
1990     LoadSubCommand(
1991         "list", CommandObjectSP(new CommandObjectThreadPlanList(interpreter)));
1992     LoadSubCommand(
1993         "discard",
1994         CommandObjectSP(new CommandObjectThreadPlanDiscard(interpreter)));
1995     LoadSubCommand(
1996         "prune",
1997         CommandObjectSP(new CommandObjectThreadPlanPrune(interpreter)));
1998   }
1999 
2000   ~CommandObjectMultiwordThreadPlan() override = default;
2001 };
2002 
2003 // Next are the subcommands of CommandObjectMultiwordTrace
2004 
2005 // CommandObjectTraceExport
2006 
2007 class CommandObjectTraceExport : public CommandObjectMultiword {
2008 public:
2009   CommandObjectTraceExport(CommandInterpreter &interpreter)
2010       : CommandObjectMultiword(
2011             interpreter, "trace thread export",
2012             "Commands for exporting traces of the threads in the current "
2013             "process to different formats.",
2014             "thread trace export <export-plugin> [<subcommand objects>]") {
2015 
2016     unsigned i = 0;
2017     for (llvm::StringRef plugin_name =
2018              PluginManager::GetTraceExporterPluginNameAtIndex(i);
2019          !plugin_name.empty();
2020          plugin_name = PluginManager::GetTraceExporterPluginNameAtIndex(i++)) {
2021       if (ThreadTraceExportCommandCreator command_creator =
2022               PluginManager::GetThreadTraceExportCommandCreatorAtIndex(i)) {
2023         LoadSubCommand(plugin_name, command_creator(interpreter));
2024       }
2025     }
2026   }
2027 };
2028 
2029 // CommandObjectTraceStart
2030 
2031 class CommandObjectTraceStart : public CommandObjectTraceProxy {
2032 public:
2033   CommandObjectTraceStart(CommandInterpreter &interpreter)
2034       : CommandObjectTraceProxy(
2035             /*live_debug_session_only=*/true, interpreter, "thread trace start",
2036             "Start tracing threads with the corresponding trace "
2037             "plug-in for the current process.",
2038             "thread trace start [<trace-options>]") {}
2039 
2040 protected:
2041   lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override {
2042     return trace.GetThreadTraceStartCommand(m_interpreter);
2043   }
2044 };
2045 
2046 // CommandObjectTraceStop
2047 
2048 class CommandObjectTraceStop : public CommandObjectMultipleThreads {
2049 public:
2050   CommandObjectTraceStop(CommandInterpreter &interpreter)
2051       : CommandObjectMultipleThreads(
2052             interpreter, "thread trace stop",
2053             "Stop tracing threads, including the ones traced with the "
2054             "\"process trace start\" command."
2055             "Defaults to the current thread. Thread indices can be "
2056             "specified as arguments.\n Use the thread-index \"all\" to stop "
2057             "tracing "
2058             "for all existing threads.",
2059             "thread trace stop [<thread-index> <thread-index> ...]",
2060             eCommandRequiresProcess | eCommandTryTargetAPILock |
2061                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
2062                 eCommandProcessMustBeTraced) {}
2063 
2064   ~CommandObjectTraceStop() override = default;
2065 
2066   bool DoExecuteOnThreads(Args &command, CommandReturnObject &result,
2067                           llvm::ArrayRef<lldb::tid_t> tids) override {
2068     ProcessSP process_sp = m_exe_ctx.GetProcessSP();
2069 
2070     TraceSP trace_sp = process_sp->GetTarget().GetTrace();
2071 
2072     if (llvm::Error err = trace_sp->Stop(tids))
2073       result.AppendError(toString(std::move(err)));
2074     else
2075       result.SetStatus(eReturnStatusSuccessFinishResult);
2076 
2077     return result.Succeeded();
2078   }
2079 };
2080 
2081 static ThreadSP GetSingleThreadFromArgs(ExecutionContext &exe_ctx, Args &args,
2082                                         CommandReturnObject &result) {
2083   if (args.GetArgumentCount() == 0)
2084     return exe_ctx.GetThreadSP();
2085 
2086   const char *arg = args.GetArgumentAtIndex(0);
2087   uint32_t thread_idx;
2088 
2089   if (!llvm::to_integer(arg, thread_idx)) {
2090     result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n", arg);
2091     return nullptr;
2092   }
2093   ThreadSP thread_sp =
2094       exe_ctx.GetProcessRef().GetThreadList().FindThreadByIndexID(thread_idx);
2095   if (!thread_sp)
2096     result.AppendErrorWithFormat("no thread with index: \"%s\"\n", arg);
2097   return thread_sp;
2098 }
2099 
2100 // CommandObjectTraceDumpFunctionCalls
2101 #define LLDB_OPTIONS_thread_trace_dump_function_calls
2102 #include "CommandOptions.inc"
2103 
2104 class CommandObjectTraceDumpFunctionCalls : public CommandObjectParsed {
2105 public:
2106   class CommandOptions : public Options {
2107   public:
2108     CommandOptions() { OptionParsingStarting(nullptr); }
2109 
2110     ~CommandOptions() override = default;
2111 
2112     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2113                           ExecutionContext *execution_context) override {
2114       Status error;
2115       const int short_option = m_getopt_table[option_idx].val;
2116 
2117       switch (short_option) {
2118       case 'j': {
2119         m_dumper_options.json = true;
2120         break;
2121       }
2122       case 'J': {
2123         m_dumper_options.json = true;
2124         m_dumper_options.pretty_print_json = true;
2125         break;
2126       }
2127       case 'F': {
2128         m_output_file.emplace(option_arg);
2129         break;
2130       }
2131       default:
2132         llvm_unreachable("Unimplemented option");
2133       }
2134       return error;
2135     }
2136 
2137     void OptionParsingStarting(ExecutionContext *execution_context) override {
2138       m_dumper_options = {};
2139       m_output_file = std::nullopt;
2140     }
2141 
2142     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2143       return llvm::ArrayRef(g_thread_trace_dump_function_calls_options);
2144     }
2145 
2146     static const size_t kDefaultCount = 20;
2147 
2148     // Instance variables to hold the values for command options.
2149     TraceDumperOptions m_dumper_options;
2150     std::optional<FileSpec> m_output_file;
2151   };
2152 
2153   CommandObjectTraceDumpFunctionCalls(CommandInterpreter &interpreter)
2154       : CommandObjectParsed(
2155             interpreter, "thread trace dump function-calls",
2156             "Dump the traced function-calls for one thread. If no "
2157             "thread is specified, the current thread is used.",
2158             nullptr,
2159             eCommandRequiresProcess | eCommandRequiresThread |
2160                 eCommandTryTargetAPILock | eCommandProcessMustBeLaunched |
2161                 eCommandProcessMustBePaused | eCommandProcessMustBeTraced) {
2162     AddSimpleArgumentList(eArgTypeThreadIndex, eArgRepeatOptional);
2163   }
2164 
2165   ~CommandObjectTraceDumpFunctionCalls() override = default;
2166 
2167   Options *GetOptions() override { return &m_options; }
2168 
2169 protected:
2170   void DoExecute(Args &args, CommandReturnObject &result) override {
2171     ThreadSP thread_sp = GetSingleThreadFromArgs(m_exe_ctx, args, result);
2172     if (!thread_sp) {
2173       result.AppendError("invalid thread\n");
2174       return;
2175     }
2176 
2177     llvm::Expected<TraceCursorSP> cursor_or_error =
2178         m_exe_ctx.GetTargetSP()->GetTrace()->CreateNewCursor(*thread_sp);
2179 
2180     if (!cursor_or_error) {
2181       result.AppendError(llvm::toString(cursor_or_error.takeError()));
2182       return;
2183     }
2184     TraceCursorSP &cursor_sp = *cursor_or_error;
2185 
2186     std::optional<StreamFile> out_file;
2187     if (m_options.m_output_file) {
2188       out_file.emplace(m_options.m_output_file->GetPath().c_str(),
2189                        File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate |
2190                            File::eOpenOptionTruncate);
2191     }
2192 
2193     m_options.m_dumper_options.forwards = true;
2194 
2195     TraceDumper dumper(std::move(cursor_sp),
2196                        out_file ? *out_file : result.GetOutputStream(),
2197                        m_options.m_dumper_options);
2198 
2199     dumper.DumpFunctionCalls();
2200   }
2201 
2202   CommandOptions m_options;
2203 };
2204 
2205 // CommandObjectTraceDumpInstructions
2206 #define LLDB_OPTIONS_thread_trace_dump_instructions
2207 #include "CommandOptions.inc"
2208 
2209 class CommandObjectTraceDumpInstructions : public CommandObjectParsed {
2210 public:
2211   class CommandOptions : public Options {
2212   public:
2213     CommandOptions() { OptionParsingStarting(nullptr); }
2214 
2215     ~CommandOptions() override = default;
2216 
2217     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2218                           ExecutionContext *execution_context) override {
2219       Status error;
2220       const int short_option = m_getopt_table[option_idx].val;
2221 
2222       switch (short_option) {
2223       case 'c': {
2224         int32_t count;
2225         if (option_arg.empty() || option_arg.getAsInteger(0, count) ||
2226             count < 0)
2227           error.SetErrorStringWithFormat(
2228               "invalid integer value for option '%s'",
2229               option_arg.str().c_str());
2230         else
2231           m_count = count;
2232         break;
2233       }
2234       case 'a': {
2235         m_count = std::numeric_limits<decltype(m_count)>::max();
2236         break;
2237       }
2238       case 's': {
2239         int32_t skip;
2240         if (option_arg.empty() || option_arg.getAsInteger(0, skip) || skip < 0)
2241           error.SetErrorStringWithFormat(
2242               "invalid integer value for option '%s'",
2243               option_arg.str().c_str());
2244         else
2245           m_dumper_options.skip = skip;
2246         break;
2247       }
2248       case 'i': {
2249         uint64_t id;
2250         if (option_arg.empty() || option_arg.getAsInteger(0, id))
2251           error.SetErrorStringWithFormat(
2252               "invalid integer value for option '%s'",
2253               option_arg.str().c_str());
2254         else
2255           m_dumper_options.id = id;
2256         break;
2257       }
2258       case 'F': {
2259         m_output_file.emplace(option_arg);
2260         break;
2261       }
2262       case 'r': {
2263         m_dumper_options.raw = true;
2264         break;
2265       }
2266       case 'f': {
2267         m_dumper_options.forwards = true;
2268         break;
2269       }
2270       case 'k': {
2271         m_dumper_options.show_control_flow_kind = true;
2272         break;
2273       }
2274       case 't': {
2275         m_dumper_options.show_timestamps = true;
2276         break;
2277       }
2278       case 'e': {
2279         m_dumper_options.show_events = true;
2280         break;
2281       }
2282       case 'j': {
2283         m_dumper_options.json = true;
2284         break;
2285       }
2286       case 'J': {
2287         m_dumper_options.pretty_print_json = true;
2288         m_dumper_options.json = true;
2289         break;
2290       }
2291       case 'E': {
2292         m_dumper_options.only_events = true;
2293         m_dumper_options.show_events = true;
2294         break;
2295       }
2296       case 'C': {
2297         m_continue = true;
2298         break;
2299       }
2300       default:
2301         llvm_unreachable("Unimplemented option");
2302       }
2303       return error;
2304     }
2305 
2306     void OptionParsingStarting(ExecutionContext *execution_context) override {
2307       m_count = kDefaultCount;
2308       m_continue = false;
2309       m_output_file = std::nullopt;
2310       m_dumper_options = {};
2311     }
2312 
2313     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2314       return llvm::ArrayRef(g_thread_trace_dump_instructions_options);
2315     }
2316 
2317     static const size_t kDefaultCount = 20;
2318 
2319     // Instance variables to hold the values for command options.
2320     size_t m_count;
2321     size_t m_continue;
2322     std::optional<FileSpec> m_output_file;
2323     TraceDumperOptions m_dumper_options;
2324   };
2325 
2326   CommandObjectTraceDumpInstructions(CommandInterpreter &interpreter)
2327       : CommandObjectParsed(
2328             interpreter, "thread trace dump instructions",
2329             "Dump the traced instructions for one thread. If no "
2330             "thread is specified, show the current thread.",
2331             nullptr,
2332             eCommandRequiresProcess | eCommandRequiresThread |
2333                 eCommandTryTargetAPILock | eCommandProcessMustBeLaunched |
2334                 eCommandProcessMustBePaused | eCommandProcessMustBeTraced) {
2335     AddSimpleArgumentList(eArgTypeThreadIndex, eArgRepeatOptional);
2336   }
2337 
2338   ~CommandObjectTraceDumpInstructions() override = default;
2339 
2340   Options *GetOptions() override { return &m_options; }
2341 
2342   std::optional<std::string> GetRepeatCommand(Args &current_command_args,
2343                                               uint32_t index) override {
2344     std::string cmd;
2345     current_command_args.GetCommandString(cmd);
2346     if (cmd.find(" --continue") == std::string::npos)
2347       cmd += " --continue";
2348     return cmd;
2349   }
2350 
2351 protected:
2352   void DoExecute(Args &args, CommandReturnObject &result) override {
2353     ThreadSP thread_sp = GetSingleThreadFromArgs(m_exe_ctx, args, result);
2354     if (!thread_sp) {
2355       result.AppendError("invalid thread\n");
2356       return;
2357     }
2358 
2359     if (m_options.m_continue && m_last_id) {
2360       // We set up the options to continue one instruction past where
2361       // the previous iteration stopped.
2362       m_options.m_dumper_options.skip = 1;
2363       m_options.m_dumper_options.id = m_last_id;
2364     }
2365 
2366     llvm::Expected<TraceCursorSP> cursor_or_error =
2367         m_exe_ctx.GetTargetSP()->GetTrace()->CreateNewCursor(*thread_sp);
2368 
2369     if (!cursor_or_error) {
2370       result.AppendError(llvm::toString(cursor_or_error.takeError()));
2371       return;
2372     }
2373     TraceCursorSP &cursor_sp = *cursor_or_error;
2374 
2375     if (m_options.m_dumper_options.id &&
2376         !cursor_sp->HasId(*m_options.m_dumper_options.id)) {
2377       result.AppendError("invalid instruction id\n");
2378       return;
2379     }
2380 
2381     std::optional<StreamFile> out_file;
2382     if (m_options.m_output_file) {
2383       out_file.emplace(m_options.m_output_file->GetPath().c_str(),
2384                        File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate |
2385                            File::eOpenOptionTruncate);
2386     }
2387 
2388     if (m_options.m_continue && !m_last_id) {
2389       // We need to stop processing data when we already ran out of instructions
2390       // in a previous command. We can fake this by setting the cursor past the
2391       // end of the trace.
2392       cursor_sp->Seek(1, lldb::eTraceCursorSeekTypeEnd);
2393     }
2394 
2395     TraceDumper dumper(std::move(cursor_sp),
2396                        out_file ? *out_file : result.GetOutputStream(),
2397                        m_options.m_dumper_options);
2398 
2399     m_last_id = dumper.DumpInstructions(m_options.m_count);
2400   }
2401 
2402   CommandOptions m_options;
2403   // Last traversed id used to continue a repeat command. std::nullopt means
2404   // that all the trace has been consumed.
2405   std::optional<lldb::user_id_t> m_last_id;
2406 };
2407 
2408 // CommandObjectTraceDumpInfo
2409 #define LLDB_OPTIONS_thread_trace_dump_info
2410 #include "CommandOptions.inc"
2411 
2412 class CommandObjectTraceDumpInfo : public CommandObjectIterateOverThreads {
2413 public:
2414   class CommandOptions : public Options {
2415   public:
2416     CommandOptions() { OptionParsingStarting(nullptr); }
2417 
2418     ~CommandOptions() override = default;
2419 
2420     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2421                           ExecutionContext *execution_context) override {
2422       Status error;
2423       const int short_option = m_getopt_table[option_idx].val;
2424 
2425       switch (short_option) {
2426       case 'v': {
2427         m_verbose = true;
2428         break;
2429       }
2430       case 'j': {
2431         m_json = true;
2432         break;
2433       }
2434       default:
2435         llvm_unreachable("Unimplemented option");
2436       }
2437       return error;
2438     }
2439 
2440     void OptionParsingStarting(ExecutionContext *execution_context) override {
2441       m_verbose = false;
2442       m_json = false;
2443     }
2444 
2445     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2446       return llvm::ArrayRef(g_thread_trace_dump_info_options);
2447     }
2448 
2449     // Instance variables to hold the values for command options.
2450     bool m_verbose;
2451     bool m_json;
2452   };
2453 
2454   CommandObjectTraceDumpInfo(CommandInterpreter &interpreter)
2455       : CommandObjectIterateOverThreads(
2456             interpreter, "thread trace dump info",
2457             "Dump the traced information for one or more threads.  If no "
2458             "threads are specified, show the current thread. Use the "
2459             "thread-index \"all\" to see all threads.",
2460             nullptr,
2461             eCommandRequiresProcess | eCommandTryTargetAPILock |
2462                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
2463                 eCommandProcessMustBeTraced) {}
2464 
2465   ~CommandObjectTraceDumpInfo() override = default;
2466 
2467   Options *GetOptions() override { return &m_options; }
2468 
2469 protected:
2470   bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
2471     const TraceSP &trace_sp = m_exe_ctx.GetTargetSP()->GetTrace();
2472     ThreadSP thread_sp =
2473         m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
2474     trace_sp->DumpTraceInfo(*thread_sp, result.GetOutputStream(),
2475                             m_options.m_verbose, m_options.m_json);
2476     return true;
2477   }
2478 
2479   CommandOptions m_options;
2480 };
2481 
2482 // CommandObjectMultiwordTraceDump
2483 class CommandObjectMultiwordTraceDump : public CommandObjectMultiword {
2484 public:
2485   CommandObjectMultiwordTraceDump(CommandInterpreter &interpreter)
2486       : CommandObjectMultiword(
2487             interpreter, "dump",
2488             "Commands for displaying trace information of the threads "
2489             "in the current process.",
2490             "thread trace dump <subcommand> [<subcommand objects>]") {
2491     LoadSubCommand(
2492         "instructions",
2493         CommandObjectSP(new CommandObjectTraceDumpInstructions(interpreter)));
2494     LoadSubCommand(
2495         "function-calls",
2496         CommandObjectSP(new CommandObjectTraceDumpFunctionCalls(interpreter)));
2497     LoadSubCommand(
2498         "info", CommandObjectSP(new CommandObjectTraceDumpInfo(interpreter)));
2499   }
2500   ~CommandObjectMultiwordTraceDump() override = default;
2501 };
2502 
2503 // CommandObjectMultiwordTrace
2504 class CommandObjectMultiwordTrace : public CommandObjectMultiword {
2505 public:
2506   CommandObjectMultiwordTrace(CommandInterpreter &interpreter)
2507       : CommandObjectMultiword(
2508             interpreter, "trace",
2509             "Commands for operating on traces of the threads in the current "
2510             "process.",
2511             "thread trace <subcommand> [<subcommand objects>]") {
2512     LoadSubCommand("dump", CommandObjectSP(new CommandObjectMultiwordTraceDump(
2513                                interpreter)));
2514     LoadSubCommand("start",
2515                    CommandObjectSP(new CommandObjectTraceStart(interpreter)));
2516     LoadSubCommand("stop",
2517                    CommandObjectSP(new CommandObjectTraceStop(interpreter)));
2518     LoadSubCommand("export",
2519                    CommandObjectSP(new CommandObjectTraceExport(interpreter)));
2520   }
2521 
2522   ~CommandObjectMultiwordTrace() override = default;
2523 };
2524 
2525 // CommandObjectMultiwordThread
2526 
2527 CommandObjectMultiwordThread::CommandObjectMultiwordThread(
2528     CommandInterpreter &interpreter)
2529     : CommandObjectMultiword(interpreter, "thread",
2530                              "Commands for operating on "
2531                              "one or more threads in "
2532                              "the current process.",
2533                              "thread <subcommand> [<subcommand-options>]") {
2534   LoadSubCommand("backtrace", CommandObjectSP(new CommandObjectThreadBacktrace(
2535                                   interpreter)));
2536   LoadSubCommand("continue",
2537                  CommandObjectSP(new CommandObjectThreadContinue(interpreter)));
2538   LoadSubCommand("list",
2539                  CommandObjectSP(new CommandObjectThreadList(interpreter)));
2540   LoadSubCommand("return",
2541                  CommandObjectSP(new CommandObjectThreadReturn(interpreter)));
2542   LoadSubCommand("jump",
2543                  CommandObjectSP(new CommandObjectThreadJump(interpreter)));
2544   LoadSubCommand("select",
2545                  CommandObjectSP(new CommandObjectThreadSelect(interpreter)));
2546   LoadSubCommand("until",
2547                  CommandObjectSP(new CommandObjectThreadUntil(interpreter)));
2548   LoadSubCommand("info",
2549                  CommandObjectSP(new CommandObjectThreadInfo(interpreter)));
2550   LoadSubCommand("exception", CommandObjectSP(new CommandObjectThreadException(
2551                                   interpreter)));
2552   LoadSubCommand("siginfo",
2553                  CommandObjectSP(new CommandObjectThreadSiginfo(interpreter)));
2554   LoadSubCommand("step-in",
2555                  CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2556                      interpreter, "thread step-in",
2557                      "Source level single step, stepping into calls.  Defaults "
2558                      "to current thread unless specified.",
2559                      nullptr, eStepTypeInto)));
2560 
2561   LoadSubCommand("step-out",
2562                  CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2563                      interpreter, "thread step-out",
2564                      "Finish executing the current stack frame and stop after "
2565                      "returning.  Defaults to current thread unless specified.",
2566                      nullptr, eStepTypeOut)));
2567 
2568   LoadSubCommand("step-over",
2569                  CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2570                      interpreter, "thread step-over",
2571                      "Source level single step, stepping over calls.  Defaults "
2572                      "to current thread unless specified.",
2573                      nullptr, eStepTypeOver)));
2574 
2575   LoadSubCommand("step-inst",
2576                  CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2577                      interpreter, "thread step-inst",
2578                      "Instruction level single step, stepping into calls.  "
2579                      "Defaults to current thread unless specified.",
2580                      nullptr, eStepTypeTrace)));
2581 
2582   LoadSubCommand("step-inst-over",
2583                  CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2584                      interpreter, "thread step-inst-over",
2585                      "Instruction level single step, stepping over calls.  "
2586                      "Defaults to current thread unless specified.",
2587                      nullptr, eStepTypeTraceOver)));
2588 
2589   LoadSubCommand(
2590       "step-scripted",
2591       CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2592           interpreter, "thread step-scripted",
2593           "Step as instructed by the script class passed in the -C option.  "
2594           "You can also specify a dictionary of key (-k) and value (-v) pairs "
2595           "that will be used to populate an SBStructuredData Dictionary, which "
2596           "will be passed to the constructor of the class implementing the "
2597           "scripted step.  See the Python Reference for more details.",
2598           nullptr, eStepTypeScripted)));
2599 
2600   LoadSubCommand("plan", CommandObjectSP(new CommandObjectMultiwordThreadPlan(
2601                              interpreter)));
2602   LoadSubCommand("trace",
2603                  CommandObjectSP(new CommandObjectMultiwordTrace(interpreter)));
2604 }
2605 
2606 CommandObjectMultiwordThread::~CommandObjectMultiwordThread() = default;
2607