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