//===-- 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;

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

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

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

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

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

      if (frame->HasDebugInformation())
        new_plan_sp = thread->QueueThreadPlanForStepOverRange(
            abort_other_plans,
            frame->GetSymbolContext(eSymbolContextEverything).line_entry,
            frame->GetSymbolContext(eSymbolContextEverything),
            stop_other_threads, new_plan_status,
            m_options.m_step_out_avoid_no_debug);
      else
        new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
            true, abort_other_plans, bool_stop_other_threads, new_plan_status);
    } else if (m_step_type == eStepTypeTrace) {
      new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
          false, abort_other_plans, bool_stop_other_threads, new_plan_status);
    } else if (m_step_type == eStepTypeTraceOver) {
      new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
          true, abort_other_plans, bool_stop_other_threads, new_plan_status);
    } else if (m_step_type == eStepTypeOut) {
      new_plan_sp = thread->QueueThreadPlanForStepOut(
          abort_other_plans, nullptr, false, bool_stop_other_threads, eVoteYes,
          eVoteNoOpinion,
          thread->GetSelectedFrameIndex(DoNoSelectMostRelevantFrame),
          new_plan_status, m_options.m_step_out_avoid_no_debug);
    } else if (m_step_type == eStepTypeScripted) {
      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;
