//===-- CommandObjectTarget.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 "CommandObjectTarget.h"

#include "lldb/Core/Address.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/DataFormatters/ValueObjectPrinter.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/OptionGroupArchitecture.h"
#include "lldb/Interpreter/OptionGroupBoolean.h"
#include "lldb/Interpreter/OptionGroupFile.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionGroupPlatform.h"
#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
#include "lldb/Interpreter/OptionGroupString.h"
#include "lldb/Interpreter/OptionGroupUInt64.h"
#include "lldb/Interpreter/OptionGroupUUID.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Interpreter/OptionGroupVariable.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/State.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/Timer.h"
#include "lldb/ValueObject/ValueObjectVariable.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private-enumerations.h"

#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Serialization/ObjectFilePCHContainerReader.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatAdapters.h"


using namespace lldb;
using namespace lldb_private;

static void DumpTargetInfo(uint32_t target_idx, Target *target,
                           const char *prefix_cstr,
                           bool show_stopped_process_status, Stream &strm) {
  const ArchSpec &target_arch = target->GetArchitecture();

  Module *exe_module = target->GetExecutableModulePointer();
  char exe_path[PATH_MAX];
  bool exe_valid = false;
  if (exe_module)
    exe_valid = exe_module->GetFileSpec().GetPath(exe_path, sizeof(exe_path));

  if (!exe_valid)
    ::strcpy(exe_path, "<none>");

  std::string formatted_label = "";
  const std::string &label = target->GetLabel();
  if (!label.empty()) {
    formatted_label = " (" + label + ")";
  }

  strm.Printf("%starget #%u%s: %s", prefix_cstr ? prefix_cstr : "", target_idx,
              formatted_label.data(), exe_path);

  uint32_t properties = 0;
  if (target_arch.IsValid()) {
    strm.Printf(" ( arch=");
    target_arch.DumpTriple(strm.AsRawOstream());
    properties++;
  }
  PlatformSP platform_sp(target->GetPlatform());
  if (platform_sp)
    strm.Format("{0}platform={1}", properties++ > 0 ? ", " : " ( ",
                platform_sp->GetName());

  ProcessSP process_sp(target->GetProcessSP());
  bool show_process_status = false;
  if (process_sp) {
    lldb::pid_t pid = process_sp->GetID();
    StateType state = process_sp->GetState();
    if (show_stopped_process_status)
      show_process_status = StateIsStoppedState(state, true);
    const char *state_cstr = StateAsCString(state);
    if (pid != LLDB_INVALID_PROCESS_ID)
      strm.Printf("%spid=%" PRIu64, properties++ > 0 ? ", " : " ( ", pid);
    strm.Printf("%sstate=%s", properties++ > 0 ? ", " : " ( ", state_cstr);
  }
  if (properties > 0)
    strm.PutCString(" )\n");
  else
    strm.EOL();
  if (show_process_status) {
    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 = false;
    process_sp->GetStatus(strm);
    process_sp->GetThreadStatus(strm, only_threads_with_stop_reason,
                                start_frame, num_frames, num_frames_with_source,
                                stop_format);
  }
}

static uint32_t DumpTargetList(TargetList &target_list,
                               bool show_stopped_process_status, Stream &strm) {
  const uint32_t num_targets = target_list.GetNumTargets();
  if (num_targets) {
    TargetSP selected_target_sp(target_list.GetSelectedTarget());
    strm.PutCString("Current targets:\n");
    for (uint32_t i = 0; i < num_targets; ++i) {
      TargetSP target_sp(target_list.GetTargetAtIndex(i));
      if (target_sp) {
        bool is_selected = target_sp.get() == selected_target_sp.get();
        DumpTargetInfo(i, target_sp.get(), is_selected ? "* " : "  ",
                       show_stopped_process_status, strm);
      }
    }
  }
  return num_targets;
}

#define LLDB_OPTIONS_target_dependents
#include "CommandOptions.inc"

class OptionGroupDependents : public OptionGroup {
public:
  OptionGroupDependents() = default;

  ~OptionGroupDependents() override = default;

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

  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
                        ExecutionContext *execution_context) override {
    Status error;

    // For compatibility no value means don't load dependents.
    if (option_value.empty()) {
      m_load_dependent_files = eLoadDependentsNo;
      return error;
    }

    const char short_option =
        g_target_dependents_options[option_idx].short_option;
    if (short_option == 'd') {
      LoadDependentFiles tmp_load_dependents;
      tmp_load_dependents = (LoadDependentFiles)OptionArgParser::ToOptionEnum(
          option_value, g_target_dependents_options[option_idx].enum_values, 0,
          error);
      if (error.Success())
        m_load_dependent_files = tmp_load_dependents;
    } else {
      error = Status::FromErrorStringWithFormat(
          "unrecognized short option '%c'", short_option);
    }

    return error;
  }

  Status SetOptionValue(uint32_t, const char *, ExecutionContext *) = delete;

  void OptionParsingStarting(ExecutionContext *execution_context) override {
    m_load_dependent_files = eLoadDependentsDefault;
  }

  LoadDependentFiles m_load_dependent_files;

private:
  OptionGroupDependents(const OptionGroupDependents &) = delete;
  const OptionGroupDependents &
  operator=(const OptionGroupDependents &) = delete;
};

#pragma mark CommandObjectTargetCreate

class CommandObjectTargetCreate : public CommandObjectParsed {
public:
  CommandObjectTargetCreate(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "target create",
            "Create a target using the argument as the main executable.",
            nullptr),
        m_platform_options(true), // Include the --platform option.
        m_core_file(LLDB_OPT_SET_1, false, "core", 'c', 0, eArgTypeFilename,
                    "Fullpath to a core file to use for this target."),
        m_label(LLDB_OPT_SET_1, false, "label", 'l', 0, eArgTypeName,
                "Optional name for this target.", nullptr),
        m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
                      eArgTypeFilename,
                      "Fullpath to a stand alone debug "
                      "symbols file for when debug symbols "
                      "are not in the executable."),
        m_remote_file(
            LLDB_OPT_SET_1, false, "remote-file", 'r', 0, eArgTypeFilename,
            "Fullpath to the file on the remote host if debugging remotely.") {

    AddSimpleArgumentList(eArgTypeFilename);

    m_option_group.Append(&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1);
    m_option_group.Append(&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_label, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_remote_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_add_dependents, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Finalize();
  }

  ~CommandObjectTargetCreate() override = default;

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

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    FileSpec core_file(m_core_file.GetOptionValue().GetCurrentValue());
    FileSpec remote_file(m_remote_file.GetOptionValue().GetCurrentValue());

    if (core_file) {
      auto file = FileSystem::Instance().Open(
          core_file, lldb_private::File::eOpenOptionReadOnly);

      if (!file) {
        result.AppendErrorWithFormatv("Cannot open '{0}': {1}.",
                                      core_file.GetPath(),
                                      llvm::toString(file.takeError()));
        return;
      }
    }

    if (argc == 1 || core_file || remote_file) {
      FileSpec symfile(m_symbol_file.GetOptionValue().GetCurrentValue());
      if (symfile) {
        auto file = FileSystem::Instance().Open(
            symfile, lldb_private::File::eOpenOptionReadOnly);

        if (!file) {
          result.AppendErrorWithFormatv("Cannot open '{0}': {1}.",
                                        symfile.GetPath(),
                                        llvm::toString(file.takeError()));
          return;
        }
      }

      const char *file_path = command.GetArgumentAtIndex(0);
      LLDB_SCOPED_TIMERF("(lldb) target create '%s'", file_path);

      bool must_set_platform_path = false;

      Debugger &debugger = GetDebugger();

      TargetSP target_sp;
      llvm::StringRef arch_cstr = m_arch_option.GetArchitectureName();
      Status error(debugger.GetTargetList().CreateTarget(
          debugger, file_path, arch_cstr,
          m_add_dependents.m_load_dependent_files, &m_platform_options,
          target_sp));

      if (!target_sp) {
        result.AppendError(error.AsCString());
        return;
      }

      const llvm::StringRef label =
          m_label.GetOptionValue().GetCurrentValueAsRef();
      if (!label.empty()) {
        if (auto E = target_sp->SetLabel(label))
          result.SetError(std::move(E));
        return;
      }

      auto on_error = llvm::make_scope_exit(
          [&target_list = debugger.GetTargetList(), &target_sp]() {
            target_list.DeleteTarget(target_sp);
          });

      // Only get the platform after we create the target because we might
      // have switched platforms depending on what the arguments were to
      // CreateTarget() we can't rely on the selected platform.

      PlatformSP platform_sp = target_sp->GetPlatform();

      FileSpec file_spec;
      if (file_path) {
        file_spec.SetFile(file_path, FileSpec::Style::native);
        FileSystem::Instance().Resolve(file_spec);

        // Try to resolve the exe based on PATH and/or platform-specific
        // suffixes, but only if using the host platform.
        if (platform_sp && platform_sp->IsHost() &&
            !FileSystem::Instance().Exists(file_spec))
          FileSystem::Instance().ResolveExecutableLocation(file_spec);
      }

      if (remote_file) {
        if (platform_sp) {
          // I have a remote file.. two possible cases
          if (file_spec && FileSystem::Instance().Exists(file_spec)) {
            // if the remote file does not exist, push it there
            if (!platform_sp->GetFileExists(remote_file)) {
              Status err = platform_sp->PutFile(file_spec, remote_file);
              if (err.Fail()) {
                result.AppendError(err.AsCString());
                return;
              }
            }
          } else {
            // there is no local file and we need one
            // in order to make the remote ---> local transfer we need a
            // platform
            // TODO: if the user has passed in a --platform argument, use it
            // to fetch the right platform
            if (file_path) {
              // copy the remote file to the local file
              Status err = platform_sp->GetFile(remote_file, file_spec);
              if (err.Fail()) {
                result.AppendError(err.AsCString());
                return;
              }
            } else {
              // If the remote file exists, we can debug reading that out of
              // memory.  If the platform is already connected to an lldb-server
              // then we can at least check the file exists remotely.  Otherwise
              // we'll just have to trust that it will be there when we do
              // process connect.
              // I don't do this for the host platform because it seems odd to
              // support supplying a remote file but no local file for a local
              // debug session.
              if (platform_sp->IsHost()) {
                result.AppendError("Supply a local file, not a remote file, "
                                   "when debugging on the host.");
                return;
              }
              if (platform_sp->IsConnected() && !platform_sp->GetFileExists(remote_file)) {
                result.AppendError("remote --> local transfer without local "
                                 "path is not implemented yet");
                return;
              }
              // Since there's only a remote file, we need to set the executable
              // file spec to the remote one.
              ProcessLaunchInfo launch_info = target_sp->GetProcessLaunchInfo();
              launch_info.SetExecutableFile(FileSpec(remote_file), true);
              target_sp->SetProcessLaunchInfo(launch_info);
            }
          }
        } else {
          result.AppendError("no platform found for target");
          return;
        }
      }

      if (symfile || remote_file) {
        ModuleSP module_sp(target_sp->GetExecutableModule());
        if (module_sp) {
          if (symfile)
            module_sp->SetSymbolFileFileSpec(symfile);
          if (remote_file) {
            std::string remote_path = remote_file.GetPath();
            target_sp->SetArg0(remote_path.c_str());
            module_sp->SetPlatformFileSpec(remote_file);
          }
        }
      }

      if (must_set_platform_path) {
        ModuleSpec main_module_spec(file_spec);
        ModuleSP module_sp =
            target_sp->GetOrCreateModule(main_module_spec, true /* notify */);
        if (module_sp)
          module_sp->SetPlatformFileSpec(remote_file);
      }

      if (core_file) {
        FileSpec core_file_dir;
        core_file_dir.SetDirectory(core_file.GetDirectory());
        target_sp->AppendExecutableSearchPaths(core_file_dir);

        ProcessSP process_sp(target_sp->CreateProcess(
            GetDebugger().GetListener(), llvm::StringRef(), &core_file, false));

        if (process_sp) {
          // Seems weird that we Launch a core file, but that is what we
          // do!
          error = process_sp->LoadCore();

          if (error.Fail()) {
            result.AppendError(error.AsCString("unknown core file format"));
            return;
          } else {
            result.AppendMessageWithFormatv(
                "Core file '{0}' ({1}) was loaded.\n", core_file.GetPath(),
                target_sp->GetArchitecture().GetArchitectureName());
            result.SetStatus(eReturnStatusSuccessFinishNoResult);
            on_error.release();
          }
        } else {
          result.AppendErrorWithFormatv("Unknown core file format '{0}'\n",
                                        core_file.GetPath());
        }
      } else {
        result.AppendMessageWithFormat(
            "Current executable set to '%s' (%s).\n",
            file_spec.GetPath().c_str(),
            target_sp->GetArchitecture().GetArchitectureName());
        result.SetStatus(eReturnStatusSuccessFinishNoResult);
        on_error.release();
      }
    } else {
      result.AppendErrorWithFormat("'%s' takes exactly one executable path "
                                   "argument, or use the --core option.\n",
                                   m_cmd_name.c_str());
    }
  }

private:
  OptionGroupOptions m_option_group;
  OptionGroupArchitecture m_arch_option;
  OptionGroupPlatform m_platform_options;
  OptionGroupFile m_core_file;
  OptionGroupString m_label;
  OptionGroupFile m_symbol_file;
  OptionGroupFile m_remote_file;
  OptionGroupDependents m_add_dependents;
};

#pragma mark CommandObjectTargetList

class CommandObjectTargetList : public CommandObjectParsed {
public:
  CommandObjectTargetList(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "target list",
            "List all current targets in the current debug session.", nullptr) {
  }

  ~CommandObjectTargetList() override = default;

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

    bool show_stopped_process_status = false;
    if (DumpTargetList(GetDebugger().GetTargetList(),
                       show_stopped_process_status, strm) == 0) {
      strm.PutCString("No targets.\n");
    }
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

#pragma mark CommandObjectTargetSelect

class CommandObjectTargetSelect : public CommandObjectParsed {
public:
  CommandObjectTargetSelect(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "target select",
            "Select a target as the current target by target index.", nullptr) {
    AddSimpleArgumentList(eArgTypeTargetID);
  }

  ~CommandObjectTargetSelect() override = default;

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    if (args.GetArgumentCount() == 1) {
      const char *target_identifier = args.GetArgumentAtIndex(0);
      uint32_t target_idx = LLDB_INVALID_INDEX32;
      TargetList &target_list = GetDebugger().GetTargetList();
      const uint32_t num_targets = target_list.GetNumTargets();
      if (llvm::to_integer(target_identifier, target_idx)) {
        if (target_idx < num_targets) {
          target_list.SetSelectedTarget(target_idx);
          Stream &strm = result.GetOutputStream();
          bool show_stopped_process_status = false;
          DumpTargetList(target_list, show_stopped_process_status, strm);
          result.SetStatus(eReturnStatusSuccessFinishResult);
        } else {
          if (num_targets > 0) {
            result.AppendErrorWithFormat(
                "index %u is out of range, valid target indexes are 0 - %u\n",
                target_idx, num_targets - 1);
          } else {
            result.AppendErrorWithFormat(
                "index %u is out of range since there are no active targets\n",
                target_idx);
          }
        }
      } else {
        for (size_t i = 0; i < num_targets; i++) {
          if (TargetSP target_sp = target_list.GetTargetAtIndex(i)) {
            const std::string &label = target_sp->GetLabel();
            if (!label.empty() && label == target_identifier) {
              target_idx = i;
              break;
            }
          }
        }

        if (target_idx != LLDB_INVALID_INDEX32) {
          target_list.SetSelectedTarget(target_idx);
          Stream &strm = result.GetOutputStream();
          bool show_stopped_process_status = false;
          DumpTargetList(target_list, show_stopped_process_status, strm);
          result.SetStatus(eReturnStatusSuccessFinishResult);
        } else {
          result.AppendErrorWithFormat("invalid index string value '%s'\n",
                                       target_identifier);
        }
      }
    } else {
      result.AppendError(
          "'target select' takes a single argument: a target index\n");
    }
  }
};

#pragma mark CommandObjectTargetDelete

class CommandObjectTargetDelete : public CommandObjectParsed {
public:
  CommandObjectTargetDelete(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "target delete",
                            "Delete one or more targets by target index.",
                            nullptr),
        m_all_option(LLDB_OPT_SET_1, false, "all", 'a', "Delete all targets.",
                     false, true),
        m_cleanup_option(
            LLDB_OPT_SET_1, false, "clean", 'c',
            "Perform extra cleanup to minimize memory consumption after "
            "deleting the target.  "
            "By default, LLDB will keep in memory any modules previously "
            "loaded by the target as well "
            "as all of its debug info.  Specifying --clean will unload all of "
            "these shared modules and "
            "cause them to be reparsed again the next time the target is run",
            false, true) {
    m_option_group.Append(&m_all_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_cleanup_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Finalize();
    AddSimpleArgumentList(eArgTypeTargetID, eArgRepeatStar);
  }

  ~CommandObjectTargetDelete() override = default;

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

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    const size_t argc = args.GetArgumentCount();
    std::vector<TargetSP> delete_target_list;
    TargetList &target_list = GetDebugger().GetTargetList();
    TargetSP target_sp;

    if (m_all_option.GetOptionValue()) {
      for (size_t i = 0; i < target_list.GetNumTargets(); ++i)
        delete_target_list.push_back(target_list.GetTargetAtIndex(i));
    } else if (argc > 0) {
      const uint32_t num_targets = target_list.GetNumTargets();
      // Bail out if don't have any targets.
      if (num_targets == 0) {
        result.AppendError("no targets to delete");
        return;
      }

      for (auto &entry : args.entries()) {
        uint32_t target_idx;
        if (entry.ref().getAsInteger(0, target_idx)) {
          result.AppendErrorWithFormat("invalid target index '%s'\n",
                                       entry.c_str());
          return;
        }
        if (target_idx < num_targets) {
          target_sp = target_list.GetTargetAtIndex(target_idx);
          if (target_sp) {
            delete_target_list.push_back(target_sp);
            continue;
          }
        }
        if (num_targets > 1)
          result.AppendErrorWithFormat("target index %u is out of range, valid "
                                       "target indexes are 0 - %u\n",
                                       target_idx, num_targets - 1);
        else
          result.AppendErrorWithFormat(
              "target index %u is out of range, the only valid index is 0\n",
              target_idx);

        return;
      }
    } else {
      target_sp = target_list.GetSelectedTarget();
      if (!target_sp) {
        result.AppendErrorWithFormat("no target is currently selected\n");
        return;
      }
      delete_target_list.push_back(target_sp);
    }

    const size_t num_targets_to_delete = delete_target_list.size();
    for (size_t idx = 0; idx < num_targets_to_delete; ++idx) {
      target_sp = delete_target_list[idx];
      target_list.DeleteTarget(target_sp);
      target_sp->Destroy();
    }
    // If "--clean" was specified, prune any orphaned shared modules from the
    // global shared module list
    if (m_cleanup_option.GetOptionValue()) {
      const bool mandatory = true;
      ModuleList::RemoveOrphanSharedModules(mandatory);
    }
    result.GetOutputStream().Printf("%u targets deleted.\n",
                                    (uint32_t)num_targets_to_delete);
    result.SetStatus(eReturnStatusSuccessFinishResult);

    return;
  }

  OptionGroupOptions m_option_group;
  OptionGroupBoolean m_all_option;
  OptionGroupBoolean m_cleanup_option;
};

class CommandObjectTargetShowLaunchEnvironment : public CommandObjectParsed {
public:
  CommandObjectTargetShowLaunchEnvironment(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "target show-launch-environment",
            "Shows the environment being passed to the process when launched, "
            "taking info account 3 settings: target.env-vars, "
            "target.inherit-env and target.unset-env-vars.",
            nullptr, eCommandRequiresTarget) {}

  ~CommandObjectTargetShowLaunchEnvironment() override = default;

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    Target *target = m_exe_ctx.GetTargetPtr();
    Environment env = target->GetEnvironment();

    std::vector<Environment::value_type *> env_vector;
    env_vector.reserve(env.size());
    for (auto &KV : env)
      env_vector.push_back(&KV);
    std::sort(env_vector.begin(), env_vector.end(),
              [](Environment::value_type *a, Environment::value_type *b) {
                return a->first() < b->first();
              });

    auto &strm = result.GetOutputStream();
    for (auto &KV : env_vector)
      strm.Format("{0}={1}\n", KV->first(), KV->second);

    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

#pragma mark CommandObjectTargetVariable

class CommandObjectTargetVariable : public CommandObjectParsed {
  static const uint32_t SHORT_OPTION_FILE = 0x66696c65; // 'file'
  static const uint32_t SHORT_OPTION_SHLB = 0x73686c62; // 'shlb'

public:
  CommandObjectTargetVariable(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "target variable",
                            "Read global variables for the current target, "
                            "before or while running a process.",
                            nullptr, eCommandRequiresTarget),
        m_option_variable(false), // Don't include frame options
        m_option_format(eFormatDefault),
        m_option_compile_units(LLDB_OPT_SET_1, false, "file", SHORT_OPTION_FILE,
                               0, eArgTypeFilename,
                               "A basename or fullpath to a file that contains "
                               "global variables. This option can be "
                               "specified multiple times."),
        m_option_shared_libraries(
            LLDB_OPT_SET_1, false, "shlib", SHORT_OPTION_SHLB, 0,
            eArgTypeFilename,
            "A basename or fullpath to a shared library to use in the search "
            "for global "
            "variables. This option can be specified multiple times.") {
    AddSimpleArgumentList(eArgTypeVarName, eArgRepeatPlus);

    m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_option_format,
                          OptionGroupFormat::OPTION_GROUP_FORMAT |
                              OptionGroupFormat::OPTION_GROUP_GDB_FMT,
                          LLDB_OPT_SET_1);
    m_option_group.Append(&m_option_compile_units, LLDB_OPT_SET_ALL,
                          LLDB_OPT_SET_1);
    m_option_group.Append(&m_option_shared_libraries, LLDB_OPT_SET_ALL,
                          LLDB_OPT_SET_1);
    m_option_group.Finalize();
  }

  ~CommandObjectTargetVariable() override = default;

  void DumpValueObject(Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp,
                       const char *root_name) {
    DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions());

    if (!valobj_sp->GetTargetSP()->GetDisplayRuntimeSupportValues() &&
        valobj_sp->IsRuntimeSupportValue())
      return;

    switch (var_sp->GetScope()) {
    case eValueTypeVariableGlobal:
      if (m_option_variable.show_scope)
        s.PutCString("GLOBAL: ");
      break;

    case eValueTypeVariableStatic:
      if (m_option_variable.show_scope)
        s.PutCString("STATIC: ");
      break;

    case eValueTypeVariableArgument:
      if (m_option_variable.show_scope)
        s.PutCString("   ARG: ");
      break;

    case eValueTypeVariableLocal:
      if (m_option_variable.show_scope)
        s.PutCString(" LOCAL: ");
      break;

    case eValueTypeVariableThreadLocal:
      if (m_option_variable.show_scope)
        s.PutCString("THREAD: ");
      break;

    default:
      break;
    }

    if (m_option_variable.show_decl) {
      bool show_fullpaths = false;
      bool show_module = true;
      if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module))
        s.PutCString(": ");
    }

    const Format format = m_option_format.GetFormat();
    if (format != eFormatDefault)
      options.SetFormat(format);

    options.SetRootValueObjectName(root_name);

    if (llvm::Error error = valobj_sp->Dump(s, options))
      s << "error: " << toString(std::move(error));
  }

  static size_t GetVariableCallback(void *baton, const char *name,
                                    VariableList &variable_list) {
    size_t old_size = variable_list.GetSize();
    Target *target = static_cast<Target *>(baton);
    if (target)
      target->GetImages().FindGlobalVariables(ConstString(name), UINT32_MAX,
                                              variable_list);
    return variable_list.GetSize() - old_size;
  }

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

protected:
  void DumpGlobalVariableList(const ExecutionContext &exe_ctx,
                              const SymbolContext &sc,
                              const VariableList &variable_list,
                              CommandReturnObject &result) {
    Stream &s = result.GetOutputStream();
    if (variable_list.Empty())
      return;
    if (sc.module_sp) {
      if (sc.comp_unit) {
        s.Format("Global variables for {0} in {1}:\n",
                 sc.comp_unit->GetPrimaryFile(), sc.module_sp->GetFileSpec());
      } else {
        s.Printf("Global variables for %s\n",
                 sc.module_sp->GetFileSpec().GetPath().c_str());
      }
    } else if (sc.comp_unit) {
      s.Format("Global variables for {0}\n", sc.comp_unit->GetPrimaryFile());
    }

    for (VariableSP var_sp : variable_list) {
      if (!var_sp)
        continue;
      ValueObjectSP valobj_sp(ValueObjectVariable::Create(
          exe_ctx.GetBestExecutionContextScope(), var_sp));

      if (valobj_sp) {
        result.GetValueObjectList().Append(valobj_sp);
        DumpValueObject(s, var_sp, valobj_sp, var_sp->GetName().GetCString());
      }
    }
  }

  void DoExecute(Args &args, CommandReturnObject &result) override {
    Target *target = m_exe_ctx.GetTargetPtr();
    const size_t argc = args.GetArgumentCount();

    if (argc > 0) {
      for (const Args::ArgEntry &arg : args) {
        VariableList variable_list;
        ValueObjectList valobj_list;

        size_t matches = 0;
        bool use_var_name = false;
        if (m_option_variable.use_regex) {
          RegularExpression regex(arg.ref());
          if (!regex.IsValid()) {
            result.GetErrorStream().Printf(
                "error: invalid regular expression: '%s'\n", arg.c_str());
            return;
          }
          use_var_name = true;
          target->GetImages().FindGlobalVariables(regex, UINT32_MAX,
                                                  variable_list);
          matches = variable_list.GetSize();
        } else {
          Status error(Variable::GetValuesForVariableExpressionPath(
              arg.c_str(), m_exe_ctx.GetBestExecutionContextScope(),
              GetVariableCallback, target, variable_list, valobj_list));
          matches = variable_list.GetSize();
        }

        if (matches == 0) {
          result.AppendErrorWithFormat("can't find global variable '%s'",
                                       arg.c_str());
          return;
        } else {
          for (uint32_t global_idx = 0; global_idx < matches; ++global_idx) {
            VariableSP var_sp(variable_list.GetVariableAtIndex(global_idx));
            if (var_sp) {
              ValueObjectSP valobj_sp(
                  valobj_list.GetValueObjectAtIndex(global_idx));
              if (!valobj_sp)
                valobj_sp = ValueObjectVariable::Create(
                    m_exe_ctx.GetBestExecutionContextScope(), var_sp);

              if (valobj_sp)
                DumpValueObject(result.GetOutputStream(), var_sp, valobj_sp,
                                use_var_name ? var_sp->GetName().GetCString()
                                             : arg.c_str());
            }
          }
        }
      }
    } else {
      const FileSpecList &compile_units =
          m_option_compile_units.GetOptionValue().GetCurrentValue();
      const FileSpecList &shlibs =
          m_option_shared_libraries.GetOptionValue().GetCurrentValue();
      SymbolContextList sc_list;
      const size_t num_compile_units = compile_units.GetSize();
      const size_t num_shlibs = shlibs.GetSize();
      if (num_compile_units == 0 && num_shlibs == 0) {
        bool success = false;
        StackFrame *frame = m_exe_ctx.GetFramePtr();
        CompileUnit *comp_unit = nullptr;
        if (frame) {
          SymbolContext sc = frame->GetSymbolContext(eSymbolContextCompUnit);
          comp_unit = sc.comp_unit;
          if (sc.comp_unit) {
            const bool can_create = true;
            VariableListSP comp_unit_varlist_sp(
                sc.comp_unit->GetVariableList(can_create));
            if (comp_unit_varlist_sp) {
              size_t count = comp_unit_varlist_sp->GetSize();
              if (count > 0) {
                DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp,
                                       result);
                success = true;
              }
            }
          }
        }
        if (!success) {
          if (frame) {
            if (comp_unit)
              result.AppendErrorWithFormatv(
                  "no global variables in current compile unit: {0}\n",
                  comp_unit->GetPrimaryFile());
            else
              result.AppendErrorWithFormat(
                  "no debug information for frame %u\n",
                  frame->GetFrameIndex());
          } else
            result.AppendError("'target variable' takes one or more global "
                               "variable names as arguments\n");
        }
      } else {
        SymbolContextList sc_list;
        // We have one or more compile unit or shlib
        if (num_shlibs > 0) {
          for (size_t shlib_idx = 0; shlib_idx < num_shlibs; ++shlib_idx) {
            const FileSpec module_file(shlibs.GetFileSpecAtIndex(shlib_idx));
            ModuleSpec module_spec(module_file);

            ModuleSP module_sp(
                target->GetImages().FindFirstModule(module_spec));
            if (module_sp) {
              if (num_compile_units > 0) {
                for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
                  module_sp->FindCompileUnits(
                      compile_units.GetFileSpecAtIndex(cu_idx), sc_list);
              } else {
                SymbolContext sc;
                sc.module_sp = module_sp;
                sc_list.Append(sc);
              }
            } else {
              // Didn't find matching shlib/module in target...
              result.AppendErrorWithFormat(
                  "target doesn't contain the specified shared library: %s\n",
                  module_file.GetPath().c_str());
            }
          }
        } else {
          // No shared libraries, we just want to find globals for the compile
          // units files that were specified
          for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
            target->GetImages().FindCompileUnits(
                compile_units.GetFileSpecAtIndex(cu_idx), sc_list);
        }

        for (const SymbolContext &sc : sc_list) {
          if (sc.comp_unit) {
            const bool can_create = true;
            VariableListSP comp_unit_varlist_sp(
                sc.comp_unit->GetVariableList(can_create));
            if (comp_unit_varlist_sp)
              DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp,
                                     result);
          } else if (sc.module_sp) {
            // Get all global variables for this module
            lldb_private::RegularExpression all_globals_regex(
                llvm::StringRef(".")); // Any global with at least one character
            VariableList variable_list;
            sc.module_sp->FindGlobalVariables(all_globals_regex, UINT32_MAX,
                                              variable_list);
            DumpGlobalVariableList(m_exe_ctx, sc, variable_list, result);
          }
        }
      }
    }

    m_interpreter.PrintWarningsIfNecessary(result.GetOutputStream(),
                                           m_cmd_name);
  }

  OptionGroupOptions m_option_group;
  OptionGroupVariable m_option_variable;
  OptionGroupFormat m_option_format;
  OptionGroupFileList m_option_compile_units;
  OptionGroupFileList m_option_shared_libraries;
  OptionGroupValueObjectDisplay m_varobj_options;
};

#pragma mark CommandObjectTargetModulesSearchPathsAdd

class CommandObjectTargetModulesSearchPathsAdd : public CommandObjectParsed {
public:
  CommandObjectTargetModulesSearchPathsAdd(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "target modules search-paths add",
                            "Add new image search paths substitution pairs to "
                            "the current target.",
                            nullptr, eCommandRequiresTarget) {
    CommandArgumentEntry arg;
    CommandArgumentData old_prefix_arg;
    CommandArgumentData new_prefix_arg;

    // Define the first variant of this arg pair.
    old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
    old_prefix_arg.arg_repetition = eArgRepeatPairPlus;

    // Define the first variant of this arg pair.
    new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
    new_prefix_arg.arg_repetition = eArgRepeatPairPlus;

    // There are two required arguments that must always occur together, i.e.
    // an argument "pair".  Because they must always occur together, they are
    // treated as two variants of one argument rather than two independent
    // arguments.  Push them both into the first argument position for
    // m_arguments...

    arg.push_back(old_prefix_arg);
    arg.push_back(new_prefix_arg);

    m_arguments.push_back(arg);
  }

  ~CommandObjectTargetModulesSearchPathsAdd() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Target &target = GetTarget();
    const size_t argc = command.GetArgumentCount();
    if (argc & 1) {
      result.AppendError("add requires an even number of arguments\n");
    } else {
      for (size_t i = 0; i < argc; i += 2) {
        const char *from = command.GetArgumentAtIndex(i);
        const char *to = command.GetArgumentAtIndex(i + 1);

        if (from[0] && to[0]) {
          Log *log = GetLog(LLDBLog::Host);
          if (log) {
            LLDB_LOGF(log,
                      "target modules search path adding ImageSearchPath "
                      "pair: '%s' -> '%s'",
                      from, to);
          }
          bool last_pair = ((argc - i) == 2);
          target.GetImageSearchPathList().Append(
              from, to, last_pair); // Notify if this is the last pair
          result.SetStatus(eReturnStatusSuccessFinishNoResult);
        } else {
          if (from[0])
            result.AppendError("<path-prefix> can't be empty\n");
          else
            result.AppendError("<new-path-prefix> can't be empty\n");
        }
      }
    }
  }
};

#pragma mark CommandObjectTargetModulesSearchPathsClear

class CommandObjectTargetModulesSearchPathsClear : public CommandObjectParsed {
public:
  CommandObjectTargetModulesSearchPathsClear(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "target modules search-paths clear",
                            "Clear all current image search path substitution "
                            "pairs from the current target.",
                            "target modules search-paths clear",
                            eCommandRequiresTarget) {}

  ~CommandObjectTargetModulesSearchPathsClear() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Target &target = GetTarget();
    bool notify = true;
    target.GetImageSearchPathList().Clear(notify);
    result.SetStatus(eReturnStatusSuccessFinishNoResult);
  }
};

#pragma mark CommandObjectTargetModulesSearchPathsInsert

class CommandObjectTargetModulesSearchPathsInsert : public CommandObjectParsed {
public:
  CommandObjectTargetModulesSearchPathsInsert(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "target modules search-paths insert",
                            "Insert a new image search path substitution pair "
                            "into the current target at the specified index.",
                            nullptr, eCommandRequiresTarget) {
    CommandArgumentEntry arg1;
    CommandArgumentEntry arg2;
    CommandArgumentData index_arg;
    CommandArgumentData old_prefix_arg;
    CommandArgumentData new_prefix_arg;

    // Define the first and only variant of this arg.
    index_arg.arg_type = eArgTypeIndex;
    index_arg.arg_repetition = eArgRepeatPlain;

    // Put the one and only variant into the first arg for m_arguments:
    arg1.push_back(index_arg);

    // Define the first variant of this arg pair.
    old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
    old_prefix_arg.arg_repetition = eArgRepeatPairPlus;

    // Define the first variant of this arg pair.
    new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
    new_prefix_arg.arg_repetition = eArgRepeatPairPlus;

    // There are two required arguments that must always occur together, i.e.
    // an argument "pair".  Because they must always occur together, they are
    // treated as two variants of one argument rather than two independent
    // arguments.  Push them both into the same argument position for
    // m_arguments...

    arg2.push_back(old_prefix_arg);
    arg2.push_back(new_prefix_arg);

    // Add arguments to m_arguments.
    m_arguments.push_back(arg1);
    m_arguments.push_back(arg2);
  }

  ~CommandObjectTargetModulesSearchPathsInsert() override = default;

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

    Target *target = m_exe_ctx.GetTargetPtr();
    const PathMappingList &list = target->GetImageSearchPathList();
    const size_t num = list.GetSize();
    ConstString old_path, new_path;
    for (size_t i = 0; i < num; ++i) {
      if (!list.GetPathsAtIndex(i, old_path, new_path))
        break;
      StreamString strm;
      strm << old_path << " -> " << new_path;
      request.TryCompleteCurrentArg(std::to_string(i), strm.GetString());
    }
  }

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Target &target = GetTarget();
    size_t argc = command.GetArgumentCount();
    // check for at least 3 arguments and an odd number of parameters
    if (argc >= 3 && argc & 1) {
      uint32_t insert_idx;

      if (!llvm::to_integer(command.GetArgumentAtIndex(0), insert_idx)) {
        result.AppendErrorWithFormat(
            "<index> parameter is not an integer: '%s'.\n",
            command.GetArgumentAtIndex(0));
        return;
      }

      // shift off the index
      command.Shift();
      argc = command.GetArgumentCount();

      for (uint32_t i = 0; i < argc; i += 2, ++insert_idx) {
        const char *from = command.GetArgumentAtIndex(i);
        const char *to = command.GetArgumentAtIndex(i + 1);

        if (from[0] && to[0]) {
          bool last_pair = ((argc - i) == 2);
          target.GetImageSearchPathList().Insert(from, to, insert_idx,
                                                 last_pair);
          result.SetStatus(eReturnStatusSuccessFinishNoResult);
        } else {
          if (from[0])
            result.AppendError("<path-prefix> can't be empty\n");
          else
            result.AppendError("<new-path-prefix> can't be empty\n");
          return;
        }
      }
    } else {
      result.AppendError("insert requires at least three arguments\n");
    }
  }
};

#pragma mark CommandObjectTargetModulesSearchPathsList

class CommandObjectTargetModulesSearchPathsList : public CommandObjectParsed {
public:
  CommandObjectTargetModulesSearchPathsList(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "target modules search-paths list",
                            "List all current image search path substitution "
                            "pairs in the current target.",
                            "target modules search-paths list",
                            eCommandRequiresTarget) {}

  ~CommandObjectTargetModulesSearchPathsList() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Target &target = GetTarget();
    target.GetImageSearchPathList().Dump(&result.GetOutputStream());
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

#pragma mark CommandObjectTargetModulesSearchPathsQuery

class CommandObjectTargetModulesSearchPathsQuery : public CommandObjectParsed {
public:
  CommandObjectTargetModulesSearchPathsQuery(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "target modules search-paths query",
            "Transform a path using the first applicable image search path.",
            nullptr, eCommandRequiresTarget) {
    AddSimpleArgumentList(eArgTypeDirectoryName);
  }

  ~CommandObjectTargetModulesSearchPathsQuery() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Target &target = GetTarget();
    if (command.GetArgumentCount() != 1) {
      result.AppendError("query requires one argument\n");
      return;
    }

    ConstString orig(command.GetArgumentAtIndex(0));
    ConstString transformed;
    if (target.GetImageSearchPathList().RemapPath(orig, transformed))
      result.GetOutputStream().Printf("%s\n", transformed.GetCString());
    else
      result.GetOutputStream().Printf("%s\n", orig.GetCString());

    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

// Static Helper functions
static void DumpModuleArchitecture(Stream &strm, Module *module,
                                   bool full_triple, uint32_t width) {
  if (module) {
    StreamString arch_strm;

    if (full_triple)
      module->GetArchitecture().DumpTriple(arch_strm.AsRawOstream());
    else
      arch_strm.PutCString(module->GetArchitecture().GetArchitectureName());
    std::string arch_str = std::string(arch_strm.GetString());

    if (width)
      strm.Printf("%-*s", width, arch_str.c_str());
    else
      strm.PutCString(arch_str);
  }
}

static void DumpModuleUUID(Stream &strm, Module *module) {
  if (module && module->GetUUID().IsValid())
    module->GetUUID().Dump(strm);
  else
    strm.PutCString("                                    ");
}

static uint32_t DumpCompileUnitLineTable(CommandInterpreter &interpreter,
                                         Stream &strm, Module *module,
                                         const FileSpec &file_spec,
                                         lldb::DescriptionLevel desc_level) {
  uint32_t num_matches = 0;
  if (module) {
    SymbolContextList sc_list;
    num_matches = module->ResolveSymbolContextsForFileSpec(
        file_spec, 0, false, eSymbolContextCompUnit, sc_list);

    bool first_module = true;
    for (const SymbolContext &sc : sc_list) {
      if (!first_module)
        strm << "\n\n";

      strm << "Line table for " << sc.comp_unit->GetPrimaryFile() << " in `"
           << module->GetFileSpec().GetFilename() << "\n";
      LineTable *line_table = sc.comp_unit->GetLineTable();
      if (line_table)
        line_table->GetDescription(
            &strm, interpreter.GetExecutionContext().GetTargetPtr(),
            desc_level);
      else
        strm << "No line table";

      first_module = false;
    }
  }
  return num_matches;
}

static void DumpFullpath(Stream &strm, const FileSpec *file_spec_ptr,
                         uint32_t width) {
  if (file_spec_ptr) {
    if (width > 0) {
      std::string fullpath = file_spec_ptr->GetPath();
      strm.Printf("%-*s", width, fullpath.c_str());
      return;
    } else {
      file_spec_ptr->Dump(strm.AsRawOstream());
      return;
    }
  }
  // Keep the width spacing correct if things go wrong...
  if (width > 0)
    strm.Printf("%-*s", width, "");
}

static void DumpDirectory(Stream &strm, const FileSpec *file_spec_ptr,
                          uint32_t width) {
  if (file_spec_ptr) {
    if (width > 0)
      strm.Printf("%-*s", width, file_spec_ptr->GetDirectory().AsCString(""));
    else
      file_spec_ptr->GetDirectory().Dump(&strm);
    return;
  }
  // Keep the width spacing correct if things go wrong...
  if (width > 0)
    strm.Printf("%-*s", width, "");
}

static void DumpBasename(Stream &strm, const FileSpec *file_spec_ptr,
                         uint32_t width) {
  if (file_spec_ptr) {
    if (width > 0)
      strm.Printf("%-*s", width, file_spec_ptr->GetFilename().AsCString(""));
    else
      file_spec_ptr->GetFilename().Dump(&strm);
    return;
  }
  // Keep the width spacing correct if things go wrong...
  if (width > 0)
    strm.Printf("%-*s", width, "");
}

static size_t DumpModuleObjfileHeaders(Stream &strm, ModuleList &module_list) {
  std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
  const size_t num_modules = module_list.GetSize();
  if (num_modules == 0)
    return 0;

  size_t num_dumped = 0;
  strm.Format("Dumping headers for {0} module(s).\n", num_modules);
  strm.IndentMore();
  for (ModuleSP module_sp : module_list.ModulesNoLocking()) {
    if (module_sp) {
      if (num_dumped++ > 0) {
        strm.EOL();
        strm.EOL();
      }
      ObjectFile *objfile = module_sp->GetObjectFile();
      if (objfile)
        objfile->Dump(&strm);
      else {
        strm.Format("No object file for module: {0:F}\n",
                    module_sp->GetFileSpec());
      }
    }
  }
  strm.IndentLess();
  return num_dumped;
}

static void DumpModuleSymtab(CommandInterpreter &interpreter, Stream &strm,
                             Module *module, SortOrder sort_order,
                             Mangled::NamePreference name_preference) {
  if (!module)
    return;
  if (Symtab *symtab = module->GetSymtab())
    symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(),
                 sort_order, name_preference);
}

static void DumpModuleSections(CommandInterpreter &interpreter, Stream &strm,
                               Module *module) {
  if (module) {
    SectionList *section_list = module->GetSectionList();
    if (section_list) {
      strm.Printf("Sections for '%s' (%s):\n",
                  module->GetSpecificationDescription().c_str(),
                  module->GetArchitecture().GetArchitectureName());
      section_list->Dump(strm.AsRawOstream(), strm.GetIndentLevel() + 2,
                         interpreter.GetExecutionContext().GetTargetPtr(), true,
                         UINT32_MAX);
    }
  }
}

static bool DumpModuleSymbolFile(Stream &strm, Module *module) {
  if (module) {
    if (SymbolFile *symbol_file = module->GetSymbolFile(true)) {
      symbol_file->Dump(strm);
      return true;
    }
  }
  return false;
}

static bool GetSeparateDebugInfoList(StructuredData::Array &list,
                                     Module *module, bool errors_only) {
  if (module) {
    if (SymbolFile *symbol_file = module->GetSymbolFile(/*can_create=*/true)) {
      StructuredData::Dictionary d;
      if (symbol_file->GetSeparateDebugInfo(d, errors_only)) {
        list.AddItem(
            std::make_shared<StructuredData::Dictionary>(std::move(d)));
        return true;
      }
    }
  }
  return false;
}

static void DumpDwoFilesTable(Stream &strm,
                              StructuredData::Array &dwo_listings) {
  strm.PutCString("Dwo ID             Err Dwo Path");
  strm.EOL();
  strm.PutCString(
      "------------------ --- -----------------------------------------");
  strm.EOL();
  dwo_listings.ForEach([&strm](StructuredData::Object *dwo) {
    StructuredData::Dictionary *dict = dwo->GetAsDictionary();
    if (!dict)
      return false;

    uint64_t dwo_id;
    if (dict->GetValueForKeyAsInteger("dwo_id", dwo_id))
      strm.Printf("0x%16.16" PRIx64 " ", dwo_id);
    else
      strm.Printf("0x???????????????? ");

    llvm::StringRef error;
    if (dict->GetValueForKeyAsString("error", error))
      strm << "E   " << error;
    else {
      llvm::StringRef resolved_dwo_path;
      if (dict->GetValueForKeyAsString("resolved_dwo_path",
                                       resolved_dwo_path)) {
        strm << "    " << resolved_dwo_path;
        if (resolved_dwo_path.ends_with(".dwp")) {
          llvm::StringRef dwo_name;
          if (dict->GetValueForKeyAsString("dwo_name", dwo_name))
            strm << "(" << dwo_name << ")";
        }
      }
    }
    strm.EOL();
    return true;
  });
}

static void DumpOsoFilesTable(Stream &strm,
                              StructuredData::Array &oso_listings) {
  strm.PutCString("Mod Time           Err Oso Path");
  strm.EOL();
  strm.PutCString("------------------ --- ---------------------");
  strm.EOL();
  oso_listings.ForEach([&strm](StructuredData::Object *oso) {
    StructuredData::Dictionary *dict = oso->GetAsDictionary();
    if (!dict)
      return false;

    uint32_t oso_mod_time;
    if (dict->GetValueForKeyAsInteger("oso_mod_time", oso_mod_time))
      strm.Printf("0x%16.16" PRIx32 " ", oso_mod_time);

    llvm::StringRef error;
    if (dict->GetValueForKeyAsString("error", error))
      strm << "E   " << error;
    else {
      llvm::StringRef oso_path;
      if (dict->GetValueForKeyAsString("oso_path", oso_path))
        strm << "    " << oso_path;
    }
    strm.EOL();
    return true;
  });
}

static void
DumpAddress(ExecutionContextScope *exe_scope, const Address &so_addr,
            bool verbose, bool all_ranges, Stream &strm,
            std::optional<Stream::HighlightSettings> settings = std::nullopt) {
  strm.IndentMore();
  strm.Indent("    Address: ");
  so_addr.Dump(&strm, exe_scope, Address::DumpStyleModuleWithFileAddress);
  strm.PutCString(" (");
  so_addr.Dump(&strm, exe_scope, Address::DumpStyleSectionNameOffset);
  strm.PutCString(")\n");
  strm.Indent("    Summary: ");
  const uint32_t save_indent = strm.GetIndentLevel();
  strm.SetIndentLevel(save_indent + 13);
  so_addr.Dump(&strm, exe_scope, Address::DumpStyleResolvedDescription,
               Address::DumpStyleInvalid, UINT32_MAX, false, settings);
  strm.SetIndentLevel(save_indent);
  // Print out detailed address information when verbose is enabled
  if (verbose) {
    strm.EOL();
    so_addr.Dump(&strm, exe_scope, Address::DumpStyleDetailedSymbolContext,
                 Address::DumpStyleInvalid, UINT32_MAX, all_ranges, settings);
  }
  strm.IndentLess();
}

static bool LookupAddressInModule(CommandInterpreter &interpreter, Stream &strm,
                                  Module *module, uint32_t resolve_mask,
                                  lldb::addr_t raw_addr, lldb::addr_t offset,
                                  bool verbose, bool all_ranges) {
  if (module) {
    lldb::addr_t addr = raw_addr - offset;
    Address so_addr;
    SymbolContext sc;
    Target *target = interpreter.GetExecutionContext().GetTargetPtr();
    if (target && target->HasLoadedSections()) {
      if (!target->ResolveLoadAddress(addr, so_addr))
        return false;
      else if (so_addr.GetModule().get() != module)
        return false;
    } else {
      if (!module->ResolveFileAddress(addr, so_addr))
        return false;
    }

    ExecutionContextScope *exe_scope =
        interpreter.GetExecutionContext().GetBestExecutionContextScope();
    DumpAddress(exe_scope, so_addr, verbose, all_ranges, strm);
    return true;
  }

  return false;
}

static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
                                     Stream &strm, Module *module,
                                     const char *name, bool name_is_regex,
                                     bool verbose, bool all_ranges) {
  if (!module)
    return 0;

  Symtab *symtab = module->GetSymtab();
  if (!symtab)
    return 0;

  SymbolContext sc;
  const bool use_color = interpreter.GetDebugger().GetUseColor();
  std::vector<uint32_t> match_indexes;
  ConstString symbol_name(name);
  uint32_t num_matches = 0;
  if (name_is_regex) {
    RegularExpression name_regexp(symbol_name.GetStringRef());
    num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType(
        name_regexp, eSymbolTypeAny, match_indexes);
  } else {
    num_matches =
        symtab->AppendSymbolIndexesWithName(symbol_name, match_indexes);
  }

  if (num_matches > 0) {
    strm.Indent();
    strm.Printf("%u symbols match %s'%s' in ", num_matches,
                name_is_regex ? "the regular expression " : "", name);
    DumpFullpath(strm, &module->GetFileSpec(), 0);
    strm.PutCString(":\n");
    strm.IndentMore();
    Stream::HighlightSettings settings(
        name, interpreter.GetDebugger().GetRegexMatchAnsiPrefix(),
        interpreter.GetDebugger().GetRegexMatchAnsiSuffix());
    for (uint32_t i = 0; i < num_matches; ++i) {
      Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]);
      if (symbol) {
        if (symbol->ValueIsAddress()) {
          DumpAddress(
              interpreter.GetExecutionContext().GetBestExecutionContextScope(),
              symbol->GetAddressRef(), verbose, all_ranges, strm,
              use_color && name_is_regex
                  ? std::optional<Stream::HighlightSettings>{settings}
                  : std::nullopt);
          strm.EOL();
        } else {
          strm.IndentMore();
          strm.Indent("    Name: ");
          strm.PutCStringColorHighlighted(
              symbol->GetDisplayName().GetStringRef(),
              use_color && name_is_regex
                  ? std::optional<Stream::HighlightSettings>{settings}
                  : std::nullopt);
          strm.EOL();
          strm.Indent("    Value: ");
          strm.Printf("0x%16.16" PRIx64 "\n", symbol->GetRawValue());
          if (symbol->GetByteSizeIsValid()) {
            strm.Indent("    Size: ");
            strm.Printf("0x%16.16" PRIx64 "\n", symbol->GetByteSize());
          }
          strm.IndentLess();
        }
      }
    }
    strm.IndentLess();
  }
  return num_matches;
}

static void DumpSymbolContextList(
    ExecutionContextScope *exe_scope, Stream &strm,
    const SymbolContextList &sc_list, bool verbose, bool all_ranges,
    std::optional<Stream::HighlightSettings> settings = std::nullopt) {
  strm.IndentMore();
  bool first_module = true;
  for (const SymbolContext &sc : sc_list) {
    if (!first_module)
      strm.EOL();

    Address addr;
    if (sc.line_entry.IsValid())
      addr = sc.line_entry.range.GetBaseAddress();
    else if (sc.block && sc.block->GetContainingInlinedBlock())
      sc.block->GetContainingInlinedBlock()->GetStartAddress(addr);
    else
      addr = sc.GetFunctionOrSymbolAddress();

    DumpAddress(exe_scope, addr, verbose, all_ranges, strm, settings);
    first_module = false;
  }
  strm.IndentLess();
}

static size_t LookupFunctionInModule(CommandInterpreter &interpreter,
                                     Stream &strm, Module *module,
                                     const char *name, bool name_is_regex,
                                     const ModuleFunctionSearchOptions &options,
                                     bool verbose, bool all_ranges) {
  if (module && name && name[0]) {
    SymbolContextList sc_list;
    size_t num_matches = 0;
    if (name_is_regex) {
      RegularExpression function_name_regex((llvm::StringRef(name)));
      module->FindFunctions(function_name_regex, options, sc_list);
    } else {
      ConstString function_name(name);
      module->FindFunctions(function_name, CompilerDeclContext(),
                            eFunctionNameTypeAuto, options, sc_list);
    }
    num_matches = sc_list.GetSize();
    if (num_matches) {
      strm.Indent();
      strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches,
                  num_matches > 1 ? "es" : "");
      DumpFullpath(strm, &module->GetFileSpec(), 0);
      strm.PutCString(":\n");
      DumpSymbolContextList(
          interpreter.GetExecutionContext().GetBestExecutionContextScope(),
          strm, sc_list, verbose, all_ranges);
    }
    return num_matches;
  }
  return 0;
}

static size_t LookupTypeInModule(Target *target,
                                 CommandInterpreter &interpreter, Stream &strm,
                                 Module *module, const char *name_cstr,
                                 bool name_is_regex) {
  if (module && name_cstr && name_cstr[0]) {
    TypeQuery query(name_cstr);
    TypeResults results;
    module->FindTypes(query, results);

    TypeList type_list;
    SymbolContext sc;
    if (module)
      sc.module_sp = module->shared_from_this();
    // Sort the type results and put the results that matched in \a module
    // first if \a module was specified.
    sc.SortTypeList(results.GetTypeMap(), type_list);
    if (type_list.Empty())
      return 0;

    const uint64_t num_matches = type_list.GetSize();

    strm.Indent();
    strm.Printf("%" PRIu64 " match%s found in ", num_matches,
                num_matches > 1 ? "es" : "");
    DumpFullpath(strm, &module->GetFileSpec(), 0);
    strm.PutCString(":\n");
    for (TypeSP type_sp : type_list.Types()) {
      if (!type_sp)
        continue;
      // Resolve the clang type so that any forward references to types
      // that haven't yet been parsed will get parsed.
      type_sp->GetFullCompilerType();
      type_sp->GetDescription(&strm, eDescriptionLevelFull, true, target);
      // Print all typedef chains
      TypeSP typedef_type_sp(type_sp);
      TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
      while (typedefed_type_sp) {
        strm.EOL();
        strm.Printf("     typedef '%s': ",
                    typedef_type_sp->GetName().GetCString());
        typedefed_type_sp->GetFullCompilerType();
        typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true,
                                          target);
        typedef_type_sp = typedefed_type_sp;
        typedefed_type_sp = typedef_type_sp->GetTypedefType();
      }
      strm.EOL();
    }
    return type_list.GetSize();
  }
  return 0;
}

static size_t LookupTypeHere(Target *target, CommandInterpreter &interpreter,
                             Stream &strm, Module &module,
                             const char *name_cstr, bool name_is_regex) {
  TypeQuery query(name_cstr);
  TypeResults results;
  module.FindTypes(query, results);
  TypeList type_list;
  SymbolContext sc;
  sc.module_sp = module.shared_from_this();
  sc.SortTypeList(results.GetTypeMap(), type_list);
  if (type_list.Empty())
    return 0;

  strm.Indent();
  strm.PutCString("Best match found in ");
  DumpFullpath(strm, &module.GetFileSpec(), 0);
  strm.PutCString(":\n");

  TypeSP type_sp(type_list.GetTypeAtIndex(0));
  if (type_sp) {
    // Resolve the clang type so that any forward references to types that
    // haven't yet been parsed will get parsed.
    type_sp->GetFullCompilerType();
    type_sp->GetDescription(&strm, eDescriptionLevelFull, true, target);
    // Print all typedef chains.
    TypeSP typedef_type_sp(type_sp);
    TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
    while (typedefed_type_sp) {
      strm.EOL();
      strm.Printf("     typedef '%s': ",
                  typedef_type_sp->GetName().GetCString());
      typedefed_type_sp->GetFullCompilerType();
      typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true,
                                        target);
      typedef_type_sp = typedefed_type_sp;
      typedefed_type_sp = typedef_type_sp->GetTypedefType();
    }
  }
  strm.EOL();
  return type_list.GetSize();
}

static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter,
                                          Stream &strm, Module *module,
                                          const FileSpec &file_spec,
                                          uint32_t line, bool check_inlines,
                                          bool verbose, bool all_ranges) {
  if (module && file_spec) {
    SymbolContextList sc_list;
    const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(
        file_spec, line, check_inlines, eSymbolContextEverything, sc_list);
    if (num_matches > 0) {
      strm.Indent();
      strm.Printf("%u match%s found in ", num_matches,
                  num_matches > 1 ? "es" : "");
      strm << file_spec;
      if (line > 0)
        strm.Printf(":%u", line);
      strm << " in ";
      DumpFullpath(strm, &module->GetFileSpec(), 0);
      strm.PutCString(":\n");
      DumpSymbolContextList(
          interpreter.GetExecutionContext().GetBestExecutionContextScope(),
          strm, sc_list, verbose, all_ranges);
      return num_matches;
    }
  }
  return 0;
}

static size_t FindModulesByName(Target *target, const char *module_name,
                                ModuleList &module_list,
                                bool check_global_list) {
  FileSpec module_file_spec(module_name);
  ModuleSpec module_spec(module_file_spec);

  const size_t initial_size = module_list.GetSize();

  if (check_global_list) {
    // Check the global list
    std::lock_guard<std::recursive_mutex> guard(
        Module::GetAllocationModuleCollectionMutex());
    const size_t num_modules = Module::GetNumberAllocatedModules();
    ModuleSP module_sp;
    for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
      Module *module = Module::GetAllocatedModuleAtIndex(image_idx);

      if (module) {
        if (module->MatchesModuleSpec(module_spec)) {
          module_sp = module->shared_from_this();
          module_list.AppendIfNeeded(module_sp);
        }
      }
    }
  } else {
    if (target) {
      target->GetImages().FindModules(module_spec, module_list);
      const size_t num_matches = module_list.GetSize();

      // Not found in our module list for our target, check the main shared
      // module list in case it is a extra file used somewhere else
      if (num_matches == 0) {
        module_spec.GetArchitecture() = target->GetArchitecture();
        ModuleList::FindSharedModules(module_spec, module_list);
      }
    } else {
      ModuleList::FindSharedModules(module_spec, module_list);
    }
  }

  return module_list.GetSize() - initial_size;
}

#pragma mark CommandObjectTargetModulesModuleAutoComplete

// A base command object class that can auto complete with module file
// paths

class CommandObjectTargetModulesModuleAutoComplete
    : public CommandObjectParsed {
public:
  CommandObjectTargetModulesModuleAutoComplete(CommandInterpreter &interpreter,
                                               const char *name,
                                               const char *help,
                                               const char *syntax,
                                               uint32_t flags = 0)
      : CommandObjectParsed(interpreter, name, help, syntax, flags) {
    AddSimpleArgumentList(eArgTypeFilename, eArgRepeatStar);
  }

  ~CommandObjectTargetModulesModuleAutoComplete() override = default;

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

#pragma mark CommandObjectTargetModulesSourceFileAutoComplete

// A base command object class that can auto complete with module source
// file paths

class CommandObjectTargetModulesSourceFileAutoComplete
    : public CommandObjectParsed {
public:
  CommandObjectTargetModulesSourceFileAutoComplete(
      CommandInterpreter &interpreter, const char *name, const char *help,
      const char *syntax, uint32_t flags)
      : CommandObjectParsed(interpreter, name, help, syntax, flags) {
    AddSimpleArgumentList(eArgTypeSourceFile, eArgRepeatPlus);
  }

  ~CommandObjectTargetModulesSourceFileAutoComplete() override = default;

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

#pragma mark CommandObjectTargetModulesDumpObjfile

class CommandObjectTargetModulesDumpObjfile
    : public CommandObjectTargetModulesModuleAutoComplete {
public:
  CommandObjectTargetModulesDumpObjfile(CommandInterpreter &interpreter)
      : CommandObjectTargetModulesModuleAutoComplete(
            interpreter, "target modules dump objfile",
            "Dump the object file headers from one or more target modules.",
            nullptr, eCommandRequiresTarget) {}

  ~CommandObjectTargetModulesDumpObjfile() override = default;

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

    uint32_t addr_byte_size = target.GetArchitecture().GetAddressByteSize();
    result.GetOutputStream().SetAddressByteSize(addr_byte_size);
    result.GetErrorStream().SetAddressByteSize(addr_byte_size);

    size_t num_dumped = 0;
    if (command.GetArgumentCount() == 0) {
      // Dump all headers for all modules images
      num_dumped = DumpModuleObjfileHeaders(result.GetOutputStream(),
                                            target.GetImages());
      if (num_dumped == 0) {
        result.AppendError("the target has no associated executable images");
      }
    } else {
      // Find the modules that match the basename or full path.
      ModuleList module_list;
      const char *arg_cstr;
      for (int arg_idx = 0;
           (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
           ++arg_idx) {
        size_t num_matched =
            FindModulesByName(&target, arg_cstr, module_list, true);
        if (num_matched == 0) {
          result.AppendWarningWithFormat(
              "Unable to find an image that matches '%s'.\n", arg_cstr);
        }
      }
      // Dump all the modules we found.
      num_dumped =
          DumpModuleObjfileHeaders(result.GetOutputStream(), module_list);
    }

    if (num_dumped > 0) {
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      result.AppendError("no matching executable images found");
    }
  }
};

#define LLDB_OPTIONS_target_modules_dump_symtab
#include "CommandOptions.inc"

class CommandObjectTargetModulesDumpSymtab
    : public CommandObjectTargetModulesModuleAutoComplete {
public:
  CommandObjectTargetModulesDumpSymtab(CommandInterpreter &interpreter)
      : CommandObjectTargetModulesModuleAutoComplete(
            interpreter, "target modules dump symtab",
            "Dump the symbol table from one or more target modules.", nullptr,
            eCommandRequiresTarget) {}

  ~CommandObjectTargetModulesDumpSymtab() 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 {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'm':
        m_prefer_mangled.SetCurrentValue(true);
        m_prefer_mangled.SetOptionWasSet();
        break;

      case 's':
        m_sort_order = (SortOrder)OptionArgParser::ToOptionEnum(
            option_arg, GetDefinitions()[option_idx].enum_values,
            eSortOrderNone, error);
        break;

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

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_sort_order = eSortOrderNone;
      m_prefer_mangled.Clear();
    }

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

    SortOrder m_sort_order = eSortOrderNone;
    OptionValueBoolean m_prefer_mangled = {false, false};
  };

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Target &target = GetTarget();
    uint32_t num_dumped = 0;
    Mangled::NamePreference name_preference =
        (m_options.m_prefer_mangled ? Mangled::ePreferMangled
                                    : Mangled::ePreferDemangled);

    uint32_t addr_byte_size = target.GetArchitecture().GetAddressByteSize();
    result.GetOutputStream().SetAddressByteSize(addr_byte_size);
    result.GetErrorStream().SetAddressByteSize(addr_byte_size);

    if (command.GetArgumentCount() == 0) {
      // Dump all sections for all modules images
      const ModuleList &module_list = target.GetImages();
      std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
      const size_t num_modules = module_list.GetSize();
      if (num_modules > 0) {
        result.GetOutputStream().Format(
            "Dumping symbol table for {0} modules.\n", num_modules);
        for (ModuleSP module_sp : module_list.ModulesNoLocking()) {
          if (num_dumped > 0) {
            result.GetOutputStream().EOL();
            result.GetOutputStream().EOL();
          }
          if (INTERRUPT_REQUESTED(GetDebugger(),
                                  "Interrupted in dump all symtabs with {0} "
                                  "of {1} dumped.", num_dumped, num_modules))
            break;

          num_dumped++;
          DumpModuleSymtab(m_interpreter, result.GetOutputStream(),
                           module_sp.get(), m_options.m_sort_order,
                           name_preference);
        }
      } else {
        result.AppendError("the target has no associated executable images");
        return;
      }
    } else {
      // Dump specified images (by basename or fullpath)
      const char *arg_cstr;
      for (int arg_idx = 0;
           (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
           ++arg_idx) {
        ModuleList module_list;
        const size_t num_matches =
            FindModulesByName(&target, arg_cstr, module_list, true);
        if (num_matches > 0) {
          for (ModuleSP module_sp : module_list.Modules()) {
            if (module_sp) {
              if (num_dumped > 0) {
                result.GetOutputStream().EOL();
                result.GetOutputStream().EOL();
              }
              if (INTERRUPT_REQUESTED(GetDebugger(),
                    "Interrupted in dump symtab list with {0} of {1} dumped.",
                    num_dumped, num_matches))
                break;

              num_dumped++;
              DumpModuleSymtab(m_interpreter, result.GetOutputStream(),
                               module_sp.get(), m_options.m_sort_order,
                               name_preference);
            }
          }
        } else
          result.AppendWarningWithFormat(
              "Unable to find an image that matches '%s'.\n", arg_cstr);
      }
    }

    if (num_dumped > 0)
      result.SetStatus(eReturnStatusSuccessFinishResult);
    else {
      result.AppendError("no matching executable images found");
    }
  }

  CommandOptions m_options;
};

#pragma mark CommandObjectTargetModulesDumpSections

// Image section dumping command

class CommandObjectTargetModulesDumpSections
    : public CommandObjectTargetModulesModuleAutoComplete {
public:
  CommandObjectTargetModulesDumpSections(CommandInterpreter &interpreter)
      : CommandObjectTargetModulesModuleAutoComplete(
            interpreter, "target modules dump sections",
            "Dump the sections from one or more target modules.",
            //"target modules dump sections [<file1> ...]")
            nullptr, eCommandRequiresTarget) {}

  ~CommandObjectTargetModulesDumpSections() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Target &target = GetTarget();
    uint32_t num_dumped = 0;

    uint32_t addr_byte_size = target.GetArchitecture().GetAddressByteSize();
    result.GetOutputStream().SetAddressByteSize(addr_byte_size);
    result.GetErrorStream().SetAddressByteSize(addr_byte_size);

    if (command.GetArgumentCount() == 0) {
      // Dump all sections for all modules images
      const size_t num_modules = target.GetImages().GetSize();
      if (num_modules == 0) {
        result.AppendError("the target has no associated executable images");
        return;
      }

      result.GetOutputStream().Format("Dumping sections for {0} modules.\n",
                                      num_modules);
      for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
        if (INTERRUPT_REQUESTED(GetDebugger(),
              "Interrupted in dump all sections with {0} of {1} dumped",
              image_idx, num_modules))
          break;

        num_dumped++;
        DumpModuleSections(
            m_interpreter, result.GetOutputStream(),
            target.GetImages().GetModulePointerAtIndex(image_idx));
      }
    } else {
      // Dump specified images (by basename or fullpath)
      const char *arg_cstr;
      for (int arg_idx = 0;
           (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
           ++arg_idx) {
        ModuleList module_list;
        const size_t num_matches =
            FindModulesByName(&target, arg_cstr, module_list, true);
        if (num_matches > 0) {
          for (size_t i = 0; i < num_matches; ++i) {
            if (INTERRUPT_REQUESTED(GetDebugger(),
                  "Interrupted in dump section list with {0} of {1} dumped.",
                  i, num_matches))
              break;

            Module *module = module_list.GetModulePointerAtIndex(i);
            if (module) {
              num_dumped++;
              DumpModuleSections(m_interpreter, result.GetOutputStream(),
                                 module);
            }
          }
        } else {
          // Check the global list
          std::lock_guard<std::recursive_mutex> guard(
              Module::GetAllocationModuleCollectionMutex());

          result.AppendWarningWithFormat(
              "Unable to find an image that matches '%s'.\n", arg_cstr);
        }
      }
    }

    if (num_dumped > 0)
      result.SetStatus(eReturnStatusSuccessFinishResult);
    else {
      result.AppendError("no matching executable images found");
    }
  }
};

class CommandObjectTargetModulesDumpClangPCMInfo : public CommandObjectParsed {
public:
  CommandObjectTargetModulesDumpClangPCMInfo(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "target modules dump pcm-info",
            "Dump information about the given clang module (pcm).") {
    // Take a single file argument.
    AddSimpleArgumentList(eArgTypeFilename);
  }

  ~CommandObjectTargetModulesDumpClangPCMInfo() override = default;

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

    const char *pcm_path = command.GetArgumentAtIndex(0);
    const FileSpec pcm_file{pcm_path};

    if (pcm_file.GetFileNameExtension() != ".pcm") {
      result.AppendError("file must have a .pcm extension");
      return;
    }

    if (!FileSystem::Instance().Exists(pcm_file)) {
      result.AppendError("pcm file does not exist");
      return;
    }

    clang::CompilerInstance compiler;
    compiler.createDiagnostics(*FileSystem::Instance().GetVirtualFileSystem());

    const char *clang_args[] = {"clang", pcm_path};
    compiler.setInvocation(clang::createInvocation(clang_args));

    // Pass empty deleter to not attempt to free memory that was allocated
    // outside of the current scope, possibly statically.
    std::shared_ptr<llvm::raw_ostream> Out(
        &result.GetOutputStream().AsRawOstream(), [](llvm::raw_ostream *) {});
    clang::DumpModuleInfoAction dump_module_info(Out);
    // DumpModuleInfoAction requires ObjectFilePCHContainerReader.
    compiler.getPCHContainerOperations()->registerReader(
        std::make_unique<clang::ObjectFilePCHContainerReader>());

    if (compiler.ExecuteAction(dump_module_info))
      result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

#pragma mark CommandObjectTargetModulesDumpClangAST

// Clang AST dumping command

class CommandObjectTargetModulesDumpClangAST
    : public CommandObjectTargetModulesModuleAutoComplete {
public:
  CommandObjectTargetModulesDumpClangAST(CommandInterpreter &interpreter)
      : CommandObjectTargetModulesModuleAutoComplete(
            interpreter, "target modules dump ast",
            "Dump the clang ast for a given module's symbol file.",
            //"target modules dump ast [<file1> ...]")
            nullptr, eCommandRequiresTarget) {}

  ~CommandObjectTargetModulesDumpClangAST() override = default;

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

    const ModuleList &module_list = target.GetImages();
    const size_t num_modules = module_list.GetSize();
    if (num_modules == 0) {
      result.AppendError("the target has no associated executable images");
      return;
    }

    if (command.GetArgumentCount() == 0) {
      // Dump all ASTs for all modules images
      result.GetOutputStream().Format("Dumping clang ast for {0} modules.\n",
                                      num_modules);
      for (ModuleSP module_sp : module_list.ModulesNoLocking()) {
        if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted dumping clang ast"))
          break;
        if (SymbolFile *sf = module_sp->GetSymbolFile())
          sf->DumpClangAST(result.GetOutputStream());
      }
      result.SetStatus(eReturnStatusSuccessFinishResult);
      return;
    }

    // Dump specified ASTs (by basename or fullpath)
    for (const Args::ArgEntry &arg : command.entries()) {
      ModuleList module_list;
      const size_t num_matches =
          FindModulesByName(&target, arg.c_str(), module_list, true);
      if (num_matches == 0) {
        // Check the global list
        std::lock_guard<std::recursive_mutex> guard(
            Module::GetAllocationModuleCollectionMutex());

        result.AppendWarningWithFormat(
            "Unable to find an image that matches '%s'.\n", arg.c_str());
        continue;
      }

      for (size_t i = 0; i < num_matches; ++i) {
        if (INTERRUPT_REQUESTED(GetDebugger(),
              "Interrupted in dump clang ast list with {0} of {1} dumped.",
              i, num_matches))
          break;

        Module *m = module_list.GetModulePointerAtIndex(i);
        if (SymbolFile *sf = m->GetSymbolFile())
          sf->DumpClangAST(result.GetOutputStream());
      }
    }
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

#pragma mark CommandObjectTargetModulesDumpSymfile

// Image debug symbol dumping command

class CommandObjectTargetModulesDumpSymfile
    : public CommandObjectTargetModulesModuleAutoComplete {
public:
  CommandObjectTargetModulesDumpSymfile(CommandInterpreter &interpreter)
      : CommandObjectTargetModulesModuleAutoComplete(
            interpreter, "target modules dump symfile",
            "Dump the debug symbol file for one or more target modules.",
            //"target modules dump symfile [<file1> ...]")
            nullptr, eCommandRequiresTarget) {}

  ~CommandObjectTargetModulesDumpSymfile() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Target &target = GetTarget();
    uint32_t num_dumped = 0;

    uint32_t addr_byte_size = target.GetArchitecture().GetAddressByteSize();
    result.GetOutputStream().SetAddressByteSize(addr_byte_size);
    result.GetErrorStream().SetAddressByteSize(addr_byte_size);

    if (command.GetArgumentCount() == 0) {
      // Dump all sections for all modules images
      const ModuleList &target_modules = target.GetImages();
      std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
      const size_t num_modules = target_modules.GetSize();
      if (num_modules == 0) {
        result.AppendError("the target has no associated executable images");
        return;
      }
      result.GetOutputStream().Format(
          "Dumping debug symbols for {0} modules.\n", num_modules);
      for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
        if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted in dumping all "
                                "debug symbols with {0} of {1} modules dumped",
                                 num_dumped, num_modules))
          break;

        if (DumpModuleSymbolFile(result.GetOutputStream(), module_sp.get()))
          num_dumped++;
      }
    } else {
      // Dump specified images (by basename or fullpath)
      const char *arg_cstr;
      for (int arg_idx = 0;
           (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
           ++arg_idx) {
        ModuleList module_list;
        const size_t num_matches =
            FindModulesByName(&target, arg_cstr, module_list, true);
        if (num_matches > 0) {
          for (size_t i = 0; i < num_matches; ++i) {
            if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted dumping {0} "
                                                   "of {1} requested modules",
                                                   i, num_matches))
              break;
            Module *module = module_list.GetModulePointerAtIndex(i);
            if (module) {
              if (DumpModuleSymbolFile(result.GetOutputStream(), module))
                num_dumped++;
            }
          }
        } else
          result.AppendWarningWithFormat(
              "Unable to find an image that matches '%s'.\n", arg_cstr);
      }
    }

    if (num_dumped > 0)
      result.SetStatus(eReturnStatusSuccessFinishResult);
    else {
      result.AppendError("no matching executable images found");
    }
  }
};

#pragma mark CommandObjectTargetModulesDumpLineTable
#define LLDB_OPTIONS_target_modules_dump
#include "CommandOptions.inc"

// Image debug line table dumping command

class CommandObjectTargetModulesDumpLineTable
    : public CommandObjectTargetModulesSourceFileAutoComplete {
public:
  CommandObjectTargetModulesDumpLineTable(CommandInterpreter &interpreter)
      : CommandObjectTargetModulesSourceFileAutoComplete(
            interpreter, "target modules dump line-table",
            "Dump the line table for one or more compilation units.", nullptr,
            eCommandRequiresTarget) {}

  ~CommandObjectTargetModulesDumpLineTable() override = default;

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

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = m_exe_ctx.GetTargetPtr();
    uint32_t total_num_dumped = 0;

    uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
    result.GetOutputStream().SetAddressByteSize(addr_byte_size);
    result.GetErrorStream().SetAddressByteSize(addr_byte_size);

    if (command.GetArgumentCount() == 0) {
      result.AppendError("file option must be specified.");
      return;
    } else {
      // Dump specified images (by basename or fullpath)
      const char *arg_cstr;
      for (int arg_idx = 0;
           (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
           ++arg_idx) {
        FileSpec file_spec(arg_cstr);

        const ModuleList &target_modules = target->GetImages();
        std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
        size_t num_modules = target_modules.GetSize();
        if (num_modules > 0) {
          uint32_t num_dumped = 0;
          for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
            if (INTERRUPT_REQUESTED(GetDebugger(),
                                    "Interrupted in dump all line tables with "
                                    "{0} of {1} dumped", num_dumped,
                                    num_modules))
              break;

            if (DumpCompileUnitLineTable(
                    m_interpreter, result.GetOutputStream(), module_sp.get(),
                    file_spec,
                    m_options.m_verbose ? eDescriptionLevelFull
                                        : eDescriptionLevelBrief))
              num_dumped++;
          }
          if (num_dumped == 0)
            result.AppendWarningWithFormat(
                "No source filenames matched '%s'.\n", arg_cstr);
          else
            total_num_dumped += num_dumped;
        }
      }
    }

    if (total_num_dumped > 0)
      result.SetStatus(eReturnStatusSuccessFinishResult);
    else {
      result.AppendError("no source filenames matched any command arguments");
    }
  }

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

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      assert(option_idx == 0 && "We only have one option.");
      m_verbose = true;

      return Status();
    }

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

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

    bool m_verbose;
  };

  CommandOptions m_options;
};

#pragma mark CommandObjectTargetModulesDumpSeparateDebugInfoFiles
#define LLDB_OPTIONS_target_modules_dump_separate_debug_info
#include "CommandOptions.inc"

// Image debug separate debug info dumping command

class CommandObjectTargetModulesDumpSeparateDebugInfoFiles
    : public CommandObjectTargetModulesModuleAutoComplete {
public:
  CommandObjectTargetModulesDumpSeparateDebugInfoFiles(
      CommandInterpreter &interpreter)
      : CommandObjectTargetModulesModuleAutoComplete(
            interpreter, "target modules dump separate-debug-info",
            "List the separate debug info symbol files for one or more target "
            "modules.",
            nullptr, eCommandRequiresTarget) {}

  ~CommandObjectTargetModulesDumpSeparateDebugInfoFiles() 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 {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'j':
        m_json.SetCurrentValue(true);
        m_json.SetOptionWasSet();
        break;
      case 'e':
        m_errors_only.SetCurrentValue(true);
        m_errors_only.SetOptionWasSet();
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }
      return error;
    }

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

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

    OptionValueBoolean m_json = false;
    OptionValueBoolean m_errors_only = false;
  };

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Target &target = GetTarget();
    uint32_t num_dumped = 0;

    uint32_t addr_byte_size = target.GetArchitecture().GetAddressByteSize();
    result.GetOutputStream().SetAddressByteSize(addr_byte_size);
    result.GetErrorStream().SetAddressByteSize(addr_byte_size);

    StructuredData::Array separate_debug_info_lists_by_module;
    if (command.GetArgumentCount() == 0) {
      // Dump all sections for all modules images
      const ModuleList &target_modules = target.GetImages();
      std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
      const size_t num_modules = target_modules.GetSize();
      if (num_modules == 0) {
        result.AppendError("the target has no associated executable images");
        return;
      }
      for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
        if (INTERRUPT_REQUESTED(
                GetDebugger(),
                "Interrupted in dumping all "
                "separate debug info with {0} of {1} modules dumped",
                num_dumped, num_modules))
          break;

        if (GetSeparateDebugInfoList(separate_debug_info_lists_by_module,
                                     module_sp.get(),
                                     bool(m_options.m_errors_only)))
          num_dumped++;
      }
    } else {
      // Dump specified images (by basename or fullpath)
      const char *arg_cstr;
      for (int arg_idx = 0;
           (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
           ++arg_idx) {
        ModuleList module_list;
        const size_t num_matches =
            FindModulesByName(&target, arg_cstr, module_list, true);
        if (num_matches > 0) {
          for (size_t i = 0; i < num_matches; ++i) {
            if (INTERRUPT_REQUESTED(GetDebugger(),
                                    "Interrupted dumping {0} "
                                    "of {1} requested modules",
                                    i, num_matches))
              break;
            Module *module = module_list.GetModulePointerAtIndex(i);
            if (GetSeparateDebugInfoList(separate_debug_info_lists_by_module,
                                         module, bool(m_options.m_errors_only)))
              num_dumped++;
          }
        } else
          result.AppendWarningWithFormat(
              "Unable to find an image that matches '%s'.\n", arg_cstr);
      }
    }

    if (num_dumped > 0) {
      Stream &strm = result.GetOutputStream();
      // Display the debug info files in some format.
      if (m_options.m_json) {
        // JSON format
        separate_debug_info_lists_by_module.Dump(strm,
                                                 /*pretty_print=*/true);
      } else {
        // Human-readable table format
        separate_debug_info_lists_by_module.ForEach(
            [&result, &strm](StructuredData::Object *obj) {
              if (!obj) {
                return false;
              }

              // Each item in `separate_debug_info_lists_by_module` should be a
              // valid structured data dictionary.
              StructuredData::Dictionary *separate_debug_info_list =
                  obj->GetAsDictionary();
              if (!separate_debug_info_list) {
                return false;
              }

              llvm::StringRef type;
              llvm::StringRef symfile;
              StructuredData::Array *files;
              if (!(separate_debug_info_list->GetValueForKeyAsString("type",
                                                                     type) &&
                    separate_debug_info_list->GetValueForKeyAsString("symfile",
                                                                     symfile) &&
                    separate_debug_info_list->GetValueForKeyAsArray(
                        "separate-debug-info-files", files))) {
                assert(false);
              }

              strm << "Symbol file: " << symfile;
              strm.EOL();
              strm << "Type: \"" << type << "\"";
              strm.EOL();
              if (type == "dwo") {
                DumpDwoFilesTable(strm, *files);
              } else if (type == "oso") {
                DumpOsoFilesTable(strm, *files);
              } else {
                result.AppendWarningWithFormat(
                    "Found unsupported debug info type '%s'.\n",
                    type.str().c_str());
              }
              return true;
            });
      }
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      result.AppendError("no matching executable images found");
    }
  }

  CommandOptions m_options;
};

#pragma mark CommandObjectTargetModulesDump

// Dump multi-word command for target modules

class CommandObjectTargetModulesDump : public CommandObjectMultiword {
public:
  // Constructors and Destructors
  CommandObjectTargetModulesDump(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "target modules dump",
            "Commands for dumping information about one or more target "
            "modules.",
            "target modules dump "
            "[objfile|symtab|sections|ast|symfile|line-table|pcm-info|separate-"
            "debug-info] "
            "[<file1> <file2> ...]") {
    LoadSubCommand("objfile",
                   CommandObjectSP(
                       new CommandObjectTargetModulesDumpObjfile(interpreter)));
    LoadSubCommand(
        "symtab",
        CommandObjectSP(new CommandObjectTargetModulesDumpSymtab(interpreter)));
    LoadSubCommand("sections",
                   CommandObjectSP(new CommandObjectTargetModulesDumpSections(
                       interpreter)));
    LoadSubCommand("symfile",
                   CommandObjectSP(
                       new CommandObjectTargetModulesDumpSymfile(interpreter)));
    LoadSubCommand(
        "ast", CommandObjectSP(
                   new CommandObjectTargetModulesDumpClangAST(interpreter)));
    LoadSubCommand("line-table",
                   CommandObjectSP(new CommandObjectTargetModulesDumpLineTable(
                       interpreter)));
    LoadSubCommand(
        "pcm-info",
        CommandObjectSP(
            new CommandObjectTargetModulesDumpClangPCMInfo(interpreter)));
    LoadSubCommand("separate-debug-info",
                   CommandObjectSP(
                       new CommandObjectTargetModulesDumpSeparateDebugInfoFiles(
                           interpreter)));
  }

  ~CommandObjectTargetModulesDump() override = default;
};

class CommandObjectTargetModulesAdd : public CommandObjectParsed {
public:
  CommandObjectTargetModulesAdd(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "target modules add",
                            "Add a new module to the current target's modules.",
                            "target modules add [<module>]",
                            eCommandRequiresTarget),
        m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
                      eArgTypeFilename,
                      "Fullpath to a stand alone debug "
                      "symbols file for when debug symbols "
                      "are not in the executable.") {
    m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
                          LLDB_OPT_SET_1);
    m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Finalize();
    AddSimpleArgumentList(eArgTypePath, eArgRepeatStar);
  }

  ~CommandObjectTargetModulesAdd() override = default;

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

protected:
  OptionGroupOptions m_option_group;
  OptionGroupUUID m_uuid_option_group;
  OptionGroupFile m_symbol_file;

  void DoExecute(Args &args, CommandReturnObject &result) override {
    Target &target = GetTarget();
    bool flush = false;

    const size_t argc = args.GetArgumentCount();
    if (argc == 0) {
      if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
        // We are given a UUID only, go locate the file
        ModuleSpec module_spec;
        module_spec.GetUUID() =
            m_uuid_option_group.GetOptionValue().GetCurrentValue();
        if (m_symbol_file.GetOptionValue().OptionWasSet())
          module_spec.GetSymbolFileSpec() =
              m_symbol_file.GetOptionValue().GetCurrentValue();
        Status error;
        if (PluginManager::DownloadObjectAndSymbolFile(module_spec, error)) {
          ModuleSP module_sp(
              target.GetOrCreateModule(module_spec, true /* notify */));
          if (module_sp) {
            result.SetStatus(eReturnStatusSuccessFinishResult);
            return;
          } else {
            StreamString strm;
            module_spec.GetUUID().Dump(strm);
            if (module_spec.GetFileSpec()) {
              if (module_spec.GetSymbolFileSpec()) {
                result.AppendErrorWithFormat(
                    "Unable to create the executable or symbol file with "
                    "UUID %s with path %s and symbol file %s",
                    strm.GetData(), module_spec.GetFileSpec().GetPath().c_str(),
                    module_spec.GetSymbolFileSpec().GetPath().c_str());
              } else {
                result.AppendErrorWithFormat(
                    "Unable to create the executable or symbol file with "
                    "UUID %s with path %s",
                    strm.GetData(),
                    module_spec.GetFileSpec().GetPath().c_str());
              }
            } else {
              result.AppendErrorWithFormat("Unable to create the executable "
                                           "or symbol file with UUID %s",
                                           strm.GetData());
            }
            return;
          }
        } else {
          StreamString strm;
          module_spec.GetUUID().Dump(strm);
          result.AppendErrorWithFormat(
              "Unable to locate the executable or symbol file with UUID %s",
              strm.GetData());
          result.SetError(std::move(error));
          return;
        }
      } else {
        result.AppendError(
            "one or more executable image paths must be specified");
        return;
      }
    } else {
      for (auto &entry : args.entries()) {
        if (entry.ref().empty())
          continue;

        FileSpec file_spec(entry.ref());
        if (FileSystem::Instance().Exists(file_spec)) {
          ModuleSpec module_spec(file_spec);
          if (m_uuid_option_group.GetOptionValue().OptionWasSet())
            module_spec.GetUUID() =
                m_uuid_option_group.GetOptionValue().GetCurrentValue();
          if (m_symbol_file.GetOptionValue().OptionWasSet())
            module_spec.GetSymbolFileSpec() =
                m_symbol_file.GetOptionValue().GetCurrentValue();
          if (!module_spec.GetArchitecture().IsValid())
            module_spec.GetArchitecture() = target.GetArchitecture();
          Status error;
          ModuleSP module_sp(
              target.GetOrCreateModule(module_spec, true /* notify */, &error));
          if (!module_sp) {
            const char *error_cstr = error.AsCString();
            if (error_cstr)
              result.AppendError(error_cstr);
            else
              result.AppendErrorWithFormat("unsupported module: %s",
                                           entry.c_str());
            return;
          } else {
            flush = true;
          }
          result.SetStatus(eReturnStatusSuccessFinishResult);
        } else {
          std::string resolved_path = file_spec.GetPath();
          if (resolved_path != entry.ref()) {
            result.AppendErrorWithFormat(
                "invalid module path '%s' with resolved path '%s'\n",
                entry.ref().str().c_str(), resolved_path.c_str());
            break;
          }
          result.AppendErrorWithFormat("invalid module path '%s'\n",
                                       entry.c_str());
          break;
        }
      }
    }

    if (flush) {
      ProcessSP process = target.GetProcessSP();
      if (process)
        process->Flush();
    }
  }
};

class CommandObjectTargetModulesLoad
    : public CommandObjectTargetModulesModuleAutoComplete {
public:
  CommandObjectTargetModulesLoad(CommandInterpreter &interpreter)
      : CommandObjectTargetModulesModuleAutoComplete(
            interpreter, "target modules load",
            "Set the load addresses for one or more sections in a target "
            "module.",
            "target modules load [--file <module> --uuid <uuid>] <sect-name> "
            "<address> [<sect-name> <address> ....]",
            eCommandRequiresTarget),
        m_file_option(LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName,
                      "Fullpath or basename for module to load.", ""),
        m_load_option(LLDB_OPT_SET_1, false, "load", 'l',
                      "Write file contents to the memory.", false, true),
        m_pc_option(LLDB_OPT_SET_1, false, "set-pc-to-entry", 'p',
                    "Set PC to the entry point."
                    " Only applicable with '--load' option.",
                    false, true),
        m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset,
                       "Set the load address for all sections to be the "
                       "virtual address in the file plus the offset.",
                       0) {
    m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
                          LLDB_OPT_SET_1);
    m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_load_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_pc_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_slide_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Finalize();
  }

  ~CommandObjectTargetModulesLoad() override = default;

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

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    Target &target = GetTarget();
    const bool load = m_load_option.GetOptionValue().GetCurrentValue();
    const bool set_pc = m_pc_option.GetOptionValue().GetCurrentValue();

    const size_t argc = args.GetArgumentCount();
    ModuleSpec module_spec;
    bool search_using_module_spec = false;

    // Allow "load" option to work without --file or --uuid option.
    if (load) {
      if (!m_file_option.GetOptionValue().OptionWasSet() &&
          !m_uuid_option_group.GetOptionValue().OptionWasSet()) {
        ModuleList &module_list = target.GetImages();
        if (module_list.GetSize() == 1) {
          search_using_module_spec = true;
          module_spec.GetFileSpec() =
              module_list.GetModuleAtIndex(0)->GetFileSpec();
        }
      }
    }

    if (m_file_option.GetOptionValue().OptionWasSet()) {
      search_using_module_spec = true;
      const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue();
      const bool use_global_module_list = true;
      ModuleList module_list;
      const size_t num_matches = FindModulesByName(
          &target, arg_cstr, module_list, use_global_module_list);
      if (num_matches == 1) {
        module_spec.GetFileSpec() =
            module_list.GetModuleAtIndex(0)->GetFileSpec();
      } else if (num_matches > 1) {
        search_using_module_spec = false;
        result.AppendErrorWithFormat(
            "more than 1 module matched by name '%s'\n", arg_cstr);
      } else {
        search_using_module_spec = false;
        result.AppendErrorWithFormat("no object file for module '%s'\n",
                                     arg_cstr);
      }
    }

    if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
      search_using_module_spec = true;
      module_spec.GetUUID() =
          m_uuid_option_group.GetOptionValue().GetCurrentValue();
    }

    if (search_using_module_spec) {
      ModuleList matching_modules;
      target.GetImages().FindModules(module_spec, matching_modules);
      const size_t num_matches = matching_modules.GetSize();

      char path[PATH_MAX];
      if (num_matches == 1) {
        Module *module = matching_modules.GetModulePointerAtIndex(0);
        if (module) {
          ObjectFile *objfile = module->GetObjectFile();
          if (objfile) {
            SectionList *section_list = module->GetSectionList();
            if (section_list) {
              bool changed = false;
              if (argc == 0) {
                if (m_slide_option.GetOptionValue().OptionWasSet()) {
                  const addr_t slide =
                      m_slide_option.GetOptionValue().GetCurrentValue();
                  const bool slide_is_offset = true;
                  module->SetLoadAddress(target, slide, slide_is_offset,
                                         changed);
                } else {
                  result.AppendError("one or more section name + load "
                                     "address pair must be specified");
                  return;
                }
              } else {
                if (m_slide_option.GetOptionValue().OptionWasSet()) {
                  result.AppendError("The \"--slide <offset>\" option can't "
                                     "be used in conjunction with setting "
                                     "section load addresses.\n");
                  return;
                }

                for (size_t i = 0; i < argc; i += 2) {
                  const char *sect_name = args.GetArgumentAtIndex(i);
                  const char *load_addr_cstr = args.GetArgumentAtIndex(i + 1);
                  if (sect_name && load_addr_cstr) {
                    ConstString const_sect_name(sect_name);
                    addr_t load_addr;
                    if (llvm::to_integer(load_addr_cstr, load_addr)) {
                      SectionSP section_sp(
                          section_list->FindSectionByName(const_sect_name));
                      if (section_sp) {
                        if (section_sp->IsThreadSpecific()) {
                          result.AppendErrorWithFormat(
                              "thread specific sections are not yet "
                              "supported (section '%s')\n",
                              sect_name);
                          break;
                        } else {
                          if (target.SetSectionLoadAddress(section_sp,
                                                           load_addr))
                            changed = true;
                          result.AppendMessageWithFormat(
                              "section '%s' loaded at 0x%" PRIx64 "\n",
                              sect_name, load_addr);
                        }
                      } else {
                        result.AppendErrorWithFormat("no section found that "
                                                     "matches the section "
                                                     "name '%s'\n",
                                                     sect_name);
                        break;
                      }
                    } else {
                      result.AppendErrorWithFormat(
                          "invalid load address string '%s'\n", load_addr_cstr);
                      break;
                    }
                  } else {
                    if (sect_name)
                      result.AppendError("section names must be followed by "
                                         "a load address.\n");
                    else
                      result.AppendError("one or more section name + load "
                                         "address pair must be specified.\n");
                    break;
                  }
                }
              }

              if (changed) {
                target.ModulesDidLoad(matching_modules);
                Process *process = m_exe_ctx.GetProcessPtr();
                if (process)
                  process->Flush();
              }
              if (load) {
                ProcessSP process = target.CalculateProcess();
                Address file_entry = objfile->GetEntryPointAddress();
                if (!process) {
                  result.AppendError("No process");
                  return;
                }
                if (set_pc && !file_entry.IsValid()) {
                  result.AppendError("No entry address in object file");
                  return;
                }
                std::vector<ObjectFile::LoadableData> loadables(
                    objfile->GetLoadableData(target));
                if (loadables.size() == 0) {
                  result.AppendError("No loadable sections");
                  return;
                }
                Status error = process->WriteObjectFile(std::move(loadables));
                if (error.Fail()) {
                  result.AppendError(error.AsCString());
                  return;
                }
                if (set_pc) {
                  ThreadList &thread_list = process->GetThreadList();
                  RegisterContextSP reg_context(
                      thread_list.GetSelectedThread()->GetRegisterContext());
                  addr_t file_entry_addr = file_entry.GetLoadAddress(&target);
                  if (!reg_context->SetPC(file_entry_addr)) {
                    result.AppendErrorWithFormat("failed to set PC value to "
                                                 "0x%" PRIx64 "\n",
                                                 file_entry_addr);
                  }
                }
              }
            } else {
              module->GetFileSpec().GetPath(path, sizeof(path));
              result.AppendErrorWithFormat("no sections in object file '%s'\n",
                                           path);
            }
          } else {
            module->GetFileSpec().GetPath(path, sizeof(path));
            result.AppendErrorWithFormat("no object file for module '%s'\n",
                                         path);
          }
        } else {
          FileSpec *module_spec_file = module_spec.GetFileSpecPtr();
          if (module_spec_file) {
            module_spec_file->GetPath(path, sizeof(path));
            result.AppendErrorWithFormat("invalid module '%s'.\n", path);
          } else
            result.AppendError("no module spec");
        }
      } else {
        std::string uuid_str;

        if (module_spec.GetFileSpec())
          module_spec.GetFileSpec().GetPath(path, sizeof(path));
        else
          path[0] = '\0';

        if (module_spec.GetUUIDPtr())
          uuid_str = module_spec.GetUUID().GetAsString();
        if (num_matches > 1) {
          result.AppendErrorWithFormat(
              "multiple modules match%s%s%s%s:\n", path[0] ? " file=" : "",
              path, !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str());
          for (size_t i = 0; i < num_matches; ++i) {
            if (matching_modules.GetModulePointerAtIndex(i)
                    ->GetFileSpec()
                    .GetPath(path, sizeof(path)))
              result.AppendMessageWithFormat("%s\n", path);
          }
        } else {
          result.AppendErrorWithFormat(
              "no modules were found  that match%s%s%s%s.\n",
              path[0] ? " file=" : "", path, !uuid_str.empty() ? " uuid=" : "",
              uuid_str.c_str());
        }
      }
    } else {
      result.AppendError("either the \"--file <module>\" or the \"--uuid "
                         "<uuid>\" option must be specified.\n");
    }
  }

  OptionGroupOptions m_option_group;
  OptionGroupUUID m_uuid_option_group;
  OptionGroupString m_file_option;
  OptionGroupBoolean m_load_option;
  OptionGroupBoolean m_pc_option;
  OptionGroupUInt64 m_slide_option;
};

#pragma mark CommandObjectTargetModulesList
// List images with associated information
#define LLDB_OPTIONS_target_modules_list
#include "CommandOptions.inc"

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

    ~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;
      if (short_option == 'g') {
        m_use_global_module_list = true;
      } else if (short_option == 'a') {
        m_module_addr = OptionArgParser::ToAddress(
            execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
      } else {
        unsigned long width = 0;
        option_arg.getAsInteger(0, width);
        m_format_array.push_back(std::make_pair(short_option, width));
      }
      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_format_array.clear();
      m_use_global_module_list = false;
      m_module_addr = LLDB_INVALID_ADDRESS;
    }

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

    // Instance variables to hold the values for command options.
    typedef std::vector<std::pair<char, uint32_t>> FormatWidthCollection;
    FormatWidthCollection m_format_array;
    bool m_use_global_module_list = false;
    lldb::addr_t m_module_addr = LLDB_INVALID_ADDRESS;
  };

  CommandObjectTargetModulesList(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "target modules list",
            "List current executable and dependent shared library images.") {
    AddSimpleArgumentList(eArgTypeModule, eArgRepeatStar);
  }

  ~CommandObjectTargetModulesList() override = default;

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

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Target &target = GetTarget();
    const bool use_global_module_list = m_options.m_use_global_module_list;
    // Define a local module list here to ensure it lives longer than any
    // "locker" object which might lock its contents below (through the
    // "module_list_ptr" variable).
    ModuleList module_list;
    uint32_t addr_byte_size = target.GetArchitecture().GetAddressByteSize();
    result.GetOutputStream().SetAddressByteSize(addr_byte_size);
    result.GetErrorStream().SetAddressByteSize(addr_byte_size);
    // Dump all sections for all modules images
    Stream &strm = result.GetOutputStream();

    if (m_options.m_module_addr != LLDB_INVALID_ADDRESS) {
      Address module_address;
      if (module_address.SetLoadAddress(m_options.m_module_addr, &target)) {
        ModuleSP module_sp(module_address.GetModule());
        if (module_sp) {
          PrintModule(target, module_sp.get(), 0, strm);
          result.SetStatus(eReturnStatusSuccessFinishResult);
        } else {
          result.AppendErrorWithFormat(
              "Couldn't find module matching address: 0x%" PRIx64 ".",
              m_options.m_module_addr);
        }
      } else {
        result.AppendErrorWithFormat(
            "Couldn't find module containing address: 0x%" PRIx64 ".",
            m_options.m_module_addr);
      }
      return;
    }

      size_t num_modules = 0;

      // This locker will be locked on the mutex in module_list_ptr if it is
      // non-nullptr. Otherwise it will lock the
      // AllocationModuleCollectionMutex when accessing the global module list
      // directly.
      std::unique_lock<std::recursive_mutex> guard(
          Module::GetAllocationModuleCollectionMutex(), std::defer_lock);

      const ModuleList *module_list_ptr = nullptr;
      const size_t argc = command.GetArgumentCount();
      if (argc == 0) {
        if (use_global_module_list) {
          guard.lock();
          num_modules = Module::GetNumberAllocatedModules();
        } else {
          module_list_ptr = &target.GetImages();
        }
      } else {
        for (const Args::ArgEntry &arg : command) {
          // Dump specified images (by basename or fullpath)
          const size_t num_matches = FindModulesByName(
              &target, arg.c_str(), module_list, use_global_module_list);
          if (num_matches == 0) {
            if (argc == 1) {
              result.AppendErrorWithFormat("no modules found that match '%s'",
                                           arg.c_str());
              return;
            }
          }
        }

        module_list_ptr = &module_list;
      }

      std::unique_lock<std::recursive_mutex> lock;
      if (module_list_ptr != nullptr) {
        lock =
            std::unique_lock<std::recursive_mutex>(module_list_ptr->GetMutex());

        num_modules = module_list_ptr->GetSize();
      }

      if (num_modules > 0) {
        for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
          ModuleSP module_sp;
          Module *module;
          if (module_list_ptr) {
            module_sp = module_list_ptr->GetModuleAtIndexUnlocked(image_idx);
            module = module_sp.get();
          } else {
            module = Module::GetAllocatedModuleAtIndex(image_idx);
            module_sp = module->shared_from_this();
          }

          const size_t indent = strm.Printf("[%3u] ", image_idx);
          PrintModule(target, module, indent, strm);
        }
        result.SetStatus(eReturnStatusSuccessFinishResult);
      } else {
        if (argc) {
          if (use_global_module_list)
            result.AppendError(
                "the global module list has no matching modules");
          else
            result.AppendError("the target has no matching modules");
        } else {
          if (use_global_module_list)
            result.AppendError("the global module list is empty");
          else
            result.AppendError(
                "the target has no associated executable images");
        }
        return;
      }
  }

  void PrintModule(Target &target, Module *module, int indent, Stream &strm) {
    if (module == nullptr) {
      strm.PutCString("Null module");
      return;
    }

    bool dump_object_name = false;
    if (m_options.m_format_array.empty()) {
      m_options.m_format_array.push_back(std::make_pair('u', 0));
      m_options.m_format_array.push_back(std::make_pair('h', 0));
      m_options.m_format_array.push_back(std::make_pair('f', 0));
      m_options.m_format_array.push_back(std::make_pair('S', 0));
    }
    const size_t num_entries = m_options.m_format_array.size();
    bool print_space = false;
    for (size_t i = 0; i < num_entries; ++i) {
      if (print_space)
        strm.PutChar(' ');
      print_space = true;
      const char format_char = m_options.m_format_array[i].first;
      uint32_t width = m_options.m_format_array[i].second;
      switch (format_char) {
      case 'A':
        DumpModuleArchitecture(strm, module, false, width);
        break;

      case 't':
        DumpModuleArchitecture(strm, module, true, width);
        break;

      case 'f':
        DumpFullpath(strm, &module->GetFileSpec(), width);
        dump_object_name = true;
        break;

      case 'd':
        DumpDirectory(strm, &module->GetFileSpec(), width);
        break;

      case 'b':
        DumpBasename(strm, &module->GetFileSpec(), width);
        dump_object_name = true;
        break;

      case 'h':
      case 'o':
        // Image header address
        {
          uint32_t addr_nibble_width =
              target.GetArchitecture().GetAddressByteSize() * 2;

          ObjectFile *objfile = module->GetObjectFile();
          if (objfile) {
            Address base_addr(objfile->GetBaseAddress());
            if (base_addr.IsValid()) {
              if (target.HasLoadedSections()) {
                lldb::addr_t load_addr = base_addr.GetLoadAddress(&target);
                if (load_addr == LLDB_INVALID_ADDRESS) {
                  base_addr.Dump(&strm, &target,
                                 Address::DumpStyleModuleWithFileAddress,
                                 Address::DumpStyleFileAddress);
                } else {
                  if (format_char == 'o') {
                    // Show the offset of slide for the image
                    strm.Printf("0x%*.*" PRIx64, addr_nibble_width,
                                addr_nibble_width,
                                load_addr - base_addr.GetFileAddress());
                  } else {
                    // Show the load address of the image
                    strm.Printf("0x%*.*" PRIx64, addr_nibble_width,
                                addr_nibble_width, load_addr);
                  }
                }
                break;
              }
              // The address was valid, but the image isn't loaded, output the
              // address in an appropriate format
              base_addr.Dump(&strm, &target, Address::DumpStyleFileAddress);
              break;
            }
          }
          strm.Printf("%*s", addr_nibble_width + 2, "");
        }
        break;

      case 'r': {
        size_t ref_count = 0;
        char in_shared_cache = 'Y';

        ModuleSP module_sp(module->shared_from_this());
        if (!ModuleList::ModuleIsInCache(module))
          in_shared_cache = 'N';
        if (module_sp) {
          // Take one away to make sure we don't count our local "module_sp"
          ref_count = module_sp.use_count() - 1;
        }
        if (width)
          strm.Printf("{%c %*" PRIu64 "}", in_shared_cache, width, (uint64_t)ref_count);
        else
          strm.Printf("{%c %" PRIu64 "}", in_shared_cache, (uint64_t)ref_count);
      } break;

      case 's':
      case 'S': {
        if (const SymbolFile *symbol_file = module->GetSymbolFile()) {
          const FileSpec symfile_spec =
              symbol_file->GetObjectFile()->GetFileSpec();
          if (format_char == 'S') {
            // Dump symbol file only if different from module file
            if (!symfile_spec || symfile_spec == module->GetFileSpec()) {
              print_space = false;
              break;
            }
            // Add a newline and indent past the index
            strm.Printf("\n%*s", indent, "");
          }
          DumpFullpath(strm, &symfile_spec, width);
          dump_object_name = true;
          break;
        }
        strm.Printf("%.*s", width, "<NONE>");
      } break;

      case 'm':
        strm.Format("{0:%c}", llvm::fmt_align(module->GetModificationTime(),
                                              llvm::AlignStyle::Left, width));
        break;

      case 'p':
        strm.Printf("%p", static_cast<void *>(module));
        break;

      case 'u':
        DumpModuleUUID(strm, module);
        break;

      default:
        break;
      }
    }
    if (dump_object_name) {
      const char *object_name = module->GetObjectName().GetCString();
      if (object_name)
        strm.Printf("(%s)", object_name);
    }
    strm.EOL();
  }

  CommandOptions m_options;
};

#pragma mark CommandObjectTargetModulesShowUnwind

// Lookup unwind information in images
#define LLDB_OPTIONS_target_modules_show_unwind
#include "CommandOptions.inc"

class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed {
public:
  enum {
    eLookupTypeInvalid = -1,
    eLookupTypeAddress = 0,
    eLookupTypeSymbol,
    eLookupTypeFunction,
    eLookupTypeFunctionOrSymbol,
    kNumLookupTypes
  };

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

    ~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': {
        m_str = std::string(option_arg);
        m_type = eLookupTypeAddress;
        m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
                                            LLDB_INVALID_ADDRESS, &error);
        if (m_addr == LLDB_INVALID_ADDRESS)
          error = Status::FromErrorStringWithFormat(
              "invalid address string '%s'", option_arg.str().c_str());
        break;
      }

      case 'n':
        m_str = std::string(option_arg);
        m_type = eLookupTypeFunctionOrSymbol;
        break;

      case 'c':
        bool value, success;
        value = OptionArgParser::ToBoolean(option_arg, false, &success);
        if (success) {
          m_cached = value;
        } else {
          return Status::FromErrorStringWithFormatv(
              "invalid boolean value '%s' passed for -c option", option_arg);
        }
        break;

      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_type = eLookupTypeInvalid;
      m_str.clear();
      m_addr = LLDB_INVALID_ADDRESS;
      m_cached = false;
    }

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

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

    int m_type = eLookupTypeInvalid; // Should be a eLookupTypeXXX enum after
                                     // parsing options
    std::string m_str; // Holds name lookup
    lldb::addr_t m_addr = LLDB_INVALID_ADDRESS; // Holds the address to lookup
    bool m_cached = true;
  };

  CommandObjectTargetModulesShowUnwind(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "target modules show-unwind",
            "Show synthesized unwind instructions for a function.", nullptr,
            eCommandRequiresTarget | eCommandRequiresProcess |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}

  ~CommandObjectTargetModulesShowUnwind() override = default;

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

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = m_exe_ctx.GetTargetPtr();
    Process *process = m_exe_ctx.GetProcessPtr();
    ABI *abi = nullptr;
    if (process)
      abi = process->GetABI().get();

    if (process == nullptr) {
      result.AppendError(
          "You must have a process running to use this command.");
      return;
    }

    ThreadList threads(process->GetThreadList());
    if (threads.GetSize() == 0) {
      result.AppendError("The process must be paused to use this command.");
      return;
    }

    ThreadSP thread(threads.GetThreadAtIndex(0));
    if (!thread) {
      result.AppendError("The process must be paused to use this command.");
      return;
    }

    SymbolContextList sc_list;

    if (m_options.m_type == eLookupTypeFunctionOrSymbol) {
      ConstString function_name(m_options.m_str.c_str());
      ModuleFunctionSearchOptions function_options;
      function_options.include_symbols = true;
      function_options.include_inlines = false;
      target->GetImages().FindFunctions(function_name, eFunctionNameTypeAuto,
                                        function_options, sc_list);
    } else if (m_options.m_type == eLookupTypeAddress && target) {
      Address addr;
      if (target->ResolveLoadAddress(m_options.m_addr, addr)) {
        SymbolContext sc;
        ModuleSP module_sp(addr.GetModule());
        module_sp->ResolveSymbolContextForAddress(addr,
                                                  eSymbolContextEverything, sc);
        if (sc.function || sc.symbol) {
          sc_list.Append(sc);
        }
      }
    } else {
      result.AppendError(
          "address-expression or function name option must be specified.");
      return;
    }

    if (sc_list.GetSize() == 0) {
      result.AppendErrorWithFormat("no unwind data found that matches '%s'.",
                                   m_options.m_str.c_str());
      return;
    }

    for (const SymbolContext &sc : sc_list) {
      if (sc.symbol == nullptr && sc.function == nullptr)
        continue;
      if (!sc.module_sp || sc.module_sp->GetObjectFile() == nullptr)
        continue;
      Address addr = sc.GetFunctionOrSymbolAddress();
      if (!addr.IsValid())
        continue;
      ConstString funcname(sc.GetFunctionName());
      if (funcname.IsEmpty())
        continue;
      addr_t start_addr = addr.GetLoadAddress(target);
      if (abi)
        start_addr = abi->FixCodeAddress(start_addr);

      UnwindTable &uw_table = sc.module_sp->GetUnwindTable();
      FuncUnwindersSP func_unwinders_sp =
          m_options.m_cached
              ? uw_table.GetFuncUnwindersContainingAddress(start_addr, sc)
              : uw_table.GetUncachedFuncUnwindersContainingAddress(start_addr,
                                                                   sc);
      if (!func_unwinders_sp)
        continue;

      result.GetOutputStream().Printf(
          "UNWIND PLANS for %s`%s (start addr 0x%" PRIx64 ")\n",
          sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(),
          funcname.AsCString(), start_addr);

      Args args;
      target->GetUserSpecifiedTrapHandlerNames(args);
      size_t count = args.GetArgumentCount();
      for (size_t i = 0; i < count; i++) {
        const char *trap_func_name = args.GetArgumentAtIndex(i);
        if (strcmp(funcname.GetCString(), trap_func_name) == 0)
          result.GetOutputStream().Printf(
              "This function is "
              "treated as a trap handler function via user setting.\n");
      }
      PlatformSP platform_sp(target->GetPlatform());
      if (platform_sp) {
        const std::vector<ConstString> trap_handler_names(
            platform_sp->GetTrapHandlerSymbolNames());
        for (ConstString trap_name : trap_handler_names) {
          if (trap_name == funcname) {
            result.GetOutputStream().Printf(
                "This function's "
                "name is listed by the platform as a trap handler.\n");
          }
        }
      }

      result.GetOutputStream().Printf("\n");

      UnwindPlanSP non_callsite_unwind_plan =
          func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread);
      if (non_callsite_unwind_plan) {
        result.GetOutputStream().Printf(
            "Asynchronous (not restricted to call-sites) UnwindPlan is '%s'\n",
            non_callsite_unwind_plan->GetSourceName().AsCString());
      }
      UnwindPlanSP callsite_unwind_plan =
          func_unwinders_sp->GetUnwindPlanAtCallSite(*target, *thread);
      if (callsite_unwind_plan) {
        result.GetOutputStream().Printf(
            "Synchronous (restricted to call-sites) UnwindPlan is '%s'\n",
            callsite_unwind_plan->GetSourceName().AsCString());
      }
      UnwindPlanSP fast_unwind_plan =
          func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread);
      if (fast_unwind_plan) {
        result.GetOutputStream().Printf(
            "Fast UnwindPlan is '%s'\n",
            fast_unwind_plan->GetSourceName().AsCString());
      }

      result.GetOutputStream().Printf("\n");

      UnwindPlanSP assembly_sp =
          func_unwinders_sp->GetAssemblyUnwindPlan(*target, *thread);
      if (assembly_sp) {
        result.GetOutputStream().Printf(
            "Assembly language inspection UnwindPlan:\n");
        assembly_sp->Dump(result.GetOutputStream(), thread.get(),
                          LLDB_INVALID_ADDRESS);
        result.GetOutputStream().Printf("\n");
      }

      UnwindPlanSP of_unwind_sp =
          func_unwinders_sp->GetObjectFileUnwindPlan(*target);
      if (of_unwind_sp) {
        result.GetOutputStream().Printf("object file UnwindPlan:\n");
        of_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
                           LLDB_INVALID_ADDRESS);
        result.GetOutputStream().Printf("\n");
      }

      UnwindPlanSP of_unwind_augmented_sp =
          func_unwinders_sp->GetObjectFileAugmentedUnwindPlan(*target, *thread);
      if (of_unwind_augmented_sp) {
        result.GetOutputStream().Printf("object file augmented UnwindPlan:\n");
        of_unwind_augmented_sp->Dump(result.GetOutputStream(), thread.get(),
                                     LLDB_INVALID_ADDRESS);
        result.GetOutputStream().Printf("\n");
      }

      UnwindPlanSP ehframe_sp =
          func_unwinders_sp->GetEHFrameUnwindPlan(*target);
      if (ehframe_sp) {
        result.GetOutputStream().Printf("eh_frame UnwindPlan:\n");
        ehframe_sp->Dump(result.GetOutputStream(), thread.get(),
                         LLDB_INVALID_ADDRESS);
        result.GetOutputStream().Printf("\n");
      }

      UnwindPlanSP ehframe_augmented_sp =
          func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(*target, *thread);
      if (ehframe_augmented_sp) {
        result.GetOutputStream().Printf("eh_frame augmented UnwindPlan:\n");
        ehframe_augmented_sp->Dump(result.GetOutputStream(), thread.get(),
                                   LLDB_INVALID_ADDRESS);
        result.GetOutputStream().Printf("\n");
      }

      if (UnwindPlanSP plan_sp =
              func_unwinders_sp->GetDebugFrameUnwindPlan(*target)) {
        result.GetOutputStream().Printf("debug_frame UnwindPlan:\n");
        plan_sp->Dump(result.GetOutputStream(), thread.get(),
                      LLDB_INVALID_ADDRESS);
        result.GetOutputStream().Printf("\n");
      }

      if (UnwindPlanSP plan_sp =
              func_unwinders_sp->GetDebugFrameAugmentedUnwindPlan(*target,
                                                                  *thread)) {
        result.GetOutputStream().Printf("debug_frame augmented UnwindPlan:\n");
        plan_sp->Dump(result.GetOutputStream(), thread.get(),
                      LLDB_INVALID_ADDRESS);
        result.GetOutputStream().Printf("\n");
      }

      UnwindPlanSP arm_unwind_sp =
          func_unwinders_sp->GetArmUnwindUnwindPlan(*target);
      if (arm_unwind_sp) {
        result.GetOutputStream().Printf("ARM.exidx unwind UnwindPlan:\n");
        arm_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
                            LLDB_INVALID_ADDRESS);
        result.GetOutputStream().Printf("\n");
      }

      if (UnwindPlanSP symfile_plan_sp =
              func_unwinders_sp->GetSymbolFileUnwindPlan(*thread)) {
        result.GetOutputStream().Printf("Symbol file UnwindPlan:\n");
        symfile_plan_sp->Dump(result.GetOutputStream(), thread.get(),
                              LLDB_INVALID_ADDRESS);
        result.GetOutputStream().Printf("\n");
      }

      UnwindPlanSP compact_unwind_sp =
          func_unwinders_sp->GetCompactUnwindUnwindPlan(*target);
      if (compact_unwind_sp) {
        result.GetOutputStream().Printf("Compact unwind UnwindPlan:\n");
        compact_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
                                LLDB_INVALID_ADDRESS);
        result.GetOutputStream().Printf("\n");
      }

      if (fast_unwind_plan) {
        result.GetOutputStream().Printf("Fast UnwindPlan:\n");
        fast_unwind_plan->Dump(result.GetOutputStream(), thread.get(),
                               LLDB_INVALID_ADDRESS);
        result.GetOutputStream().Printf("\n");
      }

      ABISP abi_sp = process->GetABI();
      if (abi_sp) {
        if (UnwindPlanSP plan_sp = abi_sp->CreateDefaultUnwindPlan()) {
          result.GetOutputStream().Printf("Arch default UnwindPlan:\n");
          plan_sp->Dump(result.GetOutputStream(), thread.get(),
                        LLDB_INVALID_ADDRESS);
          result.GetOutputStream().Printf("\n");
        }

        if (UnwindPlanSP plan_sp = abi_sp->CreateFunctionEntryUnwindPlan()) {
          result.GetOutputStream().Printf(
              "Arch default at entry point UnwindPlan:\n");
          plan_sp->Dump(result.GetOutputStream(), thread.get(),
                        LLDB_INVALID_ADDRESS);
          result.GetOutputStream().Printf("\n");
        }
      }

      result.GetOutputStream().Printf("\n");
    }
  }

  CommandOptions m_options;
};

// Lookup information in images
#define LLDB_OPTIONS_target_modules_lookup
#include "CommandOptions.inc"

class CommandObjectTargetModulesLookup : public CommandObjectParsed {
public:
  enum {
    eLookupTypeInvalid = -1,
    eLookupTypeAddress = 0,
    eLookupTypeSymbol,
    eLookupTypeFileLine, // Line is optional
    eLookupTypeFunction,
    eLookupTypeFunctionOrSymbol,
    eLookupTypeType,
    kNumLookupTypes
  };

  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 'a': {
        m_type = eLookupTypeAddress;
        m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
                                            LLDB_INVALID_ADDRESS, &error);
      } break;

      case 'o':
        if (option_arg.getAsInteger(0, m_offset))
          error = Status::FromErrorStringWithFormat(
              "invalid offset string '%s'", option_arg.str().c_str());
        break;

      case 's':
        m_str = std::string(option_arg);
        m_type = eLookupTypeSymbol;
        break;

      case 'f':
        m_file.SetFile(option_arg, FileSpec::Style::native);
        m_type = eLookupTypeFileLine;
        break;

      case 'i':
        m_include_inlines = false;
        break;

      case 'l':
        if (option_arg.getAsInteger(0, m_line_number))
          error = Status::FromErrorStringWithFormat(
              "invalid line number string '%s'", option_arg.str().c_str());
        else if (m_line_number == 0)
          error = Status::FromErrorString("zero is an invalid line number");
        m_type = eLookupTypeFileLine;
        break;

      case 'F':
        m_str = std::string(option_arg);
        m_type = eLookupTypeFunction;
        break;

      case 'n':
        m_str = std::string(option_arg);
        m_type = eLookupTypeFunctionOrSymbol;
        break;

      case 't':
        m_str = std::string(option_arg);
        m_type = eLookupTypeType;
        break;

      case 'v':
        m_verbose = true;
        break;

      case 'A':
        m_print_all = true;
        break;

      case 'r':
        m_use_regex = true;
        break;

      case '\x01':
        m_all_ranges = true;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_type = eLookupTypeInvalid;
      m_str.clear();
      m_file.Clear();
      m_addr = LLDB_INVALID_ADDRESS;
      m_offset = 0;
      m_line_number = 0;
      m_use_regex = false;
      m_include_inlines = true;
      m_all_ranges = false;
      m_verbose = false;
      m_print_all = false;
    }

    Status OptionParsingFinished(ExecutionContext *execution_context) override {
      Status status;
      if (m_all_ranges && !m_verbose) {
        status =
            Status::FromErrorString("--show-variable-ranges must be used in "
                                    "conjunction with --verbose.");
      }
      return status;
    }

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

    int m_type;        // Should be a eLookupTypeXXX enum after parsing options
    std::string m_str; // Holds name lookup
    FileSpec m_file;   // Files for file lookups
    lldb::addr_t m_addr; // Holds the address to lookup
    lldb::addr_t
        m_offset; // Subtract this offset from m_addr before doing lookups.
    uint32_t m_line_number; // Line number for file+line lookups
    bool m_use_regex;       // Name lookups in m_str are regular expressions.
    bool m_include_inlines; // Check for inline entries when looking up by
                            // file/line.
    bool m_all_ranges;      // Print all ranges or single range.
    bool m_verbose;         // Enable verbose lookup info
    bool m_print_all; // Print all matches, even in cases where there's a best
                      // match.
  };

  CommandObjectTargetModulesLookup(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "target modules lookup",
                            "Look up information within executable and "
                            "dependent shared library images.",
                            nullptr, eCommandRequiresTarget) {
    AddSimpleArgumentList(eArgTypeFilename, eArgRepeatStar);
  }

  ~CommandObjectTargetModulesLookup() override = default;

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

  bool LookupHere(CommandInterpreter &interpreter, CommandReturnObject &result,
                  bool &syntax_error) {
    switch (m_options.m_type) {
    case eLookupTypeAddress:
    case eLookupTypeFileLine:
    case eLookupTypeFunction:
    case eLookupTypeFunctionOrSymbol:
    case eLookupTypeSymbol:
    default:
      return false;
    case eLookupTypeType:
      break;
    }

    StackFrameSP frame = m_exe_ctx.GetFrameSP();

    if (!frame)
      return false;

    const SymbolContext &sym_ctx(frame->GetSymbolContext(eSymbolContextModule));

    if (!sym_ctx.module_sp)
      return false;

    switch (m_options.m_type) {
    default:
      return false;
    case eLookupTypeType:
      if (!m_options.m_str.empty()) {
        if (LookupTypeHere(&GetTarget(), m_interpreter,
                           result.GetOutputStream(), *sym_ctx.module_sp,
                           m_options.m_str.c_str(), m_options.m_use_regex)) {
          result.SetStatus(eReturnStatusSuccessFinishResult);
          return true;
        }
      }
      break;
    }

    return false;
  }

  bool LookupInModule(CommandInterpreter &interpreter, Module *module,
                      CommandReturnObject &result, bool &syntax_error) {
    switch (m_options.m_type) {
    case eLookupTypeAddress:
      if (m_options.m_addr != LLDB_INVALID_ADDRESS) {
        if (LookupAddressInModule(
                m_interpreter, result.GetOutputStream(), module,
                eSymbolContextEverything |
                    (m_options.m_verbose
                         ? static_cast<int>(eSymbolContextVariable)
                         : 0),
                m_options.m_addr, m_options.m_offset, m_options.m_verbose,
                m_options.m_all_ranges)) {
          result.SetStatus(eReturnStatusSuccessFinishResult);
          return true;
        }
      }
      break;

    case eLookupTypeSymbol:
      if (!m_options.m_str.empty()) {
        if (LookupSymbolInModule(m_interpreter, result.GetOutputStream(),
                                 module, m_options.m_str.c_str(),
                                 m_options.m_use_regex, m_options.m_verbose,
                                 m_options.m_all_ranges)) {
          result.SetStatus(eReturnStatusSuccessFinishResult);
          return true;
        }
      }
      break;

    case eLookupTypeFileLine:
      if (m_options.m_file) {
        if (LookupFileAndLineInModule(
                m_interpreter, result.GetOutputStream(), module,
                m_options.m_file, m_options.m_line_number,
                m_options.m_include_inlines, m_options.m_verbose,
                m_options.m_all_ranges)) {
          result.SetStatus(eReturnStatusSuccessFinishResult);
          return true;
        }
      }
      break;

    case eLookupTypeFunctionOrSymbol:
    case eLookupTypeFunction:
      if (!m_options.m_str.empty()) {
        ModuleFunctionSearchOptions function_options;
        function_options.include_symbols =
            m_options.m_type == eLookupTypeFunctionOrSymbol;
        function_options.include_inlines = m_options.m_include_inlines;

        if (LookupFunctionInModule(m_interpreter, result.GetOutputStream(),
                                   module, m_options.m_str.c_str(),
                                   m_options.m_use_regex, function_options,
                                   m_options.m_verbose,
                                   m_options.m_all_ranges)) {
          result.SetStatus(eReturnStatusSuccessFinishResult);
          return true;
        }
      }
      break;

    case eLookupTypeType:
      if (!m_options.m_str.empty()) {
        if (LookupTypeInModule(
                &GetTarget(), m_interpreter, result.GetOutputStream(), module,
                m_options.m_str.c_str(), m_options.m_use_regex)) {
          result.SetStatus(eReturnStatusSuccessFinishResult);
          return true;
        }
      }
      break;

    default:
      m_options.GenerateOptionUsage(
          result.GetErrorStream(), *this,
          GetCommandInterpreter().GetDebugger().GetTerminalWidth());
      syntax_error = true;
      break;
    }

    result.SetStatus(eReturnStatusFailed);
    return false;
  }

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Target &target = GetTarget();
    bool syntax_error = false;
    uint32_t i;
    uint32_t num_successful_lookups = 0;
    uint32_t addr_byte_size = target.GetArchitecture().GetAddressByteSize();
    result.GetOutputStream().SetAddressByteSize(addr_byte_size);
    result.GetErrorStream().SetAddressByteSize(addr_byte_size);
    // Dump all sections for all modules images

    if (command.GetArgumentCount() == 0) {
      ModuleSP current_module;

      // Where it is possible to look in the current symbol context first,
      // try that.  If this search was successful and --all was not passed,
      // don't print anything else.
      if (LookupHere(m_interpreter, result, syntax_error)) {
        result.GetOutputStream().EOL();
        num_successful_lookups++;
        if (!m_options.m_print_all) {
          result.SetStatus(eReturnStatusSuccessFinishResult);
          return;
        }
      }

      // Dump all sections for all other modules

      const ModuleList &target_modules = target.GetImages();
      std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
      if (target_modules.GetSize() == 0) {
        result.AppendError("the target has no associated executable images");
        return;
      }

      for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
        if (module_sp != current_module &&
            LookupInModule(m_interpreter, module_sp.get(), result,
                           syntax_error)) {
          result.GetOutputStream().EOL();
          num_successful_lookups++;
        }
      }
    } else {
      // Dump specified images (by basename or fullpath)
      const char *arg_cstr;
      for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != nullptr &&
                  !syntax_error;
           ++i) {
        ModuleList module_list;
        const size_t num_matches =
            FindModulesByName(&target, arg_cstr, module_list, false);
        if (num_matches > 0) {
          for (size_t j = 0; j < num_matches; ++j) {
            Module *module = module_list.GetModulePointerAtIndex(j);
            if (module) {
              if (LookupInModule(m_interpreter, module, result, syntax_error)) {
                result.GetOutputStream().EOL();
                num_successful_lookups++;
              }
            }
          }
        } else
          result.AppendWarningWithFormat(
              "Unable to find an image that matches '%s'.\n", arg_cstr);
      }
    }

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

  CommandOptions m_options;
};

#pragma mark CommandObjectMultiwordImageSearchPaths

// CommandObjectMultiwordImageSearchPaths

class CommandObjectTargetModulesImageSearchPaths
    : public CommandObjectMultiword {
public:
  CommandObjectTargetModulesImageSearchPaths(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "target modules search-paths",
            "Commands for managing module search paths for a target.",
            "target modules search-paths <subcommand> [<subcommand-options>]") {
    LoadSubCommand(
        "add", CommandObjectSP(
                   new CommandObjectTargetModulesSearchPathsAdd(interpreter)));
    LoadSubCommand(
        "clear", CommandObjectSP(new CommandObjectTargetModulesSearchPathsClear(
                     interpreter)));
    LoadSubCommand(
        "insert",
        CommandObjectSP(
            new CommandObjectTargetModulesSearchPathsInsert(interpreter)));
    LoadSubCommand(
        "list", CommandObjectSP(new CommandObjectTargetModulesSearchPathsList(
                    interpreter)));
    LoadSubCommand(
        "query", CommandObjectSP(new CommandObjectTargetModulesSearchPathsQuery(
                     interpreter)));
  }

  ~CommandObjectTargetModulesImageSearchPaths() override = default;
};

#pragma mark CommandObjectTargetModules

// CommandObjectTargetModules

class CommandObjectTargetModules : public CommandObjectMultiword {
public:
  // Constructors and Destructors
  CommandObjectTargetModules(CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "target modules",
                               "Commands for accessing information for one or "
                               "more target modules.",
                               "target modules <sub-command> ...") {
    LoadSubCommand(
        "add", CommandObjectSP(new CommandObjectTargetModulesAdd(interpreter)));
    LoadSubCommand("load", CommandObjectSP(new CommandObjectTargetModulesLoad(
                               interpreter)));
    LoadSubCommand("dump", CommandObjectSP(new CommandObjectTargetModulesDump(
                               interpreter)));
    LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetModulesList(
                               interpreter)));
    LoadSubCommand(
        "lookup",
        CommandObjectSP(new CommandObjectTargetModulesLookup(interpreter)));
    LoadSubCommand(
        "search-paths",
        CommandObjectSP(
            new CommandObjectTargetModulesImageSearchPaths(interpreter)));
    LoadSubCommand(
        "show-unwind",
        CommandObjectSP(new CommandObjectTargetModulesShowUnwind(interpreter)));
  }

  ~CommandObjectTargetModules() override = default;

private:
  // For CommandObjectTargetModules only
  CommandObjectTargetModules(const CommandObjectTargetModules &) = delete;
  const CommandObjectTargetModules &
  operator=(const CommandObjectTargetModules &) = delete;
};

class CommandObjectTargetSymbolsAdd : public CommandObjectParsed {
public:
  CommandObjectTargetSymbolsAdd(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "target symbols add",
            "Add a debug symbol file to one of the target's current modules by "
            "specifying a path to a debug symbols file or by using the options "
            "to specify a module.",
            "target symbols add <cmd-options> [<symfile>]",
            eCommandRequiresTarget),
        m_file_option(
            LLDB_OPT_SET_1, false, "shlib", 's', lldb::eModuleCompletion,
            eArgTypeShlibName,
            "Locate the debug symbols for the shared library specified by "
            "name."),
        m_current_frame_option(
            LLDB_OPT_SET_2, false, "frame", 'F',
            "Locate the debug symbols for the currently selected frame.", false,
            true),
        m_current_stack_option(LLDB_OPT_SET_2, false, "stack", 'S',
                               "Locate the debug symbols for every frame in "
                               "the current call stack.",
                               false, true)

  {
    m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
                          LLDB_OPT_SET_1);
    m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_current_frame_option, LLDB_OPT_SET_2,
                          LLDB_OPT_SET_2);
    m_option_group.Append(&m_current_stack_option, LLDB_OPT_SET_2,
                          LLDB_OPT_SET_2);
    m_option_group.Finalize();
    AddSimpleArgumentList(eArgTypeFilename);
  }

  ~CommandObjectTargetSymbolsAdd() override = default;

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

protected:
  bool AddModuleSymbols(Target *target, ModuleSpec &module_spec, bool &flush,
                        CommandReturnObject &result) {
    const FileSpec &symbol_fspec = module_spec.GetSymbolFileSpec();
    if (!symbol_fspec) {
      result.AppendError(
          "one or more executable image paths must be specified");
      return false;
    }

    char symfile_path[PATH_MAX];
    symbol_fspec.GetPath(symfile_path, sizeof(symfile_path));

    if (!module_spec.GetUUID().IsValid()) {
      if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec())
        module_spec.GetFileSpec().SetFilename(symbol_fspec.GetFilename());
    }

    // Now module_spec represents a symbol file for a module that might exist
    // in the current target.  Let's find possible matches.
    ModuleList matching_modules;

    // First extract all module specs from the symbol file
    lldb_private::ModuleSpecList symfile_module_specs;
    if (ObjectFile::GetModuleSpecifications(module_spec.GetSymbolFileSpec(),
                                            0, 0, symfile_module_specs)) {
      // Now extract the module spec that matches the target architecture
      ModuleSpec target_arch_module_spec;
      ModuleSpec symfile_module_spec;
      target_arch_module_spec.GetArchitecture() = target->GetArchitecture();
      if (symfile_module_specs.FindMatchingModuleSpec(target_arch_module_spec,
                                                      symfile_module_spec)) {
        if (symfile_module_spec.GetUUID().IsValid()) {
          // It has a UUID, look for this UUID in the target modules
          ModuleSpec symfile_uuid_module_spec;
          symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID();
          target->GetImages().FindModules(symfile_uuid_module_spec,
                                          matching_modules);
        }
      }

      if (matching_modules.IsEmpty()) {
        // No matches yet.  Iterate through the module specs to find a UUID
        // value that we can match up to an image in our target.
        const size_t num_symfile_module_specs = symfile_module_specs.GetSize();
        for (size_t i = 0;
             i < num_symfile_module_specs && matching_modules.IsEmpty(); ++i) {
          if (symfile_module_specs.GetModuleSpecAtIndex(
                  i, symfile_module_spec)) {
            if (symfile_module_spec.GetUUID().IsValid()) {
              // It has a UUID.  Look for this UUID in the target modules.
              ModuleSpec symfile_uuid_module_spec;
              symfile_uuid_module_spec.GetUUID() =
                  symfile_module_spec.GetUUID();
              target->GetImages().FindModules(symfile_uuid_module_spec,
                                              matching_modules);
            }
          }
        }
      }
    }

    // Just try to match up the file by basename if we have no matches at
    // this point.  For example, module foo might have symbols in foo.debug.
    if (matching_modules.IsEmpty())
      target->GetImages().FindModules(module_spec, matching_modules);

    while (matching_modules.IsEmpty()) {
      ConstString filename_no_extension(
          module_spec.GetFileSpec().GetFileNameStrippingExtension());
      // Empty string returned, let's bail
      if (!filename_no_extension)
        break;

      // Check if there was no extension to strip and the basename is the same
      if (filename_no_extension == module_spec.GetFileSpec().GetFilename())
        break;

      // Replace basename with one fewer extension
      module_spec.GetFileSpec().SetFilename(filename_no_extension);
      target->GetImages().FindModules(module_spec, matching_modules);
    }

    if (matching_modules.GetSize() > 1) {
      result.AppendErrorWithFormat("multiple modules match symbol file '%s', "
                                   "use the --uuid option to resolve the "
                                   "ambiguity.\n",
                                   symfile_path);
      return false;
    }

    if (matching_modules.GetSize() == 1) {
      ModuleSP module_sp(matching_modules.GetModuleAtIndex(0));

      // The module has not yet created its symbol vendor, we can just give
      // the existing target module the symfile path to use for when it
      // decides to create it!
      module_sp->SetSymbolFileFileSpec(symbol_fspec);

      SymbolFile *symbol_file =
          module_sp->GetSymbolFile(true, &result.GetErrorStream());
      if (symbol_file) {
        ObjectFile *object_file = symbol_file->GetObjectFile();
        if (object_file && object_file->GetFileSpec() == symbol_fspec) {
          // Provide feedback that the symfile has been successfully added.
          const FileSpec &module_fs = module_sp->GetFileSpec();
          result.AppendMessageWithFormat(
              "symbol file '%s' has been added to '%s'\n", symfile_path,
              module_fs.GetPath().c_str());

          // Let clients know something changed in the module if it is
          // currently loaded
          ModuleList module_list;
          module_list.Append(module_sp);
          target->SymbolsDidLoad(module_list);

          // Make sure we load any scripting resources that may be embedded
          // in the debug info files in case the platform supports that.
          Status error;
          StreamString feedback_stream;
          module_sp->LoadScriptingResourceInTarget(target, error,
                                                   feedback_stream);
          if (error.Fail() && error.AsCString())
            result.AppendWarningWithFormat(
                "unable to load scripting data for module %s - error "
                "reported was %s",
                module_sp->GetFileSpec()
                    .GetFileNameStrippingExtension()
                    .GetCString(),
                error.AsCString());
          else if (feedback_stream.GetSize())
            result.AppendWarning(feedback_stream.GetData());

          flush = true;
          result.SetStatus(eReturnStatusSuccessFinishResult);
          return true;
        }
      }
      // Clear the symbol file spec if anything went wrong
      module_sp->SetSymbolFileFileSpec(FileSpec());
    }

    StreamString ss_symfile_uuid;
    if (module_spec.GetUUID().IsValid()) {
      ss_symfile_uuid << " (";
      module_spec.GetUUID().Dump(ss_symfile_uuid);
      ss_symfile_uuid << ')';
    }
    result.AppendErrorWithFormat(
        "symbol file '%s'%s does not match any existing module%s\n",
        symfile_path, ss_symfile_uuid.GetData(),
        !llvm::sys::fs::is_regular_file(symbol_fspec.GetPath())
            ? "\n       please specify the full path to the symbol file"
            : "");
    return false;
  }

  bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
                                   CommandReturnObject &result, bool &flush) {
    Status error;
    if (PluginManager::DownloadObjectAndSymbolFile(module_spec, error)) {
      if (module_spec.GetSymbolFileSpec())
        return AddModuleSymbols(m_exe_ctx.GetTargetPtr(), module_spec, flush,
                                result);
    } else {
      result.SetError(std::move(error));
    }
    return false;
  }

  bool AddSymbolsForUUID(CommandReturnObject &result, bool &flush) {
    assert(m_uuid_option_group.GetOptionValue().OptionWasSet());

    ModuleSpec module_spec;
    module_spec.GetUUID() =
        m_uuid_option_group.GetOptionValue().GetCurrentValue();

    if (!DownloadObjectAndSymbolFile(module_spec, result, flush)) {
      StreamString error_strm;
      error_strm.PutCString("unable to find debug symbols for UUID ");
      module_spec.GetUUID().Dump(error_strm);
      result.AppendError(error_strm.GetString());
      return false;
    }

    return true;
  }

  bool AddSymbolsForFile(CommandReturnObject &result, bool &flush) {
    assert(m_file_option.GetOptionValue().OptionWasSet());

    ModuleSpec module_spec;
    module_spec.GetFileSpec() =
        m_file_option.GetOptionValue().GetCurrentValue();

    Target *target = m_exe_ctx.GetTargetPtr();
    ModuleSP module_sp(target->GetImages().FindFirstModule(module_spec));
    if (module_sp) {
      module_spec.GetFileSpec() = module_sp->GetFileSpec();
      module_spec.GetPlatformFileSpec() = module_sp->GetPlatformFileSpec();
      module_spec.GetUUID() = module_sp->GetUUID();
      module_spec.GetArchitecture() = module_sp->GetArchitecture();
    } else {
      module_spec.GetArchitecture() = target->GetArchitecture();
    }

    if (!DownloadObjectAndSymbolFile(module_spec, result, flush)) {
      StreamString error_strm;
      error_strm.PutCString(
          "unable to find debug symbols for the executable file ");
      error_strm << module_spec.GetFileSpec();
      result.AppendError(error_strm.GetString());
      return false;
    }

    return true;
  }

  bool AddSymbolsForFrame(CommandReturnObject &result, bool &flush) {
    assert(m_current_frame_option.GetOptionValue().OptionWasSet());

    Process *process = m_exe_ctx.GetProcessPtr();
    if (!process) {
      result.AppendError(
          "a process must exist in order to use the --frame option");
      return false;
    }

    const StateType process_state = process->GetState();
    if (!StateIsStoppedState(process_state, true)) {
      result.AppendErrorWithFormat("process is not stopped: %s",
                                   StateAsCString(process_state));
      return false;
    }

    StackFrame *frame = m_exe_ctx.GetFramePtr();
    if (!frame) {
      result.AppendError("invalid current frame");
      return false;
    }

    ModuleSP frame_module_sp(
        frame->GetSymbolContext(eSymbolContextModule).module_sp);
    if (!frame_module_sp) {
      result.AppendError("frame has no module");
      return false;
    }

    ModuleSpec module_spec;
    module_spec.GetUUID() = frame_module_sp->GetUUID();
    module_spec.GetArchitecture() = frame_module_sp->GetArchitecture();
    module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec();

    if (!DownloadObjectAndSymbolFile(module_spec, result, flush)) {
      result.AppendError("unable to find debug symbols for the current frame");
      return false;
    }

    return true;
  }

  bool AddSymbolsForStack(CommandReturnObject &result, bool &flush) {
    assert(m_current_stack_option.GetOptionValue().OptionWasSet());

    Process *process = m_exe_ctx.GetProcessPtr();
    if (!process) {
      result.AppendError(
          "a process must exist in order to use the --stack option");
      return false;
    }

    const StateType process_state = process->GetState();
    if (!StateIsStoppedState(process_state, true)) {
      result.AppendErrorWithFormat("process is not stopped: %s",
                                   StateAsCString(process_state));
      return false;
    }

    Thread *thread = m_exe_ctx.GetThreadPtr();
    if (!thread) {
      result.AppendError("invalid current thread");
      return false;
    }

    bool symbols_found = false;
    uint32_t frame_count = thread->GetStackFrameCount();
    for (uint32_t i = 0; i < frame_count; ++i) {
      lldb::StackFrameSP frame_sp = thread->GetStackFrameAtIndex(i);

      ModuleSP frame_module_sp(
          frame_sp->GetSymbolContext(eSymbolContextModule).module_sp);
      if (!frame_module_sp)
        continue;

      ModuleSpec module_spec;
      module_spec.GetUUID() = frame_module_sp->GetUUID();
      module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec();
      module_spec.GetArchitecture() = frame_module_sp->GetArchitecture();

      bool current_frame_flush = false;
      if (DownloadObjectAndSymbolFile(module_spec, result, current_frame_flush))
        symbols_found = true;
      flush |= current_frame_flush;
    }

    if (!symbols_found) {
      result.AppendError(
          "unable to find debug symbols in the current call stack");
      return false;
    }

    return true;
  }

  void DoExecute(Args &args, CommandReturnObject &result) override {
    Target *target = m_exe_ctx.GetTargetPtr();
    result.SetStatus(eReturnStatusFailed);
    bool flush = false;
    ModuleSpec module_spec;
    const bool uuid_option_set =
        m_uuid_option_group.GetOptionValue().OptionWasSet();
    const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet();
    const bool frame_option_set =
        m_current_frame_option.GetOptionValue().OptionWasSet();
    const bool stack_option_set =
        m_current_stack_option.GetOptionValue().OptionWasSet();
    const size_t argc = args.GetArgumentCount();

    if (argc == 0) {
      if (uuid_option_set)
        AddSymbolsForUUID(result, flush);
      else if (file_option_set)
        AddSymbolsForFile(result, flush);
      else if (frame_option_set)
        AddSymbolsForFrame(result, flush);
      else if (stack_option_set)
        AddSymbolsForStack(result, flush);
      else
        result.AppendError("one or more symbol file paths must be specified, "
                           "or options must be specified");
    } else {
      if (uuid_option_set) {
        result.AppendError("specify either one or more paths to symbol files "
                           "or use the --uuid option without arguments");
      } else if (frame_option_set) {
        result.AppendError("specify either one or more paths to symbol files "
                           "or use the --frame option without arguments");
      } else if (file_option_set && argc > 1) {
        result.AppendError("specify at most one symbol file path when "
                           "--shlib option is set");
      } else {
        PlatformSP platform_sp(target->GetPlatform());

        for (auto &entry : args.entries()) {
          if (!entry.ref().empty()) {
            auto &symbol_file_spec = module_spec.GetSymbolFileSpec();
            symbol_file_spec.SetFile(entry.ref(), FileSpec::Style::native);
            FileSystem::Instance().Resolve(symbol_file_spec);
            if (file_option_set) {
              module_spec.GetFileSpec() =
                  m_file_option.GetOptionValue().GetCurrentValue();
            }
            if (platform_sp) {
              FileSpec symfile_spec;
              if (platform_sp
                      ->ResolveSymbolFile(*target, module_spec, symfile_spec)
                      .Success())
                module_spec.GetSymbolFileSpec() = symfile_spec;
            }

            bool symfile_exists =
                FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec());

            if (symfile_exists) {
              if (!AddModuleSymbols(target, module_spec, flush, result))
                break;
            } else {
              std::string resolved_symfile_path =
                  module_spec.GetSymbolFileSpec().GetPath();
              if (resolved_symfile_path != entry.ref()) {
                result.AppendErrorWithFormat(
                    "invalid module path '%s' with resolved path '%s'\n",
                    entry.c_str(), resolved_symfile_path.c_str());
                break;
              }
              result.AppendErrorWithFormat("invalid module path '%s'\n",
                                           entry.c_str());
              break;
            }
          }
        }
      }
    }

    if (flush) {
      Process *process = m_exe_ctx.GetProcessPtr();
      if (process)
        process->Flush();
    }
  }

  OptionGroupOptions m_option_group;
  OptionGroupUUID m_uuid_option_group;
  OptionGroupFile m_file_option;
  OptionGroupBoolean m_current_frame_option;
  OptionGroupBoolean m_current_stack_option;
};

#pragma mark CommandObjectTargetSymbols

// CommandObjectTargetSymbols

class CommandObjectTargetSymbols : public CommandObjectMultiword {
public:
  // Constructors and Destructors
  CommandObjectTargetSymbols(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "target symbols",
            "Commands for adding and managing debug symbol files.",
            "target symbols <sub-command> ...") {
    LoadSubCommand(
        "add", CommandObjectSP(new CommandObjectTargetSymbolsAdd(interpreter)));
  }

  ~CommandObjectTargetSymbols() override = default;

private:
  // For CommandObjectTargetModules only
  CommandObjectTargetSymbols(const CommandObjectTargetSymbols &) = delete;
  const CommandObjectTargetSymbols &
  operator=(const CommandObjectTargetSymbols &) = delete;
};

#pragma mark CommandObjectTargetStopHookAdd

// CommandObjectTargetStopHookAdd
#define LLDB_OPTIONS_target_stop_hook_add
#include "CommandOptions.inc"

class CommandObjectTargetStopHookAdd : public CommandObjectParsed,
                                       public IOHandlerDelegateMultiline {
public:
  class CommandOptions : public OptionGroup {
  public:
    CommandOptions() : m_line_end(UINT_MAX) {}

    ~CommandOptions() override = default;

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

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

      switch (short_option) {
      case 'c':
        m_class_name = std::string(option_arg);
        m_sym_ctx_specified = true;
        break;

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

      case 'G': {
        bool value, success;
        value = OptionArgParser::ToBoolean(option_arg, false, &success);
        if (success) {
          m_auto_continue = value;
        } else
          error = Status::FromErrorStringWithFormat(
              "invalid boolean value '%s' passed for -G option",
              option_arg.str().c_str());
      } break;
      case 'l':
        if (option_arg.getAsInteger(0, m_line_start)) {
          error = Status::FromErrorStringWithFormat(
              "invalid start line number: \"%s\"", option_arg.str().c_str());
          break;
        }
        m_sym_ctx_specified = true;
        break;

      case 'i':
        m_no_inlines = true;
        break;

      case 'n':
        m_function_name = std::string(option_arg);
        m_func_name_type_mask |= eFunctionNameTypeAuto;
        m_sym_ctx_specified = true;
        break;

      case 'f':
        m_file_name = std::string(option_arg);
        m_sym_ctx_specified = true;
        break;

      case 's':
        m_module_name = std::string(option_arg);
        m_sym_ctx_specified = true;
        break;

      case 't':
        if (option_arg.getAsInteger(0, m_thread_id))
          error = Status::FromErrorStringWithFormat(
              "invalid thread id string '%s'", option_arg.str().c_str());
        m_thread_specified = true;
        break;

      case 'T':
        m_thread_name = std::string(option_arg);
        m_thread_specified = true;
        break;

      case 'q':
        m_queue_name = std::string(option_arg);
        m_thread_specified = true;
        break;

      case 'x':
        if (option_arg.getAsInteger(0, m_thread_index))
          error = Status::FromErrorStringWithFormat(
              "invalid thread index string '%s'", option_arg.str().c_str());
        m_thread_specified = true;
        break;

      case 'o':
        m_use_one_liner = true;
        m_one_liner.push_back(std::string(option_arg));
        break;

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

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_class_name.clear();
      m_function_name.clear();
      m_line_start = 0;
      m_line_end = LLDB_INVALID_LINE_NUMBER;
      m_file_name.clear();
      m_module_name.clear();
      m_func_name_type_mask = eFunctionNameTypeAuto;
      m_thread_id = LLDB_INVALID_THREAD_ID;
      m_thread_index = UINT32_MAX;
      m_thread_name.clear();
      m_queue_name.clear();

      m_no_inlines = false;
      m_sym_ctx_specified = false;
      m_thread_specified = false;

      m_use_one_liner = false;
      m_one_liner.clear();
      m_auto_continue = false;
    }

    std::string m_class_name;
    std::string m_function_name;
    uint32_t m_line_start = 0;
    uint32_t m_line_end = LLDB_INVALID_LINE_NUMBER;
    std::string m_file_name;
    std::string m_module_name;
    uint32_t m_func_name_type_mask =
        eFunctionNameTypeAuto; // A pick from lldb::FunctionNameType.
    lldb::tid_t m_thread_id = LLDB_INVALID_THREAD_ID;
    uint32_t m_thread_index = UINT32_MAX;
    std::string m_thread_name;
    std::string m_queue_name;
    bool m_sym_ctx_specified = false;
    bool m_no_inlines = false;
    bool m_thread_specified = false;
    // Instance variables to hold the values for one_liner options.
    bool m_use_one_liner = false;
    std::vector<std::string> m_one_liner;

    bool m_auto_continue = false;
  };

  CommandObjectTargetStopHookAdd(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "target stop-hook add",
                            "Add a hook to be executed when the target stops."
                            "The hook can either be a list of commands or an "
                            "appropriately defined Python class.  You can also "
                            "add filters so the hook only runs a certain stop "
                            "points.",
                            "target stop-hook add"),
        IOHandlerDelegateMultiline("DONE",
                                   IOHandlerDelegate::Completion::LLDBCommand),
        m_python_class_options("scripted stop-hook", true, 'P') {
    SetHelpLong(
        R"(
Command Based stop-hooks:
-------------------------
  Stop hooks can run a list of lldb commands by providing one or more
  --one-line-command options.  The commands will get run in the order they are
  added.  Or you can provide no commands, in which case you will enter a
  command editor where you can enter the commands to be run.

Python Based Stop Hooks:
------------------------
  Stop hooks can be implemented with a suitably defined Python class, whose name
  is passed in the --python-class option.

  When the stop hook is added, the class is initialized by calling:

    def __init__(self, target, extra_args, internal_dict):

    target: The target that the stop hook is being added to.
    extra_args: An SBStructuredData Dictionary filled with the -key -value
                option pairs passed to the command.
    dict: An implementation detail provided by lldb.

  Then when the stop-hook triggers, lldb will run the 'handle_stop' method.
  The method has the signature:

    def handle_stop(self, exe_ctx, stream):

    exe_ctx: An SBExecutionContext for the thread that has stopped.
    stream: An SBStream, anything written to this stream will be printed in the
            the stop message when the process stops.

    Return Value: The method returns "should_stop".  If should_stop is false
                  from all the stop hook executions on threads that stopped
                  with a reason, then the process will continue.  Note that this
                  will happen only after all the stop hooks are run.

Filter Options:
---------------
  Stop hooks can be set to always run, or to only run when the stopped thread
  matches the filter options passed on the command line.  The available filter
  options include a shared library or a thread or queue specification,
  a line range in a source file, a function name or a class name.
            )");
    m_all_options.Append(&m_python_class_options,
                         LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
                         LLDB_OPT_SET_FROM_TO(4, 6));
    m_all_options.Append(&m_options);
    m_all_options.Finalize();
  }

  ~CommandObjectTargetStopHookAdd() override = default;

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

protected:
  void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
    if (interactive) {
      if (lldb::LockableStreamFileSP output_sp =
              io_handler.GetOutputStreamFileSP()) {
        LockedStreamFile locked_stream = output_sp->Lock();
        locked_stream.PutCString(
            "Enter your stop hook command(s).  Type 'DONE' to end.\n");
      }
    }
  }

  void IOHandlerInputComplete(IOHandler &io_handler,
                              std::string &line) override {
    if (m_stop_hook_sp) {
      if (line.empty()) {
        if (lldb::LockableStreamFileSP error_sp =
                io_handler.GetErrorStreamFileSP()) {
          LockedStreamFile locked_stream = error_sp->Lock();
          locked_stream.Printf("error: stop hook #%" PRIu64
                               " aborted, no commands.\n",
                               m_stop_hook_sp->GetID());
        }
        GetTarget().UndoCreateStopHook(m_stop_hook_sp->GetID());
      } else {
        // The IOHandler editor is only for command lines stop hooks:
        Target::StopHookCommandLine *hook_ptr =
            static_cast<Target::StopHookCommandLine *>(m_stop_hook_sp.get());

        hook_ptr->SetActionFromString(line);
        if (lldb::LockableStreamFileSP output_sp =
                io_handler.GetOutputStreamFileSP()) {
          LockedStreamFile locked_stream = output_sp->Lock();
          locked_stream.Printf("Stop hook #%" PRIu64 " added.\n",
                               m_stop_hook_sp->GetID());
        }
      }
      m_stop_hook_sp.reset();
    }
    io_handler.SetIsDone(true);
  }

  void DoExecute(Args &command, CommandReturnObject &result) override {
    m_stop_hook_sp.reset();

    Target &target = GetTarget();
    Target::StopHookSP new_hook_sp =
        target.CreateStopHook(m_python_class_options.GetName().empty() ?
                               Target::StopHook::StopHookKind::CommandBased
                               : Target::StopHook::StopHookKind::ScriptBased);

    //  First step, make the specifier.
    std::unique_ptr<SymbolContextSpecifier> specifier_up;
    if (m_options.m_sym_ctx_specified) {
      specifier_up = std::make_unique<SymbolContextSpecifier>(
          GetDebugger().GetSelectedTarget());

      if (!m_options.m_module_name.empty()) {
        specifier_up->AddSpecification(
            m_options.m_module_name.c_str(),
            SymbolContextSpecifier::eModuleSpecified);
      }

      if (!m_options.m_class_name.empty()) {
        specifier_up->AddSpecification(
            m_options.m_class_name.c_str(),
            SymbolContextSpecifier::eClassOrNamespaceSpecified);
      }

      if (!m_options.m_file_name.empty()) {
        specifier_up->AddSpecification(m_options.m_file_name.c_str(),
                                       SymbolContextSpecifier::eFileSpecified);
      }

      if (m_options.m_line_start != 0) {
        specifier_up->AddLineSpecification(
            m_options.m_line_start,
            SymbolContextSpecifier::eLineStartSpecified);
      }

      if (m_options.m_line_end != UINT_MAX) {
        specifier_up->AddLineSpecification(
            m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified);
      }

      if (!m_options.m_function_name.empty()) {
        specifier_up->AddSpecification(
            m_options.m_function_name.c_str(),
            SymbolContextSpecifier::eFunctionSpecified);
      }
    }

    if (specifier_up)
      new_hook_sp->SetSpecifier(specifier_up.release());

    // Next see if any of the thread options have been entered:

    if (m_options.m_thread_specified) {
      ThreadSpec *thread_spec = new ThreadSpec();

      if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) {
        thread_spec->SetTID(m_options.m_thread_id);
      }

      if (m_options.m_thread_index != UINT32_MAX)
        thread_spec->SetIndex(m_options.m_thread_index);

      if (!m_options.m_thread_name.empty())
        thread_spec->SetName(m_options.m_thread_name.c_str());

      if (!m_options.m_queue_name.empty())
        thread_spec->SetQueueName(m_options.m_queue_name.c_str());

      new_hook_sp->SetThreadSpecifier(thread_spec);
    }

    new_hook_sp->SetAutoContinue(m_options.m_auto_continue);
    if (m_options.m_use_one_liner) {
      // This is a command line stop hook:
      Target::StopHookCommandLine *hook_ptr =
          static_cast<Target::StopHookCommandLine *>(new_hook_sp.get());
      hook_ptr->SetActionFromStrings(m_options.m_one_liner);
      result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n",
                                     new_hook_sp->GetID());
    } else if (!m_python_class_options.GetName().empty()) {
      // This is a scripted stop hook:
      Target::StopHookScripted *hook_ptr =
          static_cast<Target::StopHookScripted *>(new_hook_sp.get());
      Status error = hook_ptr->SetScriptCallback(
          m_python_class_options.GetName(),
          m_python_class_options.GetStructuredData());
      if (error.Success())
        result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n",
                                       new_hook_sp->GetID());
      else {
        // FIXME: Set the stop hook ID counter back.
        result.AppendErrorWithFormat("Couldn't add stop hook: %s",
                                     error.AsCString());
        target.UndoCreateStopHook(new_hook_sp->GetID());
        return;
      }
    } else {
      m_stop_hook_sp = new_hook_sp;
      m_interpreter.GetLLDBCommandsFromIOHandler("> ",   // Prompt
                                                 *this); // IOHandlerDelegate
    }
    result.SetStatus(eReturnStatusSuccessFinishNoResult);
  }

private:
  CommandOptions m_options;
  OptionGroupPythonClassWithDict m_python_class_options;
  OptionGroupOptions m_all_options;

  Target::StopHookSP m_stop_hook_sp;
};

#pragma mark CommandObjectTargetStopHookDelete

// CommandObjectTargetStopHookDelete

class CommandObjectTargetStopHookDelete : public CommandObjectParsed {
public:
  CommandObjectTargetStopHookDelete(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "target stop-hook delete",
                            "Delete a stop-hook.",
                            "target stop-hook delete [<idx>]") {
    AddSimpleArgumentList(eArgTypeStopHookID, eArgRepeatStar);
  }

  ~CommandObjectTargetStopHookDelete() override = default;

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

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Target &target = GetTarget();
    // FIXME: see if we can use the breakpoint id style parser?
    size_t num_args = command.GetArgumentCount();
    if (num_args == 0) {
      if (!m_interpreter.Confirm("Delete all stop hooks?", true)) {
        result.SetStatus(eReturnStatusFailed);
        return;
      } else {
        target.RemoveAllStopHooks();
      }
    } else {
      for (size_t i = 0; i < num_args; i++) {
        lldb::user_id_t user_id;
        if (!llvm::to_integer(command.GetArgumentAtIndex(i), user_id)) {
          result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
                                       command.GetArgumentAtIndex(i));
          return;
        }
        if (!target.RemoveStopHookByID(user_id)) {
          result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
                                       command.GetArgumentAtIndex(i));
          return;
        }
      }
    }
    result.SetStatus(eReturnStatusSuccessFinishNoResult);
  }
};

#pragma mark CommandObjectTargetStopHookEnableDisable

// CommandObjectTargetStopHookEnableDisable

class CommandObjectTargetStopHookEnableDisable : public CommandObjectParsed {
public:
  CommandObjectTargetStopHookEnableDisable(CommandInterpreter &interpreter,
                                           bool enable, const char *name,
                                           const char *help, const char *syntax)
      : CommandObjectParsed(interpreter, name, help, syntax), m_enable(enable) {
    AddSimpleArgumentList(eArgTypeStopHookID, eArgRepeatStar);
  }

  ~CommandObjectTargetStopHookEnableDisable() override = default;

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

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Target &target = GetTarget();
    // FIXME: see if we can use the breakpoint id style parser?
    size_t num_args = command.GetArgumentCount();
    bool success;

    if (num_args == 0) {
      target.SetAllStopHooksActiveState(m_enable);
    } else {
      for (size_t i = 0; i < num_args; i++) {
        lldb::user_id_t user_id;
        if (!llvm::to_integer(command.GetArgumentAtIndex(i), user_id)) {
          result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
                                       command.GetArgumentAtIndex(i));
          return;
        }
        success = target.SetStopHookActiveStateByID(user_id, m_enable);
        if (!success) {
          result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
                                       command.GetArgumentAtIndex(i));
          return;
        }
      }
    }
    result.SetStatus(eReturnStatusSuccessFinishNoResult);
  }

private:
  bool m_enable;
};

#pragma mark CommandObjectTargetStopHookList

// CommandObjectTargetStopHookList

class CommandObjectTargetStopHookList : public CommandObjectParsed {
public:
  CommandObjectTargetStopHookList(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "target stop-hook list",
                            "List all stop-hooks.", "target stop-hook list") {}

  ~CommandObjectTargetStopHookList() override = default;

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

    size_t num_hooks = target.GetNumStopHooks();
    if (num_hooks == 0) {
      result.GetOutputStream().PutCString("No stop hooks.\n");
    } else {
      for (size_t i = 0; i < num_hooks; i++) {
        Target::StopHookSP this_hook = target.GetStopHookAtIndex(i);
        if (i > 0)
          result.GetOutputStream().PutCString("\n");
        this_hook->GetDescription(result.GetOutputStream(),
                                  eDescriptionLevelFull);
      }
    }
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

#pragma mark CommandObjectMultiwordTargetStopHooks

// CommandObjectMultiwordTargetStopHooks

class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword {
public:
  CommandObjectMultiwordTargetStopHooks(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "target stop-hook",
            "Commands for operating on debugger target stop-hooks.",
            "target stop-hook <subcommand> [<subcommand-options>]") {
    LoadSubCommand("add", CommandObjectSP(
                              new CommandObjectTargetStopHookAdd(interpreter)));
    LoadSubCommand(
        "delete",
        CommandObjectSP(new CommandObjectTargetStopHookDelete(interpreter)));
    LoadSubCommand("disable",
                   CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
                       interpreter, false, "target stop-hook disable [<id>]",
                       "Disable a stop-hook.", "target stop-hook disable")));
    LoadSubCommand("enable",
                   CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
                       interpreter, true, "target stop-hook enable [<id>]",
                       "Enable a stop-hook.", "target stop-hook enable")));
    LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetStopHookList(
                               interpreter)));
  }

  ~CommandObjectMultiwordTargetStopHooks() override = default;
};

#pragma mark CommandObjectTargetDumpTypesystem

/// Dumps the TypeSystem of the selected Target.
class CommandObjectTargetDumpTypesystem : public CommandObjectParsed {
public:
  CommandObjectTargetDumpTypesystem(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "target dump typesystem",
            "Dump the state of the target's internal type system. Intended to "
            "be used for debugging LLDB itself.",
            nullptr, eCommandRequiresTarget) {}

  ~CommandObjectTargetDumpTypesystem() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    // Go over every scratch TypeSystem and dump to the command output.
    for (lldb::TypeSystemSP ts : GetTarget().GetScratchTypeSystems())
      if (ts)
        ts->Dump(result.GetOutputStream().AsRawOstream());

    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

#pragma mark CommandObjectTargetDumpSectionLoadList

/// Dumps the SectionLoadList of the selected Target.
class CommandObjectTargetDumpSectionLoadList : public CommandObjectParsed {
public:
  CommandObjectTargetDumpSectionLoadList(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "target dump section-load-list",
            "Dump the state of the target's internal section load list. "
            "Intended to be used for debugging LLDB itself.",
            nullptr, eCommandRequiresTarget) {}

  ~CommandObjectTargetDumpSectionLoadList() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Target &target = GetTarget();
    target.DumpSectionLoadList(result.GetOutputStream());
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

#pragma mark CommandObjectTargetDump

/// Multi-word command for 'target dump'.
class CommandObjectTargetDump : public CommandObjectMultiword {
public:
  // Constructors and Destructors
  CommandObjectTargetDump(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "target dump",
            "Commands for dumping information about the target.",
            "target dump [typesystem|section-load-list]") {
    LoadSubCommand(
        "typesystem",
        CommandObjectSP(new CommandObjectTargetDumpTypesystem(interpreter)));
    LoadSubCommand("section-load-list",
                   CommandObjectSP(new CommandObjectTargetDumpSectionLoadList(
                       interpreter)));
  }

  ~CommandObjectTargetDump() override = default;
};

#pragma mark CommandObjectMultiwordTarget

// CommandObjectMultiwordTarget

CommandObjectMultiwordTarget::CommandObjectMultiwordTarget(
    CommandInterpreter &interpreter)
    : CommandObjectMultiword(interpreter, "target",
                             "Commands for operating on debugger targets.",
                             "target <subcommand> [<subcommand-options>]") {
  LoadSubCommand("create",
                 CommandObjectSP(new CommandObjectTargetCreate(interpreter)));
  LoadSubCommand("delete",
                 CommandObjectSP(new CommandObjectTargetDelete(interpreter)));
  LoadSubCommand("dump",
                 CommandObjectSP(new CommandObjectTargetDump(interpreter)));
  LoadSubCommand("list",
                 CommandObjectSP(new CommandObjectTargetList(interpreter)));
  LoadSubCommand("select",
                 CommandObjectSP(new CommandObjectTargetSelect(interpreter)));
  LoadSubCommand("show-launch-environment",
                 CommandObjectSP(new CommandObjectTargetShowLaunchEnvironment(
                     interpreter)));
  LoadSubCommand(
      "stop-hook",
      CommandObjectSP(new CommandObjectMultiwordTargetStopHooks(interpreter)));
  LoadSubCommand("modules",
                 CommandObjectSP(new CommandObjectTargetModules(interpreter)));
  LoadSubCommand("symbols",
                 CommandObjectSP(new CommandObjectTargetSymbols(interpreter)));
  LoadSubCommand("variable",
                 CommandObjectSP(new CommandObjectTargetVariable(interpreter)));
}

CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget() = default;
