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