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/ValueObject.h"
18 #include "lldb/Host/Host.h"
19 #include "lldb/Host/OptionParser.h"
20 #include "lldb/Host/StringConvert.h"
21 #include "lldb/Interpreter/CommandInterpreter.h"
22 #include "lldb/Interpreter/CommandReturnObject.h"
23 #include "lldb/Interpreter/OptionArgParser.h"
24 #include "lldb/Interpreter/Options.h"
25 #include "lldb/Symbol/CompileUnit.h"
26 #include "lldb/Symbol/Function.h"
27 #include "lldb/Symbol/LineEntry.h"
28 #include "lldb/Symbol/LineTable.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/RegisterContext.h"
31 #include "lldb/Target/SystemRuntime.h"
32 #include "lldb/Target/Target.h"
33 #include "lldb/Target/Thread.h"
34 #include "lldb/Target/ThreadPlan.h"
35 #include "lldb/Target/ThreadPlanStepInRange.h"
36 #include "lldb/Target/ThreadPlanStepInstruction.h"
37 #include "lldb/Target/ThreadPlanStepOut.h"
38 #include "lldb/Target/ThreadPlanStepRange.h"
39 #include "lldb/Utility/State.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 code while iterating over the (locked) ThreadSP
108     // 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, so you only need
200   // to set the return status in HandleOneThread if you want to indicate an
201   // error. If m_add_return is true, a blank line will be inserted between each
202   // of the listings (except the last one.)
203 
204   virtual bool HandleOneThread(lldb::tid_t, CommandReturnObject &result) = 0;
205 
206   bool BucketThread(lldb::tid_t tid, std::set<UniqueStack> &unique_stacks,
207                     CommandReturnObject &result) {
208     // Grab the corresponding thread for the given thread id.
209     Process *process = m_exe_ctx.GetProcessPtr();
210     Thread *thread = process->GetThreadList().FindThreadByID(tid).get();
211     if (thread == nullptr) {
212       result.AppendErrorWithFormatv("Failed to process thread #{0}.\n", tid);
213       result.SetStatus(eReturnStatusFailed);
214       return false;
215     }
216 
217     // Collect the each frame's address for this call-stack
218     std::stack<lldb::addr_t> stack_frames;
219     const uint32_t frame_count = thread->GetStackFrameCount();
220     for (uint32_t frame_index = 0; frame_index < frame_count; frame_index++) {
221       const lldb::StackFrameSP frame_sp =
222           thread->GetStackFrameAtIndex(frame_index);
223       const lldb::addr_t pc = frame_sp->GetStackID().GetPC();
224       stack_frames.push(pc);
225     }
226 
227     uint32_t thread_index_id = thread->GetIndexID();
228     UniqueStack new_unique_stack(stack_frames, thread_index_id);
229 
230     // Try to match the threads stack to and existing entry.
231     std::set<UniqueStack>::iterator matching_stack =
232         unique_stacks.find(new_unique_stack);
233     if (matching_stack != unique_stacks.end()) {
234       matching_stack->AddThread(thread_index_id);
235     } else {
236       unique_stacks.insert(new_unique_stack);
237     }
238     return true;
239   }
240 
241   ReturnStatus m_success_return = eReturnStatusSuccessFinishResult;
242   bool m_unique_stacks = false;
243   bool m_add_return = true;
244 };
245 
246 //-------------------------------------------------------------------------
247 // CommandObjectThreadBacktrace
248 //-------------------------------------------------------------------------
249 
250 static constexpr OptionDefinition g_thread_backtrace_options[] = {
251     // clang-format off
252   { LLDB_OPT_SET_1, false, "count",    'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount,      "How many frames to display (-1 for all)" },
253   { LLDB_OPT_SET_1, false, "start",    's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace" },
254   { LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean,    "Show the extended backtrace, if available" }
255     // clang-format on
256 };
257 
258 class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads {
259 public:
260   class CommandOptions : public Options {
261   public:
262     CommandOptions() : Options() {
263       // Keep default values of all options in one place: OptionParsingStarting
264       // ()
265       OptionParsingStarting(nullptr);
266     }
267 
268     ~CommandOptions() override = default;
269 
270     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
271                           ExecutionContext *execution_context) override {
272       Status error;
273       const int short_option = m_getopt_table[option_idx].val;
274 
275       switch (short_option) {
276       case 'c': {
277         int32_t input_count = 0;
278         if (option_arg.getAsInteger(0, m_count)) {
279           m_count = UINT32_MAX;
280           error.SetErrorStringWithFormat(
281               "invalid integer value for option '%c'", short_option);
282         } else if (input_count < 0)
283           m_count = UINT32_MAX;
284       } break;
285       case 's':
286         if (option_arg.getAsInteger(0, m_start))
287           error.SetErrorStringWithFormat(
288               "invalid integer value for option '%c'", short_option);
289         break;
290       case 'e': {
291         bool success;
292         m_extended_backtrace =
293             OptionArgParser::ToBoolean(option_arg, false, &success);
294         if (!success)
295           error.SetErrorStringWithFormat(
296               "invalid boolean value for option '%c'", short_option);
297       } break;
298       default:
299         error.SetErrorStringWithFormat("invalid short option character '%c'",
300                                        short_option);
301         break;
302       }
303       return error;
304     }
305 
306     void OptionParsingStarting(ExecutionContext *execution_context) override {
307       m_count = UINT32_MAX;
308       m_start = 0;
309       m_extended_backtrace = false;
310     }
311 
312     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
313       return llvm::makeArrayRef(g_thread_backtrace_options);
314     }
315 
316     // Instance variables to hold the values for command options.
317     uint32_t m_count;
318     uint32_t m_start;
319     bool m_extended_backtrace;
320   };
321 
322   CommandObjectThreadBacktrace(CommandInterpreter &interpreter)
323       : CommandObjectIterateOverThreads(
324             interpreter, "thread backtrace",
325             "Show thread call stacks.  Defaults to the current thread, thread "
326             "indexes can be specified as arguments.\n"
327             "Use the thread-index \"all\" to see all threads.\n"
328             "Use the thread-index \"unique\" to see threads grouped by unique "
329             "call stacks.",
330             nullptr,
331             eCommandRequiresProcess | eCommandRequiresThread |
332                 eCommandTryTargetAPILock | eCommandProcessMustBeLaunched |
333                 eCommandProcessMustBePaused),
334         m_options() {}
335 
336   ~CommandObjectThreadBacktrace() override = default;
337 
338   Options *GetOptions() override { return &m_options; }
339 
340 protected:
341   void DoExtendedBacktrace(Thread *thread, CommandReturnObject &result) {
342     SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime();
343     if (runtime) {
344       Stream &strm = result.GetOutputStream();
345       const std::vector<ConstString> &types =
346           runtime->GetExtendedBacktraceTypes();
347       for (auto type : types) {
348         ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread(
349             thread->shared_from_this(), type);
350         if (ext_thread_sp && ext_thread_sp->IsValid()) {
351           const uint32_t num_frames_with_source = 0;
352           const bool stop_format = false;
353           if (ext_thread_sp->GetStatus(strm, m_options.m_start,
354                                        m_options.m_count,
355                                        num_frames_with_source,
356                                        stop_format)) {
357             DoExtendedBacktrace(ext_thread_sp.get(), result);
358           }
359         }
360       }
361     }
362   }
363 
364   bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
365     ThreadSP thread_sp =
366         m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
367     if (!thread_sp) {
368       result.AppendErrorWithFormat(
369           "thread disappeared while computing backtraces: 0x%" PRIx64 "\n",
370           tid);
371       result.SetStatus(eReturnStatusFailed);
372       return false;
373     }
374 
375     Thread *thread = thread_sp.get();
376 
377     Stream &strm = result.GetOutputStream();
378 
379     // Only dump stack info if we processing unique stacks.
380     const bool only_stacks = m_unique_stacks;
381 
382     // Don't show source context when doing backtraces.
383     const uint32_t num_frames_with_source = 0;
384     const bool stop_format = true;
385     if (!thread->GetStatus(strm, m_options.m_start, m_options.m_count,
386                            num_frames_with_source, stop_format, only_stacks)) {
387       result.AppendErrorWithFormat(
388           "error displaying backtrace for thread: \"0x%4.4x\"\n",
389           thread->GetIndexID());
390       result.SetStatus(eReturnStatusFailed);
391       return false;
392     }
393     if (m_options.m_extended_backtrace) {
394       DoExtendedBacktrace(thread, result);
395     }
396 
397     return true;
398   }
399 
400   CommandOptions m_options;
401 };
402 
403 enum StepScope { eStepScopeSource, eStepScopeInstruction };
404 
405 static constexpr OptionEnumValueElement g_tri_running_mode[] = {
406     {eOnlyThisThread, "this-thread", "Run only this thread"},
407     {eAllThreads, "all-threads", "Run all threads"},
408     {eOnlyDuringStepping, "while-stepping",
409      "Run only this thread while stepping"} };
410 
411 static constexpr OptionEnumValues TriRunningModes() {
412   return OptionEnumValues(g_tri_running_mode);
413 }
414 
415 static constexpr OptionDefinition g_thread_step_scope_options[] = {
416     // clang-format off
417   { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug",   'a', OptionParser::eRequiredArgument, nullptr, {},                0, eArgTypeBoolean,           "A boolean value that sets whether stepping into functions will step over functions with no debug information." },
418   { LLDB_OPT_SET_1, false, "step-out-avoids-no-debug",  'A', OptionParser::eRequiredArgument, 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." },
419   { LLDB_OPT_SET_1, false, "count",                     'c', OptionParser::eRequiredArgument, nullptr, {},                1, eArgTypeCount,             "How many times to perform the stepping operation - currently only supported for step-inst and next-inst." },
420   { LLDB_OPT_SET_1, false, "end-linenumber",            'e', OptionParser::eRequiredArgument, 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." },
421   { LLDB_OPT_SET_1, false, "run-mode",                  'm', OptionParser::eRequiredArgument, nullptr, TriRunningModes(), 0, eArgTypeRunMode,           "Determine how to run other threads while stepping the current thread." },
422   { LLDB_OPT_SET_1, false, "step-over-regexp",          'r', OptionParser::eRequiredArgument, nullptr, {},                0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in." },
423   { LLDB_OPT_SET_1, false, "step-in-target",            't', OptionParser::eRequiredArgument, nullptr, {},                0, eArgTypeFunctionName,      "The name of the directly called function step in should stop at when stepping into." },
424   { LLDB_OPT_SET_2, false, "python-class",              'C', OptionParser::eRequiredArgument, nullptr, {},                0, eArgTypePythonClass,       "The name of the class that will manage this step - only supported for Scripted Step." }
425     // clang-format on
426 };
427 
428 class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed {
429 public:
430   class CommandOptions : public Options {
431   public:
432     CommandOptions() : Options() {
433       // Keep default values of all options in one place: OptionParsingStarting
434       // ()
435       OptionParsingStarting(nullptr);
436     }
437 
438     ~CommandOptions() override = default;
439 
440     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
441                           ExecutionContext *execution_context) override {
442       Status error;
443       const int short_option = m_getopt_table[option_idx].val;
444 
445       switch (short_option) {
446       case 'a': {
447         bool success;
448         bool avoid_no_debug =
449             OptionArgParser::ToBoolean(option_arg, true, &success);
450         if (!success)
451           error.SetErrorStringWithFormat(
452               "invalid boolean value for option '%c'", short_option);
453         else {
454           m_step_in_avoid_no_debug =
455               avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
456         }
457       } break;
458 
459       case 'A': {
460         bool success;
461         bool avoid_no_debug =
462             OptionArgParser::ToBoolean(option_arg, true, &success);
463         if (!success)
464           error.SetErrorStringWithFormat(
465               "invalid boolean value for option '%c'", short_option);
466         else {
467           m_step_out_avoid_no_debug =
468               avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
469         }
470       } break;
471 
472       case 'c':
473         if (option_arg.getAsInteger(0, m_step_count))
474           error.SetErrorStringWithFormat("invalid step count '%s'",
475                                          option_arg.str().c_str());
476         break;
477 
478       case 'C':
479         m_class_name.clear();
480         m_class_name.assign(option_arg);
481         break;
482 
483       case 'm': {
484         auto enum_values = GetDefinitions()[option_idx].enum_values;
485         m_run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum(
486             option_arg, enum_values, eOnlyDuringStepping, error);
487       } break;
488 
489       case 'e':
490         if (option_arg == "block") {
491           m_end_line_is_block_end = 1;
492           break;
493         }
494         if (option_arg.getAsInteger(0, m_end_line))
495           error.SetErrorStringWithFormat("invalid end line number '%s'",
496                                          option_arg.str().c_str());
497         break;
498 
499       case 'r':
500         m_avoid_regexp.clear();
501         m_avoid_regexp.assign(option_arg);
502         break;
503 
504       case 't':
505         m_step_in_target.clear();
506         m_step_in_target.assign(option_arg);
507         break;
508 
509       default:
510         error.SetErrorStringWithFormat("invalid short option character '%c'",
511                                        short_option);
512         break;
513       }
514       return error;
515     }
516 
517     void OptionParsingStarting(ExecutionContext *execution_context) override {
518       m_step_in_avoid_no_debug = eLazyBoolCalculate;
519       m_step_out_avoid_no_debug = eLazyBoolCalculate;
520       m_run_mode = eOnlyDuringStepping;
521 
522       // Check if we are in Non-Stop mode
523       TargetSP target_sp =
524           execution_context ? execution_context->GetTargetSP() : TargetSP();
525       if (target_sp && target_sp->GetNonStopModeEnabled())
526         m_run_mode = eOnlyThisThread;
527 
528       m_avoid_regexp.clear();
529       m_step_in_target.clear();
530       m_class_name.clear();
531       m_step_count = 1;
532       m_end_line = LLDB_INVALID_LINE_NUMBER;
533       m_end_line_is_block_end = false;
534     }
535 
536     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
537       return llvm::makeArrayRef(g_thread_step_scope_options);
538     }
539 
540     // Instance variables to hold the values for command options.
541     LazyBool m_step_in_avoid_no_debug;
542     LazyBool m_step_out_avoid_no_debug;
543     RunMode m_run_mode;
544     std::string m_avoid_regexp;
545     std::string m_step_in_target;
546     std::string m_class_name;
547     uint32_t m_step_count;
548     uint32_t m_end_line;
549     bool m_end_line_is_block_end;
550   };
551 
552   CommandObjectThreadStepWithTypeAndScope(CommandInterpreter &interpreter,
553                                           const char *name, const char *help,
554                                           const char *syntax,
555                                           StepType step_type,
556                                           StepScope step_scope)
557       : CommandObjectParsed(interpreter, name, help, syntax,
558                             eCommandRequiresProcess | eCommandRequiresThread |
559                                 eCommandTryTargetAPILock |
560                                 eCommandProcessMustBeLaunched |
561                                 eCommandProcessMustBePaused),
562         m_step_type(step_type), m_step_scope(step_scope), m_options() {
563     CommandArgumentEntry arg;
564     CommandArgumentData thread_id_arg;
565 
566     // Define the first (and only) variant of this arg.
567     thread_id_arg.arg_type = eArgTypeThreadID;
568     thread_id_arg.arg_repetition = eArgRepeatOptional;
569 
570     // There is only one variant this argument could be; put it into the
571     // argument entry.
572     arg.push_back(thread_id_arg);
573 
574     // Push the data for the first argument into the m_arguments vector.
575     m_arguments.push_back(arg);
576   }
577 
578   ~CommandObjectThreadStepWithTypeAndScope() override = default;
579 
580   Options *GetOptions() override { return &m_options; }
581 
582 protected:
583   bool DoExecute(Args &command, CommandReturnObject &result) override {
584     Process *process = m_exe_ctx.GetProcessPtr();
585     bool synchronous_execution = m_interpreter.GetSynchronous();
586 
587     const uint32_t num_threads = process->GetThreadList().GetSize();
588     Thread *thread = nullptr;
589 
590     if (command.GetArgumentCount() == 0) {
591       thread = GetDefaultThread();
592 
593       if (thread == nullptr) {
594         result.AppendError("no selected thread in process");
595         result.SetStatus(eReturnStatusFailed);
596         return false;
597       }
598     } else {
599       const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
600       uint32_t step_thread_idx =
601           StringConvert::ToUInt32(thread_idx_cstr, LLDB_INVALID_INDEX32);
602       if (step_thread_idx == LLDB_INVALID_INDEX32) {
603         result.AppendErrorWithFormat("invalid thread index '%s'.\n",
604                                      thread_idx_cstr);
605         result.SetStatus(eReturnStatusFailed);
606         return false;
607       }
608       thread =
609           process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
610       if (thread == nullptr) {
611         result.AppendErrorWithFormat(
612             "Thread index %u is out of range (valid values are 0 - %u).\n",
613             step_thread_idx, num_threads);
614         result.SetStatus(eReturnStatusFailed);
615         return false;
616       }
617     }
618 
619     if (m_step_type == eStepTypeScripted) {
620       if (m_options.m_class_name.empty()) {
621         result.AppendErrorWithFormat("empty class name for scripted step.");
622         result.SetStatus(eReturnStatusFailed);
623         return false;
624       } else if (!m_interpreter.GetScriptInterpreter()->CheckObjectExists(
625                      m_options.m_class_name.c_str())) {
626         result.AppendErrorWithFormat(
627             "class for scripted step: \"%s\" does not exist.",
628             m_options.m_class_name.c_str());
629         result.SetStatus(eReturnStatusFailed);
630         return false;
631       }
632     }
633 
634     if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER &&
635         m_step_type != eStepTypeInto) {
636       result.AppendErrorWithFormat(
637           "end line option is only valid for step into");
638       result.SetStatus(eReturnStatusFailed);
639       return false;
640     }
641 
642     const bool abort_other_plans = false;
643     const lldb::RunMode stop_other_threads = m_options.m_run_mode;
644 
645     // This is a bit unfortunate, but not all the commands in this command
646     // object support only while stepping, so I use the bool for them.
647     bool bool_stop_other_threads;
648     if (m_options.m_run_mode == eAllThreads)
649       bool_stop_other_threads = false;
650     else if (m_options.m_run_mode == eOnlyDuringStepping)
651       bool_stop_other_threads =
652           (m_step_type != eStepTypeOut && m_step_type != eStepTypeScripted);
653     else
654       bool_stop_other_threads = true;
655 
656     ThreadPlanSP new_plan_sp;
657 
658     if (m_step_type == eStepTypeInto) {
659       StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
660       assert(frame != nullptr);
661 
662       if (frame->HasDebugInformation()) {
663         AddressRange range;
664         SymbolContext sc = frame->GetSymbolContext(eSymbolContextEverything);
665         if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER) {
666           Status error;
667           if (!sc.GetAddressRangeFromHereToEndLine(m_options.m_end_line, range,
668                                                    error)) {
669             result.AppendErrorWithFormat("invalid end-line option: %s.",
670                                          error.AsCString());
671             result.SetStatus(eReturnStatusFailed);
672             return false;
673           }
674         } else if (m_options.m_end_line_is_block_end) {
675           Status error;
676           Block *block = frame->GetSymbolContext(eSymbolContextBlock).block;
677           if (!block) {
678             result.AppendErrorWithFormat("Could not find the current block.");
679             result.SetStatus(eReturnStatusFailed);
680             return false;
681           }
682 
683           AddressRange block_range;
684           Address pc_address = frame->GetFrameCodeAddress();
685           block->GetRangeContainingAddress(pc_address, block_range);
686           if (!block_range.GetBaseAddress().IsValid()) {
687             result.AppendErrorWithFormat(
688                 "Could not find the current block address.");
689             result.SetStatus(eReturnStatusFailed);
690             return false;
691           }
692           lldb::addr_t pc_offset_in_block =
693               pc_address.GetFileAddress() -
694               block_range.GetBaseAddress().GetFileAddress();
695           lldb::addr_t range_length =
696               block_range.GetByteSize() - pc_offset_in_block;
697           range = AddressRange(pc_address, range_length);
698         } else {
699           range = sc.line_entry.range;
700         }
701 
702         new_plan_sp = thread->QueueThreadPlanForStepInRange(
703             abort_other_plans, range,
704             frame->GetSymbolContext(eSymbolContextEverything),
705             m_options.m_step_in_target.c_str(), stop_other_threads,
706             m_options.m_step_in_avoid_no_debug,
707             m_options.m_step_out_avoid_no_debug);
708 
709         if (new_plan_sp && !m_options.m_avoid_regexp.empty()) {
710           ThreadPlanStepInRange *step_in_range_plan =
711               static_cast<ThreadPlanStepInRange *>(new_plan_sp.get());
712           step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
713         }
714       } else
715         new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
716             false, abort_other_plans, bool_stop_other_threads);
717     } else if (m_step_type == eStepTypeOver) {
718       StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
719 
720       if (frame->HasDebugInformation())
721         new_plan_sp = thread->QueueThreadPlanForStepOverRange(
722             abort_other_plans,
723             frame->GetSymbolContext(eSymbolContextEverything).line_entry,
724             frame->GetSymbolContext(eSymbolContextEverything),
725             stop_other_threads, m_options.m_step_out_avoid_no_debug);
726       else
727         new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
728             true, abort_other_plans, bool_stop_other_threads);
729     } else if (m_step_type == eStepTypeTrace) {
730       new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
731           false, abort_other_plans, bool_stop_other_threads);
732     } else if (m_step_type == eStepTypeTraceOver) {
733       new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
734           true, abort_other_plans, bool_stop_other_threads);
735     } else if (m_step_type == eStepTypeOut) {
736       new_plan_sp = thread->QueueThreadPlanForStepOut(
737           abort_other_plans, nullptr, false, bool_stop_other_threads, eVoteYes,
738           eVoteNoOpinion, thread->GetSelectedFrameIndex(),
739           m_options.m_step_out_avoid_no_debug);
740     } else if (m_step_type == eStepTypeScripted) {
741       new_plan_sp = thread->QueueThreadPlanForStepScripted(
742           abort_other_plans, m_options.m_class_name.c_str(),
743           bool_stop_other_threads);
744     } else {
745       result.AppendError("step type is not supported");
746       result.SetStatus(eReturnStatusFailed);
747       return false;
748     }
749 
750     // If we got a new plan, then set it to be a master plan (User level Plans
751     // should be master plans so that they can be interruptible).  Then resume
752     // the process.
753 
754     if (new_plan_sp) {
755       new_plan_sp->SetIsMasterPlan(true);
756       new_plan_sp->SetOkayToDiscard(false);
757 
758       if (m_options.m_step_count > 1) {
759         if (!new_plan_sp->SetIterationCount(m_options.m_step_count)) {
760           result.AppendWarning(
761               "step operation does not support iteration count.");
762         }
763       }
764 
765       process->GetThreadList().SetSelectedThreadByID(thread->GetID());
766 
767       const uint32_t iohandler_id = process->GetIOHandlerID();
768 
769       StreamString stream;
770       Status error;
771       if (synchronous_execution)
772         error = process->ResumeSynchronous(&stream);
773       else
774         error = process->Resume();
775 
776       if (!error.Success()) {
777         result.AppendMessage(error.AsCString());
778         result.SetStatus(eReturnStatusFailed);
779         return false;
780       }
781 
782       // There is a race condition where this thread will return up the call
783       // stack to the main command handler and show an (lldb) prompt before
784       // HandlePrivateEvent (from PrivateStateThread) has a chance to call
785       // PushProcessIOHandler().
786       process->SyncIOHandler(iohandler_id, std::chrono::seconds(2));
787 
788       if (synchronous_execution) {
789         // If any state changed events had anything to say, add that to the
790         // result
791         if (stream.GetSize() > 0)
792           result.AppendMessage(stream.GetString());
793 
794         process->GetThreadList().SetSelectedThreadByID(thread->GetID());
795         result.SetDidChangeProcessState(true);
796         result.SetStatus(eReturnStatusSuccessFinishNoResult);
797       } else {
798         result.SetStatus(eReturnStatusSuccessContinuingNoResult);
799       }
800     } else {
801       result.AppendError("Couldn't find thread plan to implement step type.");
802       result.SetStatus(eReturnStatusFailed);
803     }
804     return result.Succeeded();
805   }
806 
807 protected:
808   StepType m_step_type;
809   StepScope m_step_scope;
810   CommandOptions m_options;
811 };
812 
813 //-------------------------------------------------------------------------
814 // CommandObjectThreadContinue
815 //-------------------------------------------------------------------------
816 
817 class CommandObjectThreadContinue : public CommandObjectParsed {
818 public:
819   CommandObjectThreadContinue(CommandInterpreter &interpreter)
820       : CommandObjectParsed(
821             interpreter, "thread continue",
822             "Continue execution of the current target process.  One "
823             "or more threads may be specified, by default all "
824             "threads continue.",
825             nullptr,
826             eCommandRequiresThread | eCommandTryTargetAPILock |
827                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
828     CommandArgumentEntry arg;
829     CommandArgumentData thread_idx_arg;
830 
831     // Define the first (and only) variant of this arg.
832     thread_idx_arg.arg_type = eArgTypeThreadIndex;
833     thread_idx_arg.arg_repetition = eArgRepeatPlus;
834 
835     // There is only one variant this argument could be; put it into the
836     // argument entry.
837     arg.push_back(thread_idx_arg);
838 
839     // Push the data for the first argument into the m_arguments vector.
840     m_arguments.push_back(arg);
841   }
842 
843   ~CommandObjectThreadContinue() override = default;
844 
845   bool DoExecute(Args &command, CommandReturnObject &result) override {
846     bool synchronous_execution = m_interpreter.GetSynchronous();
847 
848     if (!m_interpreter.GetDebugger().GetSelectedTarget()) {
849       result.AppendError("invalid target, create a debug target using the "
850                          "'target create' command");
851       result.SetStatus(eReturnStatusFailed);
852       return false;
853     }
854 
855     Process *process = m_exe_ctx.GetProcessPtr();
856     if (process == nullptr) {
857       result.AppendError("no process exists. Cannot continue");
858       result.SetStatus(eReturnStatusFailed);
859       return false;
860     }
861 
862     StateType state = process->GetState();
863     if ((state == eStateCrashed) || (state == eStateStopped) ||
864         (state == eStateSuspended)) {
865       const size_t argc = command.GetArgumentCount();
866       if (argc > 0) {
867         // These two lines appear at the beginning of both blocks in this
868         // if..else, but that is because we need to release the lock before
869         // calling process->Resume below.
870         std::lock_guard<std::recursive_mutex> guard(
871             process->GetThreadList().GetMutex());
872         const uint32_t num_threads = process->GetThreadList().GetSize();
873         std::vector<Thread *> resume_threads;
874         for (auto &entry : command.entries()) {
875           uint32_t thread_idx;
876           if (entry.ref.getAsInteger(0, thread_idx)) {
877             result.AppendErrorWithFormat(
878                 "invalid thread index argument: \"%s\".\n", entry.c_str());
879             result.SetStatus(eReturnStatusFailed);
880             return false;
881           }
882           Thread *thread =
883               process->GetThreadList().FindThreadByIndexID(thread_idx).get();
884 
885           if (thread) {
886             resume_threads.push_back(thread);
887           } else {
888             result.AppendErrorWithFormat("invalid thread index %u.\n",
889                                          thread_idx);
890             result.SetStatus(eReturnStatusFailed);
891             return false;
892           }
893         }
894 
895         if (resume_threads.empty()) {
896           result.AppendError("no valid thread indexes were specified");
897           result.SetStatus(eReturnStatusFailed);
898           return false;
899         } else {
900           if (resume_threads.size() == 1)
901             result.AppendMessageWithFormat("Resuming thread: ");
902           else
903             result.AppendMessageWithFormat("Resuming threads: ");
904 
905           for (uint32_t idx = 0; idx < num_threads; ++idx) {
906             Thread *thread =
907                 process->GetThreadList().GetThreadAtIndex(idx).get();
908             std::vector<Thread *>::iterator this_thread_pos =
909                 find(resume_threads.begin(), resume_threads.end(), thread);
910 
911             if (this_thread_pos != resume_threads.end()) {
912               resume_threads.erase(this_thread_pos);
913               if (!resume_threads.empty())
914                 result.AppendMessageWithFormat("%u, ", thread->GetIndexID());
915               else
916                 result.AppendMessageWithFormat("%u ", thread->GetIndexID());
917 
918               const bool override_suspend = true;
919               thread->SetResumeState(eStateRunning, override_suspend);
920             } else {
921               thread->SetResumeState(eStateSuspended);
922             }
923           }
924           result.AppendMessageWithFormat("in process %" PRIu64 "\n",
925                                          process->GetID());
926         }
927       } else {
928         // These two lines appear at the beginning of both blocks in this
929         // if..else, but that is because we need to release the lock before
930         // calling process->Resume below.
931         std::lock_guard<std::recursive_mutex> guard(
932             process->GetThreadList().GetMutex());
933         const uint32_t num_threads = process->GetThreadList().GetSize();
934         Thread *current_thread = GetDefaultThread();
935         if (current_thread == nullptr) {
936           result.AppendError("the process doesn't have a current thread");
937           result.SetStatus(eReturnStatusFailed);
938           return false;
939         }
940         // Set the actions that the threads should each take when resuming
941         for (uint32_t idx = 0; idx < num_threads; ++idx) {
942           Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
943           if (thread == current_thread) {
944             result.AppendMessageWithFormat("Resuming thread 0x%4.4" PRIx64
945                                            " in process %" PRIu64 "\n",
946                                            thread->GetID(), process->GetID());
947             const bool override_suspend = true;
948             thread->SetResumeState(eStateRunning, override_suspend);
949           } else {
950             thread->SetResumeState(eStateSuspended);
951           }
952         }
953       }
954 
955       StreamString stream;
956       Status error;
957       if (synchronous_execution)
958         error = process->ResumeSynchronous(&stream);
959       else
960         error = process->Resume();
961 
962       // We should not be holding the thread list lock when we do this.
963       if (error.Success()) {
964         result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n",
965                                        process->GetID());
966         if (synchronous_execution) {
967           // If any state changed events had anything to say, add that to the
968           // result
969           if (stream.GetSize() > 0)
970             result.AppendMessage(stream.GetString());
971 
972           result.SetDidChangeProcessState(true);
973           result.SetStatus(eReturnStatusSuccessFinishNoResult);
974         } else {
975           result.SetStatus(eReturnStatusSuccessContinuingNoResult);
976         }
977       } else {
978         result.AppendErrorWithFormat("Failed to resume process: %s\n",
979                                      error.AsCString());
980         result.SetStatus(eReturnStatusFailed);
981       }
982     } else {
983       result.AppendErrorWithFormat(
984           "Process cannot be continued from its current state (%s).\n",
985           StateAsCString(state));
986       result.SetStatus(eReturnStatusFailed);
987     }
988 
989     return result.Succeeded();
990   }
991 };
992 
993 //-------------------------------------------------------------------------
994 // CommandObjectThreadUntil
995 //-------------------------------------------------------------------------
996 
997 static constexpr OptionEnumValueElement g_duo_running_mode[] = {
998     {eOnlyThisThread, "this-thread", "Run only this thread"},
999     {eAllThreads, "all-threads", "Run all threads"} };
1000 
1001 static constexpr OptionEnumValues DuoRunningModes() {
1002   return OptionEnumValues(g_duo_running_mode);
1003 }
1004 
1005 static constexpr OptionDefinition g_thread_until_options[] = {
1006     // clang-format off
1007   { LLDB_OPT_SET_1, false, "frame",   'f', OptionParser::eRequiredArgument, nullptr, {},                0, eArgTypeFrameIndex,          "Frame index for until operation - defaults to 0" },
1008   { LLDB_OPT_SET_1, false, "thread",  't', OptionParser::eRequiredArgument, nullptr, {},                0, eArgTypeThreadIndex,         "Thread index for the thread for until operation" },
1009   { LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, nullptr, DuoRunningModes(), 0, eArgTypeRunMode,             "Determine how to run other threads while stepping this one" },
1010   { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {},                0, eArgTypeAddressOrExpression, "Run until we reach the specified address, or leave the function - can be specified multiple times." }
1011     // clang-format on
1012 };
1013 
1014 class CommandObjectThreadUntil : public CommandObjectParsed {
1015 public:
1016   class CommandOptions : public Options {
1017   public:
1018     uint32_t m_thread_idx;
1019     uint32_t m_frame_idx;
1020 
1021     CommandOptions()
1022         : Options(), m_thread_idx(LLDB_INVALID_THREAD_ID),
1023           m_frame_idx(LLDB_INVALID_FRAME_ID) {
1024       // Keep default values of all options in one place: OptionParsingStarting
1025       // ()
1026       OptionParsingStarting(nullptr);
1027     }
1028 
1029     ~CommandOptions() override = default;
1030 
1031     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1032                           ExecutionContext *execution_context) override {
1033       Status error;
1034       const int short_option = m_getopt_table[option_idx].val;
1035 
1036       switch (short_option) {
1037       case 'a': {
1038         lldb::addr_t tmp_addr = OptionArgParser::ToAddress(
1039             execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
1040         if (error.Success())
1041           m_until_addrs.push_back(tmp_addr);
1042       } break;
1043       case 't':
1044         if (option_arg.getAsInteger(0, m_thread_idx)) {
1045           m_thread_idx = LLDB_INVALID_INDEX32;
1046           error.SetErrorStringWithFormat("invalid thread index '%s'",
1047                                          option_arg.str().c_str());
1048         }
1049         break;
1050       case 'f':
1051         if (option_arg.getAsInteger(0, m_frame_idx)) {
1052           m_frame_idx = LLDB_INVALID_FRAME_ID;
1053           error.SetErrorStringWithFormat("invalid frame index '%s'",
1054                                          option_arg.str().c_str());
1055         }
1056         break;
1057       case 'm': {
1058         auto enum_values = GetDefinitions()[option_idx].enum_values;
1059         lldb::RunMode run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum(
1060             option_arg, enum_values, eOnlyDuringStepping, error);
1061 
1062         if (error.Success()) {
1063           if (run_mode == eAllThreads)
1064             m_stop_others = false;
1065           else
1066             m_stop_others = true;
1067         }
1068       } break;
1069       default:
1070         error.SetErrorStringWithFormat("invalid short option character '%c'",
1071                                        short_option);
1072         break;
1073       }
1074       return error;
1075     }
1076 
1077     void OptionParsingStarting(ExecutionContext *execution_context) override {
1078       m_thread_idx = LLDB_INVALID_THREAD_ID;
1079       m_frame_idx = 0;
1080       m_stop_others = false;
1081       m_until_addrs.clear();
1082     }
1083 
1084     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1085       return llvm::makeArrayRef(g_thread_until_options);
1086     }
1087 
1088     uint32_t m_step_thread_idx;
1089     bool m_stop_others;
1090     std::vector<lldb::addr_t> m_until_addrs;
1091 
1092     // Instance variables to hold the values for command options.
1093   };
1094 
1095   CommandObjectThreadUntil(CommandInterpreter &interpreter)
1096       : CommandObjectParsed(
1097             interpreter, "thread until",
1098             "Continue until a line number or address is reached by the "
1099             "current or specified thread.  Stops when returning from "
1100             "the current function as a safety measure.  "
1101             "The target line number(s) are given as arguments, and if more than one"
1102             " is provided, stepping will stop when the first one is hit.",
1103             nullptr,
1104             eCommandRequiresThread | eCommandTryTargetAPILock |
1105                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
1106         m_options() {
1107     CommandArgumentEntry arg;
1108     CommandArgumentData line_num_arg;
1109 
1110     // Define the first (and only) variant of this arg.
1111     line_num_arg.arg_type = eArgTypeLineNum;
1112     line_num_arg.arg_repetition = eArgRepeatPlain;
1113 
1114     // There is only one variant this argument could be; put it into the
1115     // argument entry.
1116     arg.push_back(line_num_arg);
1117 
1118     // Push the data for the first argument into the m_arguments vector.
1119     m_arguments.push_back(arg);
1120   }
1121 
1122   ~CommandObjectThreadUntil() override = default;
1123 
1124   Options *GetOptions() override { return &m_options; }
1125 
1126 protected:
1127   bool DoExecute(Args &command, CommandReturnObject &result) override {
1128     bool synchronous_execution = m_interpreter.GetSynchronous();
1129 
1130     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1131     if (target == nullptr) {
1132       result.AppendError("invalid target, create a debug target using the "
1133                          "'target create' command");
1134       result.SetStatus(eReturnStatusFailed);
1135       return false;
1136     }
1137 
1138     Process *process = m_exe_ctx.GetProcessPtr();
1139     if (process == nullptr) {
1140       result.AppendError("need a valid process to step");
1141       result.SetStatus(eReturnStatusFailed);
1142     } else {
1143       Thread *thread = nullptr;
1144       std::vector<uint32_t> line_numbers;
1145 
1146       if (command.GetArgumentCount() >= 1) {
1147         size_t num_args = command.GetArgumentCount();
1148         for (size_t i = 0; i < num_args; i++) {
1149           uint32_t line_number;
1150           line_number = StringConvert::ToUInt32(command.GetArgumentAtIndex(i),
1151                                                 UINT32_MAX);
1152           if (line_number == UINT32_MAX) {
1153             result.AppendErrorWithFormat("invalid line number: '%s'.\n",
1154                                          command.GetArgumentAtIndex(i));
1155             result.SetStatus(eReturnStatusFailed);
1156             return false;
1157           } else
1158             line_numbers.push_back(line_number);
1159         }
1160       } else if (m_options.m_until_addrs.empty()) {
1161         result.AppendErrorWithFormat("No line number or address provided:\n%s",
1162                                      GetSyntax().str().c_str());
1163         result.SetStatus(eReturnStatusFailed);
1164         return false;
1165       }
1166 
1167       if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) {
1168         thread = GetDefaultThread();
1169       } else {
1170         thread = process->GetThreadList()
1171                      .FindThreadByIndexID(m_options.m_thread_idx)
1172                      .get();
1173       }
1174 
1175       if (thread == nullptr) {
1176         const uint32_t num_threads = process->GetThreadList().GetSize();
1177         result.AppendErrorWithFormat(
1178             "Thread index %u is out of range (valid values are 0 - %u).\n",
1179             m_options.m_thread_idx, num_threads);
1180         result.SetStatus(eReturnStatusFailed);
1181         return false;
1182       }
1183 
1184       const bool abort_other_plans = false;
1185 
1186       StackFrame *frame =
1187           thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
1188       if (frame == nullptr) {
1189         result.AppendErrorWithFormat(
1190             "Frame index %u is out of range for thread %u.\n",
1191             m_options.m_frame_idx, m_options.m_thread_idx);
1192         result.SetStatus(eReturnStatusFailed);
1193         return false;
1194       }
1195 
1196       ThreadPlanSP new_plan_sp;
1197 
1198       if (frame->HasDebugInformation()) {
1199         // Finally we got here...  Translate the given line number to a bunch
1200         // of addresses:
1201         SymbolContext sc(frame->GetSymbolContext(eSymbolContextCompUnit));
1202         LineTable *line_table = nullptr;
1203         if (sc.comp_unit)
1204           line_table = sc.comp_unit->GetLineTable();
1205 
1206         if (line_table == nullptr) {
1207           result.AppendErrorWithFormat("Failed to resolve the line table for "
1208                                        "frame %u of thread index %u.\n",
1209                                        m_options.m_frame_idx,
1210                                        m_options.m_thread_idx);
1211           result.SetStatus(eReturnStatusFailed);
1212           return false;
1213         }
1214 
1215         LineEntry function_start;
1216         uint32_t index_ptr = 0, end_ptr;
1217         std::vector<addr_t> address_list;
1218 
1219         // Find the beginning & end index of the
1220         AddressRange fun_addr_range = sc.function->GetAddressRange();
1221         Address fun_start_addr = fun_addr_range.GetBaseAddress();
1222         line_table->FindLineEntryByAddress(fun_start_addr, function_start,
1223                                            &index_ptr);
1224 
1225         Address fun_end_addr(fun_start_addr.GetSection(),
1226                              fun_start_addr.GetOffset() +
1227                                  fun_addr_range.GetByteSize());
1228 
1229         bool all_in_function = true;
1230 
1231         line_table->FindLineEntryByAddress(fun_end_addr, function_start,
1232                                            &end_ptr);
1233 
1234         for (uint32_t line_number : line_numbers) {
1235           uint32_t start_idx_ptr = index_ptr;
1236           while (start_idx_ptr <= end_ptr) {
1237             LineEntry line_entry;
1238             const bool exact = false;
1239             start_idx_ptr = sc.comp_unit->FindLineEntry(
1240                 start_idx_ptr, line_number, sc.comp_unit, exact, &line_entry);
1241             if (start_idx_ptr == UINT32_MAX)
1242               break;
1243 
1244             addr_t address =
1245                 line_entry.range.GetBaseAddress().GetLoadAddress(target);
1246             if (address != LLDB_INVALID_ADDRESS) {
1247               if (fun_addr_range.ContainsLoadAddress(address, target))
1248                 address_list.push_back(address);
1249               else
1250                 all_in_function = false;
1251             }
1252             start_idx_ptr++;
1253           }
1254         }
1255 
1256         for (lldb::addr_t address : m_options.m_until_addrs) {
1257           if (fun_addr_range.ContainsLoadAddress(address, target))
1258             address_list.push_back(address);
1259           else
1260             all_in_function = false;
1261         }
1262 
1263         if (address_list.empty()) {
1264           if (all_in_function)
1265             result.AppendErrorWithFormat(
1266                 "No line entries matching until target.\n");
1267           else
1268             result.AppendErrorWithFormat(
1269                 "Until target outside of the current function.\n");
1270 
1271           result.SetStatus(eReturnStatusFailed);
1272           return false;
1273         }
1274 
1275         new_plan_sp = thread->QueueThreadPlanForStepUntil(
1276             abort_other_plans, &address_list.front(), address_list.size(),
1277             m_options.m_stop_others, m_options.m_frame_idx);
1278         // User level plans should be master plans so they can be interrupted
1279         // (e.g. by hitting a breakpoint) and other plans executed by the user
1280         // (stepping around the breakpoint) and then a "continue" will resume
1281         // 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 constexpr OptionDefinition g_thread_info_options[] = {
1427     // clang-format off
1428   { LLDB_OPT_SET_ALL, false, "json",      'j', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the thread info in JSON format." },
1429   { LLDB_OPT_SET_ALL, false, "stop-info", 's', OptionParser::eNoArgument, 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 constexpr OptionDefinition g_thread_return_options[] = {
1522     // clang-format off
1523   { LLDB_OPT_SET_ALL, false, "from-expression", 'x', OptionParser::eNoArgument, 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(llvm::StringRef command,
1611                  CommandReturnObject &result) override {
1612     // I am going to handle this by hand, because I don't want you to have to
1613     // say:
1614     // "thread return -- -5".
1615     if (command.startswith("-x")) {
1616       if (command.size() != 2U)
1617         result.AppendWarning("Return values ignored when returning from user "
1618                              "called expressions");
1619 
1620       Thread *thread = m_exe_ctx.GetThreadPtr();
1621       Status error;
1622       error = thread->UnwindInnermostExpression();
1623       if (!error.Success()) {
1624         result.AppendErrorWithFormat("Unwinding expression failed - %s.",
1625                                      error.AsCString());
1626         result.SetStatus(eReturnStatusFailed);
1627       } else {
1628         bool success =
1629             thread->SetSelectedFrameByIndexNoisily(0, result.GetOutputStream());
1630         if (success) {
1631           m_exe_ctx.SetFrameSP(thread->GetSelectedFrame());
1632           result.SetStatus(eReturnStatusSuccessFinishResult);
1633         } else {
1634           result.AppendErrorWithFormat(
1635               "Could not select 0th frame after unwinding expression.");
1636           result.SetStatus(eReturnStatusFailed);
1637         }
1638       }
1639       return result.Succeeded();
1640     }
1641 
1642     ValueObjectSP return_valobj_sp;
1643 
1644     StackFrameSP frame_sp = m_exe_ctx.GetFrameSP();
1645     uint32_t frame_idx = frame_sp->GetFrameIndex();
1646 
1647     if (frame_sp->IsInlined()) {
1648       result.AppendError("Don't know how to return from inlined frames.");
1649       result.SetStatus(eReturnStatusFailed);
1650       return false;
1651     }
1652 
1653     if (!command.empty()) {
1654       Target *target = m_exe_ctx.GetTargetPtr();
1655       EvaluateExpressionOptions options;
1656 
1657       options.SetUnwindOnError(true);
1658       options.SetUseDynamic(eNoDynamicValues);
1659 
1660       ExpressionResults exe_results = eExpressionSetupError;
1661       exe_results = target->EvaluateExpression(command, frame_sp.get(),
1662                                                return_valobj_sp, options);
1663       if (exe_results != eExpressionCompleted) {
1664         if (return_valobj_sp)
1665           result.AppendErrorWithFormat(
1666               "Error evaluating result expression: %s",
1667               return_valobj_sp->GetError().AsCString());
1668         else
1669           result.AppendErrorWithFormat(
1670               "Unknown error evaluating result expression.");
1671         result.SetStatus(eReturnStatusFailed);
1672         return false;
1673       }
1674     }
1675 
1676     Status error;
1677     ThreadSP thread_sp = m_exe_ctx.GetThreadSP();
1678     const bool broadcast = true;
1679     error = thread_sp->ReturnFromFrame(frame_sp, return_valobj_sp, broadcast);
1680     if (!error.Success()) {
1681       result.AppendErrorWithFormat(
1682           "Error returning from frame %d of thread %d: %s.", frame_idx,
1683           thread_sp->GetIndexID(), error.AsCString());
1684       result.SetStatus(eReturnStatusFailed);
1685       return false;
1686     }
1687 
1688     result.SetStatus(eReturnStatusSuccessFinishResult);
1689     return true;
1690   }
1691 
1692   CommandOptions m_options;
1693 };
1694 
1695 //-------------------------------------------------------------------------
1696 // CommandObjectThreadJump
1697 //-------------------------------------------------------------------------
1698 
1699 static constexpr OptionDefinition g_thread_jump_options[] = {
1700     // clang-format off
1701   { LLDB_OPT_SET_1,                                   false, "file",    'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,            "Specifies the source file to jump to." },
1702   { LLDB_OPT_SET_1,                                   true,  "line",    'l', OptionParser::eRequiredArgument, nullptr, {}, 0,                                         eArgTypeLineNum,             "Specifies the line number to jump to." },
1703   { LLDB_OPT_SET_2,                                   true,  "by",      'b', OptionParser::eRequiredArgument, nullptr, {}, 0,                                         eArgTypeOffset,              "Jumps by a relative line offset from the current line." },
1704   { LLDB_OPT_SET_3,                                   true,  "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0,                                         eArgTypeAddressOrExpression, "Jumps to a specific address." },
1705   { LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "force",   'r', OptionParser::eNoArgument,       nullptr, {}, 0,                                         eArgTypeNone,                "Allows the PC to leave the current function." }
1706     // clang-format on
1707 };
1708 
1709 class CommandObjectThreadJump : public CommandObjectParsed {
1710 public:
1711   class CommandOptions : public Options {
1712   public:
1713     CommandOptions() : Options() { OptionParsingStarting(nullptr); }
1714 
1715     ~CommandOptions() override = default;
1716 
1717     void OptionParsingStarting(ExecutionContext *execution_context) override {
1718       m_filenames.Clear();
1719       m_line_num = 0;
1720       m_line_offset = 0;
1721       m_load_addr = LLDB_INVALID_ADDRESS;
1722       m_force = false;
1723     }
1724 
1725     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1726                           ExecutionContext *execution_context) override {
1727       const int short_option = m_getopt_table[option_idx].val;
1728       Status error;
1729 
1730       switch (short_option) {
1731       case 'f':
1732         m_filenames.AppendIfUnique(FileSpec(option_arg));
1733         if (m_filenames.GetSize() > 1)
1734           return Status("only one source file expected.");
1735         break;
1736       case 'l':
1737         if (option_arg.getAsInteger(0, m_line_num))
1738           return Status("invalid line number: '%s'.", option_arg.str().c_str());
1739         break;
1740       case 'b':
1741         if (option_arg.getAsInteger(0, m_line_offset))
1742           return Status("invalid line offset: '%s'.", option_arg.str().c_str());
1743         break;
1744       case 'a':
1745         m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
1746                                                  LLDB_INVALID_ADDRESS, &error);
1747         break;
1748       case 'r':
1749         m_force = true;
1750         break;
1751       default:
1752         return Status("invalid short option character '%c'", short_option);
1753       }
1754       return error;
1755     }
1756 
1757     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1758       return llvm::makeArrayRef(g_thread_jump_options);
1759     }
1760 
1761     FileSpecList m_filenames;
1762     uint32_t m_line_num;
1763     int32_t m_line_offset;
1764     lldb::addr_t m_load_addr;
1765     bool m_force;
1766   };
1767 
1768   CommandObjectThreadJump(CommandInterpreter &interpreter)
1769       : CommandObjectParsed(
1770             interpreter, "thread jump",
1771             "Sets the program counter to a new address.", "thread jump",
1772             eCommandRequiresFrame | eCommandTryTargetAPILock |
1773                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
1774         m_options() {}
1775 
1776   ~CommandObjectThreadJump() override = default;
1777 
1778   Options *GetOptions() override { return &m_options; }
1779 
1780 protected:
1781   bool DoExecute(Args &args, CommandReturnObject &result) override {
1782     RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
1783     StackFrame *frame = m_exe_ctx.GetFramePtr();
1784     Thread *thread = m_exe_ctx.GetThreadPtr();
1785     Target *target = m_exe_ctx.GetTargetPtr();
1786     const SymbolContext &sym_ctx =
1787         frame->GetSymbolContext(eSymbolContextLineEntry);
1788 
1789     if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) {
1790       // Use this address directly.
1791       Address dest = Address(m_options.m_load_addr);
1792 
1793       lldb::addr_t callAddr = dest.GetCallableLoadAddress(target);
1794       if (callAddr == LLDB_INVALID_ADDRESS) {
1795         result.AppendErrorWithFormat("Invalid destination address.");
1796         result.SetStatus(eReturnStatusFailed);
1797         return false;
1798       }
1799 
1800       if (!reg_ctx->SetPC(callAddr)) {
1801         result.AppendErrorWithFormat("Error changing PC value for thread %d.",
1802                                      thread->GetIndexID());
1803         result.SetStatus(eReturnStatusFailed);
1804         return false;
1805       }
1806     } else {
1807       // Pick either the absolute line, or work out a relative one.
1808       int32_t line = (int32_t)m_options.m_line_num;
1809       if (line == 0)
1810         line = sym_ctx.line_entry.line + m_options.m_line_offset;
1811 
1812       // Try the current file, but override if asked.
1813       FileSpec file = sym_ctx.line_entry.file;
1814       if (m_options.m_filenames.GetSize() == 1)
1815         file = m_options.m_filenames.GetFileSpecAtIndex(0);
1816 
1817       if (!file) {
1818         result.AppendErrorWithFormat(
1819             "No source file available for the current location.");
1820         result.SetStatus(eReturnStatusFailed);
1821         return false;
1822       }
1823 
1824       std::string warnings;
1825       Status err = thread->JumpToLine(file, line, m_options.m_force, &warnings);
1826 
1827       if (err.Fail()) {
1828         result.SetError(err);
1829         return false;
1830       }
1831 
1832       if (!warnings.empty())
1833         result.AppendWarning(warnings.c_str());
1834     }
1835 
1836     result.SetStatus(eReturnStatusSuccessFinishResult);
1837     return true;
1838   }
1839 
1840   CommandOptions m_options;
1841 };
1842 
1843 //-------------------------------------------------------------------------
1844 // Next are the subcommands of CommandObjectMultiwordThreadPlan
1845 //-------------------------------------------------------------------------
1846 
1847 //-------------------------------------------------------------------------
1848 // CommandObjectThreadPlanList
1849 //-------------------------------------------------------------------------
1850 
1851 static constexpr OptionDefinition g_thread_plan_list_options[] = {
1852     // clang-format off
1853   { LLDB_OPT_SET_1, false, "verbose",  'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display more information about the thread plans" },
1854   { LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display internal as well as user thread plans" }
1855     // clang-format on
1856 };
1857 
1858 class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads {
1859 public:
1860   class CommandOptions : public Options {
1861   public:
1862     CommandOptions() : Options() {
1863       // Keep default values of all options in one place: OptionParsingStarting
1864       // ()
1865       OptionParsingStarting(nullptr);
1866     }
1867 
1868     ~CommandOptions() override = default;
1869 
1870     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1871                           ExecutionContext *execution_context) override {
1872       Status error;
1873       const int short_option = m_getopt_table[option_idx].val;
1874 
1875       switch (short_option) {
1876       case 'i':
1877         m_internal = true;
1878         break;
1879       case 'v':
1880         m_verbose = true;
1881         break;
1882       default:
1883         error.SetErrorStringWithFormat("invalid short option character '%c'",
1884                                        short_option);
1885         break;
1886       }
1887       return error;
1888     }
1889 
1890     void OptionParsingStarting(ExecutionContext *execution_context) override {
1891       m_verbose = false;
1892       m_internal = false;
1893     }
1894 
1895     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1896       return llvm::makeArrayRef(g_thread_plan_list_options);
1897     }
1898 
1899     // Instance variables to hold the values for command options.
1900     bool m_verbose;
1901     bool m_internal;
1902   };
1903 
1904   CommandObjectThreadPlanList(CommandInterpreter &interpreter)
1905       : CommandObjectIterateOverThreads(
1906             interpreter, "thread plan list",
1907             "Show thread plans for one or more threads.  If no threads are "
1908             "specified, show the "
1909             "current thread.  Use the thread-index \"all\" to see all threads.",
1910             nullptr,
1911             eCommandRequiresProcess | eCommandRequiresThread |
1912                 eCommandTryTargetAPILock | eCommandProcessMustBeLaunched |
1913                 eCommandProcessMustBePaused),
1914         m_options() {}
1915 
1916   ~CommandObjectThreadPlanList() override = default;
1917 
1918   Options *GetOptions() override { return &m_options; }
1919 
1920 protected:
1921   bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
1922     ThreadSP thread_sp =
1923         m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
1924     if (!thread_sp) {
1925       result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n",
1926                                    tid);
1927       result.SetStatus(eReturnStatusFailed);
1928       return false;
1929     }
1930 
1931     Thread *thread = thread_sp.get();
1932 
1933     Stream &strm = result.GetOutputStream();
1934     DescriptionLevel desc_level = eDescriptionLevelFull;
1935     if (m_options.m_verbose)
1936       desc_level = eDescriptionLevelVerbose;
1937 
1938     thread->DumpThreadPlans(&strm, desc_level, m_options.m_internal, true);
1939     return true;
1940   }
1941 
1942   CommandOptions m_options;
1943 };
1944 
1945 class CommandObjectThreadPlanDiscard : public CommandObjectParsed {
1946 public:
1947   CommandObjectThreadPlanDiscard(CommandInterpreter &interpreter)
1948       : CommandObjectParsed(interpreter, "thread plan discard",
1949                             "Discards thread plans up to and including the "
1950                             "specified index (see 'thread plan list'.)  "
1951                             "Only user visible plans can be discarded.",
1952                             nullptr,
1953                             eCommandRequiresProcess | eCommandRequiresThread |
1954                                 eCommandTryTargetAPILock |
1955                                 eCommandProcessMustBeLaunched |
1956                                 eCommandProcessMustBePaused) {
1957     CommandArgumentEntry arg;
1958     CommandArgumentData plan_index_arg;
1959 
1960     // Define the first (and only) variant of this arg.
1961     plan_index_arg.arg_type = eArgTypeUnsignedInteger;
1962     plan_index_arg.arg_repetition = eArgRepeatPlain;
1963 
1964     // There is only one variant this argument could be; put it into the
1965     // argument entry.
1966     arg.push_back(plan_index_arg);
1967 
1968     // Push the data for the first argument into the m_arguments vector.
1969     m_arguments.push_back(arg);
1970   }
1971 
1972   ~CommandObjectThreadPlanDiscard() override = default;
1973 
1974   bool DoExecute(Args &args, CommandReturnObject &result) override {
1975     Thread *thread = m_exe_ctx.GetThreadPtr();
1976     if (args.GetArgumentCount() != 1) {
1977       result.AppendErrorWithFormat("Too many arguments, expected one - the "
1978                                    "thread plan index - but got %zu.",
1979                                    args.GetArgumentCount());
1980       result.SetStatus(eReturnStatusFailed);
1981       return false;
1982     }
1983 
1984     bool success;
1985     uint32_t thread_plan_idx =
1986         StringConvert::ToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success);
1987     if (!success) {
1988       result.AppendErrorWithFormat(
1989           "Invalid thread index: \"%s\" - should be unsigned int.",
1990           args.GetArgumentAtIndex(0));
1991       result.SetStatus(eReturnStatusFailed);
1992       return false;
1993     }
1994 
1995     if (thread_plan_idx == 0) {
1996       result.AppendErrorWithFormat(
1997           "You wouldn't really want me to discard the base thread plan.");
1998       result.SetStatus(eReturnStatusFailed);
1999       return false;
2000     }
2001 
2002     if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx)) {
2003       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2004       return true;
2005     } else {
2006       result.AppendErrorWithFormat(
2007           "Could not find User thread plan with index %s.",
2008           args.GetArgumentAtIndex(0));
2009       result.SetStatus(eReturnStatusFailed);
2010       return false;
2011     }
2012   }
2013 };
2014 
2015 //-------------------------------------------------------------------------
2016 // CommandObjectMultiwordThreadPlan
2017 //-------------------------------------------------------------------------
2018 
2019 class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword {
2020 public:
2021   CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter)
2022       : CommandObjectMultiword(
2023             interpreter, "plan",
2024             "Commands for managing thread plans that control execution.",
2025             "thread plan <subcommand> [<subcommand objects]") {
2026     LoadSubCommand(
2027         "list", CommandObjectSP(new CommandObjectThreadPlanList(interpreter)));
2028     LoadSubCommand(
2029         "discard",
2030         CommandObjectSP(new CommandObjectThreadPlanDiscard(interpreter)));
2031   }
2032 
2033   ~CommandObjectMultiwordThreadPlan() override = default;
2034 };
2035 
2036 //-------------------------------------------------------------------------
2037 // CommandObjectMultiwordThread
2038 //-------------------------------------------------------------------------
2039 
2040 CommandObjectMultiwordThread::CommandObjectMultiwordThread(
2041     CommandInterpreter &interpreter)
2042     : CommandObjectMultiword(interpreter, "thread", "Commands for operating on "
2043                                                     "one or more threads in "
2044                                                     "the current process.",
2045                              "thread <subcommand> [<subcommand-options>]") {
2046   LoadSubCommand("backtrace", CommandObjectSP(new CommandObjectThreadBacktrace(
2047                                   interpreter)));
2048   LoadSubCommand("continue",
2049                  CommandObjectSP(new CommandObjectThreadContinue(interpreter)));
2050   LoadSubCommand("list",
2051                  CommandObjectSP(new CommandObjectThreadList(interpreter)));
2052   LoadSubCommand("return",
2053                  CommandObjectSP(new CommandObjectThreadReturn(interpreter)));
2054   LoadSubCommand("jump",
2055                  CommandObjectSP(new CommandObjectThreadJump(interpreter)));
2056   LoadSubCommand("select",
2057                  CommandObjectSP(new CommandObjectThreadSelect(interpreter)));
2058   LoadSubCommand("until",
2059                  CommandObjectSP(new CommandObjectThreadUntil(interpreter)));
2060   LoadSubCommand("info",
2061                  CommandObjectSP(new CommandObjectThreadInfo(interpreter)));
2062   LoadSubCommand("step-in",
2063                  CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2064                      interpreter, "thread step-in",
2065                      "Source level single step, stepping into calls.  Defaults "
2066                      "to current thread unless specified.",
2067                      nullptr, eStepTypeInto, eStepScopeSource)));
2068 
2069   LoadSubCommand("step-out",
2070                  CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2071                      interpreter, "thread step-out",
2072                      "Finish executing the current stack frame and stop after "
2073                      "returning.  Defaults to current thread unless specified.",
2074                      nullptr, eStepTypeOut, eStepScopeSource)));
2075 
2076   LoadSubCommand("step-over",
2077                  CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2078                      interpreter, "thread step-over",
2079                      "Source level single step, stepping over calls.  Defaults "
2080                      "to current thread unless specified.",
2081                      nullptr, eStepTypeOver, eStepScopeSource)));
2082 
2083   LoadSubCommand("step-inst",
2084                  CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2085                      interpreter, "thread step-inst",
2086                      "Instruction level single step, stepping into calls.  "
2087                      "Defaults to current thread unless specified.",
2088                      nullptr, eStepTypeTrace, eStepScopeInstruction)));
2089 
2090   LoadSubCommand("step-inst-over",
2091                  CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2092                      interpreter, "thread step-inst-over",
2093                      "Instruction level single step, stepping over calls.  "
2094                      "Defaults to current thread unless specified.",
2095                      nullptr, eStepTypeTraceOver, eStepScopeInstruction)));
2096 
2097   LoadSubCommand(
2098       "step-scripted",
2099       CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
2100           interpreter, "thread step-scripted",
2101           "Step as instructed by the script class passed in the -C option.",
2102           nullptr, eStepTypeScripted, eStepScopeSource)));
2103 
2104   LoadSubCommand("plan", CommandObjectSP(new CommandObjectMultiwordThreadPlan(
2105                              interpreter)));
2106 }
2107 
2108 CommandObjectMultiwordThread::~CommandObjectMultiwordThread() = default;
2109