//===-- CommandObjectTarget.cpp ---------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#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/Host/StringConvert.h"
#include "lldb/Host/Symbols.h"
#include "lldb/Interpreter/CommandInterpreter.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/OptionGroupString.h"
#include "lldb/Interpreter/OptionGroupUInt64.h"
#include "lldb/Interpreter/OptionGroupUUID.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Interpreter/OptionGroupVariable.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.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/State.h"
#include "lldb/Utility/Timer.h"

#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatAdapters.h"

#include <cerrno>

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);
    properties++;
  }
  PlatformSP platform_sp(target->GetPlatform());
  if (platform_sp)
    strm.Printf("%splatform=%s", properties++ > 0 ? ", " : " ( ",
                platform_sp->GetName().GetCString());

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

// Note that the negation in the argument name causes a slightly confusing
// mapping of the enum values,
static constexpr OptionEnumValueElement g_dependents_enumaration[] = {
    {eLoadDependentsDefault, "default",
     "Only load dependents when the target is an executable."},
    {eLoadDependentsNo, "true",
     "Don't load dependents, even if the target is an executable."},
    {eLoadDependentsYes, "false",
     "Load dependents, even if the target is not an executable."}};

static constexpr OptionDefinition g_dependents_options[] = {
    {LLDB_OPT_SET_1, false, "no-dependents", 'd',
     OptionParser::eOptionalArgument, nullptr,
     OptionEnumValues(g_dependents_enumaration), 0, eArgTypeValue,
     "Whether or not to load dependents when creating a target. If the option "
     "is not specified, the value is implicitly 'default'. If the option is "
     "specified but without a value, the value is implicitly 'true'."}};

class OptionGroupDependents : public OptionGroup {
public:
  OptionGroupDependents() {}

  ~OptionGroupDependents() override {}

  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
    return llvm::makeArrayRef(g_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_dependents_options[option_idx].short_option;
    if (short_option == 'd') {
      LoadDependentFiles tmp_load_dependents;
      tmp_load_dependents = (LoadDependentFiles)OptionArgParser::ToOptionEnum(
          option_value, g_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:
  DISALLOW_COPY_AND_ASSIGN(OptionGroupDependents);
};

#pragma mark CommandObjectTargetCreate

//-------------------------------------------------------------------------
// "target create"
//-------------------------------------------------------------------------

class CommandObjectTargetCreate : public CommandObjectParsed {
public:
  CommandObjectTargetCreate(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "target create",
            "Create a target using the argument as the main executable.",
            nullptr),
        m_option_group(), m_arch_option(),
        m_core_file(LLDB_OPT_SET_1, false, "core", 'c', 0, eArgTypeFilename,
                    "Fullpath to a core file to use for this target."),
        m_platform_path(LLDB_OPT_SET_1, false, "platform-path", 'P', 0,
                        eArgTypePath,
                        "Path to the remote 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."),
        m_add_dependents() {
    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_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_platform_path, 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; }

  int HandleArgumentCompletion(
      CompletionRequest &request,
      OptionElementVector &opt_element_vector) override {
    CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
        request, nullptr);
    return request.GetNumberOfMatches();
  }

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) {
      if (!FileSystem::Instance().Exists(core_file)) {
        result.AppendErrorWithFormat("core file '%s' doesn't exist",
                                     core_file.GetPath().c_str());
        result.SetStatus(eReturnStatusFailed);
        return false;
      }
      if (!FileSystem::Instance().Readable(core_file)) {
        result.AppendErrorWithFormat("core file '%s' is not readable",
                                     core_file.GetPath().c_str());
        result.SetStatus(eReturnStatusFailed);
        return false;
      }
    }

    if (argc == 1 || core_file || remote_file) {
      FileSpec symfile(m_symbol_file.GetOptionValue().GetCurrentValue());
      if (symfile) {
        if (FileSystem::Instance().Exists(symfile)) {
          if (!FileSystem::Instance().Readable(symfile)) {
            result.AppendErrorWithFormat("symbol file '%s' is not readable",
                                         symfile.GetPath().c_str());
            result.SetStatus(eReturnStatusFailed);
            return false;
          }
        } else {
          char symfile_path[PATH_MAX];
          symfile.GetPath(symfile_path, sizeof(symfile_path));
          result.AppendErrorWithFormat("invalid symbol file path '%s'",
                                       symfile_path);
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
      }

      const char *file_path = command.GetArgumentAtIndex(0);
      static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
      Timer scoped_timer(func_cat, "(lldb) target create '%s'", file_path);
      FileSpec file_spec;

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

      bool must_set_platform_path = false;

      Debugger &debugger = m_interpreter.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, nullptr, target_sp));

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

        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());
                  result.SetStatus(eReturnStatusFailed);
                  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 (!platform_sp) {
                result.AppendError(
                    "unable to perform remote debugging without a platform");
                result.SetStatus(eReturnStatusFailed);
                return false;
              }
              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());
                  result.SetStatus(eReturnStatusFailed);
                  return false;
                }
              } else {
                // make up a local file
                result.AppendError("remote --> local transfer without local "
                                   "path is not implemented yet");
                result.SetStatus(eReturnStatusFailed);
                return false;
              }
            }
          } else {
            result.AppendError("no platform found for target");
            result.SetStatus(eReturnStatusFailed);
            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);
            }
          }
        }

        debugger.GetTargetList().SetSelectedTarget(target_sp.get());
        if (must_set_platform_path) {
          ModuleSpec main_module_spec(file_spec);
          ModuleSP module_sp = target_sp->GetSharedModule(main_module_spec);
          if (module_sp)
            module_sp->SetPlatformFileSpec(remote_file);
        }
        if (core_file) {
          char core_path[PATH_MAX];
          core_file.GetPath(core_path, sizeof(core_path));
          if (FileSystem::Instance().Exists(core_file)) {
            if (!FileSystem::Instance().Readable(core_file)) {
              result.AppendMessageWithFormat(
                  "Core file '%s' is not readable.\n", core_path);
              result.SetStatus(eReturnStatusFailed);
              return false;
            }
            FileSpec core_file_dir;
            core_file_dir.GetDirectory() = core_file.GetDirectory();
            target_sp->GetExecutableSearchPaths().Append(core_file_dir);

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

            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"));
                result.SetStatus(eReturnStatusFailed);
                return false;
              } else {
                result.AppendMessageWithFormat(
                    "Core file '%s' (%s) was loaded.\n", core_path,
                    target_sp->GetArchitecture().GetArchitectureName());
                result.SetStatus(eReturnStatusSuccessFinishNoResult);
              }
            } else {
              result.AppendErrorWithFormat(
                  "Unable to find process plug-in for core file '%s'\n",
                  core_path);
              result.SetStatus(eReturnStatusFailed);
            }
          } else {
            result.AppendErrorWithFormat("Core file '%s' does not exist\n",
                                         core_path);
            result.SetStatus(eReturnStatusFailed);
          }
        } else {
          result.AppendMessageWithFormat(
              "Current executable set to '%s' (%s).\n", file_path,
              target_sp->GetArchitecture().GetArchitectureName());
          result.SetStatus(eReturnStatusSuccessFinishNoResult);
        }
      } else {
        result.AppendError(error.AsCString());
        result.SetStatus(eReturnStatusFailed);
      }
    } else {
      result.AppendErrorWithFormat("'%s' takes exactly one executable path "
                                   "argument, or use the --core option.\n",
                                   m_cmd_name.c_str());
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }

private:
  OptionGroupOptions m_option_group;
  OptionGroupArchitecture m_arch_option;
  OptionGroupFile m_core_file;
  OptionGroupFile m_platform_path;
  OptionGroupFile m_symbol_file;
  OptionGroupFile m_remote_file;
  OptionGroupDependents m_add_dependents;
};

#pragma mark CommandObjectTargetList

//----------------------------------------------------------------------
// "target list"
//----------------------------------------------------------------------

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 {
    if (args.GetArgumentCount() == 0) {
      Stream &strm = result.GetOutputStream();

      bool show_stopped_process_status = false;
      if (DumpTargetList(m_interpreter.GetDebugger().GetTargetList(),
                         show_stopped_process_status, strm) == 0) {
        strm.PutCString("No targets.\n");
      }
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      result.AppendError("the 'target list' command takes no arguments\n");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }
};

#pragma mark CommandObjectTargetSelect

//----------------------------------------------------------------------
// "target select"
//----------------------------------------------------------------------

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

  ~CommandObjectTargetSelect() override = default;

protected:
  bool DoExecute(Args &args, CommandReturnObject &result) override {
    if (args.GetArgumentCount() == 1) {
      bool success = false;
      const char *target_idx_arg = args.GetArgumentAtIndex(0);
      uint32_t target_idx =
          StringConvert::ToUInt32(target_idx_arg, UINT32_MAX, 0, &success);
      if (success) {
        TargetList &target_list = m_interpreter.GetDebugger().GetTargetList();
        const uint32_t num_targets = target_list.GetNumTargets();
        if (target_idx < num_targets) {
          TargetSP target_sp(target_list.GetTargetAtIndex(target_idx));
          if (target_sp) {
            Stream &strm = result.GetOutputStream();
            target_list.SetSelectedTarget(target_sp.get());
            bool show_stopped_process_status = false;
            DumpTargetList(target_list, show_stopped_process_status, strm);
            result.SetStatus(eReturnStatusSuccessFinishResult);
          } else {
            result.AppendErrorWithFormat("target #%u is NULL in target list\n",
                                         target_idx);
            result.SetStatus(eReturnStatusFailed);
          }
        } 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);
          }
          result.SetStatus(eReturnStatusFailed);
        }
      } else {
        result.AppendErrorWithFormat("invalid index string value '%s'\n",
                                     target_idx_arg);
        result.SetStatus(eReturnStatusFailed);
      }
    } else {
      result.AppendError(
          "'target select' takes a single argument: a target index\n");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }
};

#pragma mark CommandObjectTargetSelect

//----------------------------------------------------------------------
// "target delete"
//----------------------------------------------------------------------

class CommandObjectTargetDelete : public CommandObjectParsed {
public:
  CommandObjectTargetDelete(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "target delete",
                            "Delete one or more targets by target index.",
                            nullptr),
        m_option_group(), 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();
  }

  ~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 = m_interpreter.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");
        result.SetStatus(eReturnStatusFailed);
        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());
          result.SetStatus(eReturnStatusFailed);
          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);

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

#pragma mark CommandObjectTargetVariable

//----------------------------------------------------------------------
// "target variable"
//----------------------------------------------------------------------

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_group(),
        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."),
        m_varobj_options() {
    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) {
    Target *target = static_cast<Target *>(baton);
    if (target) {
      return target->GetImages().FindGlobalVariables(ConstString(name),
                                                     UINT32_MAX, variable_list);
    }
    return 0;
  }

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

protected:
  void DumpGlobalVariableList(const ExecutionContext &exe_ctx,
                              const SymbolContext &sc,
                              const VariableList &variable_list, Stream &s) {
    size_t count = variable_list.GetSize();
    if (count > 0) {
      if (sc.module_sp) {
        if (sc.comp_unit) {
          s.Printf("Global variables for %s in %s:\n",
                   sc.comp_unit->GetPath().c_str(),
                   sc.module_sp->GetFileSpec().GetPath().c_str());
        } else {
          s.Printf("Global variables for %s\n",
                   sc.module_sp->GetFileSpec().GetPath().c_str());
        }
      } else if (sc.comp_unit) {
        s.Printf("Global variables for %s\n", sc.comp_unit->GetPath().c_str());
      }

      for (uint32_t i = 0; i < count; ++i) {
        VariableSP var_sp(variable_list.GetVariableAtIndex(i));
        if (var_sp) {
          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) {

      // TODO: Convert to entry-based iteration.  Requires converting
      // DumpValueObject.
      for (size_t idx = 0; idx < argc; ++idx) {
        VariableList variable_list;
        ValueObjectList valobj_list;

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

        if (matches == 0) {
          result.GetErrorStream().Printf(
              "error: can't find global variable '%s'\n", arg);
          result.SetStatus(eReturnStatusFailed);
          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);
            }
          }
        }
      }
    } 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);
          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.AppendErrorWithFormat(
                  "no global variables in current compile unit: %s\n",
                  comp_unit->GetPath().c_str());
            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");
          result.SetStatus(eReturnStatusFailed);
        }
      } else {
        SymbolContextList sc_list;
        const bool append = true;
        // 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), append,
                      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), append, sc_list);
        }

        const uint32_t num_scs = sc_list.GetSize();
        if (num_scs > 0) {
          SymbolContext sc;
          for (uint32_t sc_idx = 0; sc_idx < num_scs; ++sc_idx) {
            if (sc_list.GetContextAtIndex(sc_idx, sc)) {
              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);
              }
            }
          }
        }
      }
    }

    if (m_interpreter.TruncationWarningNecessary()) {
      result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
                                      m_cmd_name.c_str());
      m_interpreter.TruncationWarningGiven();
    }

    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) {
    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 = m_interpreter.GetDebugger().GetSelectedTarget().get();
    if (target) {
      const size_t argc = command.GetArgumentCount();
      if (argc & 1) {
        result.AppendError("add requires an even number of arguments\n");
        result.SetStatus(eReturnStatusFailed);
      } 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 = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
            if (log) {
              log->Printf("target modules search path adding ImageSearchPath "
                          "pair: '%s' -> '%s'",
                          from, to);
            }
            bool last_pair = ((argc - i) == 2);
            target->GetImageSearchPathList().Append(
                ConstString(from), ConstString(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");
            result.SetStatus(eReturnStatusFailed);
          }
        }
      }
    } else {
      result.AppendError("invalid target\n");
      result.SetStatus(eReturnStatusFailed);
    }
    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") {}

  ~CommandObjectTargetModulesSearchPathsClear() override = default;

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    if (target) {
      bool notify = true;
      target->GetImageSearchPathList().Clear(notify);
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    } else {
      result.AppendError("invalid target\n");
      result.SetStatus(eReturnStatusFailed);
    }
    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) {
    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;

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    if (target) {
      size_t argc = command.GetArgumentCount();
      // check for at least 3 arguments and an odd number of parameters
      if (argc >= 3 && argc & 1) {
        bool success = false;

        uint32_t insert_idx = StringConvert::ToUInt32(
            command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success);

        if (!success) {
          result.AppendErrorWithFormat(
              "<index> parameter is not an integer: '%s'.\n",
              command.GetArgumentAtIndex(0));
          result.SetStatus(eReturnStatusFailed);
          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(
                ConstString(from), ConstString(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");
            result.SetStatus(eReturnStatusFailed);
            return false;
          }
        }
      } else {
        result.AppendError("insert requires at least three arguments\n");
        result.SetStatus(eReturnStatusFailed);
        return result.Succeeded();
      }

    } else {
      result.AppendError("invalid target\n");
      result.SetStatus(eReturnStatusFailed);
    }
    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") {}

  ~CommandObjectTargetModulesSearchPathsList() override = default;

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    if (target) {
      if (command.GetArgumentCount() != 0) {
        result.AppendError("list takes no arguments\n");
        result.SetStatus(eReturnStatusFailed);
        return result.Succeeded();
      }

      target->GetImageSearchPathList().Dump(&result.GetOutputStream());
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      result.AppendError("invalid target\n");
      result.SetStatus(eReturnStatusFailed);
    }
    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) {
    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 = m_interpreter.GetDebugger().GetSelectedTarget().get();
    if (target) {
      if (command.GetArgumentCount() != 1) {
        result.AppendError("query requires one argument\n");
        result.SetStatus(eReturnStatusFailed);
        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);
    } else {
      result.AppendError("invalid target\n");
      result.SetStatus(eReturnStatusFailed);
    }
    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);
    else
      arch_strm.PutCString(module->GetArchitecture().GetArchitectureName());
    std::string arch_str = 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,
                                         bool load_addresses) {
  uint32_t num_matches = 0;
  if (module) {
    SymbolContextList sc_list;
    num_matches = module->ResolveSymbolContextsForFileSpec(
        file_spec, 0, false, eSymbolContextCompUnit, sc_list);

    for (uint32_t i = 0; i < num_matches; ++i) {
      SymbolContext sc;
      if (sc_list.GetContextAtIndex(i, sc)) {
        if (i > 0)
          strm << "\n\n";

        strm << "Line table for " << *static_cast<FileSpec *>(sc.comp_unit)
             << " in `" << module->GetFileSpec().GetFilename() << "\n";
        LineTable *line_table = sc.comp_unit->GetLineTable();
        if (line_table)
          line_table->GetDescription(
              &strm, interpreter.GetExecutionContext().GetTargetPtr(),
              lldb::eDescriptionLevelBrief);
        else
          strm << "No line table";
      }
    }
  }
  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);
      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) {
  size_t num_dumped = 0;
  std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
  const size_t num_modules = module_list.GetSize();
  if (num_modules > 0) {
    strm.Printf("Dumping headers for %" PRIu64 " module(s).\n",
                static_cast<uint64_t>(num_modules));
    strm.IndentMore();
    for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
      Module *module = module_list.GetModulePointerAtIndexUnlocked(image_idx);
      if (module) {
        if (num_dumped++ > 0) {
          strm.EOL();
          strm.EOL();
        }
        ObjectFile *objfile = module->GetObjectFile();
        if (objfile)
          objfile->Dump(&strm);
        else {
          strm.Format("No object file for module: {0:F}\n",
                      module->GetFileSpec());
        }
      }
    }
    strm.IndentLess();
  }
  return num_dumped;
}

static void DumpModuleSymtab(CommandInterpreter &interpreter, Stream &strm,
                             Module *module, SortOrder sort_order) {
  if (module) {
    SymbolVendor *sym_vendor = module->GetSymbolVendor();
    if (sym_vendor) {
      Symtab *symtab = sym_vendor->GetSymtab();
      if (symtab)
        symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(),
                     sort_order);
    }
  }
}

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());
      strm.IndentMore();
      section_list->Dump(&strm,
                         interpreter.GetExecutionContext().GetTargetPtr(), true,
                         UINT32_MAX);
      strm.IndentLess();
    }
  }
}

static bool DumpModuleSymbolVendor(Stream &strm, Module *module) {
  if (module) {
    SymbolVendor *symbol_vendor = module->GetSymbolVendor(true);
    if (symbol_vendor) {
      symbol_vendor->Dump(&strm);
      return true;
    }
  }
  return false;
}

static void DumpAddress(ExecutionContextScope *exe_scope,
                        const Address &so_addr, bool verbose, 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);
  }
  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) {
  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, 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) {
  if (module) {
    SymbolContext sc;

    SymbolVendor *sym_vendor = module->GetSymbolVendor();
    if (sym_vendor) {
      Symtab *symtab = sym_vendor->GetSymtab();
      if (symtab) {
        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 && symbol->ValueIsAddress()) {
              DumpAddress(interpreter.GetExecutionContext()
                              .GetBestExecutionContextScope(),
                          symbol->GetAddressRef(), verbose, strm);
            }
          }
          strm.IndentLess();
          return num_matches;
        }
      }
    }
  }
  return 0;
}

static void DumpSymbolContextList(ExecutionContextScope *exe_scope,
                                  Stream &strm, SymbolContextList &sc_list,
                                  bool verbose) {
  strm.IndentMore();

  const uint32_t num_matches = sc_list.GetSize();

  for (uint32_t i = 0; i < num_matches; ++i) {
    SymbolContext sc;
    if (sc_list.GetContextAtIndex(i, sc)) {
      AddressRange range;

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

      DumpAddress(exe_scope, range.GetBaseAddress(), verbose, strm);
    }
  }
  strm.IndentLess();
}

static size_t LookupFunctionInModule(CommandInterpreter &interpreter,
                                     Stream &strm, Module *module,
                                     const char *name, bool name_is_regex,
                                     bool include_inlines, bool include_symbols,
                                     bool verbose) {
  if (module && name && name[0]) {
    SymbolContextList sc_list;
    const bool append = true;
    size_t num_matches = 0;
    if (name_is_regex) {
      RegularExpression function_name_regex((llvm::StringRef(name)));
      num_matches = module->FindFunctions(function_name_regex, include_symbols,
                                          include_inlines, append, sc_list);
    } else {
      ConstString function_name(name);
      num_matches = module->FindFunctions(
          function_name, nullptr, eFunctionNameTypeAuto, include_symbols,
          include_inlines, append, sc_list);
    }

    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);
    }
    return num_matches;
  }
  return 0;
}

static size_t LookupTypeInModule(CommandInterpreter &interpreter, Stream &strm,
                                 Module *module, const char *name_cstr,
                                 bool name_is_regex) {
  if (module && name_cstr && name_cstr[0]) {
    TypeList type_list;
    const uint32_t max_num_matches = UINT32_MAX;
    size_t num_matches = 0;
    bool name_is_fully_qualified = false;
    SymbolContext sc;

    ConstString name(name_cstr);
    llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
    num_matches =
        module->FindTypes(sc, name, name_is_fully_qualified, max_num_matches,
                          searched_symbol_files, type_list);

    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");
      for (TypeSP type_sp : type_list.Types()) {
        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);
          // 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);
            typedef_type_sp = typedefed_type_sp;
            typedefed_type_sp = typedef_type_sp->GetTypedefType();
          }
        }
        strm.EOL();
      }
    }
    return num_matches;
  }
  return 0;
}

static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm,
                             const SymbolContext &sym_ctx,
                             const char *name_cstr, bool name_is_regex) {
  if (!sym_ctx.module_sp)
    return 0;

  TypeList type_list;
  const uint32_t max_num_matches = UINT32_MAX;
  size_t num_matches = 1;
  bool name_is_fully_qualified = false;

  ConstString name(name_cstr);
  llvm::DenseSet<SymbolFile *> searched_symbol_files;
  num_matches = sym_ctx.module_sp->FindTypes(
      sym_ctx, name, name_is_fully_qualified, max_num_matches,
      searched_symbol_files, type_list);

  if (num_matches) {
    strm.Indent();
    strm.PutCString("Best match found in ");
    DumpFullpath(strm, &sym_ctx.module_sp->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);
      // 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);
        typedef_type_sp = typedefed_type_sp;
        typedefed_type_sp = typedef_type_sp->GetTypedefType();
      }
    }
    strm.EOL();
  }
  return num_matches;
}

static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter,
                                          Stream &strm, Module *module,
                                          const FileSpec &file_spec,
                                          uint32_t line, bool check_inlines,
                                          bool verbose) {
  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);
      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) {
      const size_t num_matches =
          target->GetImages().FindModules(module_spec, module_list);

      // 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)
      : CommandObjectParsed(interpreter, name, help, syntax) {
    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;

  int HandleArgumentCompletion(
      CompletionRequest &request,
      OptionElementVector &opt_element_vector) override {
    CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), CommandCompletions::eModuleCompletion, request,
        nullptr);
    return request.GetNumberOfMatches();
  }
};

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

  int HandleArgumentCompletion(
      CompletionRequest &request,
      OptionElementVector &opt_element_vector) override {
    CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), CommandCompletions::eSourceFileCompletion,
        request, nullptr);
    return request.GetNumberOfMatches();
  }
};

#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) {}

  ~CommandObjectTargetModulesDumpObjfile() override = default;

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    if (target == nullptr) {
      result.AppendError("invalid target, create a debug target using the "
                         "'target create' command");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

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

#pragma mark CommandObjectTargetModulesDumpSymtab

static constexpr OptionEnumValueElement g_sort_option_enumeration[] = {
    {eSortOrderNone, "none",
     "No sorting, use the original symbol table order."},
    {eSortOrderByAddress, "address", "Sort output by symbol address."},
    {eSortOrderByName, "name", "Sort output by symbol name."} };

static constexpr OptionDefinition g_target_modules_dump_symtab_options[] = {
    // clang-format off
  { LLDB_OPT_SET_1, false, "sort", 's', OptionParser::eRequiredArgument, nullptr, OptionEnumValues(g_sort_option_enumeration), 0, eArgTypeSortOrder, "Supply a sort order when dumping the symbol table." }
    // clang-format on
};

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),
        m_options() {}

  ~CommandObjectTargetModulesDumpSymtab() override = default;

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

  class CommandOptions : public Options {
  public:
    CommandOptions() : Options(), m_sort_order(eSortOrderNone) {}

    ~CommandOptions() override = default;

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

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

      default:
        error.SetErrorStringWithFormat("invalid short option character '%c'",
                                       short_option);
        break;
      }
      return error;
    }

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

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

    SortOrder m_sort_order;
  };

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    if (target == nullptr) {
      result.AppendError("invalid target, create a debug target using the "
                         "'target create' command");
      result.SetStatus(eReturnStatusFailed);
      return false;
    } else {
      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
        std::lock_guard<std::recursive_mutex> guard(
            target->GetImages().GetMutex());
        const size_t num_modules = target->GetImages().GetSize();
        if (num_modules > 0) {
          result.GetOutputStream().Printf("Dumping symbol table for %" PRIu64
                                          " modules.\n",
                                          (uint64_t)num_modules);
          for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
            if (num_dumped > 0) {
              result.GetOutputStream().EOL();
              result.GetOutputStream().EOL();
            }
            if (m_interpreter.WasInterrupted())
              break;
            num_dumped++;
            DumpModuleSymtab(
                m_interpreter, result.GetOutputStream(),
                target->GetImages().GetModulePointerAtIndexUnlocked(image_idx),
                m_options.m_sort_order);
          }
        } else {
          result.AppendError("the target has no associated executable images");
          result.SetStatus(eReturnStatusFailed);
          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 (size_t i = 0; i < num_matches; ++i) {
              Module *module = module_list.GetModulePointerAtIndex(i);
              if (module) {
                if (num_dumped > 0) {
                  result.GetOutputStream().EOL();
                  result.GetOutputStream().EOL();
                }
                if (m_interpreter.WasInterrupted())
                  break;
                num_dumped++;
                DumpModuleSymtab(m_interpreter, result.GetOutputStream(),
                                 module, m_options.m_sort_order);
              }
            }
          } 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");
        result.SetStatus(eReturnStatusFailed);
      }
    }
    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) {}

  ~CommandObjectTargetModulesDumpSections() override = default;

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    if (target == nullptr) {
      result.AppendError("invalid target, create a debug target using the "
                         "'target create' command");
      result.SetStatus(eReturnStatusFailed);
      return false;
    } else {
      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.GetOutputStream().Printf("Dumping sections for %" PRIu64
                                          " modules.\n",
                                          (uint64_t)num_modules);
          for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
            if (m_interpreter.WasInterrupted())
              break;
            num_dumped++;
            DumpModuleSections(
                m_interpreter, result.GetOutputStream(),
                target->GetImages().GetModulePointerAtIndex(image_idx));
          }
        } else {
          result.AppendError("the target has no associated executable images");
          result.SetStatus(eReturnStatusFailed);
          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 (size_t i = 0; i < num_matches; ++i) {
              if (m_interpreter.WasInterrupted())
                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");
        result.SetStatus(eReturnStatusFailed);
      }
    }
    return result.Succeeded();
  }
};

#pragma mark CommandObjectTargetModulesDumpSections

//----------------------------------------------------------------------
// 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) {}

  ~CommandObjectTargetModulesDumpClangAST() override = default;

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    if (target == nullptr) {
      result.AppendError("invalid target, create a debug target using the "
                         "'target create' command");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    const size_t num_modules = target->GetImages().GetSize();
    if (num_modules == 0) {
      result.AppendError("the target has no associated executable images");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    if (command.GetArgumentCount() == 0) {
      // Dump all ASTs for all modules images
      result.GetOutputStream().Printf("Dumping clang ast for %" PRIu64
                                      " modules.\n",
                                      (uint64_t)num_modules);
      for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
        if (m_interpreter.WasInterrupted())
          break;
        Module *m = target->GetImages().GetModulePointerAtIndex(image_idx);
        SymbolFile *sf = m->GetSymbolVendor()->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 (m_interpreter.WasInterrupted())
          break;
        Module *m = module_list.GetModulePointerAtIndex(i);
        SymbolFile *sf = m->GetSymbolVendor()->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) {}

  ~CommandObjectTargetModulesDumpSymfile() override = default;

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    if (target == nullptr) {
      result.AppendError("invalid target, create a debug target using the "
                         "'target create' command");
      result.SetStatus(eReturnStatusFailed);
      return false;
    } else {
      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.GetOutputStream().Printf("Dumping debug symbols for %" PRIu64
                                          " modules.\n",
                                          (uint64_t)num_modules);
          for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
            if (m_interpreter.WasInterrupted())
              break;
            if (DumpModuleSymbolVendor(
                    result.GetOutputStream(),
                    target_modules.GetModulePointerAtIndexUnlocked(image_idx)))
              num_dumped++;
          }
        } else {
          result.AppendError("the target has no associated executable images");
          result.SetStatus(eReturnStatusFailed);
          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 (size_t i = 0; i < num_matches; ++i) {
              if (m_interpreter.WasInterrupted())
                break;
              Module *module = module_list.GetModulePointerAtIndex(i);
              if (module) {
                if (DumpModuleSymbolVendor(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");
        result.SetStatus(eReturnStatusFailed);
      }
    }
    return result.Succeeded();
  }
};

#pragma mark CommandObjectTargetModulesDumpLineTable

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

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.");
      result.SetStatus(eReturnStatusFailed);
      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());
        const size_t num_modules = target_modules.GetSize();
        if (num_modules > 0) {
          uint32_t num_dumped = 0;
          for (uint32_t i = 0; i < num_modules; ++i) {
            if (m_interpreter.WasInterrupted())
              break;
            if (DumpCompileUnitLineTable(
                    m_interpreter, result.GetOutputStream(),
                    target_modules.GetModulePointerAtIndexUnlocked(i),
                    file_spec, m_exe_ctx.GetProcessPtr() &&
                                   m_exe_ctx.GetProcessRef().IsAlive()))
              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");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }
};

#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 "
            "[headers|symtab|sections|ast|symfile|line-table] "
            "[<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)));
  }

  ~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>]"),
        m_option_group(),
        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();
  }

  ~CommandObjectTargetModulesAdd() override = default;

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

  int HandleArgumentCompletion(
      CompletionRequest &request,
      OptionElementVector &opt_element_vector) override {
    CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
        request, nullptr);
    return request.GetNumberOfMatches();
  }

protected:
  OptionGroupOptions m_option_group;
  OptionGroupUUID m_uuid_option_group;
  OptionGroupFile m_symbol_file;

  bool DoExecute(Args &args, CommandReturnObject &result) override {
    Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    if (target == nullptr) {
      result.AppendError("invalid target, create a debug target using the "
                         "'target create' command");
      result.SetStatus(eReturnStatusFailed);
      return false;
    } else {
      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();
          if (Symbols::DownloadObjectAndSymbolFile(module_spec)) {
            ModuleSP module_sp(target->GetSharedModule(module_spec));
            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());
              }
              result.SetStatus(eReturnStatusFailed);
              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.SetStatus(eReturnStatusFailed);
            return false;
          }
        } else {
          result.AppendError(
              "one or more executable image paths must be specified");
          result.SetStatus(eReturnStatusFailed);
          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->GetSharedModule(module_spec, &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());
              result.SetStatus(eReturnStatusFailed);
              return false;
            } else {
              flush = true;
            }
            result.SetStatus(eReturnStatusSuccessFinishResult);
          } else {
            std::string resolved_path = file_spec.GetPath();
            result.SetStatus(eReturnStatusFailed);
            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> ....]"),
        m_option_group(),
        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 = m_interpreter.GetDebugger().GetSelectedTarget().get();
    const bool load = m_load_option.GetOptionValue().GetCurrentValue();
    const bool set_pc = m_pc_option.GetOptionValue().GetCurrentValue();
    if (target == nullptr) {
      result.AppendError("invalid target, create a debug target using the "
                         "'target create' command");
      result.SetStatus(eReturnStatusFailed);
      return false;
    } else {
      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);
          result.SetStatus(eReturnStatusFailed);
        } else {
          search_using_module_spec = false;
          result.AppendErrorWithFormat("no object file for module '%s'\n",
                                       arg_cstr);
          result.SetStatus(eReturnStatusFailed);
        }
      }

      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;
        const size_t num_matches =
            target->GetImages().FindModules(module_spec, matching_modules);

        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");
                    result.SetStatus(eReturnStatusFailed);
                    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");
                    result.SetStatus(eReturnStatusFailed);
                    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);
                      bool success = false;
                      addr_t load_addr = StringConvert::ToUInt64(
                          load_addr_cstr, LLDB_INVALID_ADDRESS, 0, &success);
                      if (success) {
                        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);
                            result.SetStatus(eReturnStatusFailed);
                            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);
                          result.SetStatus(eReturnStatusFailed);
                          break;
                        }
                      } else {
                        result.AppendErrorWithFormat(
                            "invalid load address string '%s'\n",
                            load_addr_cstr);
                        result.SetStatus(eReturnStatusFailed);
                        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");
                      result.SetStatus(eReturnStatusFailed);
                      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);
                      result.SetStatus(eReturnStatusFailed);
                    }
                  }
                }
              } else {
                module->GetFileSpec().GetPath(path, sizeof(path));
                result.AppendErrorWithFormat(
                    "no sections in object file '%s'\n", path);
                result.SetStatus(eReturnStatusFailed);
              }
            } else {
              module->GetFileSpec().GetPath(path, sizeof(path));
              result.AppendErrorWithFormat("no object file for module '%s'\n",
                                           path);
              result.SetStatus(eReturnStatusFailed);
            }
          } 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");
            result.SetStatus(eReturnStatusFailed);
          }
        } 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());
          }
          result.SetStatus(eReturnStatusFailed);
        }
      } else {
        result.AppendError("either the \"--file <module>\" or the \"--uuid "
                           "<uuid>\" option must be specified.\n");
        result.SetStatus(eReturnStatusFailed);
        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;
};

//----------------------------------------------------------------------
// List images with associated information
//----------------------------------------------------------------------

static constexpr OptionDefinition g_target_modules_list_options[] = {
    // clang-format off
  { LLDB_OPT_SET_1, false, "address",        'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Display the image at this address." },
  { LLDB_OPT_SET_1, false, "arch",           'A', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the architecture when listing images." },
  { LLDB_OPT_SET_1, false, "triple",         't', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the triple when listing images." },
  { LLDB_OPT_SET_1, false, "header",         'h', OptionParser::eNoArgument,       nullptr, {}, 0, eArgTypeNone,                "Display the image base address as a load address if debugging, a file address otherwise." },
  { LLDB_OPT_SET_1, false, "offset",         'o', OptionParser::eNoArgument,       nullptr, {}, 0, eArgTypeNone,                "Display the image load address offset from the base file address (the slide amount)." },
  { LLDB_OPT_SET_1, false, "uuid",           'u', OptionParser::eNoArgument,       nullptr, {}, 0, eArgTypeNone,                "Display the UUID when listing images." },
  { LLDB_OPT_SET_1, false, "fullpath",       'f', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the fullpath to the image object file." },
  { LLDB_OPT_SET_1, false, "directory",      'd', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the directory with optional width for the image object file." },
  { LLDB_OPT_SET_1, false, "basename",       'b', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the basename with optional width for the image object file." },
  { LLDB_OPT_SET_1, false, "symfile",        's', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the fullpath to the image symbol file with optional width." },
  { LLDB_OPT_SET_1, false, "symfile-unique", 'S', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the symbol file with optional width only if it is different from the executable object file." },
  { LLDB_OPT_SET_1, false, "mod-time",       'm', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the modification time with optional width of the module." },
  { LLDB_OPT_SET_1, false, "ref-count",      'r', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the reference count if the module is still in the shared module cache." },
  { LLDB_OPT_SET_1, false, "pointer",        'p', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeNone,                "Display the module pointer." },
  { LLDB_OPT_SET_1, false, "global",         'g', OptionParser::eNoArgument,       nullptr, {}, 0, eArgTypeNone,                "Display the modules from the global module list, not just the current target." }
    // clang-format on
};

class CommandObjectTargetModulesList : public CommandObjectParsed {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions()
        : Options(), m_format_array(), m_use_global_module_list(false),
          m_module_addr(LLDB_INVALID_ADDRESS) {}

    ~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::makeArrayRef(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;
    lldb::addr_t m_module_addr;
  };

  CommandObjectTargetModulesList(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "target modules list",
            "List current executable and dependent shared library images.",
            "target modules list [<cmd-options>]"),
        m_options() {}

  ~CommandObjectTargetModulesList() override = default;

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

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = m_interpreter.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");
      result.SetStatus(eReturnStatusFailed);
      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);
              result.SetStatus(eReturnStatusFailed);
            }
          } else {
            result.AppendErrorWithFormat(
                "Couldn't find module containing address: 0x%" PRIx64 ".",
                m_options.m_module_addr);
            result.SetStatus(eReturnStatusFailed);
          }
        } else {
          result.AppendError(
              "Can only look up modules by address with a valid target.");
          result.SetStatus(eReturnStatusFailed);
        }
        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 {
        // TODO: Convert to entry based iteration.  Requires converting
        // FindModulesByName.
        for (size_t i = 0; i < argc; ++i) {
          // Dump specified images (by basename or fullpath)
          const char *arg_cstr = command.GetArgumentAtIndex(i);
          const size_t num_matches = FindModulesByName(
              target, arg_cstr, module_list, use_global_module_list);
          if (num_matches == 0) {
            if (argc == 1) {
              result.AppendErrorWithFormat("no modules found that match '%s'",
                                           arg_cstr);
              result.SetStatus(eReturnStatusFailed);
              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");
        }
        result.SetStatus(eReturnStatusFailed);
        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': {
        const SymbolVendor *symbol_vendor = module->GetSymbolVendor();
        if (symbol_vendor) {
          const FileSpec symfile_spec = symbol_vendor->GetMainFileSpec();
          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
//----------------------------------------------------------------------

static constexpr OptionDefinition g_target_modules_show_unwind_options[] = {
    // clang-format off
  { LLDB_OPT_SET_1, false, "name",    'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionName,        "Show unwind instructions for a function or symbol name." },
  { LLDB_OPT_SET_2, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Show unwind instructions for a function or symbol containing an address" }
    // clang-format on
};

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

  class CommandOptions : public Options {
  public:
    CommandOptions()
        : Options(), m_type(eLookupTypeInvalid), m_str(),
          m_addr(LLDB_INVALID_ADDRESS) {}

    ~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 = 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 = option_arg;
        m_type = eLookupTypeFunctionOrSymbol;
        break;

      default:
        error.SetErrorStringWithFormat("unrecognized option %c.", short_option);
        break;
      }

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

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

    int m_type;        // Should be a eLookupTypeXXX enum after parsing options
    std::string m_str; // Holds name lookup
    lldb::addr_t m_addr; // 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),
        m_options() {}

  ~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.");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

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

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

    SymbolContextList sc_list;

    if (m_options.m_type == eLookupTypeFunctionOrSymbol) {
      ConstString function_name(m_options.m_str.c_str());
      target->GetImages().FindFunctions(function_name, eFunctionNameTypeAuto,
                                        true, false, true, 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.");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

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

    for (uint32_t idx = 0; idx < num_matches; idx++) {
      SymbolContext sc;
      sc_list.GetContextAtIndex(idx, sc);
      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->GetObjectFile()
              ->GetUnwindTable()
              .GetUncachedFuncUnwindersContainingAddress(start_addr, sc));
      if (!func_unwinders_sp)
        continue;

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

      UnwindPlanSP non_callsite_unwind_plan =
          func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread, -1);
      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, -1);
      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, 0);
      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 ehframe_sp =
          func_unwinders_sp->GetEHFrameUnwindPlan(*target, 0);
      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, 0);
      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, 0)) {
        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, 0)) {
        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, 0);
      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");
      }

      UnwindPlanSP compact_unwind_sp =
          func_unwinders_sp->GetCompactUnwindUnwindPlan(*target, 0);
      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
//----------------------------------------------------------------------

static constexpr OptionDefinition g_target_modules_lookup_options[] = {
    // clang-format off
  { LLDB_OPT_SET_1,                                  true,  "address",    'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules." },
  { LLDB_OPT_SET_1,                                  false, "offset",     'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset,              "When looking up an address subtract <offset> from any addresses before doing the lookup." },
  /* FIXME: re-enable regex for types when the LookupTypeInModule actually uses the regex option: | LLDB_OPT_SET_6 */
  { LLDB_OPT_SET_2 | LLDB_OPT_SET_4 | LLDB_OPT_SET_5, false, "regex",      'r', OptionParser::eNoArgument,      nullptr, {}, 0, eArgTypeNone,                "The <name> argument for name lookups are regular expressions." },
  { LLDB_OPT_SET_2,                                  true,  "symbol",     's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeSymbol,              "Lookup a symbol by name in the symbol tables in one or more target modules." },
  { LLDB_OPT_SET_3,                                  true,  "file",       'f', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFilename,            "Lookup a file by fullpath or basename in one or more target modules." },
  { LLDB_OPT_SET_3,                                  false, "line",       'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum,             "Lookup a line number in a file (must be used in conjunction with --file)." },
  { LLDB_OPT_SET_FROM_TO(3,5),                       false, "no-inlines", 'i', OptionParser::eNoArgument,       nullptr, {}, 0, eArgTypeNone,                "Ignore inline entries (must be used in conjunction with --file or --function)." },
  { LLDB_OPT_SET_4,                                  true,  "function",   'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionName,        "Lookup a function by name in the debug symbols in one or more target modules." },
  { LLDB_OPT_SET_5,                                  true,  "name",       'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionOrSymbol,    "Lookup a function or symbol by name in one or more target modules." },
  { LLDB_OPT_SET_6,                                  true,  "type",       't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName,                "Lookup a type by name in the debug symbols in one or more target modules." },
  { LLDB_OPT_SET_ALL,                                false, "verbose",    'v', OptionParser::eNoArgument,       nullptr, {}, 0, eArgTypeNone,                "Enable verbose lookup information." },
  { LLDB_OPT_SET_ALL,                                false, "all",        'A', OptionParser::eNoArgument,       nullptr, {}, 0, eArgTypeNone,                "Print all matches, not just the best match, if a best match is available." },
    // clang-format on
};

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() : Options() { 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 = 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 = option_arg;
        m_type = eLookupTypeFunction;
        break;

      case 'n':
        m_str = option_arg;
        m_type = eLookupTypeFunctionOrSymbol;
        break;

      case 't':
        m_str = option_arg;
        m_type = eLookupTypeType;
        break;

      case 'v':
        m_verbose = 1;
        break;

      case 'A':
        m_print_all = true;
        break;

      case 'r':
        m_use_regex = true;
        break;
      }

      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_verbose = false;
      m_print_all = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(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_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),
        m_options() {
    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(m_interpreter, result.GetOutputStream(), sym_ctx,
                           m_options.m_str.c_str(), m_options.m_use_regex)) {
          result.SetStatus(eReturnStatusSuccessFinishResult);
          return true;
        }
      }
      break;
    }

    return true;
  }

  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)) {
          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)) {
          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)) {
          result.SetStatus(eReturnStatusSuccessFinishResult);
          return true;
        }
      }
      break;

    case eLookupTypeFunctionOrSymbol:
    case eLookupTypeFunction:
      if (!m_options.m_str.empty()) {
        if (LookupFunctionInModule(
                m_interpreter, result.GetOutputStream(), module,
                m_options.m_str.c_str(), m_options.m_use_regex,
                m_options.m_include_inlines,
                m_options.m_type ==
                    eLookupTypeFunctionOrSymbol, // include symbols
                m_options.m_verbose)) {
          result.SetStatus(eReturnStatusSuccessFinishResult);
          return true;
        }
      }
      break;

    case eLookupTypeType:
      if (!m_options.m_str.empty()) {
        if (LookupTypeInModule(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 = m_interpreter.GetDebugger().GetSelectedTarget().get();
    if (target == nullptr) {
      result.AppendError("invalid target, create a debug target using the "
                         "'target create' command");
      result.SetStatus(eReturnStatusFailed);
      return false;
    } else {
      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());
        const size_t num_modules = target_modules.GetSize();
        if (num_modules > 0) {
          for (i = 0; i < num_modules && !syntax_error; ++i) {
            Module *module_pointer =
                target_modules.GetModulePointerAtIndexUnlocked(i);

            if (module_pointer != current_module.get() &&
                LookupInModule(
                    m_interpreter,
                    target_modules.GetModulePointerAtIndexUnlocked(i), result,
                    syntax_error)) {
              result.GetOutputStream().EOL();
              num_successful_lookups++;
            }
          }
        } else {
          result.AppendError("the target has no associated executable images");
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
      } 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
  //------------------------------------------------------------------
  DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetModules);
};

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 using the options "
            "to specify a module to download symbols for.",
            "target symbols add <cmd-options> [<symfile>]",
            eCommandRequiresTarget),
        m_option_group(),
        m_file_option(
            LLDB_OPT_SET_1, false, "shlib", 's',
            CommandCompletions::eModuleCompletion, eArgTypeShlibName,
            "Fullpath or basename for module to find debug symbols for."),
        m_current_frame_option(
            LLDB_OPT_SET_2, false, "frame", 'F',
            "Locate the debug symbols the currently selected frame.", 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.Finalize();
  }

  ~CommandObjectTargetSymbolsAdd() override = default;

  int HandleArgumentCompletion(
      CompletionRequest &request,
      OptionElementVector &opt_element_vector) override {
    CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
        request, nullptr);
    return request.GetNumberOfMatches();
  }

  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) {
      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().GetFilename() = symbol_fspec.GetFilename();
      }
      // We now have a module that represents a symbol file that can be used
      // for a module that might exist in the current target, so we need to
      // find that module in the target
      ModuleList matching_module_list;

      size_t num_matches = 0;
      // 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)) {
          // See if it has a UUID?
          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();
            num_matches = target->GetImages().FindModules(
                symfile_uuid_module_spec, matching_module_list);
          }
        }

        if (num_matches == 0) {
          // 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 && num_matches == 0;
               ++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();
                num_matches = target->GetImages().FindModules(
                    symfile_uuid_module_spec, matching_module_list);
              }
            }
          }
        }
      }

      // Just try to match up the file by basename if we have no matches at
      // this point
      if (num_matches == 0)
        num_matches =
            target->GetImages().FindModules(module_spec, matching_module_list);

      while (num_matches == 0) {
        ConstString filename_no_extension(
            module_spec.GetFileSpec().GetFileNameStrippingExtension());
        // Empty string returned, lets 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 less extension
        module_spec.GetFileSpec().GetFilename() = filename_no_extension;

        num_matches =
            target->GetImages().FindModules(module_spec, matching_module_list);
      }

      if (num_matches > 1) {
        result.AppendErrorWithFormat("multiple modules match symbol file '%s', "
                                     "use the --uuid option to resolve the "
                                     "ambiguity.\n",
                                     symfile_path);
      } else if (num_matches == 1) {
        ModuleSP module_sp(matching_module_list.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);

        SymbolVendor *symbol_vendor =
            module_sp->GetSymbolVendor(true, &result.GetErrorStream());
        if (symbol_vendor) {
          SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();

          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.AppendWarningWithFormat("%s", feedback_stream.GetData());

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

      namespace fs = llvm::sys::fs;
      if (module_spec.GetUUID().IsValid()) {
        StreamString ss_symfile_uuid;
        module_spec.GetUUID().Dump(&ss_symfile_uuid);
        result.AppendErrorWithFormat(
            "symbol file '%s' (%s) does not match any existing module%s\n",
            symfile_path, ss_symfile_uuid.GetData(),
            !fs::is_regular_file(symbol_fspec.GetPath())
                ? "\n       please specify the full path to the symbol file"
                : "");
      } else {
        result.AppendErrorWithFormat(
            "symbol file '%s' does not match any existing module%s\n",
            symfile_path,
            !fs::is_regular_file(symbol_fspec.GetPath())
                ? "\n       please specify the full path to the symbol file"
                : "");
      }
    } else {
      result.AppendError(
          "one or more executable image paths must be specified");
    }
    result.SetStatus(eReturnStatusFailed);
    return false;
  }

  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 size_t argc = args.GetArgumentCount();

    if (argc == 0) {
      if (uuid_option_set || file_option_set || frame_option_set) {
        bool success = false;
        bool error_set = false;
        if (frame_option_set) {
          Process *process = m_exe_ctx.GetProcessPtr();
          if (process) {
            const StateType process_state = process->GetState();
            if (StateIsStoppedState(process_state, true)) {
              StackFrame *frame = m_exe_ctx.GetFramePtr();
              if (frame) {
                ModuleSP frame_module_sp(
                    frame->GetSymbolContext(eSymbolContextModule).module_sp);
                if (frame_module_sp) {
                  if (FileSystem::Instance().Exists(
                          frame_module_sp->GetPlatformFileSpec())) {
                    module_spec.GetArchitecture() =
                        frame_module_sp->GetArchitecture();
                    module_spec.GetFileSpec() =
                        frame_module_sp->GetPlatformFileSpec();
                  }
                  module_spec.GetUUID() = frame_module_sp->GetUUID();
                  success = module_spec.GetUUID().IsValid() ||
                            module_spec.GetFileSpec();
                } else {
                  result.AppendError("frame has no module");
                  error_set = true;
                }
              } else {
                result.AppendError("invalid current frame");
                error_set = true;
              }
            } else {
              result.AppendErrorWithFormat("process is not stopped: %s",
                                           StateAsCString(process_state));
              error_set = true;
            }
          } else {
            result.AppendError(
                "a process must exist in order to use the --frame option");
            error_set = true;
          }
        } else {
          if (uuid_option_set) {
            module_spec.GetUUID() =
                m_uuid_option_group.GetOptionValue().GetCurrentValue();
            success |= module_spec.GetUUID().IsValid();
          } else if (file_option_set) {
            module_spec.GetFileSpec() =
                m_file_option.GetOptionValue().GetCurrentValue();
            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();
            }
            success |= module_spec.GetUUID().IsValid() ||
                       FileSystem::Instance().Exists(module_spec.GetFileSpec());
          }
        }

        if (success) {
          if (Symbols::DownloadObjectAndSymbolFile(module_spec)) {
            if (module_spec.GetSymbolFileSpec())
              success = AddModuleSymbols(target, module_spec, flush, result);
          }
        }

        if (!success && !error_set) {
          StreamString error_strm;
          if (uuid_option_set) {
            error_strm.PutCString("unable to find debug symbols for UUID ");
            module_spec.GetUUID().Dump(&error_strm);
          } else if (file_option_set) {
            error_strm.PutCString(
                "unable to find debug symbols for the executable file ");
            error_strm << module_spec.GetFileSpec();
          } else if (frame_option_set) {
            error_strm.PutCString(
                "unable to find debug symbols for the current frame");
          }
          result.AppendError(error_strm.GetString());
        }
      } 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;
            }

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

#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
  //------------------------------------------------------------------
  DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetSymbols);
};

#pragma mark CommandObjectTargetStopHookAdd

//-------------------------------------------------------------------------
// CommandObjectTargetStopHookAdd
//-------------------------------------------------------------------------

static constexpr OptionDefinition g_target_stop_hook_add_options[] = {
    // clang-format off
  { LLDB_OPT_SET_ALL, false, "one-liner",    'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner,                                         "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
  { LLDB_OPT_SET_ALL, false, "shlib",        's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName,    "Set the module within which the stop-hook is to be run." },
  { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex,                                      "The stop hook is run only for the thread whose index matches this argument." },
  { LLDB_OPT_SET_ALL, false, "thread-id",    't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadID,                                         "The stop hook is run only for the thread whose TID matches this argument." },
  { LLDB_OPT_SET_ALL, false, "thread-name",  'T', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadName,                                       "The stop hook is run only for the thread whose thread name matches this argument." },
  { LLDB_OPT_SET_ALL, false, "queue-name",   'q', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeQueueName,                                        "The stop hook is run only for threads in the queue whose name is given by this argument." },
  { LLDB_OPT_SET_1,   false, "file",         'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the source file within which the stop-hook is to be run." },
  { LLDB_OPT_SET_1,   false, "start-line",   'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum,                                          "Set the start of the line range for which the stop-hook is to be run." },
  { LLDB_OPT_SET_1,   false, "end-line",     'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum,                                          "Set the end of the line range for which the stop-hook is to be run." },
  { LLDB_OPT_SET_2,   false, "classname",    'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeClassName,                                        "Specify the class within which the stop-hook is to be run." },
  { LLDB_OPT_SET_3,   false, "name",         'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the function name within which the stop hook will be run." },
    // clang-format on
};

class CommandObjectTargetStopHookAdd : public CommandObjectParsed,
                                       public IOHandlerDelegateMultiline {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions()
        : Options(), m_line_start(0), m_line_end(UINT_MAX),
          m_func_name_type_mask(eFunctionNameTypeAuto),
          m_sym_ctx_specified(false), m_thread_specified(false),
          m_use_one_liner(false), m_one_liner() {}

    ~CommandOptions() override = default;

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(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 = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'c':
        m_class_name = 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 '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 = option_arg;
        m_func_name_type_mask |= eFunctionNameTypeAuto;
        m_sym_ctx_specified = true;
        break;

      case 'f':
        m_file_name = option_arg;
        m_sym_ctx_specified = true;
        break;

      case 's':
        m_module_name = 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 = option_arg;
        m_thread_specified = true;
        break;

      case 'q':
        m_queue_name = 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 = option_arg;
        break;

      default:
        error.SetErrorStringWithFormat("unrecognized option %c.", short_option);
        break;
      }
      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_class_name.clear();
      m_function_name.clear();
      m_line_start = 0;
      m_line_end = UINT_MAX;
      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();
    }

    std::string m_class_name;
    std::string m_function_name;
    uint32_t m_line_start;
    uint32_t m_line_end;
    std::string m_file_name;
    std::string m_module_name;
    uint32_t m_func_name_type_mask; // A pick from lldb::FunctionNameType.
    lldb::tid_t m_thread_id;
    uint32_t m_thread_index;
    std::string m_thread_name;
    std::string m_queue_name;
    bool m_sym_ctx_specified;
    bool m_no_inlines;
    bool m_thread_specified;
    // Instance variables to hold the values for one_liner options.
    bool m_use_one_liner;
    std::string m_one_liner;
  };

  CommandObjectTargetStopHookAdd(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "target stop-hook add",
                            "Add a hook to be executed when the target stops.",
                            "target stop-hook add"),
        IOHandlerDelegateMultiline("DONE",
                                   IOHandlerDelegate::Completion::LLDBCommand),
        m_options() {}

  ~CommandObjectTargetStopHookAdd() override = default;

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

protected:
  void IOHandlerActivated(IOHandler &io_handler) override {
    StreamFileSP output_sp(io_handler.GetOutputStreamFile());
    if (output_sp) {
      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.GetErrorStreamFile());
        if (error_sp) {
          error_sp->Printf("error: stop hook #%" PRIu64
                           " aborted, no commands.\n",
                           m_stop_hook_sp->GetID());
          error_sp->Flush();
        }
        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
        if (target)
          target->RemoveStopHookByID(m_stop_hook_sp->GetID());
      } else {
        m_stop_hook_sp->GetCommandPointer()->SplitIntoLines(line);
        StreamFileSP output_sp(io_handler.GetOutputStreamFile());
        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();
    if (target) {
      Target::StopHookSP new_hook_sp = target->CreateStopHook();

      //  First step, make the specifier.
      std::unique_ptr<SymbolContextSpecifier> specifier_ap;
      if (m_options.m_sym_ctx_specified) {
        specifier_ap.reset(new SymbolContextSpecifier(
            m_interpreter.GetDebugger().GetSelectedTarget()));

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

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

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

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

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

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

      if (specifier_ap)
        new_hook_sp->SetSpecifier(specifier_ap.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);
      }
      if (m_options.m_use_one_liner) {
        // Use one-liner.
        new_hook_sp->GetCommandPointer()->AppendString(
            m_options.m_one_liner.c_str());
        result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n",
                                       new_hook_sp->GetID());
      } else {
        m_stop_hook_sp = new_hook_sp;
        m_interpreter.GetLLDBCommandsFromIOHandler(
            "> ",     // Prompt
            *this,    // IOHandlerDelegate
            true,     // Run IOHandler in async mode
            nullptr); // Baton for the "io_handler" that will be passed back
                      // into our IOHandlerDelegate functions
      }
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    } else {
      result.AppendError("invalid target\n");
      result.SetStatus(eReturnStatusFailed);
    }

    return result.Succeeded();
  }

private:
  CommandOptions m_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>]") {}

  ~CommandObjectTargetStopHookDelete() override = default;

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = GetSelectedOrDummyTarget();
    if (target) {
      // 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 {
        bool success;
        for (size_t i = 0; i < num_args; i++) {
          lldb::user_id_t user_id = StringConvert::ToUInt32(
              command.GetArgumentAtIndex(i), 0, 0, &success);
          if (!success) {
            result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
                                         command.GetArgumentAtIndex(i));
            result.SetStatus(eReturnStatusFailed);
            return false;
          }
          success = target->RemoveStopHookByID(user_id);
          if (!success) {
            result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
                                         command.GetArgumentAtIndex(i));
            result.SetStatus(eReturnStatusFailed);
            return false;
          }
        }
      }
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    } else {
      result.AppendError("invalid target\n");
      result.SetStatus(eReturnStatusFailed);
    }

    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) {
  }

  ~CommandObjectTargetStopHookEnableDisable() override = default;

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

  ~CommandObjectTargetStopHookList() override = default;

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Target *target = GetSelectedOrDummyTarget();
    if (!target) {
      result.AppendError("invalid target\n");
      result.SetStatus(eReturnStatusFailed);
      return result.Succeeded();
    }

    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 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("list",
                 CommandObjectSP(new CommandObjectTargetList(interpreter)));
  LoadSubCommand("select",
                 CommandObjectSP(new CommandObjectTargetSelect(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;
