//===-- 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;
      case 'p': {
        // Parse provider range using same format as breakpoint IDs.
        // Supports: "N", "N-M", "N to M", "*", "all".
        llvm::StringRef trimmed = option_arg.trim();
        if (trimmed == "*" || trimmed.equals_insensitive("all")) {
          m_show_all_providers = true;
          m_provider_specific_backtrace = true;
          break;
        }

        std::string option_lower = option_arg.lower();
        static constexpr llvm::StringLiteral range_specifiers[] = {"-", "to"};

        llvm::StringRef range_from;
        llvm::StringRef range_to;
        bool is_range = false;

        // Try to find a range specifier.
        for (auto specifier : range_specifiers) {
          size_t idx = option_lower.find(specifier);
          if (idx == std::string::npos)
            continue;

          range_from = llvm::StringRef(option_lower).take_front(idx).trim();
          range_to = llvm::StringRef(option_lower)
                         .drop_front(idx + specifier.size())
                         .trim();

          if (!range_from.empty() && !range_to.empty()) {
            is_range = true;
            break;
          }
        }

        if (is_range) {
          // Parse both start and end IDs.
          if (range_from.getAsInteger(0, m_provider_start_id)) {
            error = Status::FromErrorStringWithFormat(
                "invalid start provider ID for option '%c': %s", short_option,
                range_from.data());
            break;
          }
          if (range_to.getAsInteger(0, m_provider_end_id)) {
            error = Status::FromErrorStringWithFormat(
                "invalid end provider ID for option '%c': %s", short_option,
                range_to.data());
            break;
          }

          // Validate range.
          if (m_provider_start_id > m_provider_end_id) {
            error = Status::FromErrorStringWithFormat(
                "invalid provider range for option '%c': start ID %u > end "
                "ID %u",
                short_option, m_provider_start_id, m_provider_end_id);
            break;
          }
        } else {
          // Single provider ID.
          if (option_arg.getAsInteger(0, m_provider_start_id)) {
            error = Status::FromErrorStringWithFormat(
                "invalid provider ID for option '%c': %s", short_option,
                option_arg.data());
            break;
          }
          m_provider_end_id = m_provider_start_id;
        }

        m_provider_specific_backtrace = true;
      } 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;
      m_provider_start_id = 0;
      m_provider_end_id = 0;
      m_provider_specific_backtrace = false;
      m_show_all_providers = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return 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;
    lldb::frame_list_id_t m_provider_start_id;
    lldb::frame_list_id_t m_provider_end_id;
    bool m_provider_specific_backtrace;
    bool m_show_all_providers;
  };

  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 '--provider <id>' or '--provider <start>-<end>' to view "
            "synthetic frame providers (0=base unwinder, 1+=synthetic). "
            "Range specifiers '-', 'to', 'To', 'TO' are supported.\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, tid);
      return false;
    }

    Thread *thread = thread_sp.get();
    Stream &strm = result.GetOutputStream();

    // Check if provider filtering is requested.
    if (m_options.m_provider_specific_backtrace) {
      // Disallow 'bt --provider' from within a scripted frame provider.
      // A provider's get_frame_at_index running 'bt --provider' would
      // try to evaluate the very provider that is mid-construction,
      // leading to infinite recursion.
      if (thread->IsAnyProviderActive()) {
        result.AppendErrorWithFormat(
            "cannot use '--provider' option while a scripted frame provider is "
            "being constructed on this thread");
        return false;
      }

      // Print thread status header, like regular bt. This also ensures the
      // frame list is initialized and any providers are loaded.
      thread->GetStatus(strm, /*start_frame=*/0, /*num_frames=*/0,
                        /*num_frames_with_source=*/0, /*stop_format=*/true,
                        /*show_hidden=*/false, /*only_stacks=*/false);

      if (m_options.m_show_all_providers) {
        // Show all providers: unwinder (0) through the last in the chain.
        m_options.m_provider_start_id = 0;
        const auto &chain = thread->GetProviderChainIds();
        m_options.m_provider_end_id = chain.empty() ? 0 : chain.back().second;
      }

      // Provider filter mode: show sequential views for each provider in range.
      bool first_provider = true;
      for (lldb::frame_list_id_t provider_id = m_options.m_provider_start_id;
           provider_id <= m_options.m_provider_end_id; ++provider_id) {

        // Get the frame list for this provider.
        lldb::StackFrameListSP frame_list_sp =
            thread->GetFrameListByIdentifier(provider_id);

        if (!frame_list_sp) {
          // Provider doesn't exist - skip silently.
          continue;
        }

        // Add blank line between providers for readability.
        if (!first_provider)
          strm.PutChar('\n');
        first_provider = false;

        // Print provider header.
        strm.Printf("=== Provider %u", provider_id);

        // Get provider metadata for header.
        if (provider_id == 0) {
          strm.PutCString(": Base Unwinder ===\n");
        } else {
          // Find the descriptor in the provider chain.
          const auto &provider_chain = thread->GetProviderChainIds();
          std::string provider_name = "Unknown";
          std::string provider_desc;
          std::optional<uint32_t> provider_priority;

          for (const auto &[descriptor, id] : provider_chain) {
            if (id == provider_id) {
              provider_name = descriptor.GetName().str();
              provider_desc = descriptor.GetDescription();
              provider_priority = descriptor.GetPriority();
              break;
            }
          }

          strm.Printf(": %s", provider_name.c_str());
          if (provider_priority.has_value()) {
            strm.Printf(" (priority: %u)", *provider_priority);
          }
          strm.PutCString(" ===\n");

          if (!provider_desc.empty()) {
            strm.Printf("Description: %s\n", provider_desc.c_str());
          }
        }

        // Print the backtrace for this provider.
        const uint32_t num_frames_with_source = 0;
        const StackFrameSP selected_frame_sp =
            thread->GetSelectedFrame(DoNoSelectMostRelevantFrame);
        const char *selected_frame_marker = selected_frame_sp ? "->" : nullptr;

        size_t num_frames = frame_list_sp->GetStatus(
            strm, m_options.m_start, m_options.m_count,
            /*show_frame_info=*/true, num_frames_with_source,
            /*show_unique=*/false,
            /*show_hidden=*/!m_options.m_filtered_backtrace,
            selected_frame_marker);

        if (num_frames == 0) {
          strm.PutCString("(No frames available)\n");
        }
      }

      if (first_provider) {
        result.AppendErrorWithFormat("no provider found in range %u-%u",
                                     m_options.m_provider_start_id,
                                     m_options.m_provider_end_id);
        return false;
      }
      return true;
    }

    // Original behavior: show default backtrace.
    const bool only_stacks = m_unique_stacks;
    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\"",
          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'",
                                     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)",
            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;

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

    // First see if the frame has a custom step plan for us:
    if (frame) {
      llvm::Expected<lldb::ThreadPlanSP> frame_plan_result =
          frame->GetThreadPlanForStepType(m_step_type);
      if (auto llvm_err = frame_plan_result.takeError()) {
        result.AppendErrorWithFormat(
            "scripted frame provider got an error "
            "while constructing step plan: \"%s\"",
            llvm::toString(std::move(llvm_err)).c_str());
        return;
      }
      new_plan_sp = *frame_plan_result;
    }

    if (new_plan_sp) {
      thread->QueueThreadPlan(new_plan_sp, abort_other_plans);
      new_plan_sp->SetStopOthers(bool_stop_other_threads);
    } else {
      if (m_step_type == eStepTypeInto) {
        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, 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) {

        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) {
        ScriptedMetadata scripted_metadata(m_class_options.GetName(),
                                           m_class_options.GetStructuredData());
        new_plan_sp = thread->QueueThreadPlanForStepScripted(
            abort_other_plans, scripted_metadata, 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());
        result.SetStatus(eReturnStatusFailed);
        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\"", 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", thread_idx);
            return;
          }
        }

        if (resume_threads.empty()) {
          result.AppendError("no valid thread indexes were specified");
          return;
        } else {
          Stream &strm = result.GetOutputStream();
          if (resume_threads.size() == 1)
            strm << "Resuming thread: ";
          else
            strm << "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())
                strm << llvm::formatv("{0}, ", thread->GetIndexID());
              else
                strm << llvm::formatv("{0} ", thread->GetIndexID());

              const bool override_suspend = true;
              thread->SetResumeState(eStateRunning, override_suspend);
            } else {
              thread->SetResumeState(eStateSuspended);
            }
          }
          result.AppendMessageWithFormatv("in process {0}", 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.AppendMessageWithFormatv(
                "Resuming thread {0:x4} in process {1}", 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.AppendMessageWithFormatv("Process {0} resuming",
                                        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",
                                     error.AsCString());
      }
    } else {
      result.AppendErrorWithFormat(
          "Process cannot be continued from its current state (%s)",
          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);
    }

    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'",
                                         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)",
            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,
            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,
                                       m_options.m_frame_idx, thread->GetID());
          return;
        }

        LineEntry function_start;
        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;
        }

        RangeVector<uint32_t, uint32_t> line_idx_ranges;
        for (const AddressRange &range : sc.function->GetAddressRanges()) {
          auto [begin, end] = line_table->GetLineEntryIndexRange(range);
          line_idx_ranges.Append(begin, end - begin);
        }
        line_idx_ranges.Sort();

        bool found_something = false;

        // 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;
          if (sc.comp_unit->FindLineEntry(0, line_number, nullptr, exact,
                                          &line_entry) == UINT32_MAX)
            continue;

          found_something = true;
          line_number = line_entry.line;
          exact = true;
          uint32_t end_func_idx = line_idx_ranges.GetMaxRangeEnd(0);
          uint32_t idx = sc.comp_unit->FindLineEntry(
              line_idx_ranges.GetMinRangeBase(UINT32_MAX), line_number, nullptr,
              exact, &line_entry);
          while (idx < end_func_idx) {
            if (line_idx_ranges.FindEntryIndexThatContains(idx) != UINT32_MAX) {
              addr_t address =
                  line_entry.range.GetBaseAddress().GetLoadAddress(target);
              if (address != LLDB_INVALID_ADDRESS)
                address_list.push_back(address);
            }
            idx = sc.comp_unit->FindLineEntry(idx + 1, line_number, nullptr,
                                              exact, &line_entry);
          }
        }

        for (lldb::addr_t address : m_options.m_until_addrs) {
          AddressRange unused;
          if (sc.function->GetRangeContainingLoadAddress(address, *target,
                                                         unused))
            address_list.push_back(address);
        }

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

          return;
        }

        new_plan_sp = thread->QueueThreadPlanForStepUntil(
            abort_other_plans, address_list, 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",
                                     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,
            thread->GetID());
        return;
      }

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

      if (error.Success()) {
        result.AppendMessageWithFormatv("Process {0} resuming",
                                        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",
                                     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",
          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",
                                   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",
                                     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,
                                     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;
      m_backing_thread = 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;

      case 'b':
        m_backing_thread = 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;
    bool m_backing_thread;
  };

  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, tid);
      return false;
    }

    Thread *thread = thread_sp.get();
    if (m_options.m_backing_thread && thread->GetBackingThread())
      thread = thread->GetBackingThread().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\"",
                                   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, 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, tid);
      return false;
    }

    Stream &strm = result.GetOutputStream();
    if (!thread_sp->GetDescription(strm, eDescriptionLevelFull, false, false)) {
      result.AppendErrorWithFormat("error displaying info for thread: \"%d\"",
                                   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.PutCString("(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': {
        option_arg.consume_front("+");

        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\"",
                                     args.GetArgumentAtIndex(i));
        return;
      }
      if (!process->PruneThreadPlansForTID(tid)) {
        result.AppendErrorWithFormat("Could not find unreported tid: \"%s\"",
                                     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>]") {

    for (auto &cbs : PluginManager::GetTraceExporterCallbacks()) {
      if (cbs.create_thread_trace_export_command)
        LoadSubCommand(cbs.name,
                       cbs.create_thread_trace_export_command(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\"", arg);
    return nullptr;
  }
  ThreadSP thread_sp =
      exe_ctx.GetProcessRef().GetThreadList().FindThreadByIndexID(thread_idx);
  if (!thread_sp)
    result.AppendErrorWithFormat("no thread with index: \"%s\"", 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;
