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