//===-- CommandObjectProcess.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 "CommandObjectProcess.h"
#include "CommandObjectBreakpoint.h"
#include "CommandObjectTrace.h"
#include "CommandOptionsProcessAttach.h"
#include "CommandOptionsProcessLaunch.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointName.h"
#include "lldb/Breakpoint/BreakpointSite.h"
#include "lldb/Core/Module.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/SaveCoreOptions.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/ScriptedMetadata.h"
#include "lldb/Utility/State.h"
#include "llvm/Support/FormatAdapters.h"

#include "llvm/ADT/ScopeExit.h"

#include <bitset>
#include <optional>

using namespace lldb;
using namespace lldb_private;

class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed {
public:
  CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter,
                                     const char *name, const char *help,
                                     const char *syntax, uint32_t flags,
                                     const char *new_process_action)
      : CommandObjectParsed(interpreter, name, help, syntax, flags),
        m_new_process_action(new_process_action) {}

  ~CommandObjectProcessLaunchOrAttach() override = default;

protected:
  bool StopProcessIfNecessary(Process *process, StateType &state,
                              CommandReturnObject &result) {
    state = eStateInvalid;
    if (process) {
      state = process->GetState();

      if (process->IsAlive() && state != eStateConnected) {
        std::string message;
        if (process->GetState() == eStateAttaching)
          message =
              llvm::formatv("There is a pending attach, abort it and {0}?",
                            m_new_process_action);
        else if (process->GetShouldDetach())
          message = llvm::formatv(
              "There is a running process, detach from it and {0}?",
              m_new_process_action);
        else
          message =
              llvm::formatv("There is a running process, kill it and {0}?",
                            m_new_process_action);

        if (!m_interpreter.Confirm(message, true)) {
          result.SetStatus(eReturnStatusFailed);
          return false;
        } else {
          if (process->GetShouldDetach()) {
            bool keep_stopped = false;
            Status detach_error(process->Detach(keep_stopped));
            if (detach_error.Success()) {
              result.SetStatus(eReturnStatusSuccessFinishResult);
              process = nullptr;
            } else {
              result.AppendErrorWithFormat(
                  "Failed to detach from process: %s\n",
                  detach_error.AsCString());
            }
          } else {
            Status destroy_error(process->Destroy(false));
            if (destroy_error.Success()) {
              result.SetStatus(eReturnStatusSuccessFinishResult);
              process = nullptr;
            } else {
              result.AppendErrorWithFormat("Failed to kill process: %s\n",
                                           destroy_error.AsCString());
            }
          }
        }
      }
    }
    return result.Succeeded();
  }

  std::string m_new_process_action;
};

// CommandObjectProcessLaunch
#pragma mark CommandObjectProcessLaunch
class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach {
public:
  CommandObjectProcessLaunch(CommandInterpreter &interpreter)
      : CommandObjectProcessLaunchOrAttach(
            interpreter, "process launch",
            "Launch the executable in the debugger. If no run-args are "
            "specified, the arguments from target.run-args are used.",
            nullptr, eCommandRequiresTarget, "restart"),

        m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
    m_all_options.Append(&m_options);
    m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
                         LLDB_OPT_SET_ALL);
    m_all_options.Finalize();

    AddSimpleArgumentList(eArgTypeRunArgs, eArgRepeatOptional);
  }

  ~CommandObjectProcessLaunch() override = default;

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

  std::optional<std::string> GetRepeatCommand(Args &current_command_args,
                                              uint32_t index) override {
    // No repeat for "process launch"...
    return std::string("");
  }

protected:
  void DoExecute(Args &launch_args, CommandReturnObject &result) override {
    Debugger &debugger = GetDebugger();
    Target *target = debugger.GetSelectedTarget().get();
    // If our listener is nullptr, users aren't allows to launch
    ModuleSP exe_module_sp = target->GetExecutableModule();

    // If the target already has an executable module, then use that.  If it
    // doesn't then someone must be trying to launch using a path that will
    // make sense to the remote stub, but doesn't exist on the local host.
    // In that case use the ExecutableFile that was set in the target's
    // ProcessLaunchInfo.
    if (exe_module_sp == nullptr && !target->GetProcessLaunchInfo().GetExecutableFile()) {
      result.AppendError("no file in target, create a debug target using the "
                         "'target create' command");
      return;
    }

    StateType state = eStateInvalid;

    if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result))
      return;

    // Determine whether we will disable ASLR or leave it in the default state
    // (i.e. enabled if the platform supports it). First check if the process
    // launch options explicitly turn on/off
    // disabling ASLR.  If so, use that setting;
    // otherwise, use the 'settings target.disable-aslr' setting.
    bool disable_aslr = false;
    if (m_options.disable_aslr != eLazyBoolCalculate) {
      // The user specified an explicit setting on the process launch line.
      // Use it.
      disable_aslr = (m_options.disable_aslr == eLazyBoolYes);
    } else {
      // The user did not explicitly specify whether to disable ASLR.  Fall
      // back to the target.disable-aslr setting.
      disable_aslr = target->GetDisableASLR();
    }

    if (!m_class_options.GetName().empty()) {
      m_options.launch_info.SetProcessPluginName("ScriptedProcess");
      ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
          m_class_options.GetName(), m_class_options.GetStructuredData());
      m_options.launch_info.SetScriptedMetadata(metadata_sp);
      target->SetProcessLaunchInfo(m_options.launch_info);
    }

    if (disable_aslr)
      m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
    else
      m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);

    if (target->GetInheritTCC())
      m_options.launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent);

    if (target->GetDetachOnError())
      m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError);

    if (target->GetDisableSTDIO())
      m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO);

    if (!m_options.launch_info.GetWorkingDirectory()) {
      if (llvm::StringRef wd = target->GetLaunchWorkingDirectory();
          !wd.empty()) {
        m_options.launch_info.SetWorkingDirectory(FileSpec(wd));
      }
    }

    // Merge the launch info environment with the target environment.
    Environment target_env = target->GetEnvironment();
    m_options.launch_info.GetEnvironment().insert(target_env.begin(),
                                                  target_env.end());

    llvm::StringRef target_settings_argv0 = target->GetArg0();

    if (!target_settings_argv0.empty()) {
      m_options.launch_info.GetArguments().AppendArgument(
          target_settings_argv0);
      if (exe_module_sp)
        m_options.launch_info.SetExecutableFile(
            exe_module_sp->GetPlatformFileSpec(), false);
      else
        m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), false);
    } else {
      if (exe_module_sp)
        m_options.launch_info.SetExecutableFile(
            exe_module_sp->GetPlatformFileSpec(), true);
      else
        m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), true);
    }

    if (launch_args.GetArgumentCount() == 0) {
      m_options.launch_info.GetArguments().AppendArguments(
          target->GetProcessLaunchInfo().GetArguments());
    } else {
      m_options.launch_info.GetArguments().AppendArguments(launch_args);
      // Save the arguments for subsequent runs in the current target.
      target->SetRunArguments(launch_args);
    }

    StreamString stream;
    Status error = target->Launch(m_options.launch_info, &stream);

    if (error.Success()) {
      ProcessSP process_sp(target->GetProcessSP());
      if (process_sp) {
        // 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_sp->SyncIOHandler(0, std::chrono::seconds(2));

        // If we didn't have a local executable, then we wouldn't have had an
        // executable module before launch.
        if (!exe_module_sp)
          exe_module_sp = target->GetExecutableModule();
        if (!exe_module_sp) {
          result.AppendWarning("could not get executable module after launch");
        } else {

          const char *archname =
              exe_module_sp->GetArchitecture().GetArchitectureName();
          result.AppendMessageWithFormat(
              "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(),
              exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
        }
        result.SetStatus(eReturnStatusSuccessFinishResult);
        // This message will refer to an event that happened after the process
        // launched.
        llvm::StringRef data = stream.GetString();
        if (!data.empty())
          result.AppendMessage(data);
        result.SetDidChangeProcessState(true);
      } else {
        result.AppendError(
            "no error returned from Target::Launch, and target has no process");
      }
    } else {
      result.AppendError(error.AsCString());
    }
  }

  CommandOptionsProcessLaunch m_options;
  OptionGroupPythonClassWithDict m_class_options;
  OptionGroupOptions m_all_options;
};

#define LLDB_OPTIONS_process_attach
#include "CommandOptions.inc"

#pragma mark CommandObjectProcessAttach
class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach {
public:
  CommandObjectProcessAttach(CommandInterpreter &interpreter)
      : CommandObjectProcessLaunchOrAttach(
            interpreter, "process attach", "Attach to a process.",
            "process attach <cmd-options>", 0, "attach"),
        m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
    m_all_options.Append(&m_options);
    m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
                         LLDB_OPT_SET_ALL);
    m_all_options.Finalize();
  }

  ~CommandObjectProcessAttach() override = default;

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

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    PlatformSP platform_sp(
        GetDebugger().GetPlatformList().GetSelectedPlatform());

    Target *target = GetDebugger().GetSelectedTarget().get();
    // N.B. The attach should be synchronous.  It doesn't help much to get the
    // prompt back between initiating the attach and the target actually
    // stopping.  So even if the interpreter is set to be asynchronous, we wait
    // for the stop ourselves here.

    StateType state = eStateInvalid;
    Process *process = m_exe_ctx.GetProcessPtr();

    if (!StopProcessIfNecessary(process, state, result))
      return;

    if (target == nullptr) {
      // If there isn't a current target create one.
      TargetSP new_target_sp;
      Status error;

      error = GetDebugger().GetTargetList().CreateTarget(
          GetDebugger(), "", "", eLoadDependentsNo,
          nullptr, // No platform options
          new_target_sp);
      target = new_target_sp.get();
      if (target == nullptr || error.Fail()) {
        result.AppendError(error.AsCString("Error creating target"));
        return;
      }
    }

    if (!m_class_options.GetName().empty()) {
      m_options.attach_info.SetProcessPluginName("ScriptedProcess");
      ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
          m_class_options.GetName(), m_class_options.GetStructuredData());
      m_options.attach_info.SetScriptedMetadata(metadata_sp);
    }

    // Record the old executable module, we want to issue a warning if the
    // process of attaching changed the current executable (like somebody said
    // "file foo" then attached to a PID whose executable was bar.)

    ModuleSP old_exec_module_sp = target->GetExecutableModule();
    ArchSpec old_arch_spec = target->GetArchitecture();

    StreamString stream;
    ProcessSP process_sp;
    const auto error = target->Attach(m_options.attach_info, &stream);
    if (error.Success()) {
      process_sp = target->GetProcessSP();
      if (process_sp) {
        result.AppendMessage(stream.GetString());
        result.SetStatus(eReturnStatusSuccessFinishNoResult);
        result.SetDidChangeProcessState(true);
      } else {
        result.AppendError(
            "no error returned from Target::Attach, and target has no process");
      }
    } else {
      result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString());
    }

    if (!result.Succeeded())
      return;

    // Okay, we're done.  Last step is to warn if the executable module has
    // changed:
    ModuleSP new_exec_module_sp(target->GetExecutableModule());
    if (!old_exec_module_sp) {
      // We might not have a module if we attached to a raw pid...
      if (new_exec_module_sp) {
        result.AppendMessageWithFormat(
            "Executable binary set to \"%s\".\n",
            new_exec_module_sp->GetFileSpec().GetPath().c_str());
      }
    } else if (!new_exec_module_sp) {
      result.AppendWarningWithFormat("No executable binary.");
    } else if (old_exec_module_sp->GetFileSpec() !=
               new_exec_module_sp->GetFileSpec()) {

      result.AppendWarningWithFormat(
          "Executable binary changed from \"%s\" to \"%s\".\n",
          old_exec_module_sp->GetFileSpec().GetPath().c_str(),
          new_exec_module_sp->GetFileSpec().GetPath().c_str());
    }

    if (!old_arch_spec.IsValid()) {
      result.AppendMessageWithFormat(
          "Architecture set to: %s.\n",
          target->GetArchitecture().GetTriple().getTriple().c_str());
    } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) {
      result.AppendWarningWithFormat(
          "Architecture changed from %s to %s.\n",
          old_arch_spec.GetTriple().getTriple().c_str(),
          target->GetArchitecture().GetTriple().getTriple().c_str());
    }

    // This supports the use-case scenario of immediately continuing the
    // process once attached.
    if (m_options.attach_info.GetContinueOnceAttached()) {
      // We have made a process but haven't told the interpreter about it yet,
      // so CheckRequirements will fail for "process continue".  Set the override
      // here:
      ExecutionContext exe_ctx(process_sp);
      m_interpreter.HandleCommand("process continue", eLazyBoolNo, exe_ctx, result);
    }
  }

  CommandOptionsProcessAttach m_options;
  OptionGroupPythonClassWithDict m_class_options;
  OptionGroupOptions m_all_options;
};

// CommandObjectProcessContinue

#define LLDB_OPTIONS_process_continue
#include "CommandOptions.inc"

#pragma mark CommandObjectProcessContinue

class CommandObjectProcessContinue : public CommandObjectParsed {
public:
  CommandObjectProcessContinue(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "process continue",
            "Continue execution of all threads in the current process.",
            "process continue",
            eCommandRequiresProcess | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}

  ~CommandObjectProcessContinue() override = default;

protected:
  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 *exe_ctx) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;
      switch (short_option) {
      case 'i':
        if (option_arg.getAsInteger(0, m_ignore))
          error = Status::FromErrorStringWithFormat(
              "invalid value for ignore option: \"%s\", should be a number.",
              option_arg.str().c_str());
        break;
      case 'b':
        m_run_to_bkpt_args.AppendArgument(option_arg);
        m_any_bkpts_specified = true;
        break;
      case 'F':
        m_base_direction = lldb::RunDirection::eRunForward;
        break;
      case 'R':
        m_base_direction = lldb::RunDirection::eRunReverse;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }
      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_ignore = 0;
      m_run_to_bkpt_args.Clear();
      m_any_bkpts_specified = false;
      m_base_direction = std::nullopt;
    }

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

    uint32_t m_ignore = 0;
    Args m_run_to_bkpt_args;
    bool m_any_bkpts_specified = false;
    std::optional<lldb::RunDirection> m_base_direction;
  };

  void DoExecute(Args &command, CommandReturnObject &result) override {
    Process *process = m_exe_ctx.GetProcessPtr();
    bool synchronous_execution = m_interpreter.GetSynchronous();
    StateType state = process->GetState();
    if (state == eStateStopped) {
      if (m_options.m_ignore > 0) {
        ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this());
        if (sel_thread_sp) {
          StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo();
          if (stop_info_sp &&
              stop_info_sp->GetStopReason() == eStopReasonBreakpoint) {
            lldb::break_id_t bp_site_id =
                (lldb::break_id_t)stop_info_sp->GetValue();
            BreakpointSiteSP bp_site_sp(
                process->GetBreakpointSiteList().FindByID(bp_site_id));
            if (bp_site_sp) {
              const size_t num_owners = bp_site_sp->GetNumberOfConstituents();
              for (size_t i = 0; i < num_owners; i++) {
                Breakpoint &bp_ref =
                    bp_site_sp->GetConstituentAtIndex(i)->GetBreakpoint();
                if (!bp_ref.IsInternal()) {
                  bp_ref.SetIgnoreCount(m_options.m_ignore);
                }
              }
            }
          }
        }
      }

      Target &target = GetTarget();
      BreakpointIDList run_to_bkpt_ids;
      // Don't pass an empty run_to_breakpoint list, as Verify will look for the
      // default breakpoint.
      if (m_options.m_run_to_bkpt_args.GetArgumentCount() > 0)
        CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
            m_options.m_run_to_bkpt_args, target, result, &run_to_bkpt_ids,
            BreakpointName::Permissions::disablePerm);
      if (!result.Succeeded()) {
        return;
      }
      result.Clear();
      if (m_options.m_any_bkpts_specified && run_to_bkpt_ids.GetSize() == 0) {
        result.AppendError("continue-to breakpoints did not specify any actual "
                           "breakpoints or locations");
        return;
      }

      // First figure out which breakpoints & locations were specified by the
      // user:
      size_t num_run_to_bkpt_ids = run_to_bkpt_ids.GetSize();
      std::vector<break_id_t> bkpts_disabled;
      std::vector<BreakpointID> locs_disabled;
      if (num_run_to_bkpt_ids != 0) {
        // Go through the ID's specified, and separate the breakpoints from are
        // the breakpoint.location specifications since the latter require
        // special handling.  We also figure out whether there's at least one
        // specifier in the set that is enabled.
        BreakpointList &bkpt_list = target.GetBreakpointList();
        std::unordered_set<break_id_t> bkpts_seen;
        std::unordered_set<break_id_t> bkpts_with_locs_seen;
        BreakpointIDList with_locs;
        bool any_enabled = false;

        for (size_t idx = 0; idx < num_run_to_bkpt_ids; idx++) {
          BreakpointID bkpt_id = run_to_bkpt_ids.GetBreakpointIDAtIndex(idx);
          break_id_t bp_id = bkpt_id.GetBreakpointID();
          break_id_t loc_id = bkpt_id.GetLocationID();
          BreakpointSP bp_sp
              = bkpt_list.FindBreakpointByID(bp_id);
          // Note, VerifyBreakpointOrLocationIDs checks for existence, so we
          // don't need to do it again here.
          if (bp_sp->IsEnabled()) {
            if (loc_id == LLDB_INVALID_BREAK_ID) {
              // A breakpoint (without location) was specified.  Make sure that
              // at least one of the locations is enabled.
              size_t num_locations = bp_sp->GetNumLocations();
              for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) {
                BreakpointLocationSP loc_sp
                    = bp_sp->GetLocationAtIndex(loc_idx);
                if (loc_sp->IsEnabled()) {
                  any_enabled = true;
                  break;
                }
              }
            } else {
              // A location was specified, check if it was enabled:
              BreakpointLocationSP loc_sp = bp_sp->FindLocationByID(loc_id);
              if (loc_sp->IsEnabled())
                any_enabled = true;
            }

            // Then sort the bp & bp.loc entries for later use:
            if (bkpt_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
              bkpts_seen.insert(bkpt_id.GetBreakpointID());
            else {
              bkpts_with_locs_seen.insert(bkpt_id.GetBreakpointID());
              with_locs.AddBreakpointID(bkpt_id);
            }
          }
        }
        // Do all the error checking here so once we start disabling we don't
        // have to back out half-way through.

        // Make sure at least one of the specified breakpoints is enabled.
        if (!any_enabled) {
          result.AppendError("at least one of the continue-to breakpoints must "
                             "be enabled.");
          return;
        }

        // Also, if you specify BOTH a breakpoint and one of it's locations,
        // we flag that as an error, since it won't do what you expect, the
        // breakpoint directive will mean "run to all locations", which is not
        // what the location directive means...
        for (break_id_t bp_id : bkpts_with_locs_seen) {
          if (bkpts_seen.count(bp_id)) {
            result.AppendErrorWithFormatv("can't specify both a breakpoint and "
                               "one of its locations: {0}", bp_id);
          }
        }

        // Now go through the breakpoints in the target, disabling all the ones
        // that the user didn't mention:
        for (BreakpointSP bp_sp : bkpt_list.Breakpoints()) {
          break_id_t bp_id = bp_sp->GetID();
          // Handle the case where no locations were specified.  Note we don't
          // have to worry about the case where a breakpoint and one of its
          // locations are both in the lists, we've already disallowed that.
          if (!bkpts_with_locs_seen.count(bp_id)) {
            if (!bkpts_seen.count(bp_id) && bp_sp->IsEnabled()) {
              bkpts_disabled.push_back(bp_id);
              bp_sp->SetEnabled(false);
            }
            continue;
          }
          // Next, handle the case where a location was specified:
          // Run through all the locations of this breakpoint and disable
          // the ones that aren't on our "with locations" BreakpointID list:
          size_t num_locations = bp_sp->GetNumLocations();
          BreakpointID tmp_id(bp_id, LLDB_INVALID_BREAK_ID);
          for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) {
            BreakpointLocationSP loc_sp = bp_sp->GetLocationAtIndex(loc_idx);
            tmp_id.SetBreakpointLocationID(loc_idx);
            if (!with_locs.Contains(tmp_id) && loc_sp->IsEnabled()) {
              if (llvm::Error error = loc_sp->SetEnabled(false))
                result.AppendErrorWithFormatv(
                    "failed to disable breakpoint location: {0}",
                    llvm::fmt_consume(std::move(error)));
              else
                locs_disabled.push_back(tmp_id);
            }
          }
        }
      }

      { // Scope for thread list mutex:
        std::lock_guard<std::recursive_mutex> guard(
            process->GetThreadList().GetMutex());
        const uint32_t num_threads = process->GetThreadList().GetSize();

        // Set the actions that the threads should each take when resuming
        for (uint32_t idx = 0; idx < num_threads; ++idx) {
          const bool override_suspend = false;
          process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState(
              eStateRunning, override_suspend);
        }
      }

      if (m_options.m_base_direction.has_value())
        process->SetBaseDirection(*m_options.m_base_direction);

      const uint32_t iohandler_id = process->GetIOHandlerID();

      StreamString stream;
      Status error;
      // For now we can only do -b with synchronous:
      bool old_sync = GetDebugger().GetAsyncExecution();

      if (run_to_bkpt_ids.GetSize() != 0) {
        GetDebugger().SetAsyncExecution(false);
        synchronous_execution = true;
      }
      if (synchronous_execution)
        error = process->ResumeSynchronous(&stream);
      else
        error = process->Resume();

      if (run_to_bkpt_ids.GetSize() != 0) {
        GetDebugger().SetAsyncExecution(old_sync);
      }

      // Now re-enable the breakpoints we disabled:
      BreakpointList &bkpt_list = target.GetBreakpointList();
      for (break_id_t bp_id : bkpts_disabled) {
        BreakpointSP bp_sp = bkpt_list.FindBreakpointByID(bp_id);
        if (bp_sp)
          bp_sp->SetEnabled(true);
      }
      for (const BreakpointID &bkpt_id : locs_disabled) {
        BreakpointSP bp_sp
            = bkpt_list.FindBreakpointByID(bkpt_id.GetBreakpointID());
        if (bp_sp) {
          BreakpointLocationSP loc_sp
              = bp_sp->FindLocationByID(bkpt_id.GetLocationID());
          if (loc_sp) {
            if (llvm::Error error = loc_sp->SetEnabled(true))
              result.AppendErrorWithFormatv(
                  "failed to enable breakpoint location: {0}",
                  llvm::fmt_consume(std::move(error)));
          }
        }
      }

      if (error.Success()) {
        // 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));

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

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

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

  CommandOptions m_options;
};

// CommandObjectProcessDetach
#define LLDB_OPTIONS_process_detach
#include "CommandOptions.inc"

#pragma mark CommandObjectProcessDetach

class CommandObjectProcessDetach : 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 's':
        bool tmp_result;
        bool success;
        tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success);
        if (!success)
          error = Status::FromErrorStringWithFormat(
              "invalid boolean option: \"%s\"", option_arg.str().c_str());
        else {
          if (tmp_result)
            m_keep_stopped = eLazyBoolYes;
          else
            m_keep_stopped = eLazyBoolNo;
        }
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }
      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_keep_stopped = eLazyBoolCalculate;
    }

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

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

  CommandObjectProcessDetach(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "process detach",
                            "Detach from the current target process.",
                            "process detach",
                            eCommandRequiresProcess | eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched) {}

  ~CommandObjectProcessDetach() override = default;

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

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Process *process = m_exe_ctx.GetProcessPtr();
    // FIXME: This will be a Command Option:
    bool keep_stopped;
    if (m_options.m_keep_stopped == eLazyBoolCalculate) {
      // Check the process default:
      keep_stopped = process->GetDetachKeepsStopped();
    } else if (m_options.m_keep_stopped == eLazyBoolYes)
      keep_stopped = true;
    else
      keep_stopped = false;

    Status error(process->Detach(keep_stopped));
    if (error.Success()) {
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString());
    }
  }

  CommandOptions m_options;
};

// CommandObjectProcessConnect
#define LLDB_OPTIONS_process_connect
#include "CommandOptions.inc"

#pragma mark CommandObjectProcessConnect

class CommandObjectProcessConnect : public CommandObjectParsed {
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 'p':
        plugin_name.assign(std::string(option_arg));
        break;

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

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      plugin_name.clear();
    }

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

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

    std::string plugin_name;
  };

  CommandObjectProcessConnect(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "process connect",
                            "Connect to a remote debug service.",
                            "process connect <remote-url>", 0) {
    AddSimpleArgumentList(eArgTypeConnectURL);
  }

  ~CommandObjectProcessConnect() override = default;

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

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    if (command.GetArgumentCount() != 1) {
      result.AppendErrorWithFormat(
          "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(),
          m_cmd_syntax.c_str());
      return;
    }

    Process *process = m_exe_ctx.GetProcessPtr();
    if (process && process->IsAlive()) {
      result.AppendErrorWithFormat(
          "Process %" PRIu64
          " is currently being debugged, kill the process before connecting.\n",
          process->GetID());
      return;
    }

    const char *plugin_name = nullptr;
    if (!m_options.plugin_name.empty())
      plugin_name = m_options.plugin_name.c_str();

    Status error;
    Debugger &debugger = GetDebugger();
    PlatformSP platform_sp = m_interpreter.GetPlatform(true);
    ProcessSP process_sp =
        debugger.GetAsyncExecution()
            ? platform_sp->ConnectProcess(
                  command.GetArgumentAtIndex(0), plugin_name, debugger,
                  debugger.GetSelectedTarget().get(), error)
            : platform_sp->ConnectProcessSynchronous(
                  command.GetArgumentAtIndex(0), plugin_name, debugger,
                  result.GetOutputStream(), debugger.GetSelectedTarget().get(),
                  error);
    if (error.Fail() || process_sp == nullptr) {
      result.AppendError(error.AsCString("Error connecting to the process"));
    }
  }

  CommandOptions m_options;
};

// CommandObjectProcessPlugin
#pragma mark CommandObjectProcessPlugin

class CommandObjectProcessPlugin : public CommandObjectProxy {
public:
  CommandObjectProcessPlugin(CommandInterpreter &interpreter)
      : CommandObjectProxy(
            interpreter, "process plugin",
            "Send a custom command to the current target process plug-in.",
            "process plugin <args>", 0) {}

  ~CommandObjectProcessPlugin() override = default;

  CommandObject *GetProxyCommandObject() override {
    Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
    if (process)
      return process->GetPluginCommandObject();
    return nullptr;
  }
};

// CommandObjectProcessLoad
#define LLDB_OPTIONS_process_load
#include "CommandOptions.inc"

#pragma mark CommandObjectProcessLoad

class CommandObjectProcessLoad : public CommandObjectParsed {
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;
      ArchSpec arch =
          execution_context->GetProcessPtr()->GetSystemArchitecture();
      switch (short_option) {
      case 'i':
        do_install = true;
        if (!option_arg.empty())
          install_path.SetFile(option_arg, arch.GetTriple());
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }
      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      do_install = false;
      install_path.Clear();
    }

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

    // Instance variables to hold the values for command options.
    bool do_install;
    FileSpec install_path;
  };

  CommandObjectProcessLoad(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "process load",
                            "Load a shared library into the current process.",
                            "process load <filename> [<filename> ...]",
                            eCommandRequiresProcess | eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched |
                                eCommandProcessMustBePaused) {
    AddSimpleArgumentList(eArgTypePath, eArgRepeatPlus);
  }

  ~CommandObjectProcessLoad() override = default;

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

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

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

    for (auto &entry : command.entries()) {
      Status error;
      PlatformSP platform = process->GetTarget().GetPlatform();
      llvm::StringRef image_path = entry.ref();
      uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN;

      if (!m_options.do_install) {
        FileSpec image_spec(image_path);
        platform->ResolveRemotePath(image_spec, image_spec);
        image_token =
            platform->LoadImage(process, FileSpec(), image_spec, error);
      } else if (m_options.install_path) {
        FileSpec image_spec(image_path);
        FileSystem::Instance().Resolve(image_spec);
        platform->ResolveRemotePath(m_options.install_path,
                                    m_options.install_path);
        image_token = platform->LoadImage(process, image_spec,
                                          m_options.install_path, error);
      } else {
        FileSpec image_spec(image_path);
        FileSystem::Instance().Resolve(image_spec);
        image_token =
            platform->LoadImage(process, image_spec, FileSpec(), error);
      }

      if (image_token != LLDB_INVALID_IMAGE_TOKEN) {
        result.AppendMessageWithFormat(
            "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(),
            image_token);
        result.SetStatus(eReturnStatusSuccessFinishResult);
      } else {
        result.AppendErrorWithFormat("failed to load '%s': %s",
                                     image_path.str().c_str(),
                                     error.AsCString());
      }
    }
  }

  CommandOptions m_options;
};

// CommandObjectProcessUnload
#pragma mark CommandObjectProcessUnload

class CommandObjectProcessUnload : public CommandObjectParsed {
public:
  CommandObjectProcessUnload(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "process unload",
            "Unload a shared library from the current process using the index "
            "returned by a previous call to \"process load\".",
            "process unload <index>",
            eCommandRequiresProcess | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
    AddSimpleArgumentList(eArgTypeUnsignedInteger);
  }

  ~CommandObjectProcessUnload() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {

    if (request.GetCursorIndex() || !m_exe_ctx.HasProcessScope())
      return;

    Process *process = m_exe_ctx.GetProcessPtr();

    const std::vector<lldb::addr_t> &tokens = process->GetImageTokens();
    const size_t token_num = tokens.size();
    for (size_t i = 0; i < token_num; ++i) {
      if (tokens[i] == LLDB_INVALID_IMAGE_TOKEN)
        continue;
      request.TryCompleteCurrentArg(std::to_string(i));
    }
  }

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

    for (auto &entry : command.entries()) {
      uint32_t image_token;
      if (entry.ref().getAsInteger(0, image_token)) {
        result.AppendErrorWithFormat("invalid image index argument '%s'",
                                     entry.ref().str().c_str());
        break;
      } else {
        Status error(process->GetTarget().GetPlatform()->UnloadImage(
            process, image_token));
        if (error.Success()) {
          result.AppendMessageWithFormat(
              "Unloading shared library with index %u...ok\n", image_token);
          result.SetStatus(eReturnStatusSuccessFinishResult);
        } else {
          result.AppendErrorWithFormat("failed to unload image: %s",
                                       error.AsCString());
          break;
        }
      }
    }
  }
};

// CommandObjectProcessSignal
#pragma mark CommandObjectProcessSignal

class CommandObjectProcessSignal : public CommandObjectParsed {
public:
  CommandObjectProcessSignal(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "process signal",
            "Send a UNIX signal to the current target process.", nullptr,
            eCommandRequiresProcess | eCommandTryTargetAPILock) {
    AddSimpleArgumentList(eArgTypeUnixSignal);
  }

  ~CommandObjectProcessSignal() override = default;

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

    UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals();
    int signo = signals->GetFirstSignalNumber();
    while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
      request.TryCompleteCurrentArg(signals->GetSignalAsStringRef(signo));
      signo = signals->GetNextSignalNumber(signo);
    }
  }

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

    if (command.GetArgumentCount() == 1) {
      int signo = LLDB_INVALID_SIGNAL_NUMBER;

      const char *signal_name = command.GetArgumentAtIndex(0);
      if (::isxdigit(signal_name[0])) {
        if (!llvm::to_integer(signal_name, signo))
          signo = LLDB_INVALID_SIGNAL_NUMBER;
      } else
        signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name);

      if (signo == LLDB_INVALID_SIGNAL_NUMBER) {
        result.AppendErrorWithFormat("Invalid signal argument '%s'.\n",
                                     command.GetArgumentAtIndex(0));
      } else {
        Status error(process->Signal(signo));
        if (error.Success()) {
          result.SetStatus(eReturnStatusSuccessFinishResult);
        } else {
          result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo,
                                       error.AsCString());
        }
      }
    } else {
      result.AppendErrorWithFormat(
          "'%s' takes exactly one signal number argument:\nUsage: %s\n",
          m_cmd_name.c_str(), m_cmd_syntax.c_str());
    }
  }
};

// CommandObjectProcessInterrupt
#pragma mark CommandObjectProcessInterrupt

class CommandObjectProcessInterrupt : public CommandObjectParsed {
public:
  CommandObjectProcessInterrupt(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "process interrupt",
                            "Interrupt the current target process.",
                            "process interrupt",
                            eCommandRequiresProcess | eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched) {}

  ~CommandObjectProcessInterrupt() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Process *process = m_exe_ctx.GetProcessPtr();
    if (process == nullptr) {
      result.AppendError("no process to halt");
      return;
    }

    bool clear_thread_plans = true;
    Status error(process->Halt(clear_thread_plans));
    if (error.Success()) {
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      result.AppendErrorWithFormat("Failed to halt process: %s\n",
                                   error.AsCString());
    }
  }
};

// CommandObjectProcessKill
#pragma mark CommandObjectProcessKill

class CommandObjectProcessKill : public CommandObjectParsed {
public:
  CommandObjectProcessKill(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "process kill",
                            "Terminate the current target process.",
                            "process kill",
                            eCommandRequiresProcess | eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched) {}

  ~CommandObjectProcessKill() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Process *process = m_exe_ctx.GetProcessPtr();
    if (process == nullptr) {
      result.AppendError("no process to kill");
      return;
    }

    Status error(process->Destroy(true));
    if (error.Success()) {
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      result.AppendErrorWithFormat("Failed to kill process: %s\n",
                                   error.AsCString());
    }
  }
};

#define LLDB_OPTIONS_process_save_core
#include "CommandOptions.inc"

class CommandObjectProcessSaveCore : public CommandObjectParsed {
public:
  CommandObjectProcessSaveCore(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "process save-core",
            "Save the current process as a core file using an "
            "appropriate file type.",
            "process save-core [-s corefile-style -p plugin-name] FILE",
            eCommandRequiresProcess | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched) {
    AddSimpleArgumentList(eArgTypePath);
  }

  ~CommandObjectProcessSaveCore() override = default;

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

  class CommandOptions : public Options {
  public:
    CommandOptions() = default;

    ~CommandOptions() override = default;

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      if (!m_opt_def.empty())
        return llvm::ArrayRef(m_opt_def);

      auto orig = llvm::ArrayRef(g_process_save_core_options);
      m_opt_def.resize(orig.size());
      llvm::copy(g_process_save_core_options, m_opt_def.data());
      for (OptionDefinition &value : m_opt_def) {
        llvm::StringRef opt_name = value.long_option;
        if (opt_name != "plugin-name")
          continue;

        std::vector<llvm::StringRef> plugin_names =
            PluginManager::GetSaveCorePluginNames();
        m_plugin_enums.resize(plugin_names.size());
        for (auto [num, val] : llvm::zip(plugin_names, m_plugin_enums)) {
          val.string_value = num.data();
        }
        value.enum_values = llvm::ArrayRef(m_plugin_enums);
        break;
      }
      return llvm::ArrayRef(m_opt_def);
    }

    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 'p':
        error = m_core_dump_options.SetPluginName(option_arg.data());
        break;
      case 's':
        m_core_dump_options.SetStyle(
            (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum(
                option_arg, GetDefinitions()[option_idx].enum_values,
                eSaveCoreUnspecified, error));
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_core_dump_options.Clear();
    }

    // Instance variables to hold the values for command options.
    SaveCoreOptions m_core_dump_options;
    llvm::SmallVector<OptionEnumValueElement> m_plugin_enums;
    std::vector<OptionDefinition> m_opt_def;
  };

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    ProcessSP process_sp = m_exe_ctx.GetProcessSP();
    if (process_sp) {
      if (command.GetArgumentCount() == 1) {
        FileSpec output_file(command.GetArgumentAtIndex(0));
        FileSystem::Instance().Resolve(output_file);
        auto &core_dump_options = m_options.m_core_dump_options;
        core_dump_options.SetOutputFile(output_file);
        core_dump_options.SetProcess(process_sp);
        Status error = PluginManager::SaveCore(core_dump_options);
        if (error.Success()) {
          if (core_dump_options.GetStyle() ==
                  SaveCoreStyle::eSaveCoreDirtyOnly ||
              core_dump_options.GetStyle() ==
                  SaveCoreStyle::eSaveCoreStackOnly) {
            result.AppendMessageWithFormat(
                "\nModified-memory or stack-memory only corefile "
                "created.  This corefile may \n"
                "not show library/framework/app binaries "
                "on a different system, or when \n"
                "those binaries have "
                "been updated/modified. Copies are not included\n"
                "in this corefile.  Use --style full to include all "
                "process memory.\n");
          }
          result.SetStatus(eReturnStatusSuccessFinishResult);
        } else {
          result.AppendErrorWithFormat(
              "Failed to save core file for process: %s\n", error.AsCString());
        }
      } else {
        result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n",
                                     m_cmd_name.c_str(), m_cmd_syntax.c_str());
      }
    } else {
      result.AppendError("invalid process");
    }
  }

  CommandOptions m_options;
};

// CommandObjectProcessStatus
#pragma mark CommandObjectProcessStatus
#define LLDB_OPTIONS_process_status
#include "CommandOptions.inc"

class CommandObjectProcessStatus : public CommandObjectParsed {
public:
  CommandObjectProcessStatus(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "process status",
            "Show status and stop location for the current target process.",
            "process status",
            eCommandRequiresProcess | eCommandTryTargetAPILock) {}

  ~CommandObjectProcessStatus() override = default;

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

  class CommandOptions : public Options {
  public:
    CommandOptions() = default;

    ~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 'v':
        m_verbose = true;
        break;
      case 'd':
        m_dump = true;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return {};
    }

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

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

    // Instance variables to hold the values for command options.
    bool m_verbose = false;
    bool m_dump = false;
  };

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Stream &strm = result.GetOutputStream();
    result.SetStatus(eReturnStatusSuccessFinishNoResult);

    // No need to check "process" for validity as eCommandRequiresProcess
    // ensures it is valid
    Process *process = m_exe_ctx.GetProcessPtr();
    const bool only_threads_with_stop_reason = true;
    const uint32_t start_frame = 0;
    const uint32_t num_frames = 1;
    const uint32_t num_frames_with_source = 1;
    const bool stop_format = true;
    process->GetStatus(strm);
    process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,
                             num_frames, num_frames_with_source, stop_format);

    if (m_options.m_verbose) {
      addr_t code_mask = process->GetCodeAddressMask();
      addr_t data_mask = process->GetDataAddressMask();
      if (code_mask != LLDB_INVALID_ADDRESS_MASK) {
        int bits = std::bitset<64>(~code_mask).count();
        result.AppendMessageWithFormat(
            "Addressable code address mask: 0x%" PRIx64 "\n", code_mask);
        result.AppendMessageWithFormat(
            "Addressable data address mask: 0x%" PRIx64 "\n", data_mask);
        result.AppendMessageWithFormat(
            "Number of bits used in addressing (code): %d\n", bits);
      }

      PlatformSP platform_sp = process->GetTarget().GetPlatform();
      if (!platform_sp) {
        result.AppendError("Couldn't retrieve the target's platform");
        return;
      }

      auto expected_crash_info =
          platform_sp->FetchExtendedCrashInformation(*process);

      if (!expected_crash_info) {
        result.AppendError(llvm::toString(expected_crash_info.takeError()));
        return;
      }

      StructuredData::DictionarySP crash_info_sp = *expected_crash_info;

      if (crash_info_sp) {
        strm.EOL();
        strm.PutCString("Extended Crash Information:\n");
        crash_info_sp->GetDescription(strm);
      }
    }

    if (m_options.m_dump) {
      StateType state = process->GetState();
      if (state == eStateStopped) {
        ProcessModID process_mod_id = process->GetModID();
        process_mod_id.Dump(result.GetOutputStream());
      }
    }
  }

private:
  CommandOptions m_options;
};

// CommandObjectProcessHandle
#define LLDB_OPTIONS_process_handle
#include "CommandOptions.inc"

#pragma mark CommandObjectProcessHandle

class CommandObjectProcessHandle : 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':
        do_clear = true;
        break;
      case 'd':
        dummy = true;
        break;
      case 's':
        stop = std::string(option_arg);
        break;
      case 'n':
        notify = std::string(option_arg);
        break;
      case 'p':
        pass = std::string(option_arg);
        break;
      case 't':
        only_target_values = true;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }
      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      stop.clear();
      notify.clear();
      pass.clear();
      only_target_values = false;
      do_clear = false;
      dummy = false;
    }

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

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

    std::string stop;
    std::string notify;
    std::string pass;
    bool only_target_values = false;
    bool do_clear = false;
    bool dummy = false;
  };

  CommandObjectProcessHandle(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "process handle",
                            "Manage LLDB handling of OS signals for the "
                            "current target process.  Defaults to showing "
                            "current policy.",
                            nullptr) {
    SetHelpLong("\nIf no signals are specified but one or more actions are, "
                "and there is a live process, update them all.  If no action "
                "is specified, list the current values.\n"
                "If you specify actions with no target (e.g. in an init file) "
                "or in a target with no process "
                "the values will get copied into subsequent targets, but "
                "lldb won't be able to spell-check the options since it can't "
                "know which signal set will later be in force."
                "\nYou can see the signal modifications held by the target"
                "by passing the -t option."
                "\nYou can also clear the target modification for a signal"
                "by passing the -c option");
    AddSimpleArgumentList(eArgTypeUnixSignal, eArgRepeatStar);
  }

  ~CommandObjectProcessHandle() override = default;

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

  void PrintSignalHeader(Stream &str) {
    str.Printf("NAME         PASS   STOP   NOTIFY\n");
    str.Printf("===========  =====  =====  ======\n");
  }

  void PrintSignal(Stream &str, int32_t signo, llvm::StringRef sig_name,
                   const UnixSignalsSP &signals_sp) {
    bool stop;
    bool suppress;
    bool notify;

    str.Format("{0, -11}  ", sig_name);
    if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) {
      bool pass = !suppress;
      str.Printf("%s  %s  %s", (pass ? "true " : "false"),
                 (stop ? "true " : "false"), (notify ? "true " : "false"));
    }
    str.Printf("\n");
  }

  void PrintSignalInformation(Stream &str, Args &signal_args,
                              int num_valid_signals,
                              const UnixSignalsSP &signals_sp) {
    PrintSignalHeader(str);

    if (num_valid_signals > 0) {
      size_t num_args = signal_args.GetArgumentCount();
      for (size_t i = 0; i < num_args; ++i) {
        int32_t signo = signals_sp->GetSignalNumberFromName(
            signal_args.GetArgumentAtIndex(i));
        if (signo != LLDB_INVALID_SIGNAL_NUMBER)
          PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i),
                      signals_sp);
      }
    } else // Print info for ALL signals
    {
      int32_t signo = signals_sp->GetFirstSignalNumber();
      while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
        PrintSignal(str, signo, signals_sp->GetSignalAsStringRef(signo),
                    signals_sp);
        signo = signals_sp->GetNextSignalNumber(signo);
      }
    }
  }

protected:
  void DoExecute(Args &signal_args, CommandReturnObject &result) override {
    Target &target = GetTarget();

    // Any signals that are being set should be added to the Target's
    // DummySignals so they will get applied on rerun, etc.
    // If we have a process, however, we can do a more accurate job of vetting
    // the user's options.
    ProcessSP process_sp = target.GetProcessSP();

    std::optional<bool> stop_action = {};
    std::optional<bool> pass_action = {};
    std::optional<bool> notify_action = {};

    if (!m_options.stop.empty()) {
      bool success = false;
      bool value = OptionArgParser::ToBoolean(m_options.stop, false, &success);
      if (!success) {
        result.AppendError(
            "Invalid argument for command option --stop; must be "
            "true or false.\n");
        return;
      }

      stop_action = value;
    }

    if (!m_options.pass.empty()) {
      bool success = false;
      bool value = OptionArgParser::ToBoolean(m_options.pass, false, &success);
      if (!success) {
        result.AppendError(
            "Invalid argument for command option --pass; must be "
            "true or false.\n");
        return;
      }
      pass_action = value;
    }

    if (!m_options.notify.empty()) {
      bool success = false;
      bool value =
          OptionArgParser::ToBoolean(m_options.notify, false, &success);
      if (!success) {
        result.AppendError("Invalid argument for command option --notify; must "
                           "be true or false.\n");
        return;
      }
      notify_action = value;
    }

    if (!m_options.notify.empty() && !notify_action.has_value()) {
    }

    bool no_actions = (!stop_action.has_value() && !pass_action.has_value() &&
                       !notify_action.has_value());
    if (m_options.only_target_values && !no_actions) {
      result.AppendError("-t is for reporting, not setting, target values.");
      return;
    }

    size_t num_args = signal_args.GetArgumentCount();
    UnixSignalsSP signals_sp;
    if (process_sp)
      signals_sp = process_sp->GetUnixSignals();

    int num_signals_set = 0;

    // If we were just asked to print the target values, do that here and
    // return:
    if (m_options.only_target_values) {
      target.PrintDummySignals(result.GetOutputStream(), signal_args);
      result.SetStatus(eReturnStatusSuccessFinishResult);
      return;
    }

    // This handles clearing values:
    if (m_options.do_clear) {
      target.ClearDummySignals(signal_args);
      if (m_options.dummy)
        GetDummyTarget().ClearDummySignals(signal_args);
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
      return;
    }

    // This rest handles setting values:
    if (num_args > 0) {
      for (const auto &arg : signal_args) {
        // Do the process first.  If we have a process we can catch
        // invalid signal names, which we do here.
        if (signals_sp) {
          int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
          if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
            if (stop_action.has_value())
              signals_sp->SetShouldStop(signo, *stop_action);
            if (pass_action.has_value()) {
              bool suppress = !*pass_action;
              signals_sp->SetShouldSuppress(signo, suppress);
            }
            if (notify_action.has_value())
              signals_sp->SetShouldNotify(signo, *notify_action);
            ++num_signals_set;
          } else {
            result.AppendErrorWithFormat("Invalid signal name '%s'\n",
                                          arg.c_str());
            continue;
          }
        } else {
          // If there's no process we can't check, so we just set them all.
          // But since the map signal name -> signal number across all platforms
          // is not 1-1, we can't sensibly set signal actions by number before
          // we have a process.  Check that here:
          int32_t signo;
          if (llvm::to_integer(arg.c_str(), signo)) {
            result.AppendErrorWithFormat("Can't set signal handling by signal "
                                         "number with no process");
            return;
          }
         num_signals_set = num_args;
        }
        auto set_lazy_bool = [](std::optional<bool> action) -> LazyBool {
          if (!action.has_value())
            return eLazyBoolCalculate;
          return (*action) ? eLazyBoolYes : eLazyBoolNo;
        };

        // If there were no actions, we're just listing, don't add the dummy:
        if (!no_actions)
          target.AddDummySignal(arg.ref(), set_lazy_bool(pass_action),
                                set_lazy_bool(notify_action),
                                set_lazy_bool(stop_action));
      }
    } else {
      // No signal specified, if any command options were specified, update ALL
      // signals.  But we can't do this without a process since we don't know
      // all the possible signals that might be valid for this target.
      if ((notify_action.has_value() || stop_action.has_value() ||
           pass_action.has_value()) &&
          process_sp) {
        if (m_interpreter.Confirm(
                "Do you really want to update all the signals?", false)) {
          int32_t signo = signals_sp->GetFirstSignalNumber();
          while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
            if (notify_action.has_value())
              signals_sp->SetShouldNotify(signo, *notify_action);
            if (stop_action.has_value())
              signals_sp->SetShouldStop(signo, *stop_action);
            if (pass_action.has_value()) {
              bool suppress = !*pass_action;
              signals_sp->SetShouldSuppress(signo, suppress);
            }
            signo = signals_sp->GetNextSignalNumber(signo);
          }
        }
      }
    }

    if (signals_sp)
      PrintSignalInformation(result.GetOutputStream(), signal_args,
                             num_signals_set, signals_sp);
    else
      target.PrintDummySignals(result.GetOutputStream(),
          signal_args);

    if (num_signals_set > 0)
      result.SetStatus(eReturnStatusSuccessFinishResult);
    else
      result.SetStatus(eReturnStatusFailed);
  }

  CommandOptions m_options;
};

// Next are the subcommands of CommandObjectMultiwordProcessTrace

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

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

// CommandObjectProcessTraceStop
class CommandObjectProcessTraceStop : public CommandObjectParsed {
public:
  CommandObjectProcessTraceStop(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "process trace stop",
                            "Stop tracing this process. This does not affect "
                            "traces started with the "
                            "\"thread trace start\" command.",
                            "process trace stop",
                            eCommandRequiresProcess | eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched |
                                eCommandProcessMustBePaused |
                                eCommandProcessMustBeTraced) {}

  ~CommandObjectProcessTraceStop() override = default;

  void DoExecute(Args &command, CommandReturnObject &result) override {
    ProcessSP process_sp = m_exe_ctx.GetProcessSP();

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

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

// CommandObjectMultiwordProcessTrace
class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword {
public:
  CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "trace", "Commands for tracing the current process.",
            "process trace <subcommand> [<subcommand objects>]") {
    LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart(
                                interpreter)));
    LoadSubCommand("stop", CommandObjectSP(
                               new CommandObjectProcessTraceStop(interpreter)));
  }

  ~CommandObjectMultiwordProcessTrace() override = default;
};

// CommandObjectMultiwordProcess

CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(
    CommandInterpreter &interpreter)
    : CommandObjectMultiword(
          interpreter, "process",
          "Commands for interacting with processes on the current platform.",
          "process <subcommand> [<subcommand-options>]") {
  LoadSubCommand("attach",
                 CommandObjectSP(new CommandObjectProcessAttach(interpreter)));
  LoadSubCommand("launch",
                 CommandObjectSP(new CommandObjectProcessLaunch(interpreter)));
  LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue(
                                 interpreter)));
  LoadSubCommand("connect",
                 CommandObjectSP(new CommandObjectProcessConnect(interpreter)));
  LoadSubCommand("detach",
                 CommandObjectSP(new CommandObjectProcessDetach(interpreter)));
  LoadSubCommand("load",
                 CommandObjectSP(new CommandObjectProcessLoad(interpreter)));
  LoadSubCommand("unload",
                 CommandObjectSP(new CommandObjectProcessUnload(interpreter)));
  LoadSubCommand("signal",
                 CommandObjectSP(new CommandObjectProcessSignal(interpreter)));
  LoadSubCommand("handle",
                 CommandObjectSP(new CommandObjectProcessHandle(interpreter)));
  LoadSubCommand("status",
                 CommandObjectSP(new CommandObjectProcessStatus(interpreter)));
  LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt(
                                  interpreter)));
  LoadSubCommand("kill",
                 CommandObjectSP(new CommandObjectProcessKill(interpreter)));
  LoadSubCommand("plugin",
                 CommandObjectSP(new CommandObjectProcessPlugin(interpreter)));
  LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore(
                                  interpreter)));
  LoadSubCommand(
      "trace",
      CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter)));
}

CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default;
