//===-- 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[] = {
#define LLDB_OPTIONS_target_modules_dump_symtab
#include "CommandOptions.inc"
};

class CommandObjectTargetModulesDumpSymtab
    : public CommandObjectTargetModulesModuleAutoComplete {
public:
  CommandObjectTargetModulesDumpSymtab(CommandInterpreter &interpreter)
      : CommandObjectTargetModulesModuleAutoComplete(
            interpreter, "target modules dump symtab",
            "Dump the symbol table from one or more target modules.", nullptr),
        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, *thread);
      if (callsite_unwind_plan) {
        result.GetOutputStream().Printf(
            "Synchronous (restricted to call-sites) UnwindPlan is '%s'\n",
            callsite_unwind_plan->GetSourceName().AsCString());
      }
      UnwindPlanSP fast_unwind_plan =
          func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread);
      if (fast_unwind_plan) {
        result.GetOutputStream().Printf(
            "Fast UnwindPlan is '%s'\n",
            fast_unwind_plan->GetSourceName().AsCString());
      }

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

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

      UnwindPlanSP 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 = true;
        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;
