//===-- CommandObjectThread.cpp -------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "CommandObjectThread.h"

#include <memory>
#include <optional>
#include <sstream>

#include "CommandObjectThreadUtil.h"
#include "CommandObjectTrace.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/LineEntry.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanStepInRange.h"
#include "lldb/Target/Trace.h"
#include "lldb/Target/TraceDumper.h"
#include "lldb/Utility/State.h"
#include "lldb/ValueObject/ValueObject.h"

using namespace lldb;
using namespace lldb_private;

// CommandObjectThreadBacktrace
#define LLDB_OPTIONS_thread_backtrace
#include "CommandOptions.inc"

class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() {
      // Keep default values of all options in one place: OptionParsingStarting
      // ()
      OptionParsingStarting(nullptr);
    }

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'c':
        if (option_arg.getAsInteger(0, m_count)) {
          m_count = UINT32_MAX;
          error = Status::FromErrorStringWithFormat(
              "invalid integer value for option '%c': %s", short_option,
              option_arg.data());
        }
        // A count of 0 means all frames.
        if (m_count == 0)
          m_count = UINT32_MAX;
        break;
      case 's':
        if (option_arg.getAsInteger(0, m_start))
          error = Status::FromErrorStringWithFormat(
              "invalid integer value for option '%c': %s", short_option,
              option_arg.data());
        break;
      case 'e': {
        bool success;
        m_extended_backtrace =
            OptionArgParser::ToBoolean(option_arg, false, &success);
        if (!success)
          error = Status::FromErrorStringWithFormat(
              "invalid boolean value for option '%c': %s", short_option,
              option_arg.data());
      } break;
      case 'u':
        m_filtered_backtrace = false;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }
      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_count = UINT32_MAX;
      m_start = 0;
      m_extended_backtrace = false;
      m_filtered_backtrace = true;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_thread_backtrace_options);
    }

    // Instance variables to hold the values for command options.
    uint32_t m_count;
    uint32_t m_start;
    bool m_extended_backtrace;
    bool m_filtered_backtrace;
  };

  CommandObjectThreadBacktrace(CommandInterpreter &interpreter)
      : CommandObjectIterateOverThreads(
            interpreter, "thread backtrace",
            "Show backtraces of thread call stacks.  Defaults to the current "
            "thread, thread indexes can be specified as arguments.\n"
            "Use the thread-index \"all\" to see all threads.\n"
            "Use the thread-index \"unique\" to see threads grouped by unique "
            "call stacks.\n"
            "Use 'settings set frame-format' to customize the printing of "
            "frames in the backtrace and 'settings set thread-format' to "
            "customize the thread header.\n"
            "Customizable frame recognizers may filter out less interesting "
            "frames, which results in gaps in the numbering. "
            "Use '-u' to see all frames.",
            nullptr,
            eCommandRequiresProcess | eCommandRequiresThread |
                eCommandTryTargetAPILock | eCommandProcessMustBeLaunched |
                eCommandProcessMustBePaused) {}

  ~CommandObjectThreadBacktrace() override = default;

  Options *GetOptions() override { return &m_options; }

  std::optional<std::string> GetRepeatCommand(Args &current_args,
                                              uint32_t index) override {
    llvm::StringRef count_opt("--count");
    llvm::StringRef start_opt("--start");

    // If no "count" was provided, we are dumping the entire backtrace, so
    // there isn't a repeat command.  So we search for the count option in
    // the args, and if we find it, we make a copy and insert or modify the
    // start option's value to start count indices greater.

    Args copy_args(current_args);
    size_t num_entries = copy_args.GetArgumentCount();
    // These two point at the index of the option value if found.
    size_t count_idx = 0;
    size_t start_idx = 0;
    size_t count_val = 0;
    size_t start_val = 0;

    for (size_t idx = 0; idx < num_entries; idx++) {
      llvm::StringRef arg_string = copy_args[idx].ref();
      if (arg_string == "-c" || count_opt.starts_with(arg_string)) {
        idx++;
        if (idx == num_entries)
          return std::nullopt;
        count_idx = idx;
        if (copy_args[idx].ref().getAsInteger(0, count_val))
          return std::nullopt;
      } else if (arg_string == "-s" || start_opt.starts_with(arg_string)) {
        idx++;
        if (idx == num_entries)
          return std::nullopt;
        start_idx = idx;
        if (copy_args[idx].ref().getAsInteger(0, start_val))
          return std::nullopt;
      }
    }
    if (count_idx == 0)
      return std::nullopt;

    std::string new_start_val = llvm::formatv("{0}", start_val + count_val);
    if (start_idx == 0) {
      copy_args.AppendArgument(start_opt);
      copy_args.AppendArgument(new_start_val);
    } else {
      copy_args.ReplaceArgumentAtIndex(start_idx, new_start_val);
    }
    std::string repeat_command;
    if (!copy_args.GetQuotedCommandString(repeat_command))
      return std::nullopt;
    return repeat_command;
  }

protected:
  void DoExtendedBacktrace(Thread *thread, CommandReturnObject &result) {
    SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime();
    if (runtime) {
      Stream &strm = result.GetOutputStream();
      const std::vector<ConstString> &types =
          runtime->GetExtendedBacktraceTypes();
      for (auto type : types) {
        ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread(
            thread->shared_from_this(), type);
        if (ext_thread_sp && ext_thread_sp->IsValid()) {
          const uint32_t num_frames_with_source = 0;
          const bool stop_format = false;
          strm.PutChar('\n');
          if (ext_thread_sp->GetStatus(strm, m_options.m_start,
                                       m_options.m_count,
                                       num_frames_with_source, stop_format,
                                       !m_options.m_filtered_backtrace)) {
            DoExtendedBacktrace(ext_thread_sp.get(), result);
          }
        }
      }
    }
  }

  bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
    ThreadSP thread_sp =
        m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
    if (!thread_sp) {
      result.AppendErrorWithFormat(
          "thread disappeared while computing backtraces: 0x%" PRIx64 "\n",
          tid);
      return false;
    }

    Thread *thread = thread_sp.get();

    Stream &strm = result.GetOutputStream();

    // Only dump stack info if we processing unique stacks.
    const bool only_stacks = m_unique_stacks;

    // Don't show source context when doing backtraces.
    const uint32_t num_frames_with_source = 0;
    const bool stop_format = true;
    if (!thread->GetStatus(strm, m_options.m_start, m_options.m_count,
                           num_frames_with_source, stop_format,
                           !m_options.m_filtered_backtrace, only_stacks)) {
      result.AppendErrorWithFormat(
          "error displaying backtrace for thread: \"0x%4.4x\"\n",
          thread->GetIndexID());
      return false;
    }
    if (m_options.m_extended_backtrace) {
      if (!INTERRUPT_REQUESTED(GetDebugger(),
                               "Interrupt skipped extended backtrace")) {
        DoExtendedBacktrace(thread, result);
      }
    }

    return true;
  }

  CommandOptions m_options;
};

#define LLDB_OPTIONS_thread_step_scope
#include "CommandOptions.inc"

class ThreadStepScopeOptionGroup : public OptionGroup {
public:
  ThreadStepScopeOptionGroup() {
    // Keep default values of all options in one place: OptionParsingStarting
    // ()
    OptionParsingStarting(nullptr);
  }

  ~ThreadStepScopeOptionGroup() override = default;

  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
    return llvm::ArrayRef(g_thread_step_scope_options);
  }

  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                        ExecutionContext *execution_context) override {
    Status error;
    const int short_option =
        g_thread_step_scope_options[option_idx].short_option;

    switch (short_option) {
    case 'a': {
      bool success;
      bool avoid_no_debug =
          OptionArgParser::ToBoolean(option_arg, true, &success);
      if (!success)
        error = Status::FromErrorStringWithFormat(
            "invalid boolean value for option '%c': %s", short_option,
            option_arg.data());
      else {
        m_step_in_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
      }
    } break;

    case 'A': {
      bool success;
      bool avoid_no_debug =
          OptionArgParser::ToBoolean(option_arg, true, &success);
      if (!success)
        error = Status::FromErrorStringWithFormat(
            "invalid boolean value for option '%c': %s", short_option,
            option_arg.data());
      else {
        m_step_out_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
      }
    } break;

    case 'c':
      if (option_arg.getAsInteger(0, m_step_count))
        error = Status::FromErrorStringWithFormat(
            "invalid integer value for option '%c': %s", short_option,
            option_arg.data());
      break;

    case 'm': {
      auto enum_values = GetDefinitions()[option_idx].enum_values;
      m_run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum(
          option_arg, enum_values, eOnlyDuringStepping, error);
    } break;

    case 'e':
      if (option_arg == "block") {
        m_end_line_is_block_end = true;
        break;
      }
      if (option_arg.getAsInteger(0, m_end_line))
        error = Status::FromErrorStringWithFormat(
            "invalid end line number '%s'", option_arg.str().c_str());
      break;

    case 'r':
      m_avoid_regexp.clear();
      m_avoid_regexp.assign(std::string(option_arg));
      break;

    case 't':
      m_step_in_target.clear();
      m_step_in_target.assign(std::string(option_arg));
      break;

    default:
      llvm_unreachable("Unimplemented option");
    }
    return error;
  }

  void OptionParsingStarting(ExecutionContext *execution_context) override {
    m_step_in_avoid_no_debug = eLazyBoolCalculate;
    m_step_out_avoid_no_debug = eLazyBoolCalculate;
    m_run_mode = eOnlyDuringStepping;

    // Check if we are in Non-Stop mode
    TargetSP target_sp =
        execution_context ? execution_context->GetTargetSP() : TargetSP();
    ProcessSP process_sp =
        execution_context ? execution_context->GetProcessSP() : ProcessSP();
    if (process_sp && process_sp->GetSteppingRunsAllThreads())
      m_run_mode = eAllThreads;

    m_avoid_regexp.clear();
    m_step_in_target.clear();
    m_step_count = 1;
    m_end_line = LLDB_INVALID_LINE_NUMBER;
    m_end_line_is_block_end = false;
  }

  // Instance variables to hold the values for command options.
  LazyBool m_step_in_avoid_no_debug;
  LazyBool m_step_out_avoid_no_debug;
  RunMode m_run_mode;
  std::string m_avoid_regexp;
  std::string m_step_in_target;
  uint32_t m_step_count;
  uint32_t m_end_line;
  bool m_end_line_is_block_end;
};

class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed {
public:
  CommandObjectThreadStepWithTypeAndScope(CommandInterpreter &interpreter,
                                          const char *name, const char *help,
                                          const char *syntax,
                                          StepType step_type)
      : CommandObjectParsed(interpreter, name, help, syntax,
                            eCommandRequiresProcess | eCommandRequiresThread |
                                eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched |
                                eCommandProcessMustBePaused),
        m_step_type(step_type), m_class_options("scripted step") {
    AddSimpleArgumentList(eArgTypeThreadIndex, eArgRepeatOptional);

    if (step_type == eStepTypeScripted) {
      m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
                           LLDB_OPT_SET_1);
    }
    m_all_options.Append(&m_options);
    m_all_options.Finalize();
  }

  ~CommandObjectThreadStepWithTypeAndScope() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    if (request.GetCursorIndex())
      return;
    CommandObject::HandleArgumentCompletion(request, opt_element_vector);
  }

  Options *GetOptions() override { return &m_all_options; }

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Process *process = m_exe_ctx.GetProcessPtr();
    bool synchronous_execution = m_interpreter.GetSynchronous();

    const uint32_t num_threads = process->GetThreadList().GetSize();
    Thread *thread = nullptr;

    if (command.GetArgumentCount() == 0) {
      thread = GetDefaultThread();

      if (thread == nullptr) {
        result.AppendError("no selected thread in process");
        return;
      }
    } else {
      const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
      uint32_t step_thread_idx;

      if (!llvm::to_integer(thread_idx_cstr, step_thread_idx)) {
        result.AppendErrorWithFormat("invalid thread index '%s'.\n",
                                     thread_idx_cstr);
        return;
      }
      thread =
          process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
      if (thread == nullptr) {
        result.AppendErrorWithFormat(
            "Thread index %u is out of range (valid values are 0 - %u).\n",
            step_thread_idx, num_threads);
        return;
      }
    }

    if (m_step_type == eStepTypeScripted) {
      if (m_class_options.GetName().empty()) {
        result.AppendErrorWithFormat("empty class name for scripted step.");
        return;
      } else if (!GetDebugger().GetScriptInterpreter()->CheckObjectExists(
                     m_class_options.GetName().c_str())) {
        result.AppendErrorWithFormat(
            "class for scripted step: \"%s\" does not exist.",
            m_class_options.GetName().c_str());
        return;
      }
    }

    if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER &&
        m_step_type != eStepTypeInto) {
      result.AppendErrorWithFormat(
          "end line option is only valid for step into");
      return;
    }

    const bool abort_other_plans = false;
    const lldb::RunMode stop_other_threads = m_options.m_run_mode;

    // This is a bit unfortunate, but not all the commands in this command
    // object support only while stepping, so I use the bool for them.
    bool bool_stop_other_threads;
    if (m_options.m_run_mode == eAllThreads)
      bool_stop_other_threads = false;
    else if (m_options.m_run_mode == eOnlyDuringStepping)
      bool_stop_other_threads = (m_step_type != eStepTypeOut);
    else
      bool_stop_other_threads = true;

    ThreadPlanSP new_plan_sp;
    Status new_plan_status;

    if (m_step_type == eStepTypeInto) {
      StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
      assert(frame != nullptr);

      if (frame->HasDebugInformation()) {
        AddressRange range;
        SymbolContext sc = frame->GetSymbolContext(eSymbolContextEverything);
        if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER) {
          llvm::Error err =
              sc.GetAddressRangeFromHereToEndLine(m_options.m_end_line, range);
          if (err) {
            result.AppendErrorWithFormatv("invalid end-line option: {0}.",
                                          llvm::toString(std::move(err)));
            return;
          }
        } else if (m_options.m_end_line_is_block_end) {
          Status error;
          Block *block = frame->GetSymbolContext(eSymbolContextBlock).block;
          if (!block) {
            result.AppendErrorWithFormat("Could not find the current block.");
            return;
          }

          AddressRange block_range;
          Address pc_address = frame->GetFrameCodeAddress();
          block->GetRangeContainingAddress(pc_address, block_range);
          if (!block_range.GetBaseAddress().IsValid()) {
            result.AppendErrorWithFormat(
                "Could not find the current block address.");
            return;
          }
          lldb::addr_t pc_offset_in_block =
              pc_address.GetFileAddress() -
              block_range.GetBaseAddress().GetFileAddress();
          lldb::addr_t range_length =
              block_range.GetByteSize() - pc_offset_in_block;
          range = AddressRange(pc_address, range_length);
        } else {
          range = sc.line_entry.range;
        }

        new_plan_sp = thread->QueueThreadPlanForStepInRange(
            abort_other_plans, range,
            frame->GetSymbolContext(eSymbolContextEverything),
            m_options.m_step_in_target.c_str(), stop_other_threads,
            new_plan_status, m_options.m_step_in_avoid_no_debug,
            m_options.m_step_out_avoid_no_debug);

        if (new_plan_sp && !m_options.m_avoid_regexp.empty()) {
          ThreadPlanStepInRange *step_in_range_plan =
              static_cast<ThreadPlanStepInRange *>(new_plan_sp.get());
          step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
        }
      } else
        new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
            false, abort_other_plans, bool_stop_other_threads, new_plan_status);
    } else if (m_step_type == eStepTypeOver) {
      StackFrame *frame = thread->GetStackFrameAtIndex(0).get();

      if (frame->HasDebugInformation())
        new_plan_sp = thread->QueueThreadPlanForStepOverRange(
            abort_other_plans,
            frame->GetSymbolContext(eSymbolContextEverything).line_entry,
            frame->GetSymbolContext(eSymbolContextEverything),
            stop_other_threads, new_plan_status,
            m_options.m_step_out_avoid_no_debug);
      else
        new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
            true, abort_other_plans, bool_stop_other_threads, new_plan_status);
    } else if (m_step_type == eStepTypeTrace) {
      new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
          false, abort_other_plans, bool_stop_other_threads, new_plan_status);
    } else if (m_step_type == eStepTypeTraceOver) {
      new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
          true, abort_other_plans, bool_stop_other_threads, new_plan_status);
    } else if (m_step_type == eStepTypeOut) {
      new_plan_sp = thread->QueueThreadPlanForStepOut(
          abort_other_plans, nullptr, false, bool_stop_other_threads, eVoteYes,
          eVoteNoOpinion,
          thread->GetSelectedFrameIndex(DoNoSelectMostRelevantFrame),
          new_plan_status, m_options.m_step_out_avoid_no_debug);
    } else if (m_step_type == eStepTypeScripted) {
      new_plan_sp = thread->QueueThreadPlanForStepScripted(
          abort_other_plans, m_class_options.GetName().c_str(),
          m_class_options.GetStructuredData(), bool_stop_other_threads,
          new_plan_status);
    } else {
      result.AppendError("step type is not supported");
      return;
    }

    // If we got a new plan, then set it to be a controlling plan (User level
    // Plans should be controlling plans so that they can be interruptible).
    // Then resume the process.

    if (new_plan_sp) {
      new_plan_sp->SetIsControllingPlan(true);
      new_plan_sp->SetOkayToDiscard(false);

      if (m_options.m_step_count > 1) {
        if (!new_plan_sp->SetIterationCount(m_options.m_step_count)) {
          result.AppendWarning(
              "step operation does not support iteration count.");
        }
      }

      process->GetThreadList().SetSelectedThreadByID(thread->GetID());

      const uint32_t iohandler_id = process->GetIOHandlerID();

      StreamString stream;
      Status error;
      if (synchronous_execution)
        error = process->ResumeSynchronous(&stream);
      else
        error = process->Resume();

      if (!error.Success()) {
        result.AppendMessage(error.AsCString());
        return;
      }

      // There is a race condition where this thread will return up the call
      // stack to the main command handler and show an (lldb) prompt before
      // HandlePrivateEvent (from PrivateStateThread) has a chance to call
      // PushProcessIOHandler().
      process->SyncIOHandler(iohandler_id, std::chrono::seconds(2));

      if (synchronous_execution) {
        // If any state changed events had anything to say, add that to the
        // result
        if (stream.GetSize() > 0)
          result.AppendMessage(stream.GetString());

        process->GetThreadList().SetSelectedThreadByID(thread->GetID());
        result.SetDidChangeProcessState(true);
        result.SetStatus(eReturnStatusSuccessFinishNoResult);
      } else {
        result.SetStatus(eReturnStatusSuccessContinuingNoResult);
      }
    } else {
      result.SetError(std::move(new_plan_status));
    }
  }

  StepType m_step_type;
  ThreadStepScopeOptionGroup m_options;
  OptionGroupPythonClassWithDict m_class_options;
  OptionGroupOptions m_all_options;
};

// CommandObjectThreadContinue

class CommandObjectThreadContinue : public CommandObjectParsed {
public:
  CommandObjectThreadContinue(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "thread continue",
            "Continue execution of the current target process.  One "
            "or more threads may be specified, by default all "
            "threads continue.",
            nullptr,
            eCommandRequiresThread | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
    AddSimpleArgumentList(eArgTypeThreadIndex, eArgRepeatPlus);
  }

  ~CommandObjectThreadContinue() override = default;

  void DoExecute(Args &command, CommandReturnObject &result) override {
    bool synchronous_execution = m_interpreter.GetSynchronous();

    Process *process = m_exe_ctx.GetProcessPtr();
    if (process == nullptr) {
      result.AppendError("no process exists. Cannot continue");
      return;
    }

    StateType state = process->GetState();
    if ((state == eStateCrashed) || (state == eStateStopped) ||
        (state == eStateSuspended)) {
      const size_t argc = command.GetArgumentCount();
      if (argc > 0) {
        // These two lines appear at the beginning of both blocks in this
        // if..else, but that is because we need to release the lock before
        // calling process->Resume below.
        std::lock_guard<std::recursive_mutex> guard(
            process->GetThreadList().GetMutex());
        const uint32_t num_threads = process->GetThreadList().GetSize();
        std::vector<Thread *> resume_threads;
        for (auto &entry : command.entries()) {
          uint32_t thread_idx;
          if (entry.ref().getAsInteger(0, thread_idx)) {
            result.AppendErrorWithFormat(
                "invalid thread index argument: \"%s\".\n", entry.c_str());
            return;
          }
          Thread *thread =
              process->GetThreadList().FindThreadByIndexID(thread_idx).get();

          if (thread) {
            resume_threads.push_back(thread);
          } else {
            result.AppendErrorWithFormat("invalid thread index %u.\n",
                                         thread_idx);
            return;
          }
        }

        if (resume_threads.empty()) {
          result.AppendError("no valid thread indexes were specified");
          return;
        } else {
          if (resume_threads.size() == 1)
            result.AppendMessageWithFormat("Resuming thread: ");
          else
            result.AppendMessageWithFormat("Resuming threads: ");

          for (uint32_t idx = 0; idx < num_threads; ++idx) {
            Thread *thread =
                process->GetThreadList().GetThreadAtIndex(idx).get();
            std::vector<Thread *>::iterator this_thread_pos =
                find(resume_threads.begin(), resume_threads.end(), thread);

            if (this_thread_pos != resume_threads.end()) {
              resume_threads.erase(this_thread_pos);
              if (!resume_threads.empty())
                result.AppendMessageWithFormat("%u, ", thread->GetIndexID());
              else
                result.AppendMessageWithFormat("%u ", thread->GetIndexID());

              const bool override_suspend = true;
              thread->SetResumeState(eStateRunning, override_suspend);
            } else {
              thread->SetResumeState(eStateSuspended);
            }
          }
          result.AppendMessageWithFormat("in process %" PRIu64 "\n",
                                         process->GetID());
        }
      } else {
        // These two lines appear at the beginning of both blocks in this
        // if..else, but that is because we need to release the lock before
        // calling process->Resume below.
        std::lock_guard<std::recursive_mutex> guard(
            process->GetThreadList().GetMutex());
        const uint32_t num_threads = process->GetThreadList().GetSize();
        Thread *current_thread = GetDefaultThread();
        if (current_thread == nullptr) {
          result.AppendError("the process doesn't have a current thread");
          return;
        }
        // Set the actions that the threads should each take when resuming
        for (uint32_t idx = 0; idx < num_threads; ++idx) {
          Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
          if (thread == current_thread) {
            result.AppendMessageWithFormat("Resuming thread 0x%4.4" PRIx64
                                           " in process %" PRIu64 "\n",
                                           thread->GetID(), process->GetID());
            const bool override_suspend = true;
            thread->SetResumeState(eStateRunning, override_suspend);
          } else {
            thread->SetResumeState(eStateSuspended);
          }
        }
      }

      StreamString stream;
      Status error;
      if (synchronous_execution)
        error = process->ResumeSynchronous(&stream);
      else
        error = process->Resume();

      // We should not be holding the thread list lock when we do this.
      if (error.Success()) {
        result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n",
                                       process->GetID());
        if (synchronous_execution) {
          // If any state changed events had anything to say, add that to the
          // result
          if (stream.GetSize() > 0)
            result.AppendMessage(stream.GetString());

          result.SetDidChangeProcessState(true);
          result.SetStatus(eReturnStatusSuccessFinishNoResult);
        } else {
          result.SetStatus(eReturnStatusSuccessContinuingNoResult);
        }
      } else {
        result.AppendErrorWithFormat("Failed to resume process: %s\n",
                                     error.AsCString());
      }
    } else {
      result.AppendErrorWithFormat(
          "Process cannot be continued from its current state (%s).\n",
          StateAsCString(state));
    }
  }
};

// CommandObjectThreadUntil

#define LLDB_OPTIONS_thread_until
#include "CommandOptions.inc"

class CommandObjectThreadUntil : public CommandObjectParsed {
public:
  class CommandOptions : public Options {
  public:
    uint32_t m_thread_idx = LLDB_INVALID_THREAD_ID;
    uint32_t m_frame_idx = LLDB_INVALID_FRAME_ID;

    CommandOptions() {
      // Keep default values of all options in one place: OptionParsingStarting
      // ()
      OptionParsingStarting(nullptr);
    }

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'a': {
        lldb::addr_t tmp_addr = OptionArgParser::ToAddress(
            execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
        if (error.Success())
          m_until_addrs.push_back(tmp_addr);
      } break;
      case 't':
        if (option_arg.getAsInteger(0, m_thread_idx)) {
          m_thread_idx = LLDB_INVALID_INDEX32;
          error = Status::FromErrorStringWithFormat("invalid thread index '%s'",
                                                    option_arg.str().c_str());
        }
        break;
      case 'f':
        if (option_arg.getAsInteger(0, m_frame_idx)) {
          m_frame_idx = LLDB_INVALID_FRAME_ID;
          error = Status::FromErrorStringWithFormat("invalid frame index '%s'",
                                                    option_arg.str().c_str());
        }
        break;
      case 'm': {
        auto enum_values = GetDefinitions()[option_idx].enum_values;
        lldb::RunMode run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum(
            option_arg, enum_values, eOnlyDuringStepping, error);

        if (error.Success()) {
          if (run_mode == eAllThreads)
            m_stop_others = false;
          else
            m_stop_others = true;
        }
      } break;
      default:
        llvm_unreachable("Unimplemented option");
      }
      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_thread_idx = LLDB_INVALID_THREAD_ID;
      m_frame_idx = 0;
      m_stop_others = false;
      m_until_addrs.clear();
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_thread_until_options);
    }

    uint32_t m_step_thread_idx = LLDB_INVALID_THREAD_ID;
    bool m_stop_others = false;
    std::vector<lldb::addr_t> m_until_addrs;

    // Instance variables to hold the values for command options.
  };

  CommandObjectThreadUntil(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "thread until",
            "Continue until a line number or address is reached by the "
            "current or specified thread.  Stops when returning from "
            "the current function as a safety measure.  "
            "The target line number(s) are given as arguments, and if more "
            "than one"
            " is provided, stepping will stop when the first one is hit.",
            nullptr,
            eCommandRequiresThread | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
    AddSimpleArgumentList(eArgTypeLineNum);
  }

  ~CommandObjectThreadUntil() override = default;

  Options *GetOptions() override { return &m_options; }

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    bool synchronous_execution = m_interpreter.GetSynchronous();

    Target *target = &GetTarget();

    Process *process = m_exe_ctx.GetProcessPtr();
    if (process == nullptr) {
      result.AppendError("need a valid process to step");
    } else {
      Thread *thread = nullptr;
      std::vector<uint32_t> line_numbers;

      if (command.GetArgumentCount() >= 1) {
        size_t num_args = command.GetArgumentCount();
        for (size_t i = 0; i < num_args; i++) {
          uint32_t line_number;
          if (!llvm::to_integer(command.GetArgumentAtIndex(i), line_number)) {
            result.AppendErrorWithFormat("invalid line number: '%s'.\n",
                                         command.GetArgumentAtIndex(i));
            return;
          } else
            line_numbers.push_back(line_number);
        }
      } else if (m_options.m_until_addrs.empty()) {
        result.AppendErrorWithFormat("No line number or address provided:\n%s",
                                     GetSyntax().str().c_str());
        return;
      }

      if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) {
        thread = GetDefaultThread();
      } else {
        thread = process->GetThreadList()
                     .FindThreadByIndexID(m_options.m_thread_idx)
                     .get();
      }

      if (thread == nullptr) {
        const uint32_t num_threads = process->GetThreadList().GetSize();
        result.AppendErrorWithFormat(
            "Thread index %u is out of range (valid values are 0 - %u).\n",
            m_options.m_thread_idx, num_threads);
        return;
      }

      const bool abort_other_plans = false;

      StackFrame *frame =
          thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
      if (frame == nullptr) {
        result.AppendErrorWithFormat(
            "Frame index %u is out of range for thread id %" PRIu64 ".\n",
            m_options.m_frame_idx, thread->GetID());
        return;
      }

      ThreadPlanSP new_plan_sp;
      Status new_plan_status;

      if (frame->HasDebugInformation()) {
        // Finally we got here...  Translate the given line number to a bunch
        // of addresses:
        SymbolContext sc(frame->GetSymbolContext(eSymbolContextCompUnit));
        LineTable *line_table = nullptr;
        if (sc.comp_unit)
          line_table = sc.comp_unit->GetLineTable();

        if (line_table == nullptr) {
          result.AppendErrorWithFormat("Failed to resolve the line table for "
                                       "frame %u of thread id %" PRIu64 ".\n",
                                       m_options.m_frame_idx, thread->GetID());
          return;
        }

        LineEntry function_start;
        uint32_t index_ptr = 0, end_ptr = UINT32_MAX;
        std::vector<addr_t> address_list;

        // Find the beginning & end index of the function, but first make
        // sure it is valid:
        if (!sc.function) {
          result.AppendErrorWithFormat("Have debug information but no "
                                       "function info - can't get until range.");
          return;
        }

        AddressRange fun_addr_range = sc.function->GetAddressRange();
        Address fun_start_addr = fun_addr_range.GetBaseAddress();
        line_table->FindLineEntryByAddress(fun_start_addr, function_start,
                                           &index_ptr);

        Address fun_end_addr(fun_start_addr.GetSection(),
                             fun_start_addr.GetOffset() +
                                 fun_addr_range.GetByteSize());

        bool all_in_function = true;

        line_table->FindLineEntryByAddress(fun_end_addr, function_start,
                                           &end_ptr);

        // Since not all source lines will contribute code, check if we are
        // setting the breakpoint on the exact line number or the nearest
        // subsequent line number and set breakpoints at all the line table
        // entries of the chosen line number (exact or nearest subsequent).
        for (uint32_t line_number : line_numbers) {
          LineEntry line_entry;
          bool exact = false;
          uint32_t start_idx_ptr = index_ptr;
          start_idx_ptr = sc.comp_unit->FindLineEntry(
              index_ptr, line_number, nullptr, exact, &line_entry);
          if (start_idx_ptr != UINT32_MAX)
            line_number = line_entry.line;
          exact = true;
          start_idx_ptr = index_ptr;
          while (start_idx_ptr <= end_ptr) {
            start_idx_ptr = sc.comp_unit->FindLineEntry(
                start_idx_ptr, line_number, nullptr, exact, &line_entry);
            if (start_idx_ptr == UINT32_MAX)
              break;

            addr_t address =
                line_entry.range.GetBaseAddress().GetLoadAddress(target);
            if (address != LLDB_INVALID_ADDRESS) {
              if (fun_addr_range.ContainsLoadAddress(address, target))
                address_list.push_back(address);
              else
                all_in_function = false;
            }
            start_idx_ptr++;
          }
        }

        for (lldb::addr_t address : m_options.m_until_addrs) {
          if (fun_addr_range.ContainsLoadAddress(address, target))
            address_list.push_back(address);
          else
            all_in_function = false;
        }

        if (address_list.empty()) {
          if (all_in_function)
            result.AppendErrorWithFormat(
                "No line entries matching until target.\n");
          else
            result.AppendErrorWithFormat(
                "Until target outside of the current function.\n");

          return;
        }

        new_plan_sp = thread->QueueThreadPlanForStepUntil(
            abort_other_plans, &address_list.front(), address_list.size(),
            m_options.m_stop_others, m_options.m_frame_idx, new_plan_status);
        if (new_plan_sp) {
          // User level plans should be controlling plans so they can be
          // interrupted
          // (e.g. by hitting a breakpoint) and other plans executed by the
          // user (stepping around the breakpoint) and then a "continue" will
          // resume the original plan.
          new_plan_sp->SetIsControllingPlan(true);
          new_plan_sp->SetOkayToDiscard(false);
        } else {
          result.SetError(std::move(new_plan_status));
          return;
        }
      } else {
        result.AppendErrorWithFormat("Frame index %u of thread id %" PRIu64
                                     " has no debug information.\n",
                                     m_options.m_frame_idx, thread->GetID());
        return;
      }

      if (!process->GetThreadList().SetSelectedThreadByID(thread->GetID())) {
        result.AppendErrorWithFormat(
            "Failed to set the selected thread to thread id %" PRIu64 ".\n",
            thread->GetID());
        return;
      }

      StreamString stream;
      Status error;
      if (synchronous_execution)
        error = process->ResumeSynchronous(&stream);
      else
        error = process->Resume();

      if (error.Success()) {
        result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n",
                                       process->GetID());
        if (synchronous_execution) {
          // If any state changed events had anything to say, add that to the
          // result
          if (stream.GetSize() > 0)
            result.AppendMessage(stream.GetString());

          result.SetDidChangeProcessState(true);
          result.SetStatus(eReturnStatusSuccessFinishNoResult);
        } else {
          result.SetStatus(eReturnStatusSuccessContinuingNoResult);
        }
      } else {
        result.AppendErrorWithFormat("Failed to resume process: %s.\n",
                                     error.AsCString());
      }
    }
  }

  CommandOptions m_options;
};

// CommandObjectThreadSelect

#define LLDB_OPTIONS_thread_select
#include "CommandOptions.inc"

class CommandObjectThreadSelect : public CommandObjectParsed {
public:
  class OptionGroupThreadSelect : public OptionGroup {
  public:
    OptionGroupThreadSelect() { OptionParsingStarting(nullptr); }

    ~OptionGroupThreadSelect() override = default;

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_thread_id = LLDB_INVALID_THREAD_ID;
    }

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      const int short_option = g_thread_select_options[option_idx].short_option;
      switch (short_option) {
      case 't': {
        if (option_arg.getAsInteger(0, m_thread_id)) {
          m_thread_id = LLDB_INVALID_THREAD_ID;
          return Status::FromErrorStringWithFormat("Invalid thread ID: '%s'.",
                                                   option_arg.str().c_str());
        }
        break;
      }

      default:
        llvm_unreachable("Unimplemented option");
      }

      return {};
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_thread_select_options);
    }

    lldb::tid_t m_thread_id;
  };

  CommandObjectThreadSelect(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "thread select",
                            "Change the currently selected thread.",
                            "thread select <thread-index> (or -t <thread-id>)",
                            eCommandRequiresProcess | eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched |
                                eCommandProcessMustBePaused) {
    CommandArgumentEntry arg;
    CommandArgumentData thread_idx_arg;

    // Define the first (and only) variant of this arg.
    thread_idx_arg.arg_type = eArgTypeThreadIndex;
    thread_idx_arg.arg_repetition = eArgRepeatPlain;
    thread_idx_arg.arg_opt_set_association = LLDB_OPT_SET_1;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg.push_back(thread_idx_arg);

    // Push the data for the first argument into the m_arguments vector.
    m_arguments.push_back(arg);

    m_option_group.Append(&m_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
    m_option_group.Finalize();
  }

  ~CommandObjectThreadSelect() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    if (request.GetCursorIndex())
      return;

    lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), lldb::eThreadIndexCompletion, request,
        nullptr);
  }

  Options *GetOptions() override { return &m_option_group; }

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Process *process = m_exe_ctx.GetProcessPtr();
    if (process == nullptr) {
      result.AppendError("no process");
      return;
    } else if (m_options.m_thread_id == LLDB_INVALID_THREAD_ID &&
               command.GetArgumentCount() != 1) {
      result.AppendErrorWithFormat(
          "'%s' takes exactly one thread index argument, or a thread ID "
          "option:\nUsage: %s\n",
          m_cmd_name.c_str(), m_cmd_syntax.c_str());
      return;
    } else if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID &&
               command.GetArgumentCount() != 0) {
      result.AppendErrorWithFormat("'%s' cannot take both a thread ID option "
                                   "and a thread index argument:\nUsage: %s\n",
                                   m_cmd_name.c_str(), m_cmd_syntax.c_str());
      return;
    }

    Thread *new_thread = nullptr;
    if (command.GetArgumentCount() == 1) {
      uint32_t index_id;
      if (!llvm::to_integer(command.GetArgumentAtIndex(0), index_id)) {
        result.AppendErrorWithFormat("Invalid thread index '%s'",
                                     command.GetArgumentAtIndex(0));
        return;
      }
      new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
      if (new_thread == nullptr) {
        result.AppendErrorWithFormat("Invalid thread index #%s.\n",
                                     command.GetArgumentAtIndex(0));
        return;
      }
    } else {
      new_thread =
          process->GetThreadList().FindThreadByID(m_options.m_thread_id).get();
      if (new_thread == nullptr) {
        result.AppendErrorWithFormat("Invalid thread ID %" PRIu64 ".\n",
                                     m_options.m_thread_id);
        return;
      }
    }

    process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true);
    result.SetStatus(eReturnStatusSuccessFinishNoResult);
  }

  OptionGroupThreadSelect m_options;
  OptionGroupOptions m_option_group;
};

// CommandObjectThreadList

class CommandObjectThreadList : public CommandObjectParsed {
public:
  CommandObjectThreadList(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "thread list",
            "Show a summary of each thread in the current target process.  "
            "Use 'settings set thread-format' to customize the individual "
            "thread listings.",
            "thread list",
            eCommandRequiresProcess | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}

  ~CommandObjectThreadList() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Stream &strm = result.GetOutputStream();
    result.SetStatus(eReturnStatusSuccessFinishNoResult);
    Process *process = m_exe_ctx.GetProcessPtr();
    const bool only_threads_with_stop_reason = false;
    const uint32_t start_frame = 0;
    const uint32_t num_frames = 0;
    const uint32_t num_frames_with_source = 0;
    process->GetStatus(strm);
    process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,
                             num_frames, num_frames_with_source, false);
  }
};

// CommandObjectThreadInfo
#define LLDB_OPTIONS_thread_info
#include "CommandOptions.inc"

class CommandObjectThreadInfo : public CommandObjectIterateOverThreads {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() { OptionParsingStarting(nullptr); }

    ~CommandOptions() override = default;

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_json_thread = false;
      m_json_stopinfo = false;
    }

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      const int short_option = m_getopt_table[option_idx].val;
      Status error;

      switch (short_option) {
      case 'j':
        m_json_thread = true;
        break;

      case 's':
        m_json_stopinfo = true;
        break;

      default:
        llvm_unreachable("Unimplemented option");
      }
      return error;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_thread_info_options);
    }

    bool m_json_thread;
    bool m_json_stopinfo;
  };

  CommandObjectThreadInfo(CommandInterpreter &interpreter)
      : CommandObjectIterateOverThreads(
            interpreter, "thread info",
            "Show an extended summary of one or "
            "more threads.  Defaults to the "
            "current thread.",
            "thread info",
            eCommandRequiresProcess | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
    m_add_return = false;
  }

  ~CommandObjectThreadInfo() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), lldb::eThreadIndexCompletion, request,
        nullptr);
  }

  Options *GetOptions() override { return &m_options; }

  bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
    ThreadSP thread_sp =
        m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
    if (!thread_sp) {
      result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n",
                                   tid);
      return false;
    }

    Thread *thread = thread_sp.get();

    Stream &strm = result.GetOutputStream();
    if (!thread->GetDescription(strm, eDescriptionLevelFull,
                                m_options.m_json_thread,
                                m_options.m_json_stopinfo)) {
      result.AppendErrorWithFormat("error displaying info for thread: \"%d\"\n",
                                   thread->GetIndexID());
      return false;
    }
    return true;
  }

  CommandOptions m_options;
};

// CommandObjectThreadException

class CommandObjectThreadException : public CommandObjectIterateOverThreads {
public:
  CommandObjectThreadException(CommandInterpreter &interpreter)
      : CommandObjectIterateOverThreads(
            interpreter, "thread exception",
            "Display the current exception object for a thread. Defaults to "
            "the current thread.",
            "thread exception",
            eCommandRequiresProcess | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}

  ~CommandObjectThreadException() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), lldb::eThreadIndexCompletion, request,
        nullptr);
  }

  bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
    ThreadSP thread_sp =
        m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
    if (!thread_sp) {
      result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n",
                                   tid);
      return false;
    }

    Stream &strm = result.GetOutputStream();
    ValueObjectSP exception_object_sp = thread_sp->GetCurrentException();
    if (exception_object_sp) {
      if (llvm::Error error = exception_object_sp->Dump(strm)) {
        result.AppendError(toString(std::move(error)));
        return false;
      }
    }

    ThreadSP exception_thread_sp = thread_sp->GetCurrentExceptionBacktrace();
    if (exception_thread_sp && exception_thread_sp->IsValid()) {
      const uint32_t num_frames_with_source = 0;
      const bool stop_format = false;
      exception_thread_sp->GetStatus(strm, 0, UINT32_MAX,
                                     num_frames_with_source, stop_format,
                                     /*filtered*/ false);
    }

    return true;
  }
};

class CommandObjectThreadSiginfo : public CommandObjectIterateOverThreads {
public:
  CommandObjectThreadSiginfo(CommandInterpreter &interpreter)
      : CommandObjectIterateOverThreads(
            interpreter, "thread siginfo",
            "Display the current siginfo object for a thread. Defaults to "
            "the current thread.",
            "thread siginfo",
            eCommandRequiresProcess | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}

  ~CommandObjectThreadSiginfo() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), lldb::eThreadIndexCompletion, request,
        nullptr);
  }

  bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
    ThreadSP thread_sp =
        m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
    if (!thread_sp) {
      result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n",
                                   tid);
      return false;
    }

    Stream &strm = result.GetOutputStream();
    if (!thread_sp->GetDescription(strm, eDescriptionLevelFull, false, false)) {
      result.AppendErrorWithFormat("error displaying info for thread: \"%d\"\n",
                                   thread_sp->GetIndexID());
      return false;
    }
    ValueObjectSP exception_object_sp = thread_sp->GetSiginfoValue();
    if (exception_object_sp) {
      if (llvm::Error error = exception_object_sp->Dump(strm)) {
        result.AppendError(toString(std::move(error)));
        return false;
      }
    } else
      strm.Printf("(no siginfo)\n");
    strm.PutChar('\n');

    return true;
  }
};

// CommandObjectThreadReturn
#define LLDB_OPTIONS_thread_return
#include "CommandOptions.inc"

class CommandObjectThreadReturn : public CommandObjectRaw {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() {
      // Keep default values of all options in one place: OptionParsingStarting
      // ()
      OptionParsingStarting(nullptr);
    }

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'x': {
        bool success;
        bool tmp_value =
            OptionArgParser::ToBoolean(option_arg, false, &success);
        if (success)
          m_from_expression = tmp_value;
        else {
          error = Status::FromErrorStringWithFormat(
              "invalid boolean value '%s' for 'x' option",
              option_arg.str().c_str());
        }
      } break;
      default:
        llvm_unreachable("Unimplemented option");
      }
      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_from_expression = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_thread_return_options);
    }

    bool m_from_expression = false;

    // Instance variables to hold the values for command options.
  };

  CommandObjectThreadReturn(CommandInterpreter &interpreter)
      : CommandObjectRaw(interpreter, "thread return",
                         "Prematurely return from a stack frame, "
                         "short-circuiting execution of newer frames "
                         "and optionally yielding a specified value.  Defaults "
                         "to the exiting the current stack "
                         "frame.",
                         "thread return",
                         eCommandRequiresFrame | eCommandTryTargetAPILock |
                             eCommandProcessMustBeLaunched |
                             eCommandProcessMustBePaused) {
    AddSimpleArgumentList(eArgTypeExpression, eArgRepeatOptional);
  }

  ~CommandObjectThreadReturn() override = default;

  Options *GetOptions() override { return &m_options; }

protected:
  void DoExecute(llvm::StringRef command,
                 CommandReturnObject &result) override {
    // I am going to handle this by hand, because I don't want you to have to
    // say:
    // "thread return -- -5".
    if (command.starts_with("-x")) {
      if (command.size() != 2U)
        result.AppendWarning("Return values ignored when returning from user "
                             "called expressions");

      Thread *thread = m_exe_ctx.GetThreadPtr();
      Status error;
      error = thread->UnwindInnermostExpression();
      if (!error.Success()) {
        result.AppendErrorWithFormat("Unwinding expression failed - %s.",
                                     error.AsCString());
      } else {
        bool success =
            thread->SetSelectedFrameByIndexNoisily(0, result.GetOutputStream());
        if (success) {
          m_exe_ctx.SetFrameSP(
              thread->GetSelectedFrame(DoNoSelectMostRelevantFrame));
          result.SetStatus(eReturnStatusSuccessFinishResult);
        } else {
          result.AppendErrorWithFormat(
              "Could not select 0th frame after unwinding expression.");
        }
      }
      return;
    }

    ValueObjectSP return_valobj_sp;

    StackFrameSP frame_sp = m_exe_ctx.GetFrameSP();
    uint32_t frame_idx = frame_sp->GetFrameIndex();

    if (frame_sp->IsInlined()) {
      result.AppendError("Don't know how to return from inlined frames.");
      return;
    }

    if (!command.empty()) {
      Target *target = m_exe_ctx.GetTargetPtr();
      EvaluateExpressionOptions options;

      options.SetUnwindOnError(true);
      options.SetUseDynamic(eNoDynamicValues);

      ExpressionResults exe_results = eExpressionSetupError;
      exe_results = target->EvaluateExpression(command, frame_sp.get(),
                                               return_valobj_sp, options);
      if (exe_results != eExpressionCompleted) {
        if (return_valobj_sp)
          result.AppendErrorWithFormat(
              "Error evaluating result expression: %s",
              return_valobj_sp->GetError().AsCString());
        else
          result.AppendErrorWithFormat(
              "Unknown error evaluating result expression.");
        return;
      }
    }

    Status error;
    ThreadSP thread_sp = m_exe_ctx.GetThreadSP();
    const bool broadcast = true;
    error = thread_sp->ReturnFromFrame(frame_sp, return_valobj_sp, broadcast);
    if (!error.Success()) {
      result.AppendErrorWithFormat(
          "Error returning from frame %d of thread %d: %s.", frame_idx,
          thread_sp->GetIndexID(), error.AsCString());
      return;
    }

    result.SetStatus(eReturnStatusSuccessFinishResult);
  }

  CommandOptions m_options;
};

// CommandObjectThreadJump
#define LLDB_OPTIONS_thread_jump
#include "CommandOptions.inc"

class CommandObjectThreadJump : public CommandObjectParsed {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() { OptionParsingStarting(nullptr); }

    ~CommandOptions() override = default;

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_filenames.Clear();
      m_line_num = 0;
      m_line_offset = 0;
      m_load_addr = LLDB_INVALID_ADDRESS;
      m_force = false;
    }

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      const int short_option = m_getopt_table[option_idx].val;
      Status error;

      switch (short_option) {
      case 'f':
        m_filenames.AppendIfUnique(FileSpec(option_arg));
        if (m_filenames.GetSize() > 1)
          return Status::FromErrorString("only one source file expected.");
        break;
      case 'l':
        if (option_arg.getAsInteger(0, m_line_num))
          return Status::FromErrorStringWithFormat("invalid line number: '%s'.",
                                                   option_arg.str().c_str());
        break;
      case 'b':
        if (option_arg.getAsInteger(0, m_line_offset))
          return Status::FromErrorStringWithFormat("invalid line offset: '%s'.",
                                                   option_arg.str().c_str());
        break;
      case 'a':
        m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
                                                 LLDB_INVALID_ADDRESS, &error);
        break;
      case 'r':
        m_force = true;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }
      return error;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_thread_jump_options);
    }

    FileSpecList m_filenames;
    uint32_t m_line_num;
    int32_t m_line_offset;
    lldb::addr_t m_load_addr;
    bool m_force;
  };

  CommandObjectThreadJump(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "thread jump",
            "Sets the program counter to a new address.", "thread jump",
            eCommandRequiresFrame | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}

  ~CommandObjectThreadJump() override = default;

  Options *GetOptions() override { return &m_options; }

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
    StackFrame *frame = m_exe_ctx.GetFramePtr();
    Thread *thread = m_exe_ctx.GetThreadPtr();
    Target *target = m_exe_ctx.GetTargetPtr();
    const SymbolContext &sym_ctx =
        frame->GetSymbolContext(eSymbolContextLineEntry);

    if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) {
      // Use this address directly.
      Address dest = Address(m_options.m_load_addr);

      lldb::addr_t callAddr = dest.GetCallableLoadAddress(target);
      if (callAddr == LLDB_INVALID_ADDRESS) {
        result.AppendErrorWithFormat("Invalid destination address.");
        return;
      }

      if (!reg_ctx->SetPC(callAddr)) {
        result.AppendErrorWithFormat("Error changing PC value for thread %d.",
                                     thread->GetIndexID());
        return;
      }
    } else {
      // Pick either the absolute line, or work out a relative one.
      int32_t line = (int32_t)m_options.m_line_num;
      if (line == 0)
        line = sym_ctx.line_entry.line + m_options.m_line_offset;

      // Try the current file, but override if asked.
      FileSpec file = sym_ctx.line_entry.GetFile();
      if (m_options.m_filenames.GetSize() == 1)
        file = m_options.m_filenames.GetFileSpecAtIndex(0);

      if (!file) {
        result.AppendErrorWithFormat(
            "No source file available for the current location.");
        return;
      }

      std::string warnings;
      Status err = thread->JumpToLine(file, line, m_options.m_force, &warnings);

      if (err.Fail()) {
        result.SetError(std::move(err));
        return;
      }

      if (!warnings.empty())
        result.AppendWarning(warnings.c_str());
    }

    result.SetStatus(eReturnStatusSuccessFinishResult);
  }

  CommandOptions m_options;
};

// Next are the subcommands of CommandObjectMultiwordThreadPlan

// CommandObjectThreadPlanList
#define LLDB_OPTIONS_thread_plan_list
#include "CommandOptions.inc"

class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() {
      // Keep default values of all options in one place: OptionParsingStarting
      // ()
      OptionParsingStarting(nullptr);
    }

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'i':
        m_internal = true;
        break;
      case 't':
        lldb::tid_t tid;
        if (option_arg.getAsInteger(0, tid))
          return Status::FromErrorStringWithFormat("invalid tid: '%s'.",
                                                   option_arg.str().c_str());
        m_tids.push_back(tid);
        break;
      case 'u':
        m_unreported = false;
        break;
      case 'v':
        m_verbose = true;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }
      return {};
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_verbose = false;
      m_internal = false;
      m_unreported = true; // The variable is "skip unreported" and we want to
                           // skip unreported by default.
      m_tids.clear();
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_thread_plan_list_options);
    }

    // Instance variables to hold the values for command options.
    bool m_verbose;
    bool m_internal;
    bool m_unreported;
    std::vector<lldb::tid_t> m_tids;
  };

  CommandObjectThreadPlanList(CommandInterpreter &interpreter)
      : CommandObjectIterateOverThreads(
            interpreter, "thread plan list",
            "Show thread plans for one or more threads.  If no threads are "
            "specified, show the "
            "current thread.  Use the thread-index \"all\" to see all threads.",
            nullptr,
            eCommandRequiresProcess | eCommandRequiresThread |
                eCommandTryTargetAPILock | eCommandProcessMustBeLaunched |
                eCommandProcessMustBePaused) {}

  ~CommandObjectThreadPlanList() override = default;

  Options *GetOptions() override { return &m_options; }

  void DoExecute(Args &command, CommandReturnObject &result) override {
    // If we are reporting all threads, dispatch to the Process to do that:
    if (command.GetArgumentCount() == 0 && m_options.m_tids.empty()) {
      Stream &strm = result.GetOutputStream();
      DescriptionLevel desc_level = m_options.m_verbose
                                        ? eDescriptionLevelVerbose
                                        : eDescriptionLevelFull;
      m_exe_ctx.GetProcessPtr()->DumpThreadPlans(
          strm, desc_level, m_options.m_internal, true, m_options.m_unreported);
      result.SetStatus(eReturnStatusSuccessFinishResult);
      return;
    } else {
      // Do any TID's that the user may have specified as TID, then do any
      // Thread Indexes...
      if (!m_options.m_tids.empty()) {
        Process *process = m_exe_ctx.GetProcessPtr();
        StreamString tmp_strm;
        for (lldb::tid_t tid : m_options.m_tids) {
          bool success = process->DumpThreadPlansForTID(
              tmp_strm, tid, eDescriptionLevelFull, m_options.m_internal,
              true /* condense_trivial */, m_options.m_unreported);
          // If we didn't find a TID, stop here and return an error.
          if (!success) {
            result.AppendError("Error dumping plans:");
            result.AppendError(tmp_strm.GetString());
            return;
          }
          // Otherwise, add our data to the output:
          result.GetOutputStream() << tmp_strm.GetString();
        }
      }
      return CommandObjectIterateOverThreads::DoExecute(command, result);
    }
  }

protected:
  bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
    // If we have already handled this from a -t option, skip it here.
    if (llvm::is_contained(m_options.m_tids, tid))
      return true;

    Process *process = m_exe_ctx.GetProcessPtr();

    Stream &strm = result.GetOutputStream();
    DescriptionLevel desc_level = eDescriptionLevelFull;
    if (m_options.m_verbose)
      desc_level = eDescriptionLevelVerbose;

    process->DumpThreadPlansForTID(strm, tid, desc_level, m_options.m_internal,
                                   true /* condense_trivial */,
                                   m_options.m_unreported);
    return true;
  }

  CommandOptions m_options;
};

class CommandObjectThreadPlanDiscard : public CommandObjectParsed {
public:
  CommandObjectThreadPlanDiscard(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "thread plan discard",
                            "Discards thread plans up to and including the "
                            "specified index (see 'thread plan list'.)  "
                            "Only user visible plans can be discarded.",
                            nullptr,
                            eCommandRequiresProcess | eCommandRequiresThread |
                                eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched |
                                eCommandProcessMustBePaused) {
    AddSimpleArgumentList(eArgTypeUnsignedInteger);
  }

  ~CommandObjectThreadPlanDiscard() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    if (!m_exe_ctx.HasThreadScope() || request.GetCursorIndex())
      return;

    m_exe_ctx.GetThreadPtr()->AutoCompleteThreadPlans(request);
  }

  void DoExecute(Args &args, CommandReturnObject &result) override {
    Thread *thread = m_exe_ctx.GetThreadPtr();
    if (args.GetArgumentCount() != 1) {
      result.AppendErrorWithFormat("Too many arguments, expected one - the "
                                   "thread plan index - but got %zu.",
                                   args.GetArgumentCount());
      return;
    }

    uint32_t thread_plan_idx;
    if (!llvm::to_integer(args.GetArgumentAtIndex(0), thread_plan_idx)) {
      result.AppendErrorWithFormat(
          "Invalid thread index: \"%s\" - should be unsigned int.",
          args.GetArgumentAtIndex(0));
      return;
    }

    if (thread_plan_idx == 0) {
      result.AppendErrorWithFormat(
          "You wouldn't really want me to discard the base thread plan.");
      return;
    }

    if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx)) {
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    } else {
      result.AppendErrorWithFormat(
          "Could not find User thread plan with index %s.",
          args.GetArgumentAtIndex(0));
    }
  }
};

class CommandObjectThreadPlanPrune : public CommandObjectParsed {
public:
  CommandObjectThreadPlanPrune(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "thread plan prune",
                            "Removes any thread plans associated with "
                            "currently unreported threads.  "
                            "Specify one or more TID's to remove, or if no "
                            "TID's are provides, remove threads for all "
                            "unreported threads",
                            nullptr,
                            eCommandRequiresProcess |
                                eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched |
                                eCommandProcessMustBePaused) {
    AddSimpleArgumentList(eArgTypeThreadID, eArgRepeatStar);
  }

  ~CommandObjectThreadPlanPrune() override = default;

  void DoExecute(Args &args, CommandReturnObject &result) override {
    Process *process = m_exe_ctx.GetProcessPtr();

    if (args.GetArgumentCount() == 0) {
      process->PruneThreadPlans();
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
      return;
    }

    const size_t num_args = args.GetArgumentCount();

    std::lock_guard<std::recursive_mutex> guard(
        process->GetThreadList().GetMutex());

    for (size_t i = 0; i < num_args; i++) {
      lldb::tid_t tid;
      if (!llvm::to_integer(args.GetArgumentAtIndex(i), tid)) {
        result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n",
                                     args.GetArgumentAtIndex(i));
        return;
      }
      if (!process->PruneThreadPlansForTID(tid)) {
        result.AppendErrorWithFormat("Could not find unreported tid: \"%s\"\n",
                                     args.GetArgumentAtIndex(i));
        return;
      }
    }
    result.SetStatus(eReturnStatusSuccessFinishNoResult);
  }
};

// CommandObjectMultiwordThreadPlan

class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword {
public:
  CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "plan",
            "Commands for managing thread plans that control execution.",
            "thread plan <subcommand> [<subcommand objects]") {
    LoadSubCommand(
        "list", CommandObjectSP(new CommandObjectThreadPlanList(interpreter)));
    LoadSubCommand(
        "discard",
        CommandObjectSP(new CommandObjectThreadPlanDiscard(interpreter)));
    LoadSubCommand(
        "prune",
        CommandObjectSP(new CommandObjectThreadPlanPrune(interpreter)));
  }

  ~CommandObjectMultiwordThreadPlan() override = default;
};

// Next are the subcommands of CommandObjectMultiwordTrace

// CommandObjectTraceExport

class CommandObjectTraceExport : public CommandObjectMultiword {
public:
  CommandObjectTraceExport(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "trace thread export",
            "Commands for exporting traces of the threads in the current "
            "process to different formats.",
            "thread trace export <export-plugin> [<subcommand objects>]") {

    unsigned i = 0;
    for (llvm::StringRef plugin_name =
             PluginManager::GetTraceExporterPluginNameAtIndex(i);
         !plugin_name.empty();
         plugin_name = PluginManager::GetTraceExporterPluginNameAtIndex(i++)) {
      if (ThreadTraceExportCommandCreator command_creator =
              PluginManager::GetThreadTraceExportCommandCreatorAtIndex(i)) {
        LoadSubCommand(plugin_name, command_creator(interpreter));
      }
    }
  }
};

// CommandObjectTraceStart

class CommandObjectTraceStart : public CommandObjectTraceProxy {
public:
  CommandObjectTraceStart(CommandInterpreter &interpreter)
      : CommandObjectTraceProxy(
            /*live_debug_session_only=*/true, interpreter, "thread trace start",
            "Start tracing threads with the corresponding trace "
            "plug-in for the current process.",
            "thread trace start [<trace-options>]") {}

protected:
  lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override {
    return trace.GetThreadTraceStartCommand(m_interpreter);
  }
};

// CommandObjectTraceStop

class CommandObjectTraceStop : public CommandObjectMultipleThreads {
public:
  CommandObjectTraceStop(CommandInterpreter &interpreter)
      : CommandObjectMultipleThreads(
            interpreter, "thread trace stop",
            "Stop tracing threads, including the ones traced with the "
            "\"process trace start\" command."
            "Defaults to the current thread. Thread indices can be "
            "specified as arguments.\n Use the thread-index \"all\" to stop "
            "tracing "
            "for all existing threads.",
            "thread trace stop [<thread-index> <thread-index> ...]",
            eCommandRequiresProcess | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
                eCommandProcessMustBeTraced) {}

  ~CommandObjectTraceStop() override = default;

  bool DoExecuteOnThreads(Args &command, CommandReturnObject &result,
                          llvm::ArrayRef<lldb::tid_t> tids) override {
    ProcessSP process_sp = m_exe_ctx.GetProcessSP();

    TraceSP trace_sp = process_sp->GetTarget().GetTrace();

    if (llvm::Error err = trace_sp->Stop(tids))
      result.AppendError(toString(std::move(err)));
    else
      result.SetStatus(eReturnStatusSuccessFinishResult);

    return result.Succeeded();
  }
};

static ThreadSP GetSingleThreadFromArgs(ExecutionContext &exe_ctx, Args &args,
                                        CommandReturnObject &result) {
  if (args.GetArgumentCount() == 0)
    return exe_ctx.GetThreadSP();

  const char *arg = args.GetArgumentAtIndex(0);
  uint32_t thread_idx;

  if (!llvm::to_integer(arg, thread_idx)) {
    result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n", arg);
    return nullptr;
  }
  ThreadSP thread_sp =
      exe_ctx.GetProcessRef().GetThreadList().FindThreadByIndexID(thread_idx);
  if (!thread_sp)
    result.AppendErrorWithFormat("no thread with index: \"%s\"\n", arg);
  return thread_sp;
}

// CommandObjectTraceDumpFunctionCalls
#define LLDB_OPTIONS_thread_trace_dump_function_calls
#include "CommandOptions.inc"

class CommandObjectTraceDumpFunctionCalls : public CommandObjectParsed {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() { OptionParsingStarting(nullptr); }

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'j': {
        m_dumper_options.json = true;
        break;
      }
      case 'J': {
        m_dumper_options.json = true;
        m_dumper_options.pretty_print_json = true;
        break;
      }
      case 'F': {
        m_output_file.emplace(option_arg);
        break;
      }
      default:
        llvm_unreachable("Unimplemented option");
      }
      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_dumper_options = {};
      m_output_file = std::nullopt;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_thread_trace_dump_function_calls_options);
    }

    static const size_t kDefaultCount = 20;

    // Instance variables to hold the values for command options.
    TraceDumperOptions m_dumper_options;
    std::optional<FileSpec> m_output_file;
  };

  CommandObjectTraceDumpFunctionCalls(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "thread trace dump function-calls",
            "Dump the traced function-calls for one thread. If no "
            "thread is specified, the current thread is used.",
            nullptr,
            eCommandRequiresProcess | eCommandRequiresThread |
                eCommandTryTargetAPILock | eCommandProcessMustBeLaunched |
                eCommandProcessMustBePaused | eCommandProcessMustBeTraced) {
    AddSimpleArgumentList(eArgTypeThreadIndex, eArgRepeatOptional);
  }

  ~CommandObjectTraceDumpFunctionCalls() override = default;

  Options *GetOptions() override { return &m_options; }

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    ThreadSP thread_sp = GetSingleThreadFromArgs(m_exe_ctx, args, result);
    if (!thread_sp) {
      result.AppendError("invalid thread\n");
      return;
    }

    llvm::Expected<TraceCursorSP> cursor_or_error =
        m_exe_ctx.GetTargetSP()->GetTrace()->CreateNewCursor(*thread_sp);

    if (!cursor_or_error) {
      result.AppendError(llvm::toString(cursor_or_error.takeError()));
      return;
    }
    TraceCursorSP &cursor_sp = *cursor_or_error;

    std::optional<StreamFile> out_file;
    if (m_options.m_output_file) {
      out_file.emplace(m_options.m_output_file->GetPath().c_str(),
                       File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate |
                           File::eOpenOptionTruncate);
    }

    m_options.m_dumper_options.forwards = true;

    TraceDumper dumper(std::move(cursor_sp),
                       out_file ? *out_file : result.GetOutputStream(),
                       m_options.m_dumper_options);

    dumper.DumpFunctionCalls();
  }

  CommandOptions m_options;
};

// CommandObjectTraceDumpInstructions
#define LLDB_OPTIONS_thread_trace_dump_instructions
#include "CommandOptions.inc"

class CommandObjectTraceDumpInstructions : public CommandObjectParsed {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() { OptionParsingStarting(nullptr); }

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'c': {
        int32_t count;
        if (option_arg.empty() || option_arg.getAsInteger(0, count) ||
            count < 0)
          error = Status::FromErrorStringWithFormat(
              "invalid integer value for option '%s'",
              option_arg.str().c_str());
        else
          m_count = count;
        break;
      }
      case 'a': {
        m_count = std::numeric_limits<decltype(m_count)>::max();
        break;
      }
      case 's': {
        int32_t skip;
        if (option_arg.empty() || option_arg.getAsInteger(0, skip) || skip < 0)
          error = Status::FromErrorStringWithFormat(
              "invalid integer value for option '%s'",
              option_arg.str().c_str());
        else
          m_dumper_options.skip = skip;
        break;
      }
      case 'i': {
        uint64_t id;
        if (option_arg.empty() || option_arg.getAsInteger(0, id))
          error = Status::FromErrorStringWithFormat(
              "invalid integer value for option '%s'",
              option_arg.str().c_str());
        else
          m_dumper_options.id = id;
        break;
      }
      case 'F': {
        m_output_file.emplace(option_arg);
        break;
      }
      case 'r': {
        m_dumper_options.raw = true;
        break;
      }
      case 'f': {
        m_dumper_options.forwards = true;
        break;
      }
      case 'k': {
        m_dumper_options.show_control_flow_kind = true;
        break;
      }
      case 't': {
        m_dumper_options.show_timestamps = true;
        break;
      }
      case 'e': {
        m_dumper_options.show_events = true;
        break;
      }
      case 'j': {
        m_dumper_options.json = true;
        break;
      }
      case 'J': {
        m_dumper_options.pretty_print_json = true;
        m_dumper_options.json = true;
        break;
      }
      case 'E': {
        m_dumper_options.only_events = true;
        m_dumper_options.show_events = true;
        break;
      }
      case 'C': {
        m_continue = true;
        break;
      }
      default:
        llvm_unreachable("Unimplemented option");
      }
      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_count = kDefaultCount;
      m_continue = false;
      m_output_file = std::nullopt;
      m_dumper_options = {};
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_thread_trace_dump_instructions_options);
    }

    static const size_t kDefaultCount = 20;

    // Instance variables to hold the values for command options.
    size_t m_count;
    size_t m_continue;
    std::optional<FileSpec> m_output_file;
    TraceDumperOptions m_dumper_options;
  };

  CommandObjectTraceDumpInstructions(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "thread trace dump instructions",
            "Dump the traced instructions for one thread. If no "
            "thread is specified, show the current thread.",
            nullptr,
            eCommandRequiresProcess | eCommandRequiresThread |
                eCommandTryTargetAPILock | eCommandProcessMustBeLaunched |
                eCommandProcessMustBePaused | eCommandProcessMustBeTraced) {
    AddSimpleArgumentList(eArgTypeThreadIndex, eArgRepeatOptional);
  }

  ~CommandObjectTraceDumpInstructions() override = default;

  Options *GetOptions() override { return &m_options; }

  std::optional<std::string> GetRepeatCommand(Args &current_command_args,
                                              uint32_t index) override {
    std::string cmd;
    current_command_args.GetCommandString(cmd);
    if (cmd.find(" --continue") == std::string::npos)
      cmd += " --continue";
    return cmd;
  }

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    ThreadSP thread_sp = GetSingleThreadFromArgs(m_exe_ctx, args, result);
    if (!thread_sp) {
      result.AppendError("invalid thread\n");
      return;
    }

    if (m_options.m_continue && m_last_id) {
      // We set up the options to continue one instruction past where
      // the previous iteration stopped.
      m_options.m_dumper_options.skip = 1;
      m_options.m_dumper_options.id = m_last_id;
    }

    llvm::Expected<TraceCursorSP> cursor_or_error =
        m_exe_ctx.GetTargetSP()->GetTrace()->CreateNewCursor(*thread_sp);

    if (!cursor_or_error) {
      result.AppendError(llvm::toString(cursor_or_error.takeError()));
      return;
    }
    TraceCursorSP &cursor_sp = *cursor_or_error;

    if (m_options.m_dumper_options.id &&
        !cursor_sp->HasId(*m_options.m_dumper_options.id)) {
      result.AppendError("invalid instruction id\n");
      return;
    }

    std::optional<StreamFile> out_file;
    if (m_options.m_output_file) {
      out_file.emplace(m_options.m_output_file->GetPath().c_str(),
                       File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate |
                           File::eOpenOptionTruncate);
    }

    if (m_options.m_continue && !m_last_id) {
      // We need to stop processing data when we already ran out of instructions
      // in a previous command. We can fake this by setting the cursor past the
      // end of the trace.
      cursor_sp->Seek(1, lldb::eTraceCursorSeekTypeEnd);
    }

    TraceDumper dumper(std::move(cursor_sp),
                       out_file ? *out_file : result.GetOutputStream(),
                       m_options.m_dumper_options);

    m_last_id = dumper.DumpInstructions(m_options.m_count);
  }

  CommandOptions m_options;
  // Last traversed id used to continue a repeat command. std::nullopt means
  // that all the trace has been consumed.
  std::optional<lldb::user_id_t> m_last_id;
};

// CommandObjectTraceDumpInfo
#define LLDB_OPTIONS_thread_trace_dump_info
#include "CommandOptions.inc"

class CommandObjectTraceDumpInfo : public CommandObjectIterateOverThreads {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() { OptionParsingStarting(nullptr); }

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'v': {
        m_verbose = true;
        break;
      }
      case 'j': {
        m_json = true;
        break;
      }
      default:
        llvm_unreachable("Unimplemented option");
      }
      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_verbose = false;
      m_json = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_thread_trace_dump_info_options);
    }

    // Instance variables to hold the values for command options.
    bool m_verbose;
    bool m_json;
  };

  CommandObjectTraceDumpInfo(CommandInterpreter &interpreter)
      : CommandObjectIterateOverThreads(
            interpreter, "thread trace dump info",
            "Dump the traced information for one or more threads.  If no "
            "threads are specified, show the current thread. Use the "
            "thread-index \"all\" to see all threads.",
            nullptr,
            eCommandRequiresProcess | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
                eCommandProcessMustBeTraced) {}

  ~CommandObjectTraceDumpInfo() override = default;

  Options *GetOptions() override { return &m_options; }

protected:
  bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
    const TraceSP &trace_sp = m_exe_ctx.GetTargetSP()->GetTrace();
    ThreadSP thread_sp =
        m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
    trace_sp->DumpTraceInfo(*thread_sp, result.GetOutputStream(),
                            m_options.m_verbose, m_options.m_json);
    return true;
  }

  CommandOptions m_options;
};

// CommandObjectMultiwordTraceDump
class CommandObjectMultiwordTraceDump : public CommandObjectMultiword {
public:
  CommandObjectMultiwordTraceDump(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "dump",
            "Commands for displaying trace information of the threads "
            "in the current process.",
            "thread trace dump <subcommand> [<subcommand objects>]") {
    LoadSubCommand(
        "instructions",
        CommandObjectSP(new CommandObjectTraceDumpInstructions(interpreter)));
    LoadSubCommand(
        "function-calls",
        CommandObjectSP(new CommandObjectTraceDumpFunctionCalls(interpreter)));
    LoadSubCommand(
        "info", CommandObjectSP(new CommandObjectTraceDumpInfo(interpreter)));
  }
  ~CommandObjectMultiwordTraceDump() override = default;
};

// CommandObjectMultiwordTrace
class CommandObjectMultiwordTrace : public CommandObjectMultiword {
public:
  CommandObjectMultiwordTrace(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "trace",
            "Commands for operating on traces of the threads in the current "
            "process.",
            "thread trace <subcommand> [<subcommand objects>]") {
    LoadSubCommand("dump", CommandObjectSP(new CommandObjectMultiwordTraceDump(
                               interpreter)));
    LoadSubCommand("start",
                   CommandObjectSP(new CommandObjectTraceStart(interpreter)));
    LoadSubCommand("stop",
                   CommandObjectSP(new CommandObjectTraceStop(interpreter)));
    LoadSubCommand("export",
                   CommandObjectSP(new CommandObjectTraceExport(interpreter)));
  }

  ~CommandObjectMultiwordTrace() override = default;
};

// CommandObjectMultiwordThread

CommandObjectMultiwordThread::CommandObjectMultiwordThread(
    CommandInterpreter &interpreter)
    : CommandObjectMultiword(interpreter, "thread",
                             "Commands for operating on "
                             "one or more threads in "
                             "the current process.",
                             "thread <subcommand> [<subcommand-options>]") {
  LoadSubCommand("backtrace", CommandObjectSP(new CommandObjectThreadBacktrace(
                                  interpreter)));
  LoadSubCommand("continue",
                 CommandObjectSP(new CommandObjectThreadContinue(interpreter)));
  LoadSubCommand("list",
                 CommandObjectSP(new CommandObjectThreadList(interpreter)));
  LoadSubCommand("return",
                 CommandObjectSP(new CommandObjectThreadReturn(interpreter)));
  LoadSubCommand("jump",
                 CommandObjectSP(new CommandObjectThreadJump(interpreter)));
  LoadSubCommand("select",
                 CommandObjectSP(new CommandObjectThreadSelect(interpreter)));
  LoadSubCommand("until",
                 CommandObjectSP(new CommandObjectThreadUntil(interpreter)));
  LoadSubCommand("info",
                 CommandObjectSP(new CommandObjectThreadInfo(interpreter)));
  LoadSubCommand("exception", CommandObjectSP(new CommandObjectThreadException(
                                  interpreter)));
  LoadSubCommand("siginfo",
                 CommandObjectSP(new CommandObjectThreadSiginfo(interpreter)));
  LoadSubCommand("step-in",
                 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
                     interpreter, "thread step-in",
                     "Source level single step, stepping into calls.  Defaults "
                     "to current thread unless specified.",
                     nullptr, eStepTypeInto)));

  LoadSubCommand("step-out",
                 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
                     interpreter, "thread step-out",
                     "Finish executing the current stack frame and stop after "
                     "returning.  Defaults to current thread unless specified.",
                     nullptr, eStepTypeOut)));

  LoadSubCommand("step-over",
                 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
                     interpreter, "thread step-over",
                     "Source level single step, stepping over calls.  Defaults "
                     "to current thread unless specified.",
                     nullptr, eStepTypeOver)));

  LoadSubCommand("step-inst",
                 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
                     interpreter, "thread step-inst",
                     "Instruction level single step, stepping into calls.  "
                     "Defaults to current thread unless specified.",
                     nullptr, eStepTypeTrace)));

  LoadSubCommand("step-inst-over",
                 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
                     interpreter, "thread step-inst-over",
                     "Instruction level single step, stepping over calls.  "
                     "Defaults to current thread unless specified.",
                     nullptr, eStepTypeTraceOver)));

  LoadSubCommand(
      "step-scripted",
      CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
          interpreter, "thread step-scripted",
          "Step as instructed by the script class passed in the -C option.  "
          "You can also specify a dictionary of key (-k) and value (-v) pairs "
          "that will be used to populate an SBStructuredData Dictionary, which "
          "will be passed to the constructor of the class implementing the "
          "scripted step.  See the Python Reference for more details.",
          nullptr, eStepTypeScripted)));

  LoadSubCommand("plan", CommandObjectSP(new CommandObjectMultiwordThreadPlan(
                             interpreter)));
  LoadSubCommand("trace",
                 CommandObjectSP(new CommandObjectMultiwordTrace(interpreter)));
}

CommandObjectMultiwordThread::~CommandObjectMultiwordThread() = default;
