//===-- 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-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, Stream &s) {
    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)
        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();
    Stream &s = result.GetOutputStream();

    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(s, 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, s);
                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, s);
          } 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, s);
          }
        }
      }
    }

    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->GetSectionLoadList().IsEmpty()) {
      if (!target->GetSectionLoadList().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();

    AddressRange range;

    sc.GetAddressRange(eSymbolContextEverything, 0, true, range);

    DumpAddress(exe_scope, range.GetBaseAddress(), 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.GetSectionLoadList().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.GetSectionLoadList().IsEmpty()) {
                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;

      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

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

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

  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->GetSectionLoadList().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;
      AddressRange range;
      if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0,
                              false, range))
        continue;
      if (!range.GetBaseAddress().IsValid())
        continue;
      ConstString funcname(sc.GetFunctionName());
      if (funcname.IsEmpty())
        continue;
      addr_t start_addr = range.GetBaseAddress().GetLoadAddress(target);
      if (abi)
        start_addr = abi->FixCodeAddress(start_addr);

      FuncUnwindersSP func_unwinders_sp(
          sc.module_sp->GetUnwindTable()
              .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) {
        UnwindPlan arch_default(lldb::eRegisterKindGeneric);
        if (abi_sp->CreateDefaultUnwindPlan(arch_default)) {
          result.GetOutputStream().Printf("Arch default UnwindPlan:\n");
          arch_default.Dump(result.GetOutputStream(), thread.get(),
                            LLDB_INVALID_ADDRESS);
          result.GetOutputStream().Printf("\n");
        }

        UnwindPlan arch_entry(lldb::eRegisterKindGeneric);
        if (abi_sp->CreateFunctionEntryUnwindPlan(arch_entry)) {
          result.GetOutputStream().Printf(
              "Arch default at entry point UnwindPlan:\n");
          arch_entry.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 {
    StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
    if (output_sp && interactive) {
      output_sp->PutCString(
          "Enter your stop hook command(s).  Type 'DONE' to end.\n");
      output_sp->Flush();
    }
  }

  void IOHandlerInputComplete(IOHandler &io_handler,
                              std::string &line) override {
    if (m_stop_hook_sp) {
      if (line.empty()) {
        StreamFileSP error_sp(io_handler.GetErrorStreamFileSP());
        if (error_sp) {
          error_sp->Printf("error: stop hook #%" PRIu64
                           " aborted, no commands.\n",
                           m_stop_hook_sp->GetID());
          error_sp->Flush();
        }
        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);
        StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
        if (output_sp) {
          output_sp->Printf("Stop hook #%" PRIu64 " added.\n",
                            m_stop_hook_sp->GetID());
          output_sp->Flush();
        }
      }
      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.GetSectionLoadList().Dump(result.GetOutputStream(), &target);
    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;
