//===-- 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/Debugger.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/ValueObjectVariable.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/LocateSymbolFile.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/Timer.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-private-enumerations.h"

#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
#include "llvm/ADT/ScopeExit.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>");

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

  uint32_t properties = 0;
  if (target_arch.IsValid()) {
    strm.Printf("%sarch=", properties++ > 0 ? ", " : " ( ");
    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.SetErrorStringWithFormat("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_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.") {
    CommandArgumentEntry arg;
    CommandArgumentData file_arg;

    // Define the first (and only) variant of this arg.
    file_arg.arg_type = eArgTypeFilename;
    file_arg.arg_repetition = eArgRepeatPlain;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg.push_back(file_arg);

    // Push the data for the first argument into the m_arguments vector.
    m_arguments.push_back(arg);

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

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

protected:
  bool 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 false;
      }
    }

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

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

      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 false;
              }
            }
          } 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 false;
              }
            } 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 false;
              }
              if (platform_sp->IsConnected() && !platform_sp->GetFileExists(remote_file)) {
                result.AppendError("remote --> local transfer without local "
                                 "path is not implemented yet");
                return false;
              }
              // 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 false;
        }
      }

      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("can't find plug-in for core file"));
            return false;
          } 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(
              "Unable to find process plug-in for core file '{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());
    }

    return result.Succeeded();
  }

private:
  OptionGroupOptions m_option_group;
  OptionGroupArchitecture m_arch_option;
  OptionGroupPlatform m_platform_options;
  OptionGroupFile m_core_file;
  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:
  bool 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);
    return result.Succeeded();
  }
};

#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) {
    CommandArgumentData target_arg{eArgTypeTargetID, eArgRepeatPlain};
    m_arguments.push_back({target_arg});
  }

  ~CommandObjectTargetSelect() override = default;

protected:
  bool DoExecute(Args &args, CommandReturnObject &result) override {
    if (args.GetArgumentCount() == 1) {
      const char *target_idx_arg = args.GetArgumentAtIndex(0);
      uint32_t target_idx;
      if (llvm::to_integer(target_idx_arg, target_idx)) {
        TargetList &target_list = GetDebugger().GetTargetList();
        const uint32_t num_targets = target_list.GetNumTargets();
        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 {
        result.AppendErrorWithFormat("invalid index string value '%s'\n",
                                     target_idx_arg);
      }
    } else {
      result.AppendError(
          "'target select' takes a single argument: a target index\n");
    }
    return result.Succeeded();
  }
};

#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();
    CommandArgumentData target_arg{eArgTypeTargetID, eArgRepeatStar};
    m_arguments.push_back({target_arg});
  }

  ~CommandObjectTargetDelete() override = default;

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

protected:
  bool 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 (int 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 false;
      }

      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 false;
        }
        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 false;
      }
    } else {
      target_sp = target_list.GetSelectedTarget();
      if (!target_sp) {
        result.AppendErrorWithFormat("no target is currently selected\n");
        return false;
      }
      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 true;
  }

  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:
  bool 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);
    return result.Succeeded();
  }
};

#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.") {
    CommandArgumentEntry arg;
    CommandArgumentData var_name_arg;

    // Define the first (and only) variant of this arg.
    var_name_arg.arg_type = eArgTypeVarName;
    var_name_arg.arg_repetition = eArgRepeatPlus;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg.push_back(var_name_arg);

    // Push the data for the first argument into the m_arguments vector.
    m_arguments.push_back(arg);

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

    valobj_sp->Dump(s, options);
  }

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

  bool 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 false;
          }
          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 false;
        } 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);

    return result.Succeeded();
  }

  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:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = &GetSelectedTarget();
    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");
        }
      }
    }
    return result.Succeeded();
  }
};

#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:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = &GetSelectedTarget();
    bool notify = true;
    target->GetImageSearchPathList().Clear(notify);
    result.SetStatus(eReturnStatusSuccessFinishNoResult);
    return result.Succeeded();
  }
};

#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:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = &GetSelectedTarget();
    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 result.Succeeded();
      }

      // 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 false;
        }
      }
    } else {
      result.AppendError("insert requires at least three arguments\n");
      return result.Succeeded();
    }
    return result.Succeeded();
  }
};

#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:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = &GetSelectedTarget();

    target->GetImageSearchPathList().Dump(&result.GetOutputStream());
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return result.Succeeded();
  }
};

#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) {
    CommandArgumentEntry arg;
    CommandArgumentData path_arg;

    // Define the first (and only) variant of this arg.
    path_arg.arg_type = eArgTypeDirectoryName;
    path_arg.arg_repetition = eArgRepeatPlain;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg.push_back(path_arg);

    // Push the data for the first argument into the m_arguments vector.
    m_arguments.push_back(arg);
  }

  ~CommandObjectTargetModulesSearchPathsQuery() override = default;

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

    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);
    return result.Succeeded();
  }
};

// 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 void DumpAddress(ExecutionContextScope *exe_scope,
                        const Address &so_addr, bool verbose, bool all_ranges,
                        Stream &strm) {
  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);
  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);
  }
  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);
    //        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);
    //        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);
    //        }
    //        strm.IndentLess();
    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;
  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();
    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);
          strm.EOL();
        } else {
          strm.IndentMore();
          strm.Indent("    Name: ");
          strm.PutCString(symbol->GetDisplayName().GetStringRef());
          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) {
  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);
    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) {
  TypeList type_list;
  if (module && name_cstr && name_cstr[0]) {
    const uint32_t max_num_matches = UINT32_MAX;
    bool name_is_fully_qualified = false;

    ConstString name(name_cstr);
    llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
    module->FindTypes(name, name_is_fully_qualified, max_num_matches,
                      searched_symbol_files, 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();
}

static size_t LookupTypeHere(Target *target, CommandInterpreter &interpreter,
                             Stream &strm, Module &module,
                             const char *name_cstr, bool name_is_regex) {
  TypeList type_list;
  const uint32_t max_num_matches = UINT32_MAX;
  bool name_is_fully_qualified = false;

  ConstString name(name_cstr);
  llvm::DenseSet<SymbolFile *> searched_symbol_files;
  module.FindTypes(name, name_is_fully_qualified, max_num_matches,
                   searched_symbol_files, 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) {
    CommandArgumentEntry arg;
    CommandArgumentData file_arg;

    // Define the first (and only) variant of this arg.
    file_arg.arg_type = eArgTypeFilename;
    file_arg.arg_repetition = eArgRepeatStar;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg.push_back(file_arg);

    // Push the data for the first argument into the m_arguments vector.
    m_arguments.push_back(arg);
  }

  ~CommandObjectTargetModulesModuleAutoComplete() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), CommandCompletions::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) {
    CommandArgumentEntry arg;
    CommandArgumentData source_file_arg;

    // Define the first (and only) variant of this arg.
    source_file_arg.arg_type = eArgTypeSourceFile;
    source_file_arg.arg_repetition = eArgRepeatPlus;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg.push_back(source_file_arg);

    // Push the data for the first argument into the m_arguments vector.
    m_arguments.push_back(arg);
  }

  ~CommandObjectTargetModulesSourceFileAutoComplete() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), CommandCompletions::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:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = &GetSelectedTarget();

    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");
    }
    return result.Succeeded();
  }
};

#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:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = &GetSelectedTarget();
    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 (GetDebugger().InterruptRequested())
            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 false;
      }
    } 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 (GetDebugger().InterruptRequested())
                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");
    }
    return result.Succeeded();
  }

  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:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = &GetSelectedTarget();
    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 false;
      }

      result.GetOutputStream().Format("Dumping sections for {0} modules.\n",
                                      num_modules);
      for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
        if (GetDebugger().InterruptRequested())
          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 (GetDebugger().InterruptRequested())
              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");
    }
    return result.Succeeded();
  }
};

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.
    CommandArgumentData arg{eArgTypeFilename, eArgRepeatPlain};
    m_arguments.push_back({arg});
  }

  ~CommandObjectTargetModulesDumpClangPCMInfo() override = default;

protected:
  bool 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 false;
    }

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

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

    clang::CompilerInstance compiler;
    compiler.createDiagnostics();

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

    return result.Succeeded();
  }
};

#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:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = &GetSelectedTarget();

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

    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 (GetDebugger().InterruptRequested())
          break;
        if (SymbolFile *sf = module_sp->GetSymbolFile())
          sf->DumpClangAST(result.GetOutputStream());
      }
      result.SetStatus(eReturnStatusSuccessFinishResult);
      return true;
    }

    // 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 (GetDebugger().InterruptRequested())
          break;
        Module *m = module_list.GetModulePointerAtIndex(i);
        if (SymbolFile *sf = m->GetSymbolFile())
          sf->DumpClangAST(result.GetOutputStream());
      }
    }
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }
};

#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:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = &GetSelectedTarget();
    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 false;
      }
      result.GetOutputStream().Format(
          "Dumping debug symbols for {0} modules.\n", num_modules);
      for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
        if (GetDebugger().InterruptRequested())
          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 (GetDebugger().InterruptRequested())
              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");
    }
    return result.Succeeded();
  }
};

#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:
  bool 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 result.Succeeded();
    } 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());
        if (target_modules.GetSize() > 0) {
          uint32_t num_dumped = 0;
          for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
            if (GetDebugger().InterruptRequested())
              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");
    }
    return result.Succeeded();
  }

  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 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] "
            "[<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)));
  }

  ~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();
    CommandArgumentData module_arg{eArgTypePath, eArgRepeatStar};
    m_arguments.push_back({module_arg});
  }

  ~CommandObjectTargetModulesAdd() override = default;

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

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

protected:
  OptionGroupOptions m_option_group;
  OptionGroupUUID m_uuid_option_group;
  OptionGroupFile m_symbol_file;

  bool DoExecute(Args &args, CommandReturnObject &result) override {
    Target *target = &GetSelectedTarget();
    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 (Symbols::DownloadObjectAndSymbolFile(module_spec, error)) {
          ModuleSP module_sp(
              target->GetOrCreateModule(module_spec, true /* notify */));
          if (module_sp) {
            result.SetStatus(eReturnStatusSuccessFinishResult);
            return true;
          } 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 false;
          }
        } 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(error);
          return false;
        }
      } else {
        result.AppendError(
            "one or more executable image paths must be specified");
        return false;
      }
    } 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 false;
          } 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();
    }

    return result.Succeeded();
  }
};

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:
  bool DoExecute(Args &args, CommandReturnObject &result) override {
    Target *target = &GetSelectedTarget();
    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 false;
                }
              } 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 false;
                }

                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 false;
                }
                if (set_pc && !file_entry.IsValid()) {
                  result.AppendError("No entry address in object file");
                  return false;
                }
                std::vector<ObjectFile::LoadableData> loadables(
                    objfile->GetLoadableData(*target));
                if (loadables.size() == 0) {
                  result.AppendError("No loadable sections");
                  return false;
                }
                Status error = process->WriteObjectFile(std::move(loadables));
                if (error.Fail()) {
                  result.AppendError(error.AsCString());
                  return false;
                }
                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");
      return false;
    }
    return result.Succeeded();
  }

  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.") {
    CommandArgumentData module_arg{eArgTypeShlibName, eArgRepeatStar};
    m_arguments.push_back({module_arg});
  }

  ~CommandObjectTargetModulesList() override = default;

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

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = GetDebugger().GetSelectedTarget().get();
    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;
    if (target == nullptr && !use_global_module_list) {
      result.AppendError("invalid target, create a debug target using the "
                         "'target create' command");
      return false;
    } else {
      if (target) {
        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) {
        if (target) {
          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);
          }
        } else {
          result.AppendError(
              "Can only look up modules by address with a valid target.");
        }
        return result.Succeeded();
      }

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

        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 false;
      }
    }
    return result.Succeeded();
  }

  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 ? (target->GetArchitecture().GetAddressByteSize() * 2)
                     : 16;

          ObjectFile *objfile = module->GetObjectFile();
          if (objfile) {
            Address base_addr(objfile->GetBaseAddress());
            if (base_addr.IsValid()) {
              if (target && !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;
        ModuleSP module_sp(module->shared_from_this());
        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("{%*" PRIu64 "}", width, (uint64_t)ref_count);
        else
          strm.Printf("{%" PRIu64 "}", (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.SetErrorStringWithFormat("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:
  bool 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 false;
    }

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

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

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

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

    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");
    }
    return result.Succeeded();
  }

  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.SetErrorStringWithFormat("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.SetErrorStringWithFormat("invalid line number string '%s'",
                                         option_arg.str().c_str());
        else if (m_line_number == 0)
          error.SetErrorString("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.SetErrorString("--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) {
    CommandArgumentEntry arg;
    CommandArgumentData file_arg;

    // Define the first (and only) variant of this arg.
    file_arg.arg_type = eArgTypeFilename;
    file_arg.arg_repetition = eArgRepeatStar;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg.push_back(file_arg);

    // Push the data for the first argument into the m_arguments vector.
    m_arguments.push_back(arg);
  }

  ~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(&GetSelectedTarget(), 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(
                &GetSelectedTarget(), 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:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = &GetSelectedTarget();
    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 result.Succeeded();
        }
      }

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

      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);
    return result.Succeeded();
  }

  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',
            CommandCompletions::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();
    CommandArgumentData module_arg{eArgTypeShlibName, eArgRepeatPlain};
    m_arguments.push_back({module_arg});
  }

  ~CommandObjectTargetSymbolsAdd() override = default;

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

  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 (Symbols::DownloadObjectAndSymbolFile(module_spec, error)) {
      if (module_spec.GetSymbolFileSpec())
        return AddModuleSymbols(m_exe_ctx.GetTargetPtr(), module_spec, flush,
                                result);
    } else {
      result.SetError(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();

    if (FileSystem::Instance().Exists(frame_module_sp->GetPlatformFileSpec())) {
      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();

      if (FileSystem::Instance().Exists(
              frame_module_sp->GetPlatformFileSpec())) {
        module_spec.GetArchitecture() = frame_module_sp->GetArchitecture();
        module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec();
      }

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

  bool 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();
    }
    return result.Succeeded();
  }

  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.SetErrorStringWithFormat("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.SetErrorStringWithFormat(
              "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.SetErrorStringWithFormat("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.SetErrorStringWithFormat("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.SetErrorStringWithFormat("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();
        }
        Target *target = GetDebugger().GetSelectedTarget().get();
        if (target) {
          target->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);
  }

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

    Target &target = GetSelectedOrDummyTarget();
    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 false;
      }
    } else {
      m_stop_hook_sp = new_hook_sp;
      m_interpreter.GetLLDBCommandsFromIOHandler("> ",   // Prompt
                                                 *this); // IOHandlerDelegate
    }
    result.SetStatus(eReturnStatusSuccessFinishNoResult);

    return result.Succeeded();
  }

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>]") {
    CommandArgumentData hook_arg{eArgTypeStopHookID, eArgRepeatStar};
    m_arguments.push_back({hook_arg});
  }

  ~CommandObjectTargetStopHookDelete() override = default;

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

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target &target = GetSelectedOrDummyTarget();
    // 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 false;
      } 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 false;
        }
        if (!target.RemoveStopHookByID(user_id)) {
          result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
                                       command.GetArgumentAtIndex(i));
          return false;
        }
      }
    }
    result.SetStatus(eReturnStatusSuccessFinishNoResult);
    return result.Succeeded();
  }
};

#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) {
    CommandArgumentData hook_arg{eArgTypeStopHookID, eArgRepeatStar};
    m_arguments.push_back({hook_arg});
  }

  ~CommandObjectTargetStopHookEnableDisable() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    if (request.GetCursorIndex())
      return;
    CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), CommandCompletions::eStopHookIDCompletion,
        request, nullptr);
  }

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target &target = GetSelectedOrDummyTarget();
    // 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 false;
        }
        success = target.SetStopHookActiveStateByID(user_id, m_enable);
        if (!success) {
          result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
                                       command.GetArgumentAtIndex(i));
          return false;
        }
      }
    }
    result.SetStatus(eReturnStatusSuccessFinishNoResult);
    return result.Succeeded();
  }

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:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target &target = GetSelectedOrDummyTarget();

    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);
    return result.Succeeded();
  }
};

#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.\n"
            "Intended to be used for debugging LLDB itself.",
            nullptr, eCommandRequiresTarget) {}

  ~CommandObjectTargetDumpTypesystem() override = default;

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

    result.SetStatus(eReturnStatusSuccessFinishResult);
    return result.Succeeded();
  }
};

#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]") {
    LoadSubCommand(
        "typesystem",
        CommandObjectSP(new CommandObjectTargetDumpTypesystem(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;
