//===-- CommandObjectTarget.cpp ---------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "CommandObjectTarget.h"

#include "lldb/Core/Debugger.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Host/StringConvert.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/LocateSymbolFile.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 = 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->GetOrCreateModule(main_module_spec,
                                                          true /* notify */);
          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->AppendExecutableSearchPaths(core_file_dir);

            ProcessSP process_sp(target_sp->CreateProcess(
                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(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 = 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 = 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 = 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 = 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 = 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 = 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 = 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,
                                         lldb::DescriptionLevel desc_level) {
  uint32_t num_matches = 0;
  if (module) {
    SymbolContextList sc_list;
    num_matches = module->ResolveSymbolContextsForFileSpec(
        file_spec, 0, false, eSymbolContextCompUnit, sc_list);

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

    ConstString name(name_cstr);
    llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
    num_matches =
        module->FindTypes(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,
                             Module &module, const char *name_cstr,
                             bool name_is_regex) {
  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 = module.FindTypes(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, &module.GetFileSpec(), 0);
    strm.PutCString(":\n");

    TypeSP type_sp(type_list.GetTypeAtIndex(0));
    if (type_sp) {
      // Resolve the clang type so that any forward references to types that
      // haven't yet been parsed will get parsed.
      type_sp->GetFullCompilerType();
      type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
      // 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 = 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 = 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 = 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 = 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 = 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;

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

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

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

    if (command.GetArgumentCount() == 0) {
      result.AppendError("file option must be specified.");
      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_options.m_verbose ? eDescriptionLevelFull
                                        : eDescriptionLevelBrief))
              num_dumped++;
          }
          if (num_dumped == 0)
            result.AppendWarningWithFormat(
                "No source filenames matched '%s'.\n", arg_cstr);
          else
            total_num_dumped += num_dumped;
        }
      }
    }

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

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

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

      return Status();
    }

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

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      static constexpr OptionDefinition g_options[] = {
          {LLDB_OPT_SET_ALL,
           false,
           "verbose",
           'v',
           OptionParser::eNoArgument,
           nullptr,
           {},
           0,
           eArgTypeNone,
           "Enable verbose dump."},
      };
      return llvm::makeArrayRef(g_options);
    }

    bool m_verbose;
  };

  CommandOptions m_options;
};

#pragma mark CommandObjectTargetModulesDump

// Dump multi-word command for target modules

class CommandObjectTargetModulesDump : public CommandObjectMultiword {
public:
  // Constructors and Destructors
  CommandObjectTargetModulesDump(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "target modules dump",
            "Commands for dumping information about one or "
            "more target modules.",
            "target modules dump "
            "[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 = 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->GetOrCreateModule(module_spec,
                                                 true /* notify */));
            if (module_sp) {
              result.SetStatus(eReturnStatusSuccessFinishResult);
              return true;
            } else {
              StreamString strm;
              module_spec.GetUUID().Dump(&strm);
              if (module_spec.GetFileSpec()) {
                if (module_spec.GetSymbolFileSpec()) {
                  result.AppendErrorWithFormat(
                      "Unable to create the executable or symbol file with "
                      "UUID %s with path %s and symbol file %s",
                      strm.GetData(),
                      module_spec.GetFileSpec().GetPath().c_str(),
                      module_spec.GetSymbolFileSpec().GetPath().c_str());
                } else {
                  result.AppendErrorWithFormat(
                      "Unable to create the executable or symbol file with "
                      "UUID %s with path %s",
                      strm.GetData(),
                      module_spec.GetFileSpec().GetPath().c_str());
                }
              } else {
                result.AppendErrorWithFormat("Unable to create the executable "
                                             "or symbol file with UUID %s",
                                             strm.GetData());
              }
              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->GetOrCreateModule(module_spec, 
                                            true /* notify */, &error));
            if (!module_sp) {
              const char *error_cstr = error.AsCString();
              if (error_cstr)
                result.AppendError(error_cstr);
              else
                result.AppendErrorWithFormat("unsupported module: %s",
                                             entry.c_str());
              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 = 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 = 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->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);
      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);
      if (callsite_unwind_plan) {
        result.GetOutputStream().Printf(
            "Synchronous (restricted to call-sites) UnwindPlan is '%s'\n",
            callsite_unwind_plan->GetSourceName().AsCString());
      }
      UnwindPlanSP fast_unwind_plan =
          func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread);
      if (fast_unwind_plan) {
        result.GetOutputStream().Printf(
            "Fast UnwindPlan is '%s'\n",
            fast_unwind_plan->GetSourceName().AsCString());
      }

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

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

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

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

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

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

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

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

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

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

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

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

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

  CommandOptions m_options;
};

// Lookup information in images

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.module_sp, 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 = 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,                                         "Add a command for the stop hook.  Can be specified more than once, and commands will be run in the order they appear." },
  { 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." },
  { LLDB_OPT_SET_ALL, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean,     "The breakpoint will auto-continue after running its commands." },
    // 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 'G': {
        bool value, success;
        value = OptionArgParser::ToBoolean(option_arg, false, &success);
        if (success) {
          m_auto_continue = value;
        } else
          error.SetErrorStringWithFormat(
              "invalid boolean value '%s' passed for -G option",
              option_arg.str().c_str());
      }
      break;
      case 'l':
        if (option_arg.getAsInteger(0, m_line_start)) {
          error.SetErrorStringWithFormat("invalid start line number: \"%s\"",
                                         option_arg.str().c_str());
          break;
        }
        m_sym_ctx_specified = true;
        break;

      case 'i':
        m_no_inlines = true;
        break;

      case 'n':
        m_function_name = 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.push_back(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();
      m_auto_continue = false;
    }

    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::vector<std::string> m_one_liner;
    bool m_auto_continue;
  };

  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, bool interactive) override {
    StreamFileSP output_sp(io_handler.GetOutputStreamFile());
    if (output_sp && interactive) {
      output_sp->PutCString(
          "Enter your stop hook command(s).  Type 'DONE' to end.\n");
      output_sp->Flush();
    }
  }

  void IOHandlerInputComplete(IOHandler &io_handler,
                              std::string &line) override {
    if (m_stop_hook_sp) {
      if (line.empty()) {
        StreamFileSP error_sp(io_handler.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 = 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_up;
      if (m_options.m_sym_ctx_specified) {
        specifier_up.reset(
            new SymbolContextSpecifier(GetDebugger().GetSelectedTarget()));

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

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

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

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

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

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

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

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

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

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

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

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

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

        new_hook_sp->SetThreadSpecifier(thread_spec);
      }
      
      new_hook_sp->SetAutoContinue(m_options.m_auto_continue);
      if (m_options.m_use_one_liner) {
        // Use one-liners.
        for (auto cmd : m_options.m_one_liner)
          new_hook_sp->GetCommandPointer()->AppendString(
            cmd.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;
