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

#include "lldb/Target/Target.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/BreakpointPrecondition.h"
#include "lldb/Breakpoint/BreakpointResolver.h"
#include "lldb/Breakpoint/BreakpointResolverAddress.h"
#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
#include "lldb/Breakpoint/BreakpointResolverFileRegex.h"
#include "lldb/Breakpoint/BreakpointResolverName.h"
#include "lldb/Breakpoint/BreakpointResolverScripted.h"
#include "lldb/Breakpoint/ScriptedBreakpointOverrideResolver.h"
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/SearchFilter.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/SourceManager.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Core/Telemetry.h"
#include "lldb/DataFormatters/FormatterSection.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Expression/REPL.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h"
#include "lldb/Interpreter/Interfaces/ScriptedHookInterface.h"
#include "lldb/Interpreter/OptionGroupWatchpoint.h"
#include "lldb/Interpreter/OptionValueEnumeration.h"
#include "lldb/Interpreter/OptionValues.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterTypeBuilder.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/AnsiTerminal.h"
#include "lldb/Utility/Event.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Policy.h"
#include "lldb/Utility/RealpathPrefixes.h"
#include "lldb/Utility/State.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Support/ErrorExtras.h"
#include "llvm/Support/ThreadPool.h"

#include <memory>
#include <mutex>
#include <optional>
#include <set>
#include <sstream>

using namespace lldb;
using namespace lldb_private;

namespace {

struct ExecutableInstaller {

  ExecutableInstaller(PlatformSP platform, ModuleSP module)
      : m_platform{platform}, m_module{module},
        m_local_file{m_module->GetFileSpec()},
        m_remote_file{m_module->GetRemoteInstallFileSpec()} {}

  void setupRemoteFile() const { m_module->SetPlatformFileSpec(m_remote_file); }

  PlatformSP m_platform;
  ModuleSP m_module;
  const FileSpec m_local_file;
  const FileSpec m_remote_file;
};

struct MainExecutableInstaller {

  MainExecutableInstaller(PlatformSP platform, ModuleSP module, TargetSP target,
                          ProcessLaunchInfo &launch_info)
      : m_platform{platform}, m_module{module},
        m_local_file{m_module->GetFileSpec()},
        m_remote_file{
            getRemoteFileSpec(m_platform, target, m_module, m_local_file)},
        m_launch_info{launch_info} {}

  void setupRemoteFile() const {
    m_module->SetPlatformFileSpec(m_remote_file);
    m_launch_info.SetExecutableFile(m_remote_file,
                                    /*add_exe_file_as_first_arg=*/false);
    m_platform->SetFilePermissions(m_remote_file, 0700 /*-rwx------*/);
  }

  PlatformSP m_platform;
  ModuleSP m_module;
  const FileSpec m_local_file;
  const FileSpec m_remote_file;

private:
  static FileSpec getRemoteFileSpec(PlatformSP platform, TargetSP target,
                                    ModuleSP module,
                                    const FileSpec &local_file) {
    FileSpec remote_file = module->GetRemoteInstallFileSpec();
    if (remote_file || !target->GetAutoInstallMainExecutable())
      return remote_file;

    if (!local_file)
      return {};

    remote_file = platform->GetRemoteWorkingDirectory();
    remote_file.AppendPathComponent(local_file.GetFilename());

    return remote_file;
  }

  ProcessLaunchInfo &m_launch_info;
};
} // namespace

static std::atomic<lldb::user_id_t> g_target_unique_id{1};

template <typename Installer>
static Status installExecutable(const Installer &installer) {
  if (!installer.m_local_file || !installer.m_remote_file)
    return Status();

  Status error = installer.m_platform->Install(installer.m_local_file,
                                               installer.m_remote_file);
  if (error.Fail())
    return error;

  installer.setupRemoteFile();
  return Status();
}

Target::Arch::Arch(const ArchSpec &spec)
    : m_spec(spec),
      m_plugin_up(PluginManager::CreateArchitectureInstance(spec)) {}

const Target::Arch &Target::Arch::operator=(const ArchSpec &spec) {
  m_spec = spec;
  m_plugin_up = PluginManager::CreateArchitectureInstance(spec);
  return *this;
}

llvm::StringRef Target::GetStaticBroadcasterClass() {
  static constexpr llvm::StringLiteral class_name("lldb.target");
  return class_name;
}

Target::Target(Debugger &debugger, const ArchSpec &target_arch,
               const lldb::PlatformSP &platform_sp, bool is_dummy_target)
    : TargetProperties(this),
      Broadcaster(debugger.GetBroadcasterManager(),
                  Target::GetStaticBroadcasterClass().str()),
      ExecutionContextScope(), m_debugger(debugger), m_platform_sp(platform_sp),
      m_mutex(), m_arch(target_arch), m_images(this), m_section_load_history(),
      m_breakpoint_list(false), m_internal_breakpoint_list(true),
      m_watchpoint_list(), m_process_sp(), m_search_filter_sp(),
      m_image_search_paths(ImageSearchPathsChanged, this),
      m_source_manager_up(), m_stop_hooks(), m_stop_hook_next_id(0),
      m_internal_stop_hooks(), m_latest_stop_hook_id(0), m_valid(true),
      m_suppress_stop_hooks(false), m_is_dummy_target(is_dummy_target),
      m_target_unique_id(g_target_unique_id++),
      m_target_session_name(
          llvm::formatv("Session {0}", m_target_unique_id).str()),
      m_frame_recognizer_manager_up(
          std::make_unique<StackFrameRecognizerManager>()) {
  SetEventName(eBroadcastBitBreakpointChanged, "breakpoint-changed");
  SetEventName(eBroadcastBitModulesLoaded, "modules-loaded");
  SetEventName(eBroadcastBitModulesUnloaded, "modules-unloaded");
  SetEventName(eBroadcastBitWatchpointChanged, "watchpoint-changed");
  SetEventName(eBroadcastBitSymbolsLoaded, "symbols-loaded");
  SetEventName(eBroadcastBitNewTargetCreated, "new-target-created");

  CheckInWithManager();

  LLDB_LOG(GetLog(LLDBLog::Object), "{0} Target::Target()",
           static_cast<void *>(this));
  if (target_arch.IsValid()) {
    LLDB_LOG(GetLog(LLDBLog::Target),
             "Target::Target created with architecture {0} ({1})",
             target_arch.GetArchitectureName(),
             target_arch.GetTriple().getTriple().c_str());
  }

  UpdateLaunchInfoFromProperties();
}

Target::~Target() {
  Log *log = GetLog(LLDBLog::Object);
  LLDB_LOG(log, "{0} Target::~Target()", static_cast<void *>(this));
  DeleteCurrentProcess();
}

void Target::PrimeFromDummyTarget(Target &target) {
  m_stop_hooks = target.m_stop_hooks;
  m_stop_hook_next_id = target.m_stop_hook_next_id;
  m_internal_stop_hooks = target.m_internal_stop_hooks;
  m_hooks = target.m_hooks;
  m_hook_next_id = target.m_hook_next_id;

  for (const auto &breakpoint_sp : target.m_breakpoint_list.Breakpoints()) {
    if (breakpoint_sp->IsInternal())
      continue;

    BreakpointSP new_bp(
        Breakpoint::CopyFromBreakpoint(shared_from_this(), *breakpoint_sp));
    AddBreakpoint(std::move(new_bp), false);
  }

  for (const auto &bp_name_entry : target.m_breakpoint_names) {
    AddBreakpointName(std::make_unique<BreakpointName>(*bp_name_entry.second));
  }

  for (auto const &elem : target.m_breakpoint_overrides) {
    BreakpointResolverOverrideUP new_override_up =
        elem.second->CopyIntoNewTarget(*this);
    if (new_override_up->Validate())
      AddBreakpointResolverOverride(std::move(new_override_up));
  }

  m_frame_recognizer_manager_up = std::make_unique<StackFrameRecognizerManager>(
      *target.m_frame_recognizer_manager_up);

  m_dummy_signals = target.m_dummy_signals;
}

void Target::Dump(Stream *s, lldb::DescriptionLevel description_level) {
  //    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
  if (description_level != lldb::eDescriptionLevelBrief) {
    s->Indent();
    s->PutCString("Target\n");
    s->IndentMore();
    m_images.Dump(s);
    m_breakpoint_list.Dump(s);
    m_internal_breakpoint_list.Dump(s);
    s->IndentLess();
  } else {
    Module *exe_module = GetExecutableModulePointer();
    if (exe_module)
      s->PutCString(exe_module->GetFileSpec().GetFilename());
    else
      s->PutCString("No executable module.");
  }
}

void Target::CleanupProcess() {
  // Do any cleanup of the target we need to do between process instances.
  // NB It is better to do this before destroying the process in case the
  // clean up needs some help from the process.
  m_breakpoint_list.ClearAllBreakpointSites();
  m_internal_breakpoint_list.ClearAllBreakpointSites();
  ResetBreakpointHitCounts();
  llvm::consumeError(m_process_sp->FlushDelayedBreakpoints());
  // Disable watchpoints just on the debugger side.
  std::unique_lock<std::recursive_mutex> lock;
  this->GetWatchpointList().GetListMutex(lock);
  DisableAllWatchpoints(false);
  ClearAllWatchpointHitCounts();
  ClearAllWatchpointHistoricValues();
  m_latest_stop_hook_id = 0;
}

void Target::DeleteCurrentProcess() {
  if (m_process_sp) {
    // We dispose any active tracing sessions on the current process
    m_trace_sp.reset();

    if (m_process_sp->IsAlive())
      m_process_sp->Destroy(false);

    m_process_sp->Finalize(false /* not destructing */);

    // Let the process finalize itself first, then clear the section load
    // history. Some objects owned by the process might end up calling
    // SectionLoadHistory::SetSectionUnloaded() which can create entries in
    // the section load history that can mess up subsequent processes.
    m_section_load_history.Clear();

    CleanupProcess();

    m_process_sp.reset();
  }
}

const lldb::ProcessSP &Target::CreateProcess(ListenerSP listener_sp,
                                             llvm::StringRef plugin_name,
                                             const FileSpec *crash_file,
                                             bool can_connect) {
  if (!listener_sp)
    listener_sp = GetDebugger().GetListener();
  DeleteCurrentProcess();
  m_process_sp = Process::FindPlugin(shared_from_this(), plugin_name,
                                     listener_sp, crash_file, can_connect);
  return m_process_sp;
}

const lldb::ProcessSP &Target::GetProcessSP() const { return m_process_sp; }

lldb::REPLSP Target::GetREPL(Status &err, lldb::LanguageType language,
                             const char *repl_options, bool can_create) {
  if (language == eLanguageTypeUnknown)
    language = m_debugger.GetREPLLanguage();

  if (language == eLanguageTypeUnknown) {
    LanguageSet repl_languages = Language::GetLanguagesSupportingREPLs();

    if (auto single_lang = repl_languages.GetSingularLanguage()) {
      language = *single_lang;
    } else if (repl_languages.Empty()) {
      err = Status::FromErrorString(
          "LLDB isn't configured with REPL support for any languages.");
      return REPLSP();
    } else {
      err = Status::FromErrorString(
          "Multiple possible REPL languages.  Please specify a language.");
      return REPLSP();
    }
  }

  REPLMap::iterator pos = m_repl_map.find(language);

  if (pos != m_repl_map.end()) {
    return pos->second;
  }

  if (!can_create) {
    err = Status::FromErrorStringWithFormat(
        "Couldn't find an existing REPL for %s, and can't create a new one",
        Language::GetNameForLanguageType(language));
    return lldb::REPLSP();
  }

  Debugger *const debugger = nullptr;
  lldb::REPLSP ret = REPL::Create(err, language, debugger, this, repl_options);

  if (ret) {
    m_repl_map[language] = ret;
    return m_repl_map[language];
  }

  if (err.Success()) {
    err = Status::FromErrorStringWithFormat(
        "Couldn't create a REPL for %s",
        Language::GetNameForLanguageType(language));
  }

  return lldb::REPLSP();
}

void Target::SetREPL(lldb::LanguageType language, lldb::REPLSP repl_sp) {
  lldbassert(!m_repl_map.count(language));

  m_repl_map[language] = repl_sp;
}

void Target::Destroy() {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  m_valid = false;
  DeleteCurrentProcess();
  m_platform_sp.reset();
  m_arch = ArchSpec();
  ClearModules(true);
  m_section_load_history.Clear();
  const bool notify = false;
  m_breakpoint_list.RemoveAll(notify);
  m_internal_breakpoint_list.RemoveAll(notify);
  m_last_created_breakpoint.reset();
  m_watchpoint_list.RemoveAll(notify);
  m_last_created_watchpoint.reset();
  m_search_filter_sp.reset();
  m_image_search_paths.Clear(notify);
  m_stop_hooks.clear();
  m_stop_hook_next_id = 0;
  m_internal_stop_hooks.clear();
  m_suppress_stop_hooks = false;
  m_repl_map.clear();
  Args signal_args;
  ClearDummySignals(signal_args);
}

llvm::StringRef Target::GetABIName() const {
  lldb::ABISP abi_sp;
  if (m_process_sp)
    abi_sp = m_process_sp->GetABI();
  if (!abi_sp)
    abi_sp = ABI::FindPlugin(ProcessSP(), GetArchitecture());
  if (abi_sp)
      return abi_sp->GetPluginName();
  return {};
}

BreakpointList &Target::GetBreakpointList(bool internal) {
  if (internal)
    return m_internal_breakpoint_list;
  else
    return m_breakpoint_list;
}

const BreakpointList &Target::GetBreakpointList(bool internal) const {
  if (internal)
    return m_internal_breakpoint_list;
  else
    return m_breakpoint_list;
}

BreakpointSP Target::GetBreakpointByID(break_id_t break_id) {
  BreakpointSP bp_sp;

  if (LLDB_BREAK_ID_IS_INTERNAL(break_id))
    bp_sp = m_internal_breakpoint_list.FindBreakpointByID(break_id);
  else
    bp_sp = m_breakpoint_list.FindBreakpointByID(break_id);

  return bp_sp;
}

lldb::BreakpointSP
lldb_private::Target::CreateBreakpointAtUserEntry(Status &error) {
  ModuleSP main_module_sp = GetExecutableModule();
  if (!main_module_sp) {
    error = Status::FromErrorString("target has no executable\n");
    return lldb::BreakpointSP();
  }
  FileSpecList shared_lib_filter;
  shared_lib_filter.Append(main_module_sp->GetFileSpec());
  llvm::SetVector<std::string, std::vector<std::string>,
                  std::unordered_set<std::string>>
      entryPointNamesSet;
  for (LanguageType lang_type : Language::GetSupportedLanguages()) {
    Language *lang = Language::FindPlugin(lang_type);
    if (!lang) {
      error = Status::FromErrorString("Language not found\n");
      return lldb::BreakpointSP();
    }
    std::string entryPointName = lang->GetUserEntryPointName().str();
    if (!entryPointName.empty())
      entryPointNamesSet.insert(entryPointName);
  }
  if (entryPointNamesSet.empty()) {
    error = Status::FromErrorString("No entry point name found\n");
    return lldb::BreakpointSP();
  }
  BreakpointSP bp_sp = CreateBreakpoint(
      &shared_lib_filter,
      /*containingSourceFiles=*/nullptr, entryPointNamesSet.takeVector(),
      /*func_name_type_mask=*/eFunctionNameTypeFull,
      /*language=*/eLanguageTypeUnknown,
      /*offset=*/0,
      /*skip_prologue=*/eLazyBoolNo,
      /*internal=*/false,
      /*hardware=*/false);
  if (!bp_sp) {
    error = Status::FromErrorString("Breakpoint creation failed.\n");
    return lldb::BreakpointSP();
  }
  bp_sp->SetOneShot(true);
  return bp_sp;
}

BreakpointSP Target::CreateSourceRegexBreakpoint(
    const FileSpecList *containingModules,
    const FileSpecList *source_file_spec_list,
    const std::unordered_set<std::string> &function_names,
    RegularExpression source_regex, bool internal, bool hardware,
    LazyBool move_to_nearest_code) {
  SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList(
      containingModules, source_file_spec_list));
  if (move_to_nearest_code == eLazyBoolCalculate)
    move_to_nearest_code = GetMoveToNearestCode() ? eLazyBoolYes : eLazyBoolNo;
  BreakpointResolverSP resolver_sp(new BreakpointResolverFileRegex(
      nullptr, std::move(source_regex), function_names,
      !static_cast<bool>(move_to_nearest_code)));

  return CreateBreakpoint(filter_sp, resolver_sp, internal, hardware, true);
}

BreakpointSP Target::CreateBreakpoint(const FileSpecList *containingModules,
                                      const FileSpec &file, uint32_t line_no,
                                      uint32_t column, lldb::addr_t offset,
                                      LazyBool check_inlines,
                                      LazyBool skip_prologue, bool internal,
                                      bool hardware,
                                      LazyBool move_to_nearest_code) {
  FileSpec remapped_file;
  std::optional<llvm::StringRef> removed_prefix_opt =
      GetSourcePathMap().ReverseRemapPath(file, remapped_file);
  if (!removed_prefix_opt)
    remapped_file = file;

  if (check_inlines == eLazyBoolCalculate) {
    const InlineStrategy inline_strategy = GetInlineStrategy();
    switch (inline_strategy) {
    case eInlineBreakpointsNever:
      check_inlines = eLazyBoolNo;
      break;

    case eInlineBreakpointsHeaders:
      if (remapped_file.IsSourceImplementationFile())
        check_inlines = eLazyBoolNo;
      else
        check_inlines = eLazyBoolYes;
      break;

    case eInlineBreakpointsAlways:
      check_inlines = eLazyBoolYes;
      break;
    }
  }
  SearchFilterSP filter_sp;
  if (check_inlines == eLazyBoolNo) {
    // Not checking for inlines, we are looking only for matching compile units
    FileSpecList compile_unit_list;
    compile_unit_list.Append(remapped_file);
    filter_sp = GetSearchFilterForModuleAndCUList(containingModules,
                                                  &compile_unit_list);
  } else {
    filter_sp = GetSearchFilterForModuleList(containingModules);
  }
  if (skip_prologue == eLazyBoolCalculate)
    skip_prologue = GetSkipPrologue() ? eLazyBoolYes : eLazyBoolNo;
  if (move_to_nearest_code == eLazyBoolCalculate)
    move_to_nearest_code = GetMoveToNearestCode() ? eLazyBoolYes : eLazyBoolNo;

  SourceLocationSpec location_spec(remapped_file, line_no, column,
                                   check_inlines,
                                   !static_cast<bool>(move_to_nearest_code));
  if (!location_spec)
    return nullptr;

  BreakpointResolverSP resolver_sp(new BreakpointResolverFileLine(
      nullptr, offset, skip_prologue, location_spec, removed_prefix_opt));
  return CreateBreakpoint(filter_sp, resolver_sp, internal, hardware, true);
}

BreakpointSP Target::CreateBreakpoint(lldb::addr_t addr, bool internal,
                                      bool hardware) {
  Address so_addr;

  // Check for any reason we want to move this breakpoint to other address.
  addr = GetBreakableLoadAddress(addr);

  // Attempt to resolve our load address if possible, though it is ok if it
  // doesn't resolve to section/offset.

  // Try and resolve as a load address if possible
  GetSectionLoadList().ResolveLoadAddress(addr, so_addr);
  if (!so_addr.IsValid()) {
    // The address didn't resolve, so just set this as an absolute address
    so_addr.SetOffset(addr);
  }
  BreakpointSP bp_sp(CreateBreakpoint(so_addr, internal, hardware));
  return bp_sp;
}

BreakpointSP Target::CreateBreakpoint(const Address &addr, bool internal,
                                      bool hardware) {
  SearchFilterSP filter_sp =
      std::make_shared<SearchFilterForUnconstrainedSearches>(
          shared_from_this());
  BreakpointResolverSP resolver_sp =
      std::make_shared<BreakpointResolverAddress>(nullptr, addr);
  return CreateBreakpoint(filter_sp, resolver_sp, internal, hardware, false);
}

lldb::BreakpointSP
Target::CreateAddressInModuleBreakpoint(lldb::addr_t file_addr, bool internal,
                                        const FileSpec &file_spec,
                                        bool request_hardware) {
  SearchFilterSP filter_sp =
      std::make_shared<SearchFilterForUnconstrainedSearches>(
          shared_from_this());
  BreakpointResolverSP resolver_sp =
      std::make_shared<BreakpointResolverAddress>(nullptr, Address(file_addr),
                                                  file_spec);
  return CreateBreakpoint(filter_sp, resolver_sp, internal, request_hardware,
                          false);
}

BreakpointSP Target::CreateBreakpoint(
    const FileSpecList *containingModules,
    const FileSpecList *containingSourceFiles, const char *func_name,
    FunctionNameType func_name_type_mask, LanguageType language,
    lldb::addr_t offset, bool offset_is_insn_count, LazyBool skip_prologue,
    bool internal, bool hardware) {
  BreakpointSP bp_sp;
  if (func_name) {
    SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList(
        containingModules, containingSourceFiles));

    if (skip_prologue == eLazyBoolCalculate)
      skip_prologue = GetSkipPrologue() ? eLazyBoolYes : eLazyBoolNo;
    if (language == lldb::eLanguageTypeUnknown)
      language = GetLanguage().AsLanguageType();

    BreakpointResolverSP resolver_sp(new BreakpointResolverName(
        nullptr, func_name, func_name_type_mask, language, Breakpoint::Exact,
        offset, offset_is_insn_count, skip_prologue));
    bp_sp = CreateBreakpoint(filter_sp, resolver_sp, internal, hardware, true);
  }
  return bp_sp;
}

lldb::BreakpointSP
Target::CreateBreakpoint(const FileSpecList *containingModules,
                         const FileSpecList *containingSourceFiles,
                         const std::vector<std::string> &func_names,
                         FunctionNameType func_name_type_mask,
                         LanguageType language, lldb::addr_t offset,
                         LazyBool skip_prologue, bool internal, bool hardware) {
  BreakpointSP bp_sp;
  size_t num_names = func_names.size();
  if (num_names > 0) {
    SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList(
        containingModules, containingSourceFiles));

    if (skip_prologue == eLazyBoolCalculate)
      skip_prologue = GetSkipPrologue() ? eLazyBoolYes : eLazyBoolNo;
    if (language == lldb::eLanguageTypeUnknown)
      language = GetLanguage().AsLanguageType();

    BreakpointResolverSP resolver_sp(
        new BreakpointResolverName(nullptr, func_names, func_name_type_mask,
                                   language, offset, skip_prologue));
    bp_sp = CreateBreakpoint(filter_sp, resolver_sp, internal, hardware, true);
  }
  return bp_sp;
}

BreakpointSP
Target::CreateBreakpoint(const FileSpecList *containingModules,
                         const FileSpecList *containingSourceFiles,
                         const char *func_names[], size_t num_names,
                         FunctionNameType func_name_type_mask,
                         LanguageType language, lldb::addr_t offset,
                         LazyBool skip_prologue, bool internal, bool hardware) {
  BreakpointSP bp_sp;
  if (num_names > 0) {
    SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList(
        containingModules, containingSourceFiles));

    if (skip_prologue == eLazyBoolCalculate) {
      if (offset == 0)
        skip_prologue = GetSkipPrologue() ? eLazyBoolYes : eLazyBoolNo;
      else
        skip_prologue = eLazyBoolNo;
    }
    if (language == lldb::eLanguageTypeUnknown)
      language = GetLanguage().AsLanguageType();

    BreakpointResolverSP resolver_sp(new BreakpointResolverName(
        nullptr, func_names, num_names, func_name_type_mask, language, offset,
        skip_prologue));
    resolver_sp->SetOffset(offset);
    bp_sp = CreateBreakpoint(filter_sp, resolver_sp, internal, hardware, true);
  }
  return bp_sp;
}

SearchFilterSP
Target::GetSearchFilterForModule(const FileSpec *containingModule) {
  SearchFilterSP filter_sp;
  if (containingModule != nullptr) {
    // TODO: We should look into sharing module based search filters
    // across many breakpoints like we do for the simple target based one
    filter_sp = std::make_shared<SearchFilterByModule>(shared_from_this(),
                                                       *containingModule);
  } else {
    if (!m_search_filter_sp)
      m_search_filter_sp =
          std::make_shared<SearchFilterForUnconstrainedSearches>(
              shared_from_this());
    filter_sp = m_search_filter_sp;
  }
  return filter_sp;
}

SearchFilterSP
Target::GetSearchFilterForModuleList(const FileSpecList *containingModules) {
  SearchFilterSP filter_sp;
  if (containingModules && containingModules->GetSize() != 0) {
    // TODO: We should look into sharing module based search filters
    // across many breakpoints like we do for the simple target based one
    filter_sp = std::make_shared<SearchFilterByModuleList>(shared_from_this(),
                                                           *containingModules);
  } else {
    if (!m_search_filter_sp)
      m_search_filter_sp =
          std::make_shared<SearchFilterForUnconstrainedSearches>(
              shared_from_this());
    filter_sp = m_search_filter_sp;
  }
  return filter_sp;
}

SearchFilterSP Target::GetSearchFilterForModuleAndCUList(
    const FileSpecList *containingModules,
    const FileSpecList *containingSourceFiles) {
  if (containingSourceFiles == nullptr || containingSourceFiles->GetSize() == 0)
    return GetSearchFilterForModuleList(containingModules);

  SearchFilterSP filter_sp;
  if (containingModules == nullptr) {
    // We could make a special "CU List only SearchFilter".  Better yet was if
    // these could be composable, but that will take a little reworking.

    filter_sp = std::make_shared<SearchFilterByModuleListAndCU>(
        shared_from_this(), FileSpecList(), *containingSourceFiles);
  } else {
    filter_sp = std::make_shared<SearchFilterByModuleListAndCU>(
        shared_from_this(), *containingModules, *containingSourceFiles);
  }
  return filter_sp;
}

BreakpointSP Target::CreateFuncRegexBreakpoint(
    const FileSpecList *containingModules,
    const FileSpecList *containingSourceFiles, RegularExpression func_regex,
    lldb::LanguageType requested_language, LazyBool skip_prologue,
    bool internal, bool hardware) {
  SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList(
      containingModules, containingSourceFiles));
  bool skip = (skip_prologue == eLazyBoolCalculate)
                  ? GetSkipPrologue()
                  : static_cast<bool>(skip_prologue);
  BreakpointResolverSP resolver_sp(new BreakpointResolverName(
      nullptr, std::move(func_regex), requested_language, 0, skip));

  return CreateBreakpoint(filter_sp, resolver_sp, internal, hardware, true);
}

lldb::BreakpointSP
Target::CreateExceptionBreakpoint(enum lldb::LanguageType language,
                                  bool catch_bp, bool throw_bp, bool internal,
                                  Args *additional_args, Status *error) {
  BreakpointSP exc_bkpt_sp = LanguageRuntime::CreateExceptionBreakpoint(
      *this, language, catch_bp, throw_bp, internal);
  if (exc_bkpt_sp && additional_args) {
    BreakpointPreconditionSP precondition_sp = exc_bkpt_sp->GetPrecondition();
    if (precondition_sp && additional_args) {
      if (error)
        *error = precondition_sp->ConfigurePrecondition(*additional_args);
      else
        precondition_sp->ConfigurePrecondition(*additional_args);
    }
  }
  return exc_bkpt_sp;
}

lldb::BreakpointSP Target::CreateScriptedBreakpoint(
    const llvm::StringRef class_name, const FileSpecList *containingModules,
    const FileSpecList *containingSourceFiles, bool internal,
    bool request_hardware, StructuredData::ObjectSP extra_args_sp,
    Status *creation_error) {
  SearchFilterSP filter_sp;

  lldb::SearchDepth depth = lldb::eSearchDepthTarget;
  bool has_files =
      containingSourceFiles && containingSourceFiles->GetSize() > 0;
  bool has_modules = containingModules && containingModules->GetSize() > 0;

  if (has_files && has_modules) {
    filter_sp = GetSearchFilterForModuleAndCUList(containingModules,
                                                  containingSourceFiles);
  } else if (has_files) {
    filter_sp =
        GetSearchFilterForModuleAndCUList(nullptr, containingSourceFiles);
  } else if (has_modules) {
    filter_sp = GetSearchFilterForModuleList(containingModules);
  } else {
    filter_sp = std::make_shared<SearchFilterForUnconstrainedSearches>(
        shared_from_this());
  }

  BreakpointResolverSP resolver_sp(new BreakpointResolverScripted(
      nullptr, class_name, depth, StructuredDataImpl(extra_args_sp)));
  return CreateBreakpoint(filter_sp, resolver_sp, internal, false, true);
}

BreakpointSP Target::CreateBreakpoint(SearchFilterSP &filter_sp,
                                      BreakpointResolverSP &resolver_sp,
                                      bool internal, bool request_hardware,
                                      bool resolve_indirect_symbols) {
  BreakpointSP bp_sp;
  if (filter_sp && resolver_sp) {
    // Now check whether there are any "Breakpoint Overrides" registered, and
    // if there are see if one of them want to handle this request instead.
    // But we don't allow overrides for internal breakpoints:
    if (!internal) {
      BreakpointResolverSP overridden_sp =
          CheckBreakpointOverrides(resolver_sp);
      if (overridden_sp)
        resolver_sp = overridden_sp;
    }
    const bool hardware = request_hardware || GetRequireHardwareBreakpoints();
    bp_sp.reset(new Breakpoint(*this, filter_sp, resolver_sp, hardware,
                               resolve_indirect_symbols));
    resolver_sp->SetBreakpoint(bp_sp);
    AddBreakpoint(bp_sp, internal);
  }
  return bp_sp;
}

void Target::AddBreakpoint(lldb::BreakpointSP bp_sp, bool internal) {
  if (!bp_sp)
    return;
  if (internal)
    m_internal_breakpoint_list.Add(bp_sp, false);
  else
    m_breakpoint_list.Add(bp_sp, true);

  Log *log = GetLog(LLDBLog::Breakpoints);
  if (log) {
    StreamString s;
    bp_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
    LLDB_LOGF(log, "Target::%s (internal = %s) => break_id = %s\n",
              __FUNCTION__, bp_sp->IsInternal() ? "yes" : "no", s.GetData());
  }

  bp_sp->ResolveBreakpoint();

  if (!internal) {
    m_last_created_breakpoint = bp_sp;
  }
}

void Target::AddNameToBreakpoint(BreakpointID &id, llvm::StringRef name,
                                 Status &error) {
  BreakpointSP bp_sp =
      m_breakpoint_list.FindBreakpointByID(id.GetBreakpointID());
  if (!bp_sp) {
    StreamString s;
    id.GetDescription(&s, eDescriptionLevelBrief);
    error = Status::FromErrorStringWithFormat("Could not find breakpoint %s",
                                              s.GetData());
    return;
  }
  AddNameToBreakpoint(bp_sp, name, error);
}

void Target::AddNameToBreakpoint(BreakpointSP &bp_sp, llvm::StringRef name,
                                 Status &error) {
  if (!bp_sp)
    return;

  BreakpointName *bp_name = FindBreakpointName(name, true, error);
  if (!bp_name)
    return;

  bp_name->ConfigureBreakpoint(bp_sp);
  bp_sp->AddName(name);
}

void Target::AddBreakpointName(std::unique_ptr<BreakpointName> bp_name) {
  m_breakpoint_names.insert(
      std::make_pair(bp_name->GetName(), std::move(bp_name)));
}

BreakpointName *Target::FindBreakpointName(llvm::StringRef name,
                                           bool can_create, Status &error) {
  BreakpointID::StringIsBreakpointName(name, error);
  if (!error.Success())
    return nullptr;

  BreakpointNameMap::iterator iter = m_breakpoint_names.find(name);
  if (iter != m_breakpoint_names.end()) {
    return iter->second.get();
  }

  if (!can_create) {
    error = Status::FromErrorStringWithFormatv(
        "Breakpoint name \"{0}\" doesn't exist and can_create is false.", name);
    return nullptr;
  }

  return m_breakpoint_names
      .insert(
          std::make_pair(name, std::make_unique<BreakpointName>(name.str())))
      .first->second.get();
}

void Target::DeleteBreakpointName(llvm::StringRef name) {
  BreakpointNameMap::iterator iter = m_breakpoint_names.find(name);

  if (iter != m_breakpoint_names.end()) {
    m_breakpoint_names.erase(iter);
    for (auto bp_sp : m_breakpoint_list.Breakpoints())
      bp_sp->RemoveName(name);
  }
}

void Target::RemoveNameFromBreakpoint(lldb::BreakpointSP &bp_sp,
                                      llvm::StringRef name) {
  bp_sp->RemoveName(name);
}

void Target::ConfigureBreakpointName(
    BreakpointName &bp_name, const BreakpointOptions &new_options,
    const BreakpointName::Permissions &new_permissions) {
  bp_name.GetOptions().CopyOverSetOptions(new_options);
  bp_name.GetPermissions().MergeInto(new_permissions);
  ApplyNameToBreakpoints(bp_name);
}

void Target::ApplyNameToBreakpoints(BreakpointName &bp_name) {
  llvm::Expected<std::vector<BreakpointSP>> expected_vector =
      m_breakpoint_list.FindBreakpointsByName(bp_name.GetName());

  if (!expected_vector) {
    LLDB_LOG(GetLog(LLDBLog::Breakpoints), "invalid breakpoint name: {}",
             llvm::toString(expected_vector.takeError()));
    return;
  }

  for (auto bp_sp : *expected_vector)
    bp_name.ConfigureBreakpoint(bp_sp);
}

void Target::GetBreakpointNames(std::vector<std::string> &names) {
  names.clear();
  for (const auto &bp_name_entry : m_breakpoint_names) {
    names.push_back(bp_name_entry.first().str());
  }
  llvm::sort(names);
}

llvm::Expected<lldb::user_id_t> Target::AddBreakpointResolverOverride(
    llvm::StringRef class_name, uint64_t type_mask,
    StructuredData::DictionarySP args_data_sp, llvm::StringRef description) {
  if (class_name.empty())
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "empty class name");

  if (!BreakpointResolver::TypeMaskIsValid(type_mask))
    return llvm::createStringErrorV(
        llvm::inconvertibleErrorCode(),
        "invalid breakpoint type mask: {0}, should be composed of the "
        "elements of the BreakpointResolverType enum.",
        type_mask);

  StructuredDataImpl impl;
  impl.SetObjectSP(args_data_sp);

  BreakpointResolverOverrideUP new_override_up(
      new ScriptedBreakpointResolverOverride(*this, std::string(description),
                                             type_mask, std::string(class_name),
                                             impl));
  llvm::Error error = new_override_up->Validate();
  if (error)
    return error;

  return AddBreakpointResolverOverride(std::move(new_override_up));
}

std::string Target::BreakpointResolverOverride::DescribeTypeMask() {
  return BreakpointResolver::DescribeMask(m_type_mask);
}

void Target::DescribeBreakpointOverrides(Stream &stream,
                                         std::vector<lldb::user_id_t> &idxs,
                                         uint32_t output_width,
                                         bool use_color) {
  if (m_breakpoint_overrides.size() == 0) {
    stream << "No overrides.\n";
    return;
  }

  bool empty = idxs.empty();
  bool print_first = true;
  for (auto const &elem : m_breakpoint_overrides) {
    auto idx_pos = llvm::find(idxs, elem.first);
    if (empty || idx_pos != idxs.end()) {
      if (print_first) {

        ansi::OutputWordWrappedLines(stream, "ID    Mask    Description\n",
                                     output_width, use_color);
        ansi::OutputWordWrappedLines(stream, "----  ------  -----------\n",
                                     output_width, use_color);
        print_first = false;
      }
      auto content = llvm::formatv("{0,4}  {1,6}  {2}\n", elem.first,
                                   elem.second->DescribeTypeMask(),
                                   elem.second->GetDescription())
                         .str();
      ansi::OutputWordWrappedLines(stream, content, output_width, use_color);
      if (!empty)
        idxs.erase(idx_pos);
    }
  }
}

bool Target::ProcessIsValid() {
  return (m_process_sp && m_process_sp->IsAlive());
}

lldb::BreakpointResolverSP
Target::CheckBreakpointOverrides(lldb::BreakpointResolverSP original_sp) {
  for (auto const &elem : m_breakpoint_overrides) {
    if (!original_sp->ResolverTyInMask(elem.second->GetTypeMask()))
      continue;
    if (lldb::BreakpointResolverSP overriden_sp =
            elem.second->CheckForOverride(*this, original_sp))
      return overriden_sp;
  }
  return {};
}

static bool CheckIfWatchpointsSupported(Target *target, Status &error) {
  std::optional<uint32_t> num_supported_hardware_watchpoints =
      target->GetProcessSP()->GetWatchpointSlotCount();

  // If unable to determine the # of watchpoints available,
  // assume they are supported.
  if (!num_supported_hardware_watchpoints)
    return true;

  if (*num_supported_hardware_watchpoints == 0) {
    error = Status::FromErrorStringWithFormat(
        "Target supports (%u) hardware watchpoint slots.\n",
        *num_supported_hardware_watchpoints);
    return false;
  }
  return true;
}

// See also Watchpoint::SetWatchpointType(uint32_t type) and the
// OptionGroupWatchpoint::WatchType enum type.
WatchpointSP Target::CreateWatchpoint(lldb::addr_t addr, size_t size,
                                      const CompilerType *type, uint32_t kind,
                                      Status &error) {
  Log *log = GetLog(LLDBLog::Watchpoints);
  LLDB_LOGF(log,
            "Target::%s (addr = 0x%8.8" PRIx64 " size = %" PRIu64
            " type = %u)\n",
            __FUNCTION__, addr, (uint64_t)size, kind);

  WatchpointSP wp_sp;
  if (!ProcessIsValid()) {
    error = Status::FromErrorString("process is not alive");
    return wp_sp;
  }

  if (addr == LLDB_INVALID_ADDRESS || size == 0) {
    if (size == 0)
      error = Status::FromErrorString(
          "cannot set a watchpoint with watch_size of 0");
    else
      error = Status::FromErrorStringWithFormat(
          "invalid watch address: %" PRIu64, addr);
    return wp_sp;
  }

  if (!LLDB_WATCH_TYPE_IS_VALID(kind)) {
    error =
        Status::FromErrorStringWithFormat("invalid watchpoint type: %d", kind);
  }

  if (!CheckIfWatchpointsSupported(this, error))
    return wp_sp;

  // Currently we only support one watchpoint per address, with total number of
  // watchpoints limited by the hardware which the inferior is running on.

  // Grab the list mutex while doing operations.
  const bool notify = false; // Don't notify about all the state changes we do
                             // on creating the watchpoint.

  // Mask off ignored bits from watchpoint address.
  if (ABISP abi = m_process_sp->GetABI())
    addr = abi->FixDataAddress(addr);

  // LWP_TODO this sequence is looking for an existing watchpoint
  // at the exact same user-specified address, disables the new one
  // if addr/size/type match.  If type/size differ, disable old one.
  // This isn't correct, we need both watchpoints to use a shared
  // WatchpointResource in the target, and expand the WatchpointResource
  // to handle the needs of both Watchpoints.
  // Also, even if the addresses don't match, they may need to be
  // supported by the same WatchpointResource, e.g. a watchpoint
  // watching 1 byte at 0x102 and a watchpoint watching 1 byte at 0x103.
  // They're in the same word and must be watched by a single hardware
  // watchpoint register.

  std::unique_lock<std::recursive_mutex> lock;
  this->GetWatchpointList().GetListMutex(lock);
  WatchpointSP matched_sp = m_watchpoint_list.FindByAddress(addr);
  if (matched_sp) {
    size_t old_size = matched_sp->GetByteSize();
    uint32_t old_type =
        (matched_sp->WatchpointRead() ? LLDB_WATCH_TYPE_READ : 0) |
        (matched_sp->WatchpointWrite() ? LLDB_WATCH_TYPE_WRITE : 0) |
        (matched_sp->WatchpointModify() ? LLDB_WATCH_TYPE_MODIFY : 0);
    // Return the existing watchpoint if both size and type match.
    if (size == old_size && kind == old_type) {
      wp_sp = matched_sp;
      wp_sp->SetEnabled(false, notify);
    } else {
      // Nil the matched watchpoint; we will be creating a new one.
      m_process_sp->DisableWatchpoint(matched_sp, notify);
      m_watchpoint_list.Remove(matched_sp->GetID(), true);
    }
  }

  if (!wp_sp) {
    wp_sp = std::make_shared<Watchpoint>(*this, addr, size, type);
    wp_sp->SetWatchpointType(kind, notify);
    m_watchpoint_list.Add(wp_sp, true);
  }

  error = m_process_sp->EnableWatchpoint(wp_sp, notify);
  LLDB_LOGF(log, "Target::%s (creation of watchpoint %s with id = %u)\n",
            __FUNCTION__, error.Success() ? "succeeded" : "failed",
            wp_sp->GetID());

  if (error.Fail()) {
    // Enabling the watchpoint on the device side failed. Remove the said
    // watchpoint from the list maintained by the target instance.
    m_watchpoint_list.Remove(wp_sp->GetID(), true);
    wp_sp.reset();
  } else
    m_last_created_watchpoint = wp_sp;
  return wp_sp;
}

void Target::RemoveAllowedBreakpoints() {
  Log *log = GetLog(LLDBLog::Breakpoints);
  LLDB_LOGF(log, "Target::%s \n", __FUNCTION__);

  m_breakpoint_list.RemoveAllowed(true);

  m_last_created_breakpoint.reset();
}

void Target::RemoveAllBreakpoints(bool internal_also) {
  Log *log = GetLog(LLDBLog::Breakpoints);
  LLDB_LOGF(log, "Target::%s (internal_also = %s)\n", __FUNCTION__,
            internal_also ? "yes" : "no");

  m_breakpoint_list.RemoveAll(true);
  if (internal_also)
    m_internal_breakpoint_list.RemoveAll(false);

  m_last_created_breakpoint.reset();
}

void Target::DisableAllBreakpoints(bool internal_also) {
  Log *log = GetLog(LLDBLog::Breakpoints);
  LLDB_LOGF(log, "Target::%s (internal_also = %s)\n", __FUNCTION__,
            internal_also ? "yes" : "no");

  m_breakpoint_list.SetEnabledAll(false);
  if (internal_also)
    m_internal_breakpoint_list.SetEnabledAll(false);
}

void Target::DisableAllowedBreakpoints() {
  Log *log = GetLog(LLDBLog::Breakpoints);
  LLDB_LOGF(log, "Target::%s", __FUNCTION__);

  m_breakpoint_list.SetEnabledAllowed(false);
}

void Target::EnableAllBreakpoints(bool internal_also) {
  Log *log = GetLog(LLDBLog::Breakpoints);
  LLDB_LOGF(log, "Target::%s (internal_also = %s)\n", __FUNCTION__,
            internal_also ? "yes" : "no");

  m_breakpoint_list.SetEnabledAll(true);
  if (internal_also)
    m_internal_breakpoint_list.SetEnabledAll(true);
}

void Target::EnableAllowedBreakpoints() {
  Log *log = GetLog(LLDBLog::Breakpoints);
  LLDB_LOGF(log, "Target::%s", __FUNCTION__);

  m_breakpoint_list.SetEnabledAllowed(true);
}

bool Target::RemoveBreakpointByID(break_id_t break_id) {
  Log *log = GetLog(LLDBLog::Breakpoints);
  LLDB_LOGF(log, "Target::%s (break_id = %i, internal = %s)\n", __FUNCTION__,
            break_id, LLDB_BREAK_ID_IS_INTERNAL(break_id) ? "yes" : "no");

  if (DisableBreakpointByID(break_id)) {
    if (LLDB_BREAK_ID_IS_INTERNAL(break_id))
      m_internal_breakpoint_list.Remove(break_id, false);
    else {
      if (m_last_created_breakpoint) {
        if (m_last_created_breakpoint->GetID() == break_id)
          m_last_created_breakpoint.reset();
      }
      m_breakpoint_list.Remove(break_id, true);
    }
    return true;
  }
  return false;
}

bool Target::DisableBreakpointByID(break_id_t break_id) {
  Log *log = GetLog(LLDBLog::Breakpoints);
  LLDB_LOGF(log, "Target::%s (break_id = %i, internal = %s)\n", __FUNCTION__,
            break_id, LLDB_BREAK_ID_IS_INTERNAL(break_id) ? "yes" : "no");

  BreakpointSP bp_sp;

  if (LLDB_BREAK_ID_IS_INTERNAL(break_id))
    bp_sp = m_internal_breakpoint_list.FindBreakpointByID(break_id);
  else
    bp_sp = m_breakpoint_list.FindBreakpointByID(break_id);
  if (bp_sp) {
    bp_sp->SetEnabled(false);
    return true;
  }
  return false;
}

bool Target::EnableBreakpointByID(break_id_t break_id) {
  Log *log = GetLog(LLDBLog::Breakpoints);
  LLDB_LOGF(log, "Target::%s (break_id = %i, internal = %s)\n", __FUNCTION__,
            break_id, LLDB_BREAK_ID_IS_INTERNAL(break_id) ? "yes" : "no");

  BreakpointSP bp_sp;

  if (LLDB_BREAK_ID_IS_INTERNAL(break_id))
    bp_sp = m_internal_breakpoint_list.FindBreakpointByID(break_id);
  else
    bp_sp = m_breakpoint_list.FindBreakpointByID(break_id);

  if (bp_sp) {
    bp_sp->SetEnabled(true);
    return true;
  }
  return false;
}

void Target::ResetBreakpointHitCounts() {
  GetBreakpointList().ResetHitCounts();
}

Status Target::SerializeBreakpointsToFile(const FileSpec &file,
                                          const BreakpointIDList &bp_ids,
                                          bool append) {
  Status error;

  if (!file) {
    error = Status::FromErrorString("Invalid FileSpec.");
    return error;
  }

  std::string path(file.GetPath());
  StructuredData::ObjectSP input_data_sp;

  StructuredData::ArraySP break_store_sp;
  StructuredData::Array *break_store_ptr = nullptr;

  if (append) {
    input_data_sp = StructuredData::ParseJSONFromFile(file, error);
    if (error.Success()) {
      break_store_ptr = input_data_sp->GetAsArray();
      if (!break_store_ptr) {
        error = Status::FromErrorStringWithFormat(
            "Tried to append to invalid input file %s", path.c_str());
        return error;
      }
    }
  }

  if (!break_store_ptr) {
    break_store_sp = std::make_shared<StructuredData::Array>();
    break_store_ptr = break_store_sp.get();
  }

  StreamFile out_file(path.c_str(),
                      File::eOpenOptionTruncate | File::eOpenOptionWriteOnly |
                          File::eOpenOptionCanCreate |
                          File::eOpenOptionCloseOnExec,
                      lldb::eFilePermissionsFileDefault);
  if (!out_file.GetFile().IsValid()) {
    error = Status::FromErrorStringWithFormat("Unable to open output file: %s.",
                                              path.c_str());
    return error;
  }

  std::unique_lock<std::recursive_mutex> lock;
  GetBreakpointList().GetListMutex(lock);

  if (bp_ids.GetSize() == 0) {
    const BreakpointList &breakpoints = GetBreakpointList();

    size_t num_breakpoints = breakpoints.GetSize();
    for (size_t i = 0; i < num_breakpoints; i++) {
      Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
      StructuredData::ObjectSP bkpt_save_sp = bp->SerializeToStructuredData();
      // If a breakpoint can't serialize it, just ignore it for now:
      if (bkpt_save_sp)
        break_store_ptr->AddItem(bkpt_save_sp);
    }
  } else {

    std::unordered_set<lldb::break_id_t> processed_bkpts;
    const size_t count = bp_ids.GetSize();
    for (size_t i = 0; i < count; ++i) {
      BreakpointID cur_bp_id = bp_ids.GetBreakpointIDAtIndex(i);
      lldb::break_id_t bp_id = cur_bp_id.GetBreakpointID();

      if (bp_id != LLDB_INVALID_BREAK_ID) {
        // Only do each breakpoint once:
        std::pair<std::unordered_set<lldb::break_id_t>::iterator, bool>
            insert_result = processed_bkpts.insert(bp_id);
        if (!insert_result.second)
          continue;

        Breakpoint *bp = GetBreakpointByID(bp_id).get();
        StructuredData::ObjectSP bkpt_save_sp = bp->SerializeToStructuredData();
        // If the user explicitly asked to serialize a breakpoint, and we
        // can't, then raise an error:
        if (!bkpt_save_sp) {
          error = Status::FromErrorStringWithFormat(
              "Unable to serialize breakpoint %d", bp_id);
          return error;
        }
        break_store_ptr->AddItem(bkpt_save_sp);
      }
    }
  }

  break_store_ptr->Dump(out_file, false);
  out_file.PutChar('\n');
  return error;
}

Status Target::CreateBreakpointsFromFile(const FileSpec &file,
                                         BreakpointIDList &new_bps) {
  std::vector<std::string> no_names;
  return CreateBreakpointsFromFile(file, no_names, new_bps);
}

Status Target::CreateBreakpointsFromFile(const FileSpec &file,
                                         std::vector<std::string> &names,
                                         BreakpointIDList &new_bps) {
  std::unique_lock<std::recursive_mutex> lock;
  GetBreakpointList().GetListMutex(lock);

  Status error;
  StructuredData::ObjectSP input_data_sp =
      StructuredData::ParseJSONFromFile(file, error);
  if (!error.Success()) {
    return error;
  } else if (!input_data_sp || !input_data_sp->IsValid()) {
    error = Status::FromErrorStringWithFormat(
        "Invalid JSON from input file: %s.", file.GetPath().c_str());
    return error;
  }

  StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
  if (!bkpt_array) {
    error = Status::FromErrorStringWithFormat(
        "Invalid breakpoint data from input file: %s.", file.GetPath().c_str());
    return error;
  }

  size_t num_bkpts = bkpt_array->GetSize();
  size_t num_names = names.size();

  for (size_t i = 0; i < num_bkpts; i++) {
    StructuredData::ObjectSP bkpt_object_sp = bkpt_array->GetItemAtIndex(i);
    // Peel off the breakpoint key, and feed the rest to the Breakpoint:
    StructuredData::Dictionary *bkpt_dict = bkpt_object_sp->GetAsDictionary();
    if (!bkpt_dict) {
      error = Status::FromErrorStringWithFormat(
          "Invalid breakpoint data for element %zu from input file: %s.", i,
          file.GetPath().c_str());
      return error;
    }
    StructuredData::ObjectSP bkpt_data_sp =
        bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
    if (num_names &&
        !Breakpoint::SerializedBreakpointMatchesNames(bkpt_data_sp, names))
      continue;

    BreakpointSP bkpt_sp = Breakpoint::CreateFromStructuredData(
        shared_from_this(), bkpt_data_sp, error);
    if (!error.Success()) {
      error = Status::FromErrorStringWithFormat(
          "Error restoring breakpoint %zu from %s: %s.", i,
          file.GetPath().c_str(), error.AsCString());
      return error;
    }
    new_bps.AddBreakpointID(BreakpointID(bkpt_sp->GetID()));
  }
  return error;
}

// The flag 'end_to_end', default to true, signifies that the operation is
// performed end to end, for both the debugger and the debuggee.

// Assumption: Caller holds the list mutex lock for m_watchpoint_list for end
// to end operations.
bool Target::RemoveAllWatchpoints(bool end_to_end) {
  Log *log = GetLog(LLDBLog::Watchpoints);
  LLDB_LOGF(log, "Target::%s\n", __FUNCTION__);

  if (!end_to_end) {
    m_watchpoint_list.RemoveAll(true);
    return true;
  }

  // Otherwise, it's an end to end operation.

  if (!ProcessIsValid())
    return false;

  for (WatchpointSP wp_sp : m_watchpoint_list.Watchpoints()) {
    if (!wp_sp)
      return false;

    Status rc = m_process_sp->DisableWatchpoint(wp_sp);
    if (rc.Fail())
      return false;
  }
  m_watchpoint_list.RemoveAll(true);
  m_last_created_watchpoint.reset();
  return true; // Success!
}

// Assumption: Caller holds the list mutex lock for m_watchpoint_list for end
// to end operations.
bool Target::DisableAllWatchpoints(bool end_to_end) {
  Log *log = GetLog(LLDBLog::Watchpoints);
  LLDB_LOGF(log, "Target::%s\n", __FUNCTION__);

  if (!end_to_end) {
    m_watchpoint_list.SetEnabledAll(false);
    return true;
  }

  // Otherwise, it's an end to end operation.

  if (!ProcessIsValid())
    return false;

  for (WatchpointSP wp_sp : m_watchpoint_list.Watchpoints()) {
    if (!wp_sp)
      return false;

    Status rc = m_process_sp->DisableWatchpoint(wp_sp);
    if (rc.Fail())
      return false;
  }
  return true; // Success!
}

// Assumption: Caller holds the list mutex lock for m_watchpoint_list for end
// to end operations.
bool Target::EnableAllWatchpoints(bool end_to_end) {
  Log *log = GetLog(LLDBLog::Watchpoints);
  LLDB_LOGF(log, "Target::%s\n", __FUNCTION__);

  if (!end_to_end) {
    m_watchpoint_list.SetEnabledAll(true);
    return true;
  }

  // Otherwise, it's an end to end operation.

  if (!ProcessIsValid())
    return false;

  for (WatchpointSP wp_sp : m_watchpoint_list.Watchpoints()) {
    if (!wp_sp)
      return false;

    Status rc = m_process_sp->EnableWatchpoint(wp_sp);
    if (rc.Fail())
      return false;
  }
  return true; // Success!
}

// Assumption: Caller holds the list mutex lock for m_watchpoint_list.
bool Target::ClearAllWatchpointHitCounts() {
  Log *log = GetLog(LLDBLog::Watchpoints);
  LLDB_LOGF(log, "Target::%s\n", __FUNCTION__);

  for (WatchpointSP wp_sp : m_watchpoint_list.Watchpoints()) {
    if (!wp_sp)
      return false;

    wp_sp->ResetHitCount();
  }
  return true; // Success!
}

// Assumption: Caller holds the list mutex lock for m_watchpoint_list.
bool Target::ClearAllWatchpointHistoricValues() {
  Log *log = GetLog(LLDBLog::Watchpoints);
  LLDB_LOGF(log, "Target::%s\n", __FUNCTION__);

  for (WatchpointSP wp_sp : m_watchpoint_list.Watchpoints()) {
    if (!wp_sp)
      return false;

    wp_sp->ResetHistoricValues();
  }
  return true; // Success!
}

// Assumption: Caller holds the list mutex lock for m_watchpoint_list during
// these operations.
bool Target::IgnoreAllWatchpoints(uint32_t ignore_count) {
  Log *log = GetLog(LLDBLog::Watchpoints);
  LLDB_LOGF(log, "Target::%s\n", __FUNCTION__);

  if (!ProcessIsValid())
    return false;

  for (WatchpointSP wp_sp : m_watchpoint_list.Watchpoints()) {
    if (!wp_sp)
      return false;

    wp_sp->SetIgnoreCount(ignore_count);
  }
  return true; // Success!
}

// Assumption: Caller holds the list mutex lock for m_watchpoint_list.
bool Target::DisableWatchpointByID(lldb::watch_id_t watch_id) {
  Log *log = GetLog(LLDBLog::Watchpoints);
  LLDB_LOGF(log, "Target::%s (watch_id = %i)\n", __FUNCTION__, watch_id);

  if (!ProcessIsValid())
    return false;

  WatchpointSP wp_sp = m_watchpoint_list.FindByID(watch_id);
  if (wp_sp) {
    Status rc = m_process_sp->DisableWatchpoint(wp_sp);
    if (rc.Success())
      return true;

    // Else, fallthrough.
  }
  return false;
}

// Assumption: Caller holds the list mutex lock for m_watchpoint_list.
bool Target::EnableWatchpointByID(lldb::watch_id_t watch_id) {
  Log *log = GetLog(LLDBLog::Watchpoints);
  LLDB_LOGF(log, "Target::%s (watch_id = %i)\n", __FUNCTION__, watch_id);

  if (!ProcessIsValid())
    return false;

  WatchpointSP wp_sp = m_watchpoint_list.FindByID(watch_id);
  if (wp_sp) {
    Status rc = m_process_sp->EnableWatchpoint(wp_sp);
    if (rc.Success())
      return true;

    // Else, fallthrough.
  }
  return false;
}

// Assumption: Caller holds the list mutex lock for m_watchpoint_list.
bool Target::RemoveWatchpointByID(lldb::watch_id_t watch_id) {
  Log *log = GetLog(LLDBLog::Watchpoints);
  LLDB_LOGF(log, "Target::%s (watch_id = %i)\n", __FUNCTION__, watch_id);

  WatchpointSP watch_to_remove_sp = m_watchpoint_list.FindByID(watch_id);
  if (watch_to_remove_sp == m_last_created_watchpoint)
    m_last_created_watchpoint.reset();

  if (DisableWatchpointByID(watch_id)) {
    m_watchpoint_list.Remove(watch_id, true);
    return true;
  }
  return false;
}

// Assumption: Caller holds the list mutex lock for m_watchpoint_list.
bool Target::IgnoreWatchpointByID(lldb::watch_id_t watch_id,
                                  uint32_t ignore_count) {
  Log *log = GetLog(LLDBLog::Watchpoints);
  LLDB_LOGF(log, "Target::%s (watch_id = %i)\n", __FUNCTION__, watch_id);

  if (!ProcessIsValid())
    return false;

  WatchpointSP wp_sp = m_watchpoint_list.FindByID(watch_id);
  if (wp_sp) {
    wp_sp->SetIgnoreCount(ignore_count);
    return true;
  }
  return false;
}

ModuleSP Target::GetExecutableModule() {
  std::lock_guard<std::recursive_mutex> lock(m_images.GetMutex());

  // Search for the first executable in the module list.
  for (ModuleSP module_sp : m_images.ModulesNoLocking()) {
    lldb_private::ObjectFile *obj = module_sp->GetObjectFile();
    if (obj == nullptr)
      continue;
    if (obj->GetType() == ObjectFile::Type::eTypeExecutable)
      return module_sp;
  }

  // If there is none, fall back to the module marked as the executable.
  ModuleSP executable_sp = m_executable_module_wp.lock();
  if (executable_sp &&
      m_images.GetIndexForModule(executable_sp.get()) != LLDB_INVALID_INDEX32)
    return executable_sp;
  return nullptr;
}

Module *Target::GetExecutableModulePointer() {
  return GetExecutableModule().get();
}

void Target::MarkExecutableModule(const ModuleSP &module_sp) {
  std::lock_guard<std::recursive_mutex> lock(m_images.GetMutex());
  m_executable_module_wp = module_sp;
}

void Target::ClearModules(bool delete_locations) {
  ModulesDidUnload(m_images, delete_locations);
  m_section_load_history.Clear();
  m_images.Clear();
  MarkExecutableModule(nullptr);
  m_scratch_type_system_map.Clear();
}

void Target::DidExec() {
  // When a process exec's we need to know about it so we can do some cleanup.
  m_breakpoint_list.RemoveInvalidLocations(m_arch.GetSpec());
  m_internal_breakpoint_list.RemoveInvalidLocations(m_arch.GetSpec());
}

void Target::RebuildModuleListWithExecutable(
    ModuleSP &executable_sp, LoadDependentFiles load_dependent_files) {
  telemetry::ScopedDispatcher<telemetry::ExecutableModuleInfo> helper(
      &m_debugger);
  Log *log = GetLog(LLDBLog::Target);
  ClearModules(false);

  if (executable_sp) {
    lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
    if (ProcessSP proc = GetProcessSP())
      pid = proc->GetID();

    helper.DispatchNow([&](telemetry::ExecutableModuleInfo *info) {
      info->exec_mod = executable_sp;
      info->uuid = executable_sp->GetUUID();
      info->pid = pid;
      info->triple = executable_sp->GetArchitecture().GetTriple().getTriple();
      info->is_start_entry = true;
    });

    helper.DispatchOnExit([&, pid](telemetry::ExecutableModuleInfo *info) {
      info->exec_mod = executable_sp;
      info->uuid = executable_sp->GetUUID();
      info->pid = pid;
    });

    ElapsedTime elapsed(m_stats.GetCreateTime());
    LLDB_SCOPED_TIMERF(
        "Target::RebuildModuleListWithExecutable (executable = '%s')",
        executable_sp->GetFileSpec().GetPath().c_str());

    const bool notify = true;
    // Mark it before appending, because the append notifies observers that
    // may ask for the executable.
    MarkExecutableModule(executable_sp);
    m_images.Append(executable_sp,
                    notify); // The first image is our executable file

    // If we haven't set an architecture yet, reset our architecture based on
    // what we found in the executable module.
    if (!m_arch.GetSpec().IsValid()) {
      m_arch = executable_sp->GetArchitecture();
      LLDB_LOG(log,
               "Target::RebuildModuleListWithExecutable setting architecture "
               "to {0} ({1}) "
               "based on executable file",
               m_arch.GetSpec().GetArchitectureName(),
               m_arch.GetSpec().GetTriple().getTriple());
    }

    ObjectFile *executable_objfile = executable_sp->GetObjectFile();
    bool load_dependents = true;
    switch (load_dependent_files) {
    case eLoadDependentsDefault:
      load_dependents = executable_sp->IsExecutable();
      break;
    case eLoadDependentsYes:
      load_dependents = true;
      break;
    case eLoadDependentsNo:
      load_dependents = false;
      break;
    }

    if (executable_objfile && load_dependents) {
      // FileSpecList is not thread safe and needs to be synchronized.
      FileSpecList dependent_files;
      std::mutex dependent_files_mutex;

      // ModuleList is thread safe.
      ModuleList added_modules;

      auto GetDependentModules = [&](FileSpec dependent_file_spec) {
        FileSpec platform_dependent_file_spec;
        if (m_platform_sp)
          m_platform_sp->GetFileWithUUID(dependent_file_spec, nullptr,
                                         platform_dependent_file_spec);
        else
          platform_dependent_file_spec = dependent_file_spec;

        ModuleSpec module_spec(platform_dependent_file_spec, m_arch.GetSpec());
        ModuleSP image_module_sp(
            GetOrCreateModule(module_spec, false /* notify */));
        if (image_module_sp) {
          added_modules.AppendIfNeeded(image_module_sp, false);
          ObjectFile *objfile = image_module_sp->GetObjectFile();
          if (objfile) {
            // Create a local copy of the dependent file list so we don't have
            // to lock for the whole duration of GetDependentModules.
            FileSpecList dependent_files_copy;
            {
              std::lock_guard<std::mutex> guard(dependent_files_mutex);
              dependent_files_copy = dependent_files;
            }

            // Remember the size of the local copy so we can append only the
            // modules that have been added by GetDependentModules.
            const size_t previous_dependent_files =
                dependent_files_copy.GetSize();

            objfile->GetDependentModules(dependent_files_copy);

            {
              std::lock_guard<std::mutex> guard(dependent_files_mutex);
              for (size_t i = previous_dependent_files;
                   i < dependent_files_copy.GetSize(); ++i)
                dependent_files.AppendIfUnique(
                    dependent_files_copy.GetFileSpecAtIndex(i));
            }
          }
        }
      };

      executable_objfile->GetDependentModules(dependent_files);

      llvm::ThreadPoolTaskGroup task_group(Debugger::GetThreadPool());
      for (uint32_t i = 0; i < dependent_files.GetSize(); i++) {
        // Process all currently known dependencies in parallel in the innermost
        // loop. This may create newly discovered dependencies to be appended to
        // dependent_files. We'll deal with these files during the next
        // iteration of the outermost loop.
        {
          std::lock_guard<std::mutex> guard(dependent_files_mutex);
          for (; i < dependent_files.GetSize(); i++)
            task_group.async(GetDependentModules,
                             dependent_files.GetFileSpecAtIndex(i));
        }
        task_group.wait();
      }
      ModulesDidLoad(added_modules);
    }
  }
}

bool Target::SetArchitecture(const ArchSpec &arch_spec, bool set_platform,
                             bool merge) {
  Log *log = GetLog(LLDBLog::Target);
  bool missing_local_arch = !m_arch.GetSpec().IsValid();
  bool replace_local_arch = true;
  bool compatible_local_arch = false;
  ArchSpec other(arch_spec);

  // Changing the architecture might mean that the currently selected platform
  // isn't compatible. Set the platform correctly if we are asked to do so,
  // otherwise assume the user will set the platform manually.
  if (set_platform) {
    if (other.IsValid()) {
      auto platform_sp = GetPlatform();
      if (!platform_sp || !platform_sp->IsCompatibleArchitecture(
                              other, {}, ArchSpec::CompatibleMatch, nullptr)) {
        ArchSpec platform_arch;
        if (PlatformSP arch_platform_sp =
                GetDebugger().GetPlatformList().GetOrCreate(other, {},
                                                            &platform_arch)) {
          arch_platform_sp->SetLocateModuleCallback(
              platform_sp->GetLocateModuleCallback());
          SetPlatform(arch_platform_sp);
          if (platform_arch.IsValid())
            other = platform_arch;
        }
      }
    }
  }

  if (!missing_local_arch) {
    if (merge && m_arch.GetSpec().IsCompatibleMatch(arch_spec)) {
      other.MergeFrom(m_arch.GetSpec());

      if (m_arch.GetSpec().IsCompatibleMatch(other)) {
        compatible_local_arch = true;

        if (m_arch.GetSpec().GetTriple() == other.GetTriple())
          replace_local_arch = false;
      }
    }
  }

  if (compatible_local_arch || missing_local_arch) {
    // If we haven't got a valid arch spec, or the architectures are compatible
    // update the architecture, unless the one we already have is more
    // specified
    if (replace_local_arch)
      m_arch = other;
    LLDB_LOG(log,
             "Target::SetArchitecture merging compatible arch; arch "
             "is now {0} ({1})",
             m_arch.GetSpec().GetArchitectureName(),
             m_arch.GetSpec().GetTriple().getTriple());
    return true;
  }

  // If we have an executable file, try to reset the executable to the desired
  // architecture
  LLDB_LOGF(
      log,
      "Target::SetArchitecture changing architecture to %s (%s) from %s (%s)",
      arch_spec.GetArchitectureName(),
      arch_spec.GetTriple().getTriple().c_str(),
      m_arch.GetSpec().GetArchitectureName(),
      m_arch.GetSpec().GetTriple().getTriple().c_str());
  m_arch = other;
  ModuleSP executable_sp = GetExecutableModule();

  ClearModules(true);
  // Need to do something about unsetting breakpoints.

  if (executable_sp) {
    LLDB_LOGF(log,
              "Target::SetArchitecture Trying to select executable file "
              "architecture %s (%s)",
              arch_spec.GetArchitectureName(),
              arch_spec.GetTriple().getTriple().c_str());
    ModuleSpec module_spec(executable_sp->GetFileSpec(), other);
    module_spec.SetTarget(shared_from_this());
    Status error = ModuleList::GetSharedModule(module_spec, executable_sp,
                                               nullptr, nullptr);

    if (!error.Fail() && executable_sp) {
      RebuildModuleListWithExecutable(executable_sp, eLoadDependentsYes);
      return true;
    }
  }
  return false;
}

bool Target::MergeArchitecture(const ArchSpec &arch_spec) {
  Log *log = GetLog(LLDBLog::Target);
  if (arch_spec.IsValid()) {
    if (m_arch.GetSpec().IsCompatibleMatch(arch_spec)) {
      // The current target arch is compatible with "arch_spec", see if we can
      // improve our current architecture using bits from "arch_spec"

      LLDB_LOGF(log,
                "Target::MergeArchitecture target has arch %s, merging with "
                "arch %s",
                m_arch.GetSpec().GetTriple().getTriple().c_str(),
                arch_spec.GetTriple().getTriple().c_str());

      // Merge bits from arch_spec into "merged_arch" and set our architecture
      ArchSpec merged_arch(m_arch.GetSpec());
      merged_arch.MergeFrom(arch_spec);
      return SetArchitecture(merged_arch);
    } else {
      // The new architecture is different, we just need to replace it
      return SetArchitecture(arch_spec);
    }
  }
  return false;
}

void Target::NotifyWillClearList(const ModuleList &module_list) {}

void Target::NotifyModuleAdded(const ModuleList &module_list,
                               const ModuleSP &module_sp) {
  // A module is being added to this target for the first time
  if (m_valid) {
    ModuleList my_module_list;
    my_module_list.Append(module_sp);
    ModulesDidLoad(my_module_list);
  }
}

void Target::NotifyModuleRemoved(const ModuleList &module_list,
                                 const ModuleSP &module_sp) {
  // A module is being removed from this target.
  if (m_valid) {
    ModuleList my_module_list;
    my_module_list.Append(module_sp);
    ModulesDidUnload(my_module_list, false);
  }
}

void Target::NotifyModuleUpdated(const ModuleList &module_list,
                                 const ModuleSP &old_module_sp,
                                 const ModuleSP &new_module_sp) {
  // A module is replacing an already added module
  if (m_valid) {
    m_breakpoint_list.UpdateBreakpointsWhenModuleIsReplaced(old_module_sp,
                                                            new_module_sp);
    m_internal_breakpoint_list.UpdateBreakpointsWhenModuleIsReplaced(
        old_module_sp, new_module_sp);
  }
}

void Target::NotifyModulesRemoved(lldb_private::ModuleList &module_list) {
  ModulesDidUnload(module_list, false);
}

void Target::ModulesDidLoad(ModuleList &module_list) {
  if (GetPreloadSymbols())
    module_list.PreloadSymbols(GetParallelModuleLoad());

  const size_t num_images = module_list.GetSize();
  if (m_valid && num_images) {
    std::list<Status> errors;
    module_list.LoadScriptingResourcesInTarget(this, errors);
    for (const auto &err : errors)
      GetDebugger().GetAsyncErrorStream()->PutCString(err.AsCString());

    for (size_t idx = 0; idx < num_images; ++idx) {
      ModuleSP module_sp(module_list.GetModuleAtIndex(idx));
      LoadTypeSummariesForModule(module_sp);
      LoadFormattersForModule(module_sp);
    }
    m_breakpoint_list.UpdateBreakpoints(module_list, true, false);
    m_internal_breakpoint_list.UpdateBreakpoints(module_list, true, false);
    if (m_process_sp) {
      m_process_sp->ModulesDidLoad(module_list);
    }
    RunModuleHooks(/*is_load=*/true);
    auto data_sp =
        std::make_shared<TargetEventData>(shared_from_this(), module_list);
    BroadcastEvent(eBroadcastBitModulesLoaded, data_sp);
  }
}

void Target::SymbolsDidLoad(ModuleList &module_list) {
  if (m_valid && module_list.GetSize()) {
    if (m_process_sp) {
      for (LanguageRuntime *runtime : m_process_sp->GetLanguageRuntimes()) {
        runtime->SymbolsDidLoad(module_list);
      }
    }

    m_breakpoint_list.UpdateBreakpoints(module_list, true, false);
    m_internal_breakpoint_list.UpdateBreakpoints(module_list, true, false);
    auto data_sp =
        std::make_shared<TargetEventData>(shared_from_this(), module_list);
    BroadcastEvent(eBroadcastBitSymbolsLoaded, data_sp);
  }
}

void Target::ModulesDidUnload(ModuleList &module_list, bool delete_locations) {
  if (m_valid && module_list.GetSize()) {
    UnloadModuleSections(module_list);
    auto data_sp =
        std::make_shared<TargetEventData>(shared_from_this(), module_list);
    BroadcastEvent(eBroadcastBitModulesUnloaded, data_sp);
    m_breakpoint_list.UpdateBreakpoints(module_list, false, delete_locations);
    m_internal_breakpoint_list.UpdateBreakpoints(module_list, false,
                                                 delete_locations);

    // If a module was torn down it will have torn down the 'TypeSystemClang's
    // that we used as source 'ASTContext's for the persistent variables in
    // the current target. Those would now be unsafe to access because the
    // 'DeclOrigin' are now possibly stale. Thus clear all persistent
    // variables. We only want to flush 'TypeSystem's if the module being
    // unloaded was capable of describing a source type. JITted module unloads
    // happen frequently for Objective-C utility functions or the REPL and rely
    // on the persistent variables to stick around.
    const bool should_flush_type_systems =
        module_list.AnyOf([](lldb_private::Module &module) {
          auto *object_file = module.GetObjectFile();

          if (!object_file)
            return false;

          auto type = object_file->GetType();

          // eTypeExecutable: when debugged binary was rebuilt
          // eTypeSharedLibrary: if dylib was re-loaded
          return module.FileHasChanged() &&
                 (type == ObjectFile::eTypeObjectFile ||
                  type == ObjectFile::eTypeExecutable ||
                  type == ObjectFile::eTypeSharedLibrary);
        });

    if (should_flush_type_systems)
      m_scratch_type_system_map.Clear();

    RunModuleHooks(/*is_load=*/false);
  }
}

bool Target::ModuleIsExcludedForUnconstrainedSearches(
    const FileSpec &module_file_spec) {
  if (GetBreakpointsConsultPlatformAvoidList()) {
    ModuleList matchingModules;
    ModuleSpec module_spec(module_file_spec);
    GetImages().FindModules(module_spec, matchingModules);
    size_t num_modules = matchingModules.GetSize();

    // If there is more than one module for this file spec, only
    // return true if ALL the modules are on the black list.
    if (num_modules > 0) {
      for (size_t i = 0; i < num_modules; i++) {
        if (!ModuleIsExcludedForUnconstrainedSearches(
                matchingModules.GetModuleAtIndex(i)))
          return false;
      }
      return true;
    }
  }
  return false;
}

bool Target::ModuleIsExcludedForUnconstrainedSearches(
    const lldb::ModuleSP &module_sp) {
  if (GetBreakpointsConsultPlatformAvoidList()) {
    if (m_platform_sp)
      return m_platform_sp->ModuleIsExcludedForUnconstrainedSearches(*this,
                                                                     module_sp);
  }
  return false;
}

size_t Target::ReadMemoryFromFileCache(const Address &addr, void *dst,
                                       size_t dst_len, Status &error) {
  SectionSP section_sp(addr.GetSection());
  if (section_sp) {
    // If the contents of this section are encrypted, the on-disk file is
    // unusable.  Read only from live memory.
    if (section_sp->IsEncrypted()) {
      error = Status::FromErrorString("section is encrypted");
      return 0;
    }
    ModuleSP module_sp(section_sp->GetModule());
    if (module_sp) {
      ObjectFile *objfile = section_sp->GetModule()->GetObjectFile();
      if (objfile) {
        size_t bytes_read = objfile->ReadSectionData(
            section_sp.get(), addr.GetOffset(), dst, dst_len);
        if (bytes_read > 0)
          return bytes_read;
        else
          error = Status::FromErrorStringWithFormatv(
              "error reading data from section {0}", section_sp->GetName());
      } else
        error = Status::FromErrorString("address isn't from a object file");
    } else
      error = Status::FromErrorString("address isn't in a module");
  } else
    error = Status::FromErrorString(
        "address doesn't contain a section that points to a "
        "section in a object file");

  return 0;
}

size_t Target::ReadMemory(const Address &addr, void *dst, size_t dst_len,
                          Status &error, bool force_live_memory,
                          lldb::addr_t *load_addr_ptr,
                          bool *did_read_live_memory) {
  error.Clear();
  if (did_read_live_memory)
    *did_read_live_memory = false;

  Address fixed_addr = addr;
  if (ProcessIsValid())
    if (const ABISP &abi = m_process_sp->GetABI())
      fixed_addr.SetLoadAddress(abi->FixAnyAddress(addr.GetLoadAddress(this)),
                                this);

  // if we end up reading this from process memory, we will fill this with the
  // actual load address
  if (load_addr_ptr)
    *load_addr_ptr = LLDB_INVALID_ADDRESS;

  size_t bytes_read = 0;

  addr_t load_addr = LLDB_INVALID_ADDRESS;
  addr_t file_addr = LLDB_INVALID_ADDRESS;
  Address resolved_addr;
  if (!fixed_addr.IsSectionOffset()) {
    SectionLoadList &section_load_list = GetSectionLoadList();
    if (section_load_list.IsEmpty()) {
      // No sections are loaded, so we must assume we are not running yet and
      // anything we are given is a file address.
      file_addr =
          fixed_addr.GetOffset(); // "fixed_addr" doesn't have a section, so
                                  // its offset is the file address
      m_images.ResolveFileAddress(file_addr, resolved_addr);
    } else {
      // We have at least one section loaded. This can be because we have
      // manually loaded some sections with "target modules load ..." or
      // because we have a live process that has sections loaded through
      // the dynamic loader
      load_addr =
          fixed_addr.GetOffset(); // "fixed_addr" doesn't have a section, so
                                  // its offset is the load address
      section_load_list.ResolveLoadAddress(load_addr, resolved_addr);
    }
  }
  if (!resolved_addr.IsValid())
    resolved_addr = fixed_addr;

  // If we read from the file cache but can't get as many bytes as requested,
  // we keep the result around in this buffer, in case this result is the
  // best we can do.
  std::unique_ptr<uint8_t[]> file_cache_read_buffer;
  size_t file_cache_bytes_read = 0;

  // Read from file cache if read-only section.
  if (!force_live_memory && resolved_addr.IsSectionOffset()) {
    SectionSP section_sp(resolved_addr.GetSection());
    if (section_sp) {
      auto permissions = Flags(section_sp->GetPermissions());
      bool is_readonly = !permissions.Test(ePermissionsWritable) &&
                         permissions.Test(ePermissionsReadable);
      if (is_readonly) {
        file_cache_bytes_read =
            ReadMemoryFromFileCache(resolved_addr, dst, dst_len, error);
        if (file_cache_bytes_read == dst_len)
          return file_cache_bytes_read;
        else if (file_cache_bytes_read > 0) {
          file_cache_read_buffer =
              std::make_unique<uint8_t[]>(file_cache_bytes_read);
          std::memcpy(file_cache_read_buffer.get(), dst, file_cache_bytes_read);
        }
      }
    }
  }

  if (ProcessIsValid()) {
    if (load_addr == LLDB_INVALID_ADDRESS)
      load_addr = resolved_addr.GetLoadAddress(this);

    if (load_addr == LLDB_INVALID_ADDRESS) {
      ModuleSP addr_module_sp(resolved_addr.GetModule());
      if (addr_module_sp && addr_module_sp->GetFileSpec())
        error = Status::FromErrorStringWithFormatv(
            "{0:F}[{1:x+}] can't be resolved, {0:F} is not currently loaded",
            addr_module_sp->GetFileSpec(), resolved_addr.GetFileAddress());
      else
        error = Status::FromErrorStringWithFormat(
            "0x%" PRIx64 " can't be resolved", resolved_addr.GetFileAddress());
    } else {
      bytes_read = m_process_sp->ReadMemory(load_addr, dst, dst_len, error);
      if (bytes_read != dst_len) {
        if (error.Success()) {
          if (bytes_read == 0)
            error = Status::FromErrorStringWithFormat(
                "read memory from 0x%" PRIx64 " failed", load_addr);
          else
            error = Status::FromErrorStringWithFormat(
                "only %" PRIu64 " of %" PRIu64
                " bytes were read from memory at 0x%" PRIx64,
                (uint64_t)bytes_read, (uint64_t)dst_len, load_addr);
        }
      }
      if (bytes_read) {
        if (load_addr_ptr)
          *load_addr_ptr = load_addr;
        if (did_read_live_memory)
          *did_read_live_memory = true;
        return bytes_read;
      }
    }
  }

  if (file_cache_read_buffer && file_cache_bytes_read > 0) {
    // Reading from the process failed. If we've previously succeeded in reading
    // something from the file cache, then copy that over and return that.
    std::memcpy(dst, file_cache_read_buffer.get(), file_cache_bytes_read);
    return file_cache_bytes_read;
  }

  if (!file_cache_read_buffer && resolved_addr.IsSectionOffset()) {
    // If we didn't already try and read from the object file cache, then try
    // it after failing to read from the process.
    error.Clear();
    bytes_read = ReadMemoryFromFileCache(resolved_addr, dst, dst_len, error);
    // A short read here is only a failure if a live read already failed too.
    // Reaching this point with a valid process means the process contributed
    // nothing.
    if (bytes_read > 0 && bytes_read != dst_len && error.Success() &&
        ProcessIsValid())
      error = Status::FromErrorStringWithFormatv(
          "only {0} of {1} bytes were read from the object file cache",
          bytes_read, dst_len);
    return bytes_read;
  }
  return 0;
}

size_t Target::ReadCStringFromMemory(const Address &addr, std::string &out_str,
                                     Status &error, bool force_live_memory) {
  char buf[256];
  out_str.clear();
  addr_t curr_addr = addr.GetLoadAddress(this);
  Address address(addr);
  while (true) {
    size_t length = ReadCStringFromMemory(address, buf, sizeof(buf), error,
                                          force_live_memory);
    if (length == 0)
      break;
    out_str.append(buf, length);
    // If we got "length - 1" bytes, we didn't get the whole C string, we need
    // to read some more characters
    if (length == sizeof(buf) - 1)
      curr_addr += length;
    else
      break;
    address = Address(curr_addr);
  }
  return out_str.size();
}

size_t Target::ReadCStringFromMemory(const Address &addr, char *dst,
                                     size_t dst_max_len, Status &result_error,
                                     bool force_live_memory) {
  size_t total_cstr_len = 0;
  if (dst && dst_max_len) {
    result_error.Clear();
    // NULL out everything just to be safe
    memset(dst, 0, dst_max_len);
    addr_t curr_addr = addr.GetLoadAddress(this);
    Address address(addr);

    // We could call m_process_sp->GetMemoryCacheLineSize() but I don't think
    // this really needs to be tied to the memory cache subsystem's cache line
    // size, so leave this as a fixed constant.
    const size_t cache_line_size = 512;

    size_t bytes_left = dst_max_len - 1;
    char *curr_dst = dst;

    while (bytes_left > 0) {
      addr_t cache_line_bytes_left =
          cache_line_size - (curr_addr % cache_line_size);
      addr_t bytes_to_read =
          std::min<addr_t>(bytes_left, cache_line_bytes_left);
      Status error;
      size_t bytes_read = ReadMemory(address, curr_dst, bytes_to_read, error,
                                     force_live_memory);

      if (bytes_read == 0) {
        result_error = std::move(error);
        dst[total_cstr_len] = '\0';
        break;
      }
      const size_t len = strlen(curr_dst);

      total_cstr_len += len;

      if (len < bytes_to_read)
        break;

      curr_dst += bytes_read;
      curr_addr += bytes_read;
      bytes_left -= bytes_read;
      address = Address(curr_addr);
    }
  } else {
    if (dst == nullptr)
      result_error = Status::FromErrorString("invalid arguments");
    else
      result_error.Clear();
  }
  return total_cstr_len;
}

addr_t Target::GetReasonableReadSize(const Address &addr) {
  addr_t load_addr = addr.GetLoadAddress(this);
  if (load_addr != LLDB_INVALID_ADDRESS && m_process_sp) {
    // Avoid crossing cache line boundaries.
    addr_t cache_line_size = m_process_sp->GetMemoryCacheLineSize();
    return cache_line_size - (load_addr % cache_line_size);
  }

  // The read is going to go to the file cache, so we can just pick a largish
  // value.
  return 0x1000;
}

size_t Target::ReadStringFromMemory(const Address &addr, char *dst,
                                    size_t max_bytes, Status &error,
                                    size_t type_width, bool force_live_memory) {
  if (!dst || !max_bytes || !type_width || max_bytes < type_width)
    return 0;

  size_t total_bytes_read = 0;

  // Ensure a null terminator independent of the number of bytes that is
  // read.
  memset(dst, 0, max_bytes);
  size_t bytes_left = max_bytes - type_width;

  const char terminator[4] = {'\0', '\0', '\0', '\0'};
  assert(sizeof(terminator) >= type_width && "Attempting to validate a "
                                             "string with more than 4 bytes "
                                             "per character!");

  Address address = addr;
  char *curr_dst = dst;

  error.Clear();
  while (bytes_left > 0 && error.Success()) {
    addr_t bytes_to_read =
        std::min<addr_t>(bytes_left, GetReasonableReadSize(address));
    size_t bytes_read =
        ReadMemory(address, curr_dst, bytes_to_read, error, force_live_memory);

    if (bytes_read == 0)
      break;

    // Search for a null terminator of correct size and alignment in
    // bytes_read
    size_t aligned_start = total_bytes_read - total_bytes_read % type_width;
    for (size_t i = aligned_start;
         i + type_width <= total_bytes_read + bytes_read; i += type_width)
      if (::memcmp(&dst[i], terminator, type_width) == 0) {
        error.Clear();
        return i;
      }

    total_bytes_read += bytes_read;
    curr_dst += bytes_read;
    address.Slide(bytes_read);
    bytes_left -= bytes_read;
  }
  return total_bytes_read;
}

size_t Target::ReadScalarIntegerFromMemory(const Address &addr, uint32_t byte_size,
                                           bool is_signed, Scalar &scalar,
                                           Status &error,
                                           bool force_live_memory) {
  uint64_t uval;

  if (byte_size <= sizeof(uval)) {
    size_t bytes_read =
        ReadMemory(addr, &uval, byte_size, error, force_live_memory);
    if (bytes_read == byte_size) {
      DataExtractor data(&uval, sizeof(uval), m_arch.GetSpec().GetByteOrder(),
                         m_arch.GetSpec().GetAddressByteSize());
      lldb::offset_t offset = 0;
      if (byte_size <= 4)
        scalar = data.GetMaxU32(&offset, byte_size);
      else
        scalar = data.GetMaxU64(&offset, byte_size);

      if (is_signed) {
        scalar.MakeSigned();
        scalar.SignExtend(byte_size * 8);
      }
      return bytes_read;
    }
  } else {
    error = Status::FromErrorStringWithFormat(
        "byte size of %u is too large for integer scalar type", byte_size);
  }
  return 0;
}

int64_t Target::ReadSignedIntegerFromMemory(const Address &addr,
                                            size_t integer_byte_size,
                                            int64_t fail_value, Status &error,
                                            bool force_live_memory) {
  Scalar scalar;
  if (ReadScalarIntegerFromMemory(addr, integer_byte_size, true, scalar, error,
                                  force_live_memory))
    return scalar.SLongLong(fail_value);
  return fail_value;
}

uint64_t Target::ReadUnsignedIntegerFromMemory(const Address &addr,
                                               size_t integer_byte_size,
                                               uint64_t fail_value, Status &error,
                                               bool force_live_memory) {
  Scalar scalar;
  if (ReadScalarIntegerFromMemory(addr, integer_byte_size, false, scalar, error,
                                  force_live_memory))
    return scalar.ULongLong(fail_value);
  return fail_value;
}

bool Target::ReadPointerFromMemory(const Address &addr, Status &error,
                                   Address &pointer_addr,
                                   bool force_live_memory) {
  Scalar scalar;
  if (ReadScalarIntegerFromMemory(addr, m_arch.GetSpec().GetAddressByteSize(),
                                  false, scalar, error, force_live_memory)) {
    addr_t pointer_vm_addr = scalar.ULongLong(LLDB_INVALID_ADDRESS);
    if (pointer_vm_addr != LLDB_INVALID_ADDRESS) {
      SectionLoadList &section_load_list = GetSectionLoadList();
      if (section_load_list.IsEmpty()) {
        // No sections are loaded, so we must assume we are not running yet and
        // anything we are given is a file address.
        m_images.ResolveFileAddress(pointer_vm_addr, pointer_addr);
      } else {
        // We have at least one section loaded. This can be because we have
        // manually loaded some sections with "target modules load ..." or
        // because we have a live process that has sections loaded through
        // the dynamic loader
        section_load_list.ResolveLoadAddress(pointer_vm_addr, pointer_addr);
      }
      // We weren't able to resolve the pointer value, so just return an
      // address with no section
      if (!pointer_addr.IsValid())
        pointer_addr.SetOffset(pointer_vm_addr);
      return true;
    }
  }
  return false;
}

ModuleSP Target::GetOrCreateModule(const ModuleSpec &orig_module_spec,
                                   bool notify, Status *error_ptr) {
  ModuleSP module_sp;

  Status error;

  // Apply any remappings specified in target.object-map:
  ModuleSpec module_spec(orig_module_spec);
  module_spec.SetTarget(shared_from_this());
  PathMappingList &obj_mapping = GetObjectPathMap();
  if (std::optional<FileSpec> remapped_obj_file =
          obj_mapping.RemapPath(orig_module_spec.GetFileSpec().GetPath(),
                                true /* only_if_exists */)) {
    module_spec.GetFileSpec().SetPath(remapped_obj_file->GetPath());
  }

  // First see if we already have this module in our module list.  If we do,
  // then we're done, we don't need to consult the shared modules list.  But
  // only do this if we are passed a UUID.

  if (module_spec.GetUUID().IsValid())
    module_sp = m_images.FindFirstModule(module_spec);

  if (!module_sp) {
    llvm::SmallVector<ModuleSP, 1>
        old_modules; // This will get filled in if we have a new version
                     // of the library
    bool did_create_module = false;
    FileSpecList search_paths = GetExecutableSearchPaths();
    FileSpec symbol_file_spec;

    // Call locate module callback if set. This allows users to implement their
    // own module cache system. For example, to leverage build system artifacts,
    // to bypass pulling files from remote platform, or to search symbol files
    // from symbol servers.
    if (m_platform_sp)
      m_platform_sp->CallLocateModuleCallbackIfSet(
          module_spec, module_sp, symbol_file_spec, &did_create_module);

    // The result of this CallLocateModuleCallbackIfSet is one of the following.
    // 1. module_sp:loaded, symbol_file_spec:set
    //      The callback found a module file and a symbol file for the
    //      module_spec. We will call module_sp->SetSymbolFileFileSpec with
    //      the symbol_file_spec later.
    // 2. module_sp:loaded, symbol_file_spec:empty
    //      The callback only found a module file for the module_spec.
    // 3. module_sp:empty, symbol_file_spec:set
    //      The callback only found a symbol file for the module. We continue
    //      to find a module file for this module_spec and we will call
    //      module_sp->SetSymbolFileFileSpec with the symbol_file_spec later.
    // 4. module_sp:empty, symbol_file_spec:empty
    //      Platform does not exist, the callback is not set, the callback did
    //      not find any module files nor any symbol files, the callback failed,
    //      or something went wrong. We continue to find a module file for this
    //      module_spec.

    if (!module_sp) {
      // If there are image search path entries, try to use them to acquire a
      // suitable image.
      if (m_image_search_paths.GetSize()) {
        ModuleSpec transformed_spec(module_spec);
        std::string transformed_dir;
        if (m_image_search_paths.RemapPath(
                module_spec.GetFileSpec().GetDirectory(), transformed_dir)) {
          transformed_spec.GetFileSpec().SetDirectory(transformed_dir);
          transformed_spec.GetFileSpec().SetFilename(
                module_spec.GetFileSpec().GetFilename());
          transformed_spec.SetTarget(shared_from_this());
          error = ModuleList::GetSharedModule(transformed_spec, module_sp,
                                              &old_modules, &did_create_module);
        }
      }
    }

    if (!module_sp) {
      // If we have a UUID, we can check our global shared module list in case
      // we already have it. If we don't have a valid UUID, then we can't since
      // the path in "module_spec" will be a platform path, and we will need to
      // let the platform find that file. For example, we could be asking for
      // "/usr/lib/dyld" and if we do not have a UUID, we don't want to pick
      // the local copy of "/usr/lib/dyld" since our platform could be a remote
      // platform that has its own "/usr/lib/dyld" in an SDK or in a local file
      // cache.
      if (module_spec.GetUUID().IsValid()) {
        // We have a UUID, it is OK to check the global module list...
        error = ModuleList::GetSharedModule(module_spec, module_sp,
                                            &old_modules, &did_create_module);
      }

      if (!module_sp) {
        // The platform is responsible for finding and caching an appropriate
        // module in the shared module cache.
        if (m_platform_sp) {
          error = m_platform_sp->GetSharedModule(
              module_spec, *this, module_sp, &old_modules, &did_create_module);
        } else {
          error = Status::FromErrorString("no platform is currently set");
        }
      }
    }

    // We found a module that wasn't in our target list.  Let's make sure that
    // there wasn't an equivalent module in the list already, and if there was,
    // let's remove it.
    if (module_sp) {
      ObjectFile *objfile = module_sp->GetObjectFile();
      if (objfile) {
        switch (objfile->GetType()) {
        case ObjectFile::eTypeCoreFile: /// A core file that has a checkpoint of
                                        /// a program's execution state
        case ObjectFile::eTypeExecutable:    /// A normal executable
        case ObjectFile::eTypeDynamicLinker: /// The platform's dynamic linker
                                             /// executable
        case ObjectFile::eTypeObjectFile:    /// An intermediate object file
        case ObjectFile::eTypeSharedLibrary: /// A shared library that can be
                                             /// used during execution
          break;
        case ObjectFile::eTypeDebugInfo: /// An object file that contains only
                                         /// debug information
          if (error_ptr)
            *error_ptr = Status::FromErrorString(
                "debug info files aren't valid target "
                "modules, please specify an executable");
          return ModuleSP();
        case ObjectFile::eTypeStubLibrary: /// A library that can be linked
                                           /// against but not used for
                                           /// execution
          if (error_ptr)
            *error_ptr = Status::FromErrorString(
                "stub libraries aren't valid target "
                "modules, please specify an executable");
          return ModuleSP();
        default:
          if (error_ptr)
            *error_ptr = Status::FromErrorString(
                "unsupported file type, please specify an executable");
          return ModuleSP();
        }
        // GetSharedModule is not guaranteed to find the old shared module, for
        // instance in the common case where you pass in the UUID, it is only
        // going to find the one module matching the UUID.  In fact, it has no
        // good way to know what the "old module" relevant to this target is,
        // since there might be many copies of a module with this file spec in
        // various running debug sessions, but only one of them will belong to
        // this target. So let's remove the UUID from the module list, and look
        // in the target's module list. Only do this if there is SOMETHING else
        // in the module spec...
        if (module_spec.GetUUID().IsValid() &&
            !module_spec.GetFileSpec().GetFilename().empty() &&
            !module_spec.GetFileSpec().GetDirectory().empty()) {
          ModuleSpec module_spec_copy(module_spec.GetFileSpec());
          module_spec_copy.GetUUID().Clear();

          ModuleList found_modules;
          m_images.FindModules(module_spec_copy, found_modules);
          found_modules.ForEach([&](const ModuleSP &found_module) {
            old_modules.push_back(found_module);
            return IterationAction::Continue;
          });
        }

        // If the locate module callback had found a symbol file, set it to the
        // module_sp before preloading symbols.
        if (symbol_file_spec)
          module_sp->SetSymbolFileFileSpec(symbol_file_spec);

        llvm::SmallVector<ModuleSP, 1> replaced_modules;
        for (ModuleSP &old_module_sp : old_modules) {
          if (m_images.GetIndexForModule(old_module_sp.get()) !=
              LLDB_INVALID_INDEX32) {
            if (replaced_modules.empty())
              m_images.ReplaceModule(old_module_sp, module_sp);
            else
              m_images.Remove(old_module_sp);

            replaced_modules.push_back(std::move(old_module_sp));
          }
        }

        if (replaced_modules.size() > 1) {
          // The same new module replaced multiple old modules
          // simultaneously.  It's not clear this should ever
          // happen (if we always replace old modules as we add
          // new ones, presumably we should never have more than
          // one old one).  If there are legitimate cases where
          // this happens, then the ModuleList::Notifier interface
          // may need to be adjusted to allow reporting this.
          // In the meantime, just log that this has happened; just
          // above we called ReplaceModule on the first one, and Remove
          // on the rest.
          if (Log *log = GetLog(LLDBLog::Target | LLDBLog::Modules)) {
            StreamString message;
            auto dump = [&message](Module &dump_module) -> void {
              UUID dump_uuid = dump_module.GetUUID();

              message << '[';
              dump_module.GetDescription(message.AsRawOstream());
              message << " (uuid ";

              if (dump_uuid.IsValid())
                dump_uuid.Dump(message);
              else
                message << "not specified";

              message << ")]";
            };

            message << "New module ";
            dump(*module_sp);
            message.AsRawOstream()
                << llvm::formatv(" simultaneously replaced {0} old modules: ",
                                 replaced_modules.size());
            for (ModuleSP &replaced_module_sp : replaced_modules)
              dump(*replaced_module_sp);

            log->PutString(message.GetString());
          }
        }

        if (replaced_modules.empty()) {
          if (!m_images.AppendIfNeeded(module_sp, notify) && notify)
            NotifyModuleAdded(m_images, module_sp);
        }

        for (ModuleSP &old_module_sp : replaced_modules) {
          auto old_module_wp = old_module_sp->weak_from_this();
          old_module_sp.reset();
          ModuleList::RemoveSharedModuleIfOrphaned(old_module_wp);
        }
      } else
        module_sp.reset();
    }
  }
  if (error_ptr)
    *error_ptr = std::move(error);
  return module_sp;
}

TargetSP Target::CalculateTarget() { return shared_from_this(); }

ProcessSP Target::CalculateProcess() { return m_process_sp; }

ThreadSP Target::CalculateThread() { return ThreadSP(); }

StackFrameSP Target::CalculateStackFrame() { return StackFrameSP(); }

void Target::CalculateExecutionContext(ExecutionContext &exe_ctx) {
  exe_ctx.Clear();
  exe_ctx.SetTargetPtr(this);
}

PathMappingList &Target::GetImageSearchPathList() {
  return m_image_search_paths;
}

void Target::ImageSearchPathsChanged(const PathMappingList &path_list,
                                     void *baton) {
  Target *target = (Target *)baton;
  ModuleSP exe_module_sp(target->GetExecutableModule());
  if (exe_module_sp)
    target->RebuildModuleListWithExecutable(exe_module_sp, eLoadDependentsYes);
}

llvm::Expected<lldb::TypeSystemSP>
Target::GetScratchTypeSystemForLanguage(lldb::LanguageType language,
                                        bool create_on_demand) {
  if (!m_valid)
    return llvm::createStringError("invalid target");

  if (language == eLanguageTypeMipsAssembler // GNU AS and LLVM use it for all
                                             // assembly code
      || language == eLanguageTypeAssembly ||
      language == eLanguageTypeUnknown) {
    LanguageSet languages_for_expressions =
        Language::GetLanguagesSupportingTypeSystemsForExpressions();

    if (languages_for_expressions[eLanguageTypeC]) {
      language = eLanguageTypeC; // LLDB's default.  Override by setting the
                                 // target language.
    } else {
      if (languages_for_expressions.Empty())
        return llvm::createStringError(
            "No expression support for any languages");
      language = (LanguageType)languages_for_expressions.bitvector.find_first();
    }
  }

  return m_scratch_type_system_map.GetTypeSystemForLanguage(language, this,
                                                            create_on_demand);
}

CompilerType Target::GetRegisterType(const RegisterInfo &reg_info) {
  if (!m_register_type_builder_sp)
    m_register_type_builder_sp = PluginManager::GetRegisterTypeBuilder(*this);
  assert(m_register_type_builder_sp);
  return m_register_type_builder_sp->GetRegisterType(reg_info);
}

std::vector<lldb::TypeSystemSP>
Target::GetScratchTypeSystems(bool create_on_demand) {
  if (!m_valid)
    return {};

  // Some TypeSystem instances are associated with several LanguageTypes so
  // they will show up several times in the loop below. The SetVector filters
  // out all duplicates as they serve no use for the caller.
  //
  // The insertion order matters: callers such as SBTarget::GetBasicType query
  // the TypeSystems in order and use the first one that can answer, so the
  // result has to be a function of the languages and not of where the
  // instances happen to live in memory.
  llvm::SetVector<lldb::TypeSystemSP, std::vector<lldb::TypeSystemSP>,
                  std::set<lldb::TypeSystemSP>>
      scratch_type_systems;

  LanguageSet languages_for_expressions =
      Language::GetLanguagesSupportingTypeSystemsForExpressions();

  for (auto bit : languages_for_expressions.bitvector.set_bits()) {
    auto language = (LanguageType)bit;
    auto type_system_or_err =
        GetScratchTypeSystemForLanguage(language, create_on_demand);
    if (!type_system_or_err)
      LLDB_LOG_ERROR(
          GetLog(LLDBLog::Target), type_system_or_err.takeError(),
          "Language '{1}' has expression support but no scratch type "
          "system available: {0}",
          Language::GetNameForLanguageType(language));
    else if (auto ts = *type_system_or_err)
      scratch_type_systems.insert(ts);
  }

  return scratch_type_systems.takeVector();
}

PersistentExpressionState *
Target::GetPersistentExpressionStateForLanguage(lldb::LanguageType language) {
  auto type_system_or_err = GetScratchTypeSystemForLanguage(language, true);

  if (auto err = type_system_or_err.takeError()) {
    LLDB_LOG_ERROR(
        GetLog(LLDBLog::Target), std::move(err),
        "Unable to get persistent expression state for language {1}: {0}",
        Language::GetNameForLanguageType(language));
    return nullptr;
  }

  if (auto ts = *type_system_or_err)
    return ts->GetPersistentExpressionState();

  LLDB_LOG(GetLog(LLDBLog::Target),
           "Unable to get persistent expression state for language {}:",
           Language::GetNameForLanguageType(language));
  return nullptr;
}

UserExpression *Target::GetUserExpressionForLanguage(
    llvm::StringRef expr, llvm::StringRef prefix, SourceLanguage language,
    Expression::ResultType desired_type,
    const EvaluateExpressionOptions &options, ValueObject *ctx_obj,
    Status &error) {
  auto type_system_or_err =
      GetScratchTypeSystemForLanguage(language.AsLanguageType());
  if (auto err = type_system_or_err.takeError()) {
    error = Status::FromErrorStringWithFormat(
        "Could not find type system for language %s: %s",
        Language::GetNameForLanguageType(language.AsLanguageType()),
        llvm::toString(std::move(err)).c_str());
    return nullptr;
  }

  auto ts = *type_system_or_err;
  if (!ts) {
    error = Status::FromErrorStringWithFormat(
        "Type system for language %s is no longer live",
        language.GetDescription().data());
    return nullptr;
  }

  auto *user_expr = ts->GetUserExpression(expr, prefix, language, desired_type,
                                          options, ctx_obj);
  if (!user_expr)
    error = Status::FromErrorStringWithFormat(
        "Could not create an expression for language %s",
        language.GetDescription().data());

  return user_expr;
}

FunctionCaller *Target::GetFunctionCallerForLanguage(
    lldb::LanguageType language, const CompilerType &return_type,
    const Address &function_address, const ValueList &arg_value_list,
    const char *name, Status &error) {
  auto type_system_or_err = GetScratchTypeSystemForLanguage(language);
  if (auto err = type_system_or_err.takeError()) {
    error = Status::FromErrorStringWithFormat(
        "Could not find type system for language %s: %s",
        Language::GetNameForLanguageType(language),
        llvm::toString(std::move(err)).c_str());
    return nullptr;
  }
  auto ts = *type_system_or_err;
  if (!ts) {
    error = Status::FromErrorStringWithFormat(
        "Type system for language %s is no longer live",
        Language::GetNameForLanguageType(language));
    return nullptr;
  }
  auto *persistent_fn = ts->GetFunctionCaller(return_type, function_address,
                                              arg_value_list, name);
  if (!persistent_fn)
    error = Status::FromErrorStringWithFormat(
        "Could not create an expression for language %s",
        Language::GetNameForLanguageType(language));

  return persistent_fn;
}

llvm::Expected<std::unique_ptr<UtilityFunction>>
Target::CreateUtilityFunction(std::string expression, std::string name,
                              lldb::LanguageType language,
                              ExecutionContext &exe_ctx) {
  auto type_system_or_err = GetScratchTypeSystemForLanguage(language);
  if (!type_system_or_err)
    return type_system_or_err.takeError();
  auto ts = *type_system_or_err;
  if (!ts)
    return llvm::createStringError(
        llvm::StringRef("Type system for language ") +
        Language::GetNameForLanguageType(language) +
        llvm::StringRef(" is no longer live"));
  std::unique_ptr<UtilityFunction> utility_fn =
      ts->CreateUtilityFunction(std::move(expression), std::move(name));
  if (!utility_fn)
    return llvm::createStringError(
        llvm::StringRef("Could not create an expression for language") +
        Language::GetNameForLanguageType(language));

  DiagnosticManager diagnostics;
  if (!utility_fn->Install(diagnostics, exe_ctx))
    return diagnostics.GetAsError(lldb::eExpressionSetupError,
                                  "Could not install utility function:");

  return std::move(utility_fn);
}

void Target::SettingsInitialize() { Process::SettingsInitialize(); }

void Target::SettingsTerminate() { Process::SettingsTerminate(); }

FileSpecList Target::GetDefaultExecutableSearchPaths() {
  return Target::GetGlobalProperties().GetExecutableSearchPaths();
}

FileSpecList Target::GetDefaultDebugFileSearchPaths() {
  return Target::GetGlobalProperties().GetDebugFileSearchPaths();
}

ArchSpec Target::GetDefaultArchitecture() {
  return Target::GetGlobalProperties().GetDefaultArchitecture();
}

void Target::SetDefaultArchitecture(const ArchSpec &arch) {
  LLDB_LOG(GetLog(LLDBLog::Target),
           "setting target's default architecture to  {0} ({1})",
           arch.GetArchitectureName(), arch.GetTriple().getTriple());
  Target::GetGlobalProperties().SetDefaultArchitecture(arch);
}

llvm::Error Target::SetLabel(llvm::StringRef label) {
  size_t n = LLDB_INVALID_INDEX32;
  if (llvm::to_integer(label, n))
    return llvm::createStringError("cannot use integer as target label");
  TargetList &targets = GetDebugger().GetTargetList();
  for (size_t i = 0; i < targets.GetNumTargets(); i++) {
    TargetSP target_sp = targets.GetTargetAtIndex(i);
    if (target_sp && target_sp->GetLabel() == label) {
      return llvm::createStringErrorV(
          "Cannot use label '{0}' since it's set in target #{1}.", label, i);
    }
  }

  m_label = label.str();
  return llvm::Error::success();
}

Target *Target::GetTargetFromContexts(const ExecutionContext *exe_ctx_ptr,
                                      const SymbolContext *sc_ptr) {
  // The target can either exist in the "process" of ExecutionContext, or in
  // the "target_sp" member of SymbolContext. This accessor helper function
  // will get the target from one of these locations.

  Target *target = nullptr;
  if (sc_ptr != nullptr)
    target = sc_ptr->target_sp.get();
  if (target == nullptr && exe_ctx_ptr)
    target = exe_ctx_ptr->GetTargetPtr();
  return target;
}

ExpressionResults Target::EvaluateExpression(
    llvm::StringRef expr, ExecutionContextScope *exe_scope,
    lldb::ValueObjectSP &result_valobj_sp,
    const EvaluateExpressionOptions &options, std::string *fixed_expression,
    ValueObject *ctx_obj) {
  result_valobj_sp.reset();

  ExpressionResults execution_results = eExpressionSetupError;

  if (expr.empty()) {
    m_stats.GetExpressionStats().NotifyFailure();
    return execution_results;
  }

  // We shouldn't run stop hooks in expressions.
  bool old_suppress_value = m_suppress_stop_hooks;
  m_suppress_stop_hooks = true;
  llvm::scope_exit on_exit([this, old_suppress_value]() {
    m_suppress_stop_hooks = old_suppress_value;
  });

  ExecutionContext exe_ctx;

  if (exe_scope) {
    exe_scope->CalculateExecutionContext(exe_ctx);
  } else if (m_process_sp) {
    m_process_sp->CalculateExecutionContext(exe_ctx);
  } else {
    CalculateExecutionContext(exe_ctx);
  }

  // Make sure we aren't just trying to see the value of a persistent variable
  // (something like "$0")
  // Only check for persistent variables the expression starts with a '$'
  lldb::ExpressionVariableSP persistent_var_sp;
  if (expr[0] == '$') {
    auto type_system_or_err =
            GetScratchTypeSystemForLanguage(eLanguageTypeC);
    if (auto err = type_system_or_err.takeError()) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Target), std::move(err),
                     "Unable to get scratch type system: {0}");
    } else {
      auto ts = *type_system_or_err;
      if (!ts)
        LLDB_LOG_ERROR(GetLog(LLDBLog::Target), std::move(err),
                       "Scratch type system is no longer live: {0}");
      else
        persistent_var_sp =
            ts->GetPersistentExpressionState()->GetVariable(expr);
    }
  }
  if (persistent_var_sp) {
    result_valobj_sp = persistent_var_sp->GetValueObject();
    execution_results = eExpressionCompleted;
  } else {
    llvm::StringRef prefix = GetExpressionPrefixContents();
    execution_results =
        UserExpression::Evaluate(exe_ctx, options, expr, prefix,
                                 result_valobj_sp, fixed_expression, ctx_obj);
  }

  if (execution_results == eExpressionCompleted)
    m_stats.GetExpressionStats().NotifySuccess();
  else
    m_stats.GetExpressionStats().NotifyFailure();
  return execution_results;
}

lldb::ExpressionVariableSP Target::GetPersistentVariable(ConstString name) {
  lldb::ExpressionVariableSP variable_sp;
  m_scratch_type_system_map.ForEach(
      [name, &variable_sp](TypeSystemSP type_system) -> bool {
        auto ts = type_system.get();
        if (!ts)
          return true;
        if (PersistentExpressionState *persistent_state =
                ts->GetPersistentExpressionState()) {
          variable_sp = persistent_state->GetVariable(name);

          if (variable_sp)
            return false; // Stop iterating the ForEach
        }
        return true; // Keep iterating the ForEach
      });
  return variable_sp;
}

lldb::addr_t Target::GetPersistentSymbol(ConstString name) {
  lldb::addr_t address = LLDB_INVALID_ADDRESS;

  m_scratch_type_system_map.ForEach(
      [name, &address](lldb::TypeSystemSP type_system) -> bool {
        auto ts = type_system.get();
        if (!ts)
          return true;

        if (PersistentExpressionState *persistent_state =
                ts->GetPersistentExpressionState()) {
          address = persistent_state->LookupSymbol(name);
          if (address != LLDB_INVALID_ADDRESS)
            return false; // Stop iterating the ForEach
        }
        return true; // Keep iterating the ForEach
      });
  return address;
}

llvm::Expected<lldb_private::Address> Target::GetEntryPointAddress() {
  Module *exe_module = GetExecutableModulePointer();

  // Try to find the entry point address in the primary executable.
  const bool has_primary_executable = exe_module && exe_module->GetObjectFile();
  if (has_primary_executable) {
    Address entry_addr = exe_module->GetObjectFile()->GetEntryPointAddress();
    if (entry_addr.IsValid())
      return entry_addr;
  }

  const ModuleList &modules = GetImages();
  const size_t num_images = modules.GetSize();
  for (size_t idx = 0; idx < num_images; ++idx) {
    ModuleSP module_sp(modules.GetModuleAtIndex(idx));
    if (!module_sp || !module_sp->GetObjectFile())
      continue;

    Address entry_addr = module_sp->GetObjectFile()->GetEntryPointAddress();
    if (entry_addr.IsValid())
      return entry_addr;
  }

  // We haven't found the entry point address. Return an appropriate error.
  if (!has_primary_executable)
    return llvm::createStringError(
        "No primary executable found and could not find entry point address in "
        "any executable module");

  return llvm::createStringError(
      "Could not find entry point address for primary executable module \"" +
      exe_module->GetFileSpec().GetFilename() + "\"");
}

lldb::addr_t Target::GetCallableLoadAddress(lldb::addr_t load_addr,
                                            AddressClass addr_class) const {
  auto arch_plugin = GetArchitecturePlugin();
  return arch_plugin
             ? arch_plugin->GetCallableLoadAddress(load_addr, addr_class)
             : load_addr;
}

lldb::addr_t Target::GetOpcodeLoadAddress(lldb::addr_t load_addr,
                                          AddressClass addr_class) const {
  auto arch_plugin = GetArchitecturePlugin();
  return arch_plugin ? arch_plugin->GetOpcodeLoadAddress(load_addr, addr_class)
                     : load_addr;
}

lldb::addr_t Target::GetBreakableLoadAddress(lldb::addr_t addr) {
  auto arch_plugin = GetArchitecturePlugin();
  return arch_plugin ? arch_plugin->GetBreakableLoadAddress(addr, *this) : addr;
}

llvm::Expected<lldb::DisassemblerSP>
Target::ReadInstructions(const Address &start_addr, uint32_t count,
                         const char *flavor_string) {
  DataBufferHeap data(GetArchitecture().GetMaximumOpcodeByteSize() * count, 0);
  bool force_live_memory = true;
  lldb_private::Status error;
  lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
  const size_t bytes_read =
      ReadMemory(start_addr, data.GetBytes(), data.GetByteSize(), error,
                 force_live_memory, &load_addr);

  if (error.Fail()) {
    return llvm::joinErrors(
        llvm::createStringErrorV(
            "Target::ReadInstructions failed to read memory at {:x}: ",
            start_addr.GetLoadAddress(this)),
        error.takeError());
  }

  const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
  if (!flavor_string || flavor_string[0] == '\0') {
    // FIXME - we don't have the mechanism in place to do per-architecture
    // settings.  But since we know that for now we only support flavors on
    // x86 & x86_64,
    const llvm::Triple::ArchType arch = GetArchitecture().GetTriple().getArch();
    if (arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64)
      flavor_string = GetDisassemblyFlavor();
  }

  return Disassembler::DisassembleBytes(
      GetArchitecture(), nullptr, flavor_string, GetDisassemblyCPU(),
      GetDisassemblyFeatures(), start_addr, data.GetBytes(), bytes_read, count,
      data_from_file);
}

SourceManager &Target::GetSourceManager() {
  if (!m_source_manager_up)
    m_source_manager_up = std::make_unique<SourceManager>(shared_from_this());
  return *m_source_manager_up;
}

Target::StopHookSP Target::CreateStopHook(StopHook::StopHookKind kind,
                                          bool internal) {
  user_id_t new_uid = (internal ? LLDB_INVALID_UID : ++m_stop_hook_next_id);
  Target::StopHookSP stop_hook_sp;
  switch (kind) {
  case StopHook::StopHookKind::CommandBased:
    stop_hook_sp.reset(new StopHookCommandLine(shared_from_this(), new_uid));
    break;
  case StopHook::StopHookKind::ScriptBased:
    stop_hook_sp.reset(new StopHookScripted(shared_from_this(), new_uid));
    break;
  case StopHook::StopHookKind::CodeBased:
    stop_hook_sp.reset(new StopHookCoded(shared_from_this(), new_uid));
    break;
  }
  if (internal)
    m_internal_stop_hooks.push_back(stop_hook_sp);
  else
    m_stop_hooks[new_uid] = stop_hook_sp;
  return stop_hook_sp;
}

void Target::UndoCreateStopHook(lldb::user_id_t user_id) {
  if (!RemoveStopHookByID(user_id))
    return;
  if (user_id == m_stop_hook_next_id)
    m_stop_hook_next_id--;
}

bool Target::RemoveStopHookByID(lldb::user_id_t user_id) {
  size_t num_removed = m_stop_hooks.erase(user_id);
  return (num_removed != 0);
}

void Target::RemoveAllStopHooks() { m_stop_hooks.clear(); }

Target::StopHookSP Target::GetStopHookByID(lldb::user_id_t user_id) {
  StopHookSP found_hook;

  StopHookCollection::iterator specified_hook_iter;
  specified_hook_iter = m_stop_hooks.find(user_id);
  if (specified_hook_iter != m_stop_hooks.end())
    found_hook = (*specified_hook_iter).second;
  return found_hook;
}

bool Target::SetStopHookActiveStateByID(lldb::user_id_t user_id,
                                        bool active_state) {
  StopHookCollection::iterator specified_hook_iter;
  specified_hook_iter = m_stop_hooks.find(user_id);
  if (specified_hook_iter == m_stop_hooks.end())
    return false;

  (*specified_hook_iter).second->SetIsActive(active_state);
  return true;
}

void Target::SetAllStopHooksActiveState(bool active_state) {
  StopHookCollection::iterator pos, end = m_stop_hooks.end();
  for (pos = m_stop_hooks.begin(); pos != end; pos++) {
    (*pos).second->SetIsActive(active_state);
  }
}

// FIXME:  Ideally we would like to return a `const &` (const reference) instead
//   of creating copy here, but that is not possible due to different container
//   types.  In C++20, we should be able to use `std::ranges::views::values` to
//   adapt the key-pair entries in the `std::map` (behind `StopHookCollection`)
//   to avoid creating the copy.
const std::vector<Target::StopHookSP>
Target::GetStopHooks(bool internal) const {
  if (internal)
    return m_internal_stop_hooks;

  std::vector<StopHookSP> stop_hooks;
  for (auto &[_, hook] : m_stop_hooks)
    stop_hooks.push_back(hook);

  return stop_hooks;
}

bool Target::RunStopHooks(bool at_initial_stop) {
  if (m_suppress_stop_hooks)
    return false;

  if (!m_process_sp)
    return false;

  // Somebody might have restarted the process:
  // Still return false, the return value is about US restarting the target.
  lldb::StateType state = m_process_sp->GetState();
  if (!(state == eStateStopped || state == eStateAttaching))
    return false;

  auto is_active = [at_initial_stop](StopHookSP hook) {
    bool should_run_now = (!at_initial_stop || hook->GetRunAtInitialStop());
    return hook->IsActive() && should_run_now;
  };

  // Create list of active internal and user stop hooks.
  std::vector<StopHookSP> active_hooks;
  llvm::copy_if(m_internal_stop_hooks, std::back_inserter(active_hooks),
                is_active);
  for (auto &[_, hook] : m_stop_hooks) {
    if (is_active(hook))
      active_hooks.push_back(hook);
  }

  // Also collect unified hooks that fire on process stop.
  std::vector<HookSP> active_unified_hooks;
  for (auto &[_, hook] : m_hooks) {
    if (hook->IsEnabled() && hook->FiresOn(Hook::kProcessStop) &&
        (!at_initial_stop || hook->GetRunAtInitialStop()))
      active_unified_hooks.push_back(hook);
  }

  if (active_hooks.empty() && active_unified_hooks.empty())
    return false;

  // Make sure we check that we are not stopped because of us running a user
  // expression since in that case we do not want to run the stop-hooks. Note,
  // you can't just check whether the last stop was for a User Expression,
  // because breakpoint commands get run before stop hooks, and one of them
  // might have run an expression. You have to ensure you run the stop hooks
  // once per natural stop.
  uint32_t last_natural_stop = m_process_sp->GetModIDRef().GetLastNaturalStopID();
  if (last_natural_stop != 0 && m_latest_stop_hook_id == last_natural_stop)
    return false;

  std::vector<ExecutionContext> exc_ctx_with_reasons;

  ThreadList &cur_threadlist = m_process_sp->GetThreadList();
  size_t num_threads = cur_threadlist.GetSize();
  for (size_t i = 0; i < num_threads; i++) {
    lldb::ThreadSP cur_thread_sp = cur_threadlist.GetThreadAtIndex(i);
    if (cur_thread_sp->ThreadStoppedForAReason()) {
      lldb::StackFrameSP cur_frame_sp = cur_thread_sp->GetStackFrameAtIndex(0);
      exc_ctx_with_reasons.emplace_back(m_process_sp.get(), cur_thread_sp.get(),
                                        cur_frame_sp.get());
    }
  }

  // If no threads stopped for a reason, don't run the stop-hooks.
  // However, if this is the FIRST stop for this process, then we are in the
  // state where an attach or a core file load was completed without designating
  // a particular thread as responsible for the stop.  In that case, we do
  // want to run the stop hooks, but do so just on one thread.
  size_t num_exe_ctx = exc_ctx_with_reasons.size();
  if (num_exe_ctx == 0) {
    if (at_initial_stop && num_threads > 0) {
      lldb::ThreadSP thread_to_use_sp = cur_threadlist.GetThreadAtIndex(0);
      exc_ctx_with_reasons.emplace_back(
          m_process_sp.get(), thread_to_use_sp.get(),
          thread_to_use_sp->GetStackFrameAtIndex(0).get());
      num_exe_ctx = 1;
    } else {
      return false;
    }
  }

  m_latest_stop_hook_id = last_natural_stop;

  StreamSP output_sp = m_debugger.GetAsyncOutputStream();
  llvm::scope_exit on_exit([output_sp] { output_sp->Flush(); });

  size_t num_hooks_with_output = llvm::count_if(
      active_hooks, [](auto h) { return !h->GetSuppressOutput(); });
  num_hooks_with_output += llvm::count_if(
      active_unified_hooks, [](auto h) { return !h->GetSuppressOutput(); });
  bool print_hook_header = (num_hooks_with_output > 1);
  bool print_thread_header = (num_exe_ctx > 1);
  bool should_stop = false;
  bool requested_continue = false;

  // A stop hook might get deleted while running stop hooks.
  // We have to decide what that means.  We will follow the rule that deleting
  // a stop hook while processing these stop hooks will delete it for FUTURE
  // stops but not this stop.  Fortunately, copying the m_stop_hooks to the
  // active_hooks list before iterating over the hooks has this effect.
  for (auto cur_hook_sp : active_hooks) {
    bool any_thread_matched = false;
    for (auto exc_ctx : exc_ctx_with_reasons) {
      if (!cur_hook_sp->ExecutionContextPasses(exc_ctx))
        continue;

      bool suppress_output = cur_hook_sp->GetSuppressOutput();
      if (print_hook_header && !any_thread_matched && !suppress_output) {
        StreamString s;
        cur_hook_sp->GetDescription(s, eDescriptionLevelBrief);
        if (s.GetSize() != 0)
          output_sp->Printf("\n- Hook %" PRIu64 " (%s)\n", cur_hook_sp->GetID(),
                            s.GetData());
        else
          output_sp->Printf("\n- Hook %" PRIu64 "\n", cur_hook_sp->GetID());
        any_thread_matched = true;
      }

      if (print_thread_header && !suppress_output)
        output_sp->Printf("-- Thread %d\n",
                          exc_ctx.GetThreadPtr()->GetIndexID());

      auto result = cur_hook_sp->HandleStop(exc_ctx, output_sp);
      switch (result) {
      case StopHook::StopHookResult::KeepStopped:
        if (cur_hook_sp->GetAutoContinue())
          requested_continue = true;
        else
          should_stop = true;
        break;
      case StopHook::StopHookResult::RequestContinue:
        requested_continue = true;
        break;
      case StopHook::StopHookResult::NoPreference:
        // Do nothing
        break;
      case StopHook::StopHookResult::AlreadyContinued:
        // We don't have a good way to prohibit people from restarting the
        // target willy nilly in a stop hook.  If the hook did so, give a
        // gentle suggestion here and back out of the hook processing.
        output_sp->Printf("\nAborting stop hooks, hook %" PRIu64
                          " set the program running.\n"
                          "  Consider using '-G true' to make "
                          "stop hooks auto-continue.\n",
                          cur_hook_sp->GetID());
        // FIXME: if we are doing non-stop mode for real, we would have to
        // check that OUR thread was restarted, otherwise we should keep
        // processing stop hooks.
        return true;
      }
    }
  }

  // Run unified hooks that fire on process stop.
  for (auto cur_hook_sp : active_unified_hooks) {
    bool any_thread_matched = false;
    for (auto exc_ctx : exc_ctx_with_reasons) {
      if (!cur_hook_sp->ExecutionContextPasses(exc_ctx))
        continue;

      bool suppress_output = cur_hook_sp->GetSuppressOutput();
      if (print_hook_header && !any_thread_matched && !suppress_output) {
        StreamString s;
        cur_hook_sp->GetDescription(s, eDescriptionLevelBrief);
        if (s.GetSize() != 0)
          output_sp->Printf("\n- Hook %" PRIu64 " (%s)\n", cur_hook_sp->GetID(),
                            s.GetData());
        else
          output_sp->Printf("\n- Hook %" PRIu64 "\n", cur_hook_sp->GetID());
        any_thread_matched = true;
      }

      if (print_thread_header && !suppress_output)
        output_sp->Printf("-- Thread %d\n",
                          exc_ctx.GetThreadPtr()->GetIndexID());

      auto result = cur_hook_sp->HandleStop(exc_ctx, output_sp);
      switch (result) {
      case StopHook::StopHookResult::KeepStopped:
        if (cur_hook_sp->GetAutoContinue())
          requested_continue = true;
        else
          should_stop = true;
        break;
      case StopHook::StopHookResult::RequestContinue:
        requested_continue = true;
        break;
      case StopHook::StopHookResult::NoPreference:
        break;
      case StopHook::StopHookResult::AlreadyContinued:
        output_sp->Printf("\nAborting stop hooks, hook %" PRIu64
                          " set the program running.\n"
                          "  Consider using '-G true' to make "
                          "stop hooks auto-continue.\n",
                          cur_hook_sp->GetID());
        return true;
      }
    }
  }

  // Resume iff at least one hook requested to continue and no hook asked to
  // stop.
  if (requested_continue && !should_stop) {
    Log *log = GetLog(LLDBLog::Process);
    Status error = m_process_sp->PrivateResume();
    if (error.Success()) {
      LLDB_LOG(log, "Resuming from RunStopHooks");
      return true;
    } else {
      LLDB_LOG(log, "Resuming from RunStopHooks failed: {0}", error);
      return false;
    }
  }

  return false;
}

TargetProperties &Target::GetGlobalProperties() {
  // NOTE: intentional leak so we don't crash if global destructor chain gets
  // called as other threads still use the result of this function
  static TargetProperties *g_settings_ptr =
      new TargetProperties(nullptr);
  return *g_settings_ptr;
}

Status Target::Install(ProcessLaunchInfo *launch_info) {
  Status error;
  PlatformSP platform_sp(GetPlatform());
  if (!platform_sp || !platform_sp->IsRemote() || !platform_sp->IsConnected())
    return error;

  // Install all files that have an install path when connected to a
  // remote platform. If target.auto-install-main-executable is set then
  // also install the main executable even if it does not have an explicit
  // install path specified.

  for (auto module_sp : GetImages().Modules()) {
    if (module_sp == GetExecutableModule()) {
      MainExecutableInstaller installer{platform_sp, module_sp,
                                        shared_from_this(), *launch_info};
      error = installExecutable(installer);
    } else {
      ExecutableInstaller installer{platform_sp, module_sp};
      error = installExecutable(installer);
    }

    if (error.Fail())
      return error;
  }

  return error;
}

bool Target::ResolveLoadAddress(addr_t load_addr, Address &so_addr,
                                uint32_t stop_id, bool allow_section_end) {
  return m_section_load_history.ResolveLoadAddress(stop_id, load_addr, so_addr,
                                                   allow_section_end);
}

bool Target::ResolveFileAddress(lldb::addr_t file_addr,
                                Address &resolved_addr) {
  return m_images.ResolveFileAddress(file_addr, resolved_addr);
}

bool Target::SetSectionLoadAddress(const SectionSP &section_sp,
                                   addr_t new_section_load_addr,
                                   bool warn_multiple) {
  const addr_t old_section_load_addr =
      m_section_load_history.GetSectionLoadAddress(
          SectionLoadHistory::eStopIDNow, section_sp);
  if (old_section_load_addr != new_section_load_addr) {
    uint32_t stop_id = 0;
    ProcessSP process_sp(GetProcessSP());
    if (process_sp)
      stop_id = process_sp->GetStopID();
    else
      stop_id = m_section_load_history.GetLastStopID();
    if (m_section_load_history.SetSectionLoadAddress(
            stop_id, section_sp, new_section_load_addr, warn_multiple))
      return true; // Return true if the section load address was changed...
  }
  return false; // Return false to indicate nothing changed
}

size_t Target::UnloadModuleSections(const ModuleList &module_list) {
  size_t section_unload_count = 0;
  size_t num_modules = module_list.GetSize();
  for (size_t i = 0; i < num_modules; ++i) {
    section_unload_count +=
        UnloadModuleSections(module_list.GetModuleAtIndex(i));
  }
  return section_unload_count;
}

size_t Target::UnloadModuleSections(const lldb::ModuleSP &module_sp) {
  uint32_t stop_id = 0;
  ProcessSP process_sp(GetProcessSP());
  if (process_sp)
    stop_id = process_sp->GetStopID();
  else
    stop_id = m_section_load_history.GetLastStopID();
  SectionList *sections = module_sp->GetSectionList();
  size_t section_unload_count = 0;
  if (sections) {
    const uint32_t num_sections = sections->GetNumSections(0);
    for (uint32_t i = 0; i < num_sections; ++i) {
      section_unload_count += m_section_load_history.SetSectionUnloaded(
          stop_id, sections->GetSectionAtIndex(i));
    }
  }
  return section_unload_count;
}

bool Target::SetSectionUnloaded(const lldb::SectionSP &section_sp) {
  uint32_t stop_id = 0;
  ProcessSP process_sp(GetProcessSP());
  if (process_sp)
    stop_id = process_sp->GetStopID();
  else
    stop_id = m_section_load_history.GetLastStopID();
  return m_section_load_history.SetSectionUnloaded(stop_id, section_sp);
}

bool Target::SetSectionUnloaded(const lldb::SectionSP &section_sp,
                                addr_t load_addr) {
  uint32_t stop_id = 0;
  ProcessSP process_sp(GetProcessSP());
  if (process_sp)
    stop_id = process_sp->GetStopID();
  else
    stop_id = m_section_load_history.GetLastStopID();
  return m_section_load_history.SetSectionUnloaded(stop_id, section_sp,
                                                   load_addr);
}

void Target::ClearAllLoadedSections() { m_section_load_history.Clear(); }

lldb_private::SummaryStatisticsSP Target::GetSummaryStatisticsSPForProviderName(
    lldb_private::TypeSummaryImpl &summary_provider) {
  return m_summary_statistics_cache.GetSummaryStatisticsForProvider(
      summary_provider);
}

SummaryStatisticsCache &Target::GetSummaryStatisticsCache() {
  return m_summary_statistics_cache;
}

void Target::SaveScriptedLaunchInfo(lldb_private::ProcessInfo &process_info) {
  if (process_info.IsScriptedProcess()) {
    // Only copy scripted process launch options.
    ProcessLaunchInfo &default_launch_info = const_cast<ProcessLaunchInfo &>(
        GetGlobalProperties().GetProcessLaunchInfo());
    default_launch_info.SetProcessPluginName("ScriptedProcess");
    default_launch_info.SetScriptedMetadata(process_info.GetScriptedMetadata());
    SetProcessLaunchInfo(default_launch_info);
  }
}

Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
  m_stats.SetLaunchOrAttachTime();
  Status error;
  Log *log = GetLog(LLDBLog::Target);

  LLDB_LOGF(log, "Target::%s() called for %s", __FUNCTION__,
            launch_info.GetExecutableFile().GetPath().c_str());

  StateType state = eStateInvalid;

  // Scope to temporarily get the process state in case someone has manually
  // remotely connected already to a process and we can skip the platform
  // launching.
  {
    ProcessSP process_sp(GetProcessSP());

    if (process_sp) {
      state = process_sp->GetState();
      LLDB_LOGF(log,
                "Target::%s the process exists, and its current state is %s",
                __FUNCTION__, StateAsCString(state));
    } else {
      LLDB_LOGF(log, "Target::%s the process instance doesn't currently exist.",
                __FUNCTION__);
    }
  }

  launch_info.GetFlags().Set(eLaunchFlagDebug);

  SaveScriptedLaunchInfo(launch_info);

  // Get the value of synchronous execution here.  If you wait till after you
  // have started to run, then you could have hit a breakpoint, whose command
  // might switch the value, and then you'll pick up that incorrect value.
  Debugger &debugger = GetDebugger();
  const bool synchronous_execution =
      debugger.GetCommandInterpreter().GetSynchronous();

  PlatformSP platform_sp(GetPlatform());

  FinalizeFileActions(launch_info);

  if (state == eStateConnected) {
    if (launch_info.GetFlags().Test(eLaunchFlagLaunchInTTY))
      return Status::FromErrorString(
          "can't launch in tty when launching through a remote connection");
  }

  if (!launch_info.GetArchitecture().IsValid())
    launch_info.GetArchitecture() = GetArchitecture();

  // Hijacking events of the process to be created to be sure that all events
  // until the first stop are intercepted (in case if platform doesn't define
  // its own hijacking listener or if the process is created by the target
  // manually, without the platform).
  if (!launch_info.GetHijackListener())
    launch_info.SetHijackListener(
        Listener::MakeListener(Process::LaunchSynchronousHijackListenerName));

  // If we're not already connected to the process, and if we have a platform
  // that can launch a process for debugging, go ahead and do that here.
  if (state != eStateConnected && platform_sp &&
      platform_sp->CanDebugProcess() && !launch_info.IsScriptedProcess()) {
    LLDB_LOGF(log, "Target::%s asking the platform to debug the process",
              __FUNCTION__);

    // If there was a previous process, delete it before we make the new one.
    // One subtle point, we delete the process before we release the reference
    // to m_process_sp.  That way even if we are the last owner, the process
    // will get Finalized before it gets destroyed.
    DeleteCurrentProcess();

    m_process_sp =
        GetPlatform()->DebugProcess(launch_info, debugger, *this, error);

  } else {
    LLDB_LOGF(log,
              "Target::%s the platform doesn't know how to debug a "
              "process, getting a process plugin to do this for us.",
              __FUNCTION__);

    if (state == eStateConnected) {
      assert(m_process_sp);
    } else {
      // Use a Process plugin to construct the process.
      CreateProcess(launch_info.GetListener(),
                    launch_info.GetProcessPluginName(), nullptr, false);
    }

    // Since we didn't have a platform launch the process, launch it here.
    if (m_process_sp) {
      m_process_sp->HijackProcessEvents(launch_info.GetHijackListener());
      m_process_sp->SetShadowListener(launch_info.GetShadowListener());
      error = m_process_sp->Launch(launch_info);
    }
  }

  if (!error.Success())
    return error;

  if (!m_process_sp)
    return Status::FromErrorString("failed to launch or debug process");

  bool rebroadcast_first_stop =
      !synchronous_execution &&
      launch_info.GetFlags().Test(eLaunchFlagStopAtEntry);

  assert(launch_info.GetHijackListener());

  EventSP first_stop_event_sp;
  state = m_process_sp->WaitForProcessToStop(std::nullopt, &first_stop_event_sp,
                                             rebroadcast_first_stop,
                                             launch_info.GetHijackListener());
  m_process_sp->RestoreProcessEvents();

  if (rebroadcast_first_stop) {
    // We don't need to run the stop hooks by hand here, they will get
    // triggered when this rebroadcast event gets fetched.
    assert(first_stop_event_sp);
    m_process_sp->BroadcastEvent(first_stop_event_sp);
    return error;
  }
  // Run the stop hooks that want to run at entry.
  RunStopHooks(true /* at entry point */);

  switch (state) {
  case eStateStopped: {
    if (launch_info.GetFlags().Test(eLaunchFlagStopAtEntry))
      break;
    if (synchronous_execution)
      // Now we have handled the stop-from-attach, and we are just
      // switching to a synchronous resume.  So we should switch to the
      // SyncResume hijacker.
      m_process_sp->ResumeSynchronous(stream);
    else
      error = m_process_sp->Resume();
    if (!error.Success()) {
      error = Status::FromErrorStringWithFormat(
          "process resume at entry point failed: %s", error.AsCString());
    }
  } break;
  case eStateExited: {
    bool with_shell = !!launch_info.GetShell();
    const int exit_status = m_process_sp->GetExitStatus();
    const char *exit_desc = m_process_sp->GetExitDescription();
    std::string desc;
    if (exit_desc && exit_desc[0])
      desc = " (" + std::string(exit_desc) + ')';
    if (with_shell)
      error = Status::FromErrorStringWithFormat(
          "process exited with status %i%s\n"
          "'r' and 'run' are aliases that default to launching through a "
          "shell.\n"
          "Try launching without going through a shell by using "
          "'process launch'.",
          exit_status, desc.c_str());
    else
      error = Status::FromErrorStringWithFormat(
          "process exited with status %i%s", exit_status, desc.c_str());
  } break;
  default:
    error = Status::FromErrorStringWithFormat(
        "initial process state wasn't stopped: %s", StateAsCString(state));
    break;
  }
  return error;
}

void Target::SetTrace(const TraceSP &trace_sp) { m_trace_sp = trace_sp; }

TraceSP Target::GetTrace() { return m_trace_sp; }

llvm::Expected<TraceSP> Target::CreateTrace() {
  if (!m_process_sp)
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "A process is required for tracing");
  if (m_trace_sp)
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "A trace already exists for the target");

  llvm::Expected<TraceSupportedResponse> trace_type =
      m_process_sp->TraceSupported();
  if (!trace_type)
    return llvm::createStringError(
        llvm::inconvertibleErrorCode(), "Tracing is not supported. %s",
        llvm::toString(trace_type.takeError()).c_str());
  if (llvm::Expected<TraceSP> trace_sp =
          Trace::FindPluginForLiveProcess(trace_type->name, *m_process_sp))
    m_trace_sp = *trace_sp;
  else
    return llvm::createStringError(
        llvm::inconvertibleErrorCode(),
        "Couldn't create a Trace object for the process. %s",
        llvm::toString(trace_sp.takeError()).c_str());
  return m_trace_sp;
}

llvm::Expected<TraceSP> Target::GetTraceOrCreate() {
  if (m_trace_sp)
    return m_trace_sp;
  return CreateTrace();
}

Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) {
  Progress attach_progress("Waiting to attach to process");
  m_stats.SetLaunchOrAttachTime();
  auto state = eStateInvalid;
  auto process_sp = GetProcessSP();
  if (process_sp) {
    state = process_sp->GetState();
    if (process_sp->IsAlive() && state != eStateConnected) {
      if (state == eStateAttaching)
        return Status::FromErrorString("process attach is in progress");
      return Status::FromErrorString("a process is already being debugged");
    }
  }

  const ModuleSP old_exec_module_sp = GetExecutableModule();

  // If no process info was specified, then use the target executable name as
  // the process to attach to by default
  if (!attach_info.ProcessInfoSpecified()) {
    if (old_exec_module_sp)
      attach_info.GetExecutableFile().SetFilename(
            old_exec_module_sp->GetPlatformFileSpec().GetFilename());

    if (!attach_info.ProcessInfoSpecified()) {
      return Status::FromErrorString(
          "no process specified, create a target with a file, or "
          "specify the --pid or --name");
    }
  }

  const auto platform_sp =
      GetDebugger().GetPlatformList().GetSelectedPlatform();
  ListenerSP hijack_listener_sp;
  const bool async = attach_info.GetAsync();
  if (!async) {
    hijack_listener_sp =
        Listener::MakeListener(Process::AttachSynchronousHijackListenerName);
    attach_info.SetHijackListener(hijack_listener_sp);
  }

  Status error;
  if (state != eStateConnected && platform_sp != nullptr &&
      platform_sp->CanDebugProcess() && !attach_info.IsScriptedProcess()) {
    SetPlatform(platform_sp);
    process_sp = platform_sp->Attach(attach_info, GetDebugger(), this, error);
  } else {
    if (state != eStateConnected) {
      SaveScriptedLaunchInfo(attach_info);
      llvm::StringRef plugin_name = attach_info.GetProcessPluginName();
      process_sp =
          CreateProcess(attach_info.GetListenerForProcess(GetDebugger()),
                        plugin_name, nullptr, false);
      if (!process_sp) {
        error = Status::FromErrorStringWithFormatv(
            "failed to create process using plugin '{0}'",
            plugin_name.empty() ? "<empty>" : plugin_name);
        return error;
      }
    }
    if (hijack_listener_sp)
      process_sp->HijackProcessEvents(hijack_listener_sp);
    error = process_sp->Attach(attach_info);
  }

  if (error.Success() && process_sp) {
    if (async) {
      process_sp->RestoreProcessEvents();
    } else {
      // We are stopping all the way out to the user, so update selected frames.
      state = process_sp->WaitForProcessToStop(
          std::nullopt, nullptr, false, attach_info.GetHijackListener(), stream,
          true, SelectMostRelevantFrame);
      process_sp->RestoreProcessEvents();

      // Run the stop hooks here.  Since we were hijacking the events, they
      // wouldn't have gotten run as part of event delivery.
      RunStopHooks(/* at_initial_stop= */ true);

      if (state != eStateStopped) {
        const char *exit_desc = process_sp->GetExitDescription();
        if (exit_desc)
          error = Status::FromErrorStringWithFormat("%s", exit_desc);
        else
          error = Status::FromErrorString(
              "process did not stop (no such process or permission problem?)");
        process_sp->Destroy(false);
      }
    }
  }
  return error;
}

llvm::Expected<uint32_t> Target::AddScriptedFrameProviderDescriptor(
    const ScriptedFrameProviderDescriptor &descriptor) {
  if (!descriptor.IsValid())
    return llvm::createStringError("invalid frame provider descriptor");

  llvm::StringRef name = descriptor.GetName();
  if (name.empty())
    return llvm::createStringError(
        "frame provider descriptor has no class name");

  {
    std::unique_lock<std::recursive_mutex> guard(
        m_frame_provider_descriptors_mutex);

    // Check for duplicate: same class name and args (content hash).
    uint32_t descriptor_hash = descriptor.GetHash();
    for (const auto &entry : m_frame_provider_descriptors) {
      if (entry.second.GetHash() == descriptor_hash)
        GetDebugger().ReportWarning(
            llvm::formatv("frame provider idx={0} with the same class name and "
                          "arguments is already registered",
                          entry.second.GetID())
                .str());
    }

    uint32_t descriptor_id = m_next_frame_provider_id++;
    ScriptedFrameProviderDescriptor new_descriptor = descriptor;
    new_descriptor.SetID(descriptor_id);
    m_frame_provider_descriptors[descriptor_id] = new_descriptor;

    InvalidateThreadFrameProviders();

    return descriptor_id;
  }
}

bool Target::RemoveScriptedFrameProviderDescriptor(uint32_t id) {
  bool removed = false;
  {
    std::lock_guard<std::recursive_mutex> guard(
        m_frame_provider_descriptors_mutex);
    removed = m_frame_provider_descriptors.erase(id);
  }

  if (removed)
    InvalidateThreadFrameProviders();
  return removed;
}

void Target::ClearScriptedFrameProviderDescriptors() {
  {
    std::lock_guard<std::recursive_mutex> guard(
        m_frame_provider_descriptors_mutex);
    m_frame_provider_descriptors.clear();
    m_next_frame_provider_id = 1;
  }

  InvalidateThreadFrameProviders();
}

const llvm::MapVector<uint32_t, ScriptedFrameProviderDescriptor> &
Target::GetScriptedFrameProviderDescriptors() const {
  std::lock_guard<std::recursive_mutex> guard(
      m_frame_provider_descriptors_mutex);
  return m_frame_provider_descriptors;
}

void Target::InvalidateThreadFrameProviders() {
  ProcessSP process_sp = GetProcessSP();
  if (!process_sp)
    return;
  for (ThreadSP thread_sp : process_sp->Threads()) {
    // Clear frame providers on existing threads so they reload with new config.
    thread_sp->ClearScriptedFrameProvider();
    // Notify threads that the stack traces might have changed.
    if (thread_sp->EventTypeHasListeners(Thread::eBroadcastBitStackChanged)) {
      auto data_sp = std::make_shared<Thread::ThreadEventData>(thread_sp);
      thread_sp->BroadcastEvent(Thread::eBroadcastBitStackChanged, data_sp);
    }
  }
}

void Target::FinalizeFileActions(ProcessLaunchInfo &info) {
  Log *log = GetLog(LLDBLog::Process);

  // Finalize the file actions, and if none were given, default to opening up a
  // pseudo terminal
  PlatformSP platform_sp = GetPlatform();
  const bool default_to_use_pty =
      m_platform_sp ? m_platform_sp->IsHost() : false;
  LLDB_LOG(
      log,
      "have platform={0}, platform_sp->IsHost()={1}, default_to_use_pty={2}",
      bool(platform_sp),
      platform_sp ? (platform_sp->IsHost() ? "true" : "false") : "n/a",
      default_to_use_pty);

  // If nothing for stdin or stdout or stderr was specified, then check the
  // process for any default settings that were set with "settings set"
  if (info.GetFileActionForFD(STDIN_FILENO) == nullptr ||
      info.GetFileActionForFD(STDOUT_FILENO) == nullptr ||
      info.GetFileActionForFD(STDERR_FILENO) == nullptr) {
    LLDB_LOG(log, "at least one of stdin/stdout/stderr was not set, evaluating "
                  "default handling");

    if (info.GetFlags().Test(eLaunchFlagLaunchInTTY)) {
      // Do nothing, if we are launching in a remote terminal no file actions
      // should be done at all.
      return;
    }

    if (info.GetFlags().Test(eLaunchFlagDisableSTDIO)) {
      LLDB_LOG(log, "eLaunchFlagDisableSTDIO set, adding suppression action "
                    "for stdin, stdout and stderr");
      info.AppendSuppressFileAction(STDIN_FILENO, true, false);
      info.AppendSuppressFileAction(STDOUT_FILENO, false, true);
      info.AppendSuppressFileAction(STDERR_FILENO, false, true);
    } else {
      // Check for any values that might have gotten set with any of: (lldb)
      // settings set target.input-path (lldb) settings set target.output-path
      // (lldb) settings set target.error-path
      FileSpec in_file_spec;
      FileSpec out_file_spec;
      FileSpec err_file_spec;
      // Only override with the target settings if we don't already have an
      // action for in, out or error
      if (info.GetFileActionForFD(STDIN_FILENO) == nullptr)
        in_file_spec = GetStandardInputPath();
      if (info.GetFileActionForFD(STDOUT_FILENO) == nullptr)
        out_file_spec = GetStandardOutputPath();
      if (info.GetFileActionForFD(STDERR_FILENO) == nullptr)
        err_file_spec = GetStandardErrorPath();

      LLDB_LOG(log, "target stdin='{0}', target stdout='{1}', stderr='{2}'",
               in_file_spec, out_file_spec, err_file_spec);

      if (in_file_spec) {
        info.AppendOpenFileAction(STDIN_FILENO, in_file_spec, true, false);
        LLDB_LOG(log, "appended stdin open file action for {0}", in_file_spec);
      }

      if (out_file_spec) {
        info.AppendOpenFileAction(STDOUT_FILENO, out_file_spec, false, true);
        LLDB_LOG(log, "appended stdout open file action for {0}",
                 out_file_spec);
      }

      if (err_file_spec) {
        info.AppendOpenFileAction(STDERR_FILENO, err_file_spec, false, true);
        LLDB_LOG(log, "appended stderr open file action for {0}",
                 err_file_spec);
      }

      if (default_to_use_pty) {
#ifdef _WIN32
        if (info.GetFlags().Test(eLaunchFlagUsePipes) ||
            ::getenv("LLDB_LAUNCH_FLAG_USE_PIPES")) {
          llvm::Error Err = info.SetUpPipeRedirection();
          LLDB_LOG_ERROR(log, std::move(Err),
                         "SetUpPipeRedirection failed: {0}");
        } else {
#endif
          llvm::Error Err = info.SetUpPtyRedirection();
          LLDB_LOG_ERROR(log, std::move(Err),
                         "SetUpPtyRedirection failed: {0}");
#ifdef _WIN32
        }
#endif
      }
    }
  }
}

void Target::AddDummySignal(llvm::StringRef name, LazyBool pass, LazyBool notify,
                            LazyBool stop) {
    if (name.empty())
      return;
    // Don't add a signal if all the actions are trivial:
    if (pass == eLazyBoolCalculate && notify == eLazyBoolCalculate
        && stop == eLazyBoolCalculate)
      return;

    auto& elem = m_dummy_signals[name];
    elem.pass = pass;
    elem.notify = notify;
    elem.stop = stop;
}

bool Target::UpdateSignalFromDummy(UnixSignalsSP signals_sp,
                                          const DummySignalElement &elem) {
  if (!signals_sp)
    return false;

  int32_t signo
      = signals_sp->GetSignalNumberFromName(elem.first().str().c_str());
  if (signo == LLDB_INVALID_SIGNAL_NUMBER)
    return false;

  if (elem.second.pass == eLazyBoolYes)
    signals_sp->SetShouldSuppress(signo, false);
  else if (elem.second.pass == eLazyBoolNo)
    signals_sp->SetShouldSuppress(signo, true);

  if (elem.second.notify == eLazyBoolYes)
    signals_sp->SetShouldNotify(signo, true);
  else if (elem.second.notify == eLazyBoolNo)
    signals_sp->SetShouldNotify(signo, false);

  if (elem.second.stop == eLazyBoolYes)
    signals_sp->SetShouldStop(signo, true);
  else if (elem.second.stop == eLazyBoolNo)
    signals_sp->SetShouldStop(signo, false);
  return true;
}

bool Target::ResetSignalFromDummy(UnixSignalsSP signals_sp,
                                          const DummySignalElement &elem) {
  if (!signals_sp)
    return false;
  int32_t signo
      = signals_sp->GetSignalNumberFromName(elem.first().str().c_str());
  if (signo == LLDB_INVALID_SIGNAL_NUMBER)
    return false;
  bool do_pass = elem.second.pass != eLazyBoolCalculate;
  bool do_stop = elem.second.stop != eLazyBoolCalculate;
  bool do_notify = elem.second.notify != eLazyBoolCalculate;
  signals_sp->ResetSignal(signo, do_stop, do_notify, do_pass);
  return true;
}

void Target::UpdateSignalsFromDummy(UnixSignalsSP signals_sp,
                                    StreamSP warning_stream_sp) {
  if (!signals_sp)
    return;

  for (const auto &elem : m_dummy_signals) {
    if (!UpdateSignalFromDummy(signals_sp, elem))
      warning_stream_sp->Printf("Target signal '%s' not found in process\n",
          elem.first().str().c_str());
  }
}

void Target::ClearDummySignals(Args &signal_names) {
  ProcessSP process_sp = GetProcessSP();
  // The simplest case, delete them all with no process to update.
  if (signal_names.GetArgumentCount() == 0 && !process_sp) {
    m_dummy_signals.clear();
    return;
  }
  UnixSignalsSP signals_sp;
  if (process_sp)
    signals_sp = process_sp->GetUnixSignals();

  for (const Args::ArgEntry &entry : signal_names) {
    const char *signal_name = entry.c_str();
    auto elem = m_dummy_signals.find(signal_name);
    // If we didn't find it go on.
    // FIXME: Should I pipe error handling through here?
    if (elem == m_dummy_signals.end()) {
      continue;
    }
    if (signals_sp)
      ResetSignalFromDummy(signals_sp, *elem);
    m_dummy_signals.erase(elem);
  }
}

void Target::PrintDummySignals(Stream &strm, Args &signal_args) {
  strm.PutCString("NAME         PASS     STOP     NOTIFY\n");
  strm.PutCString("===========  =======  =======  =======\n");

  auto str_for_lazy = [] (LazyBool lazy) -> const char * {
    switch (lazy) {
      case eLazyBoolCalculate: return "not set";
      case eLazyBoolYes: return "true   ";
      case eLazyBoolNo: return "false  ";
    }
    llvm_unreachable("Fully covered switch above!");
  };
  size_t num_args = signal_args.GetArgumentCount();
  for (const auto &elem : m_dummy_signals) {
    bool print_it = false;
    for (size_t idx = 0; idx < num_args; idx++) {
      if (elem.first() == signal_args.GetArgumentAtIndex(idx)) {
        print_it = true;
        break;
      }
    }
    if (print_it) {
      strm.Printf("%-11s  ", elem.first().str().c_str());
      strm.Printf("%s  %s  %s\n", str_for_lazy(elem.second.pass),
                  str_for_lazy(elem.second.stop),
                  str_for_lazy(elem.second.notify));
    }
  }
}

// Target::StopHook
Target::StopHook::StopHook(lldb::TargetSP target_sp, lldb::user_id_t uid)
    : UserID(uid), m_target_sp(target_sp), m_specifier_sp(),
      m_thread_spec_up() {}

Target::StopHook::StopHook(const StopHook &rhs)
    : UserID(rhs.GetID()), m_target_sp(rhs.m_target_sp),
      m_specifier_sp(rhs.m_specifier_sp), m_thread_spec_up(),
      m_active(rhs.m_active), m_auto_continue(rhs.m_auto_continue) {
  if (rhs.m_thread_spec_up)
    m_thread_spec_up = std::make_unique<ThreadSpec>(*rhs.m_thread_spec_up);
}

void Target::StopHook::SetSpecifier(SymbolContextSpecifier *specifier) {
  m_specifier_sp.reset(specifier);
}

void Target::StopHook::SetThreadSpecifier(ThreadSpec *specifier) {
  m_thread_spec_up.reset(specifier);
}

bool Target::StopHook::ExecutionContextPasses(const ExecutionContext &exc_ctx) {
  SymbolContextSpecifier *specifier = GetSpecifier();
  if (!specifier)
    return true;

  bool will_run = true;
  if (exc_ctx.GetFramePtr())
    will_run = GetSpecifier()->SymbolContextMatches(
        exc_ctx.GetFramePtr()->GetSymbolContext(eSymbolContextEverything));
  if (will_run && GetThreadSpecifier() != nullptr)
    will_run =
        GetThreadSpecifier()->ThreadPassesBasicTests(exc_ctx.GetThreadRef());

  return will_run;
}

void Target::StopHook::GetDescription(Stream &s,
                                      lldb::DescriptionLevel level) const {

  // For brief descriptions, only print the subclass description:
  if (level == eDescriptionLevelBrief) {
    GetSubclassDescription(s, level);
    return;
  }

  auto indent_scope = s.MakeIndentScope();

  s.Printf("Hook: %" PRIu64 "\n", GetID());
  if (m_active)
    s.Indent("State: enabled\n");
  else
    s.Indent("State: disabled\n");

  if (m_auto_continue)
    s.Indent("AutoContinue on\n");

  if (m_specifier_sp) {
    s.Indent();
    s.PutCString("Specifier:\n");
    auto indent_scope = s.MakeIndentScope();
    m_specifier_sp->GetDescription(&s, level);
  }

  if (m_thread_spec_up) {
    StreamString tmp;
    s.Indent("Thread:\n");
    m_thread_spec_up->GetDescription(&tmp, level);
    auto indent_scope = s.MakeIndentScope();
    s.Indent(tmp.GetString());
    s.PutCString("\n");
  }
  GetSubclassDescription(s, level);
}

void Target::StopHookCommandLine::GetSubclassDescription(
    Stream &s, lldb::DescriptionLevel level) const {
  // The brief description just prints the first command.
  if (level == eDescriptionLevelBrief) {
    if (m_commands.GetSize() == 1)
      s.PutCString(m_commands.GetStringAtIndex(0));
    return;
  }
  s.Indent("Commands:\n");
  auto indent_scope = s.MakeIndentScope(4);
  uint32_t num_commands = m_commands.GetSize();
  for (uint32_t i = 0; i < num_commands; i++) {
    s.Indent(m_commands.GetStringAtIndex(i));
    s.PutCString("\n");
  }
}

// Target::StopHookCommandLine
void Target::StopHookCommandLine::SetActionFromString(const std::string &string) {
  GetCommands().SplitIntoLines(string);
}

void Target::StopHookCommandLine::SetActionFromStrings(
    const std::vector<std::string> &strings) {
  for (auto string : strings)
    GetCommands().AppendString(string.c_str());
}

Target::StopHook::StopHookResult
Target::StopHookCommandLine::HandleStop(ExecutionContext &exc_ctx,
                                        StreamSP output_sp) {
  assert(exc_ctx.GetTargetPtr() && "Can't call PerformAction on a context "
                                   "with no target");

  if (!m_commands.GetSize())
    return StopHookResult::KeepStopped;

  CommandReturnObject result(false);
  result.SetImmediateOutputStream(output_sp);
  result.SetImmediateErrorStream(output_sp);
  result.SetInteractive(false);
  Debugger &debugger = exc_ctx.GetTargetPtr()->GetDebugger();
  CommandInterpreterRunOptions options;
  options.SetStopOnContinue(true);
  options.SetStopOnError(true);
  options.SetEchoCommands(false);
  options.SetPrintResults(true);
  options.SetPrintErrors(true);
  options.SetAddToHistory(false);

  // Force Async:
  bool old_async = debugger.GetAsyncExecution();
  debugger.SetAsyncExecution(true);
  debugger.GetCommandInterpreter().HandleCommands(GetCommands(), exc_ctx,
                                                  options, result);
  debugger.SetAsyncExecution(old_async);
  lldb::ReturnStatus status = result.GetStatus();
  if (status == eReturnStatusSuccessContinuingNoResult ||
      status == eReturnStatusSuccessContinuingResult)
    return StopHookResult::AlreadyContinued;
  return StopHookResult::KeepStopped;
}

// Target::StopHookScripted
Status Target::StopHookScripted::SetScriptCallback(
    const ScriptedMetadata &scripted_metadata) {
  Status error;

  ScriptInterpreter *script_interp =
      GetTarget()->GetDebugger().GetScriptInterpreter();
  if (!script_interp) {
    error = Status::FromErrorString("No script interpreter installed.");
    return error;
  }

  m_interface_sp = script_interp->CreateScriptedHookInterface();
  if (!m_interface_sp) {
    error = Status::FromErrorStringWithFormat(
        "ScriptedStopHook::%s () - ERROR: %s", __FUNCTION__,
        "Script interpreter couldn't create Scripted Stop Hook Interface");
    return error;
  }

  auto obj_or_err =
      m_interface_sp->CreatePluginObject(scripted_metadata, GetTarget());
  if (!obj_or_err) {
    return Status::FromError(obj_or_err.takeError());
  }

  StructuredData::ObjectSP object_sp = *obj_or_err;
  if (!object_sp || !object_sp->IsValid()) {
    error = Status::FromErrorStringWithFormat(
        "ScriptedStopHook::%s () - ERROR: %s", __FUNCTION__,
        "Failed to create valid script object");
    return error;
  }

  return {};
}

/// Hook callbacks have no caller to return an error to, so report a failure
/// as a debugger diagnostic. \a what names the hook, e.g. "stop hook 1".
static void ReportScriptedHookError(llvm::Error error, llvm::StringRef what,
                                    Debugger &debugger) {
  if (!error)
    return;

  Debugger::ReportError(
      llvm::formatv("{0} failed: {1}", what, llvm::toString(std::move(error)))
          .str(),
      debugger.GetID());
}

Target::StopHook::StopHookResult
Target::StopHookScripted::HandleStop(ExecutionContext &exc_ctx,
                                     StreamSP output_sp) {
  assert(exc_ctx.GetTargetPtr() && "Can't call HandleStop on a context "
                                   "with no target");

  if (!m_interface_sp)
    return StopHookResult::KeepStopped;

  lldb::StreamSP stream = std::make_shared<lldb_private::StreamString>();
  auto should_stop_or_err = m_interface_sp->HandleStop(exc_ctx, stream);
  output_sp->PutCString(
      reinterpret_cast<StreamString *>(stream.get())->GetData());
  if (!should_stop_or_err) {
    ReportScriptedHookError(should_stop_or_err.takeError(),
                            llvm::formatv("stop hook {0}", GetID()).str(),
                            exc_ctx.GetTargetPtr()->GetDebugger());
    return StopHookResult::KeepStopped;
  }

  return *should_stop_or_err ? StopHookResult::KeepStopped
                             : StopHookResult::RequestContinue;
}

llvm::StringRef Target::StopHookScripted::GetScriptClassName() const {
  if (m_interface_sp && m_interface_sp->GetScriptedMetadata())
    return m_interface_sp->GetScriptedMetadata()->GetClassName();
  return "<unknown>";
}

void Target::StopHookScripted::GetSubclassDescription(
    Stream &s, lldb::DescriptionLevel level) const {
  llvm::StringRef class_name = GetScriptClassName();
  if (level == eDescriptionLevelBrief) {
    s.PutCString(class_name);
    return;
  }
  s.Indent("Class:");
  s.Format("{0}\n", class_name);

  // Now print the extra args:
  // FIXME: We should use StructuredData.GetDescription on the args dict
  // but that seems to rely on some printing plugin that doesn't exist.
  StructuredData::DictionarySP as_dict =
      (m_interface_sp && m_interface_sp->GetScriptedMetadata())
          ? m_interface_sp->GetScriptedMetadata()->GetArgsSP()
          : nullptr;
  if (!as_dict || !as_dict->IsValid())
    return;

  uint32_t num_keys = as_dict->GetSize();
  if (num_keys == 0)
    return;

  s.Indent("Args:\n");
  auto indent_scope = s.MakeIndentScope(4);

  auto print_one_element = [&s](llvm::StringRef key,
                                StructuredData::Object *object) {
    s.Indent();
    s.Format("{0} : {1}\n", key, object->GetStringValue());
    return true;
  };

  as_dict->ForEach(print_one_element);
}

// Hook

Target::Hook::Hook(lldb::TargetSP target_sp, lldb::user_id_t uid, HookKind kind)
    : UserID(uid), m_target_sp(std::move(target_sp)), m_kind(kind) {}

Target::Hook::Hook(const Hook &rhs)
    : UserID(rhs.GetID()), m_target_sp(rhs.m_target_sp), m_kind(rhs.m_kind),
      m_enabled(rhs.m_enabled), m_trigger_mask(rhs.m_trigger_mask),
      m_sc_specifier_sp(rhs.m_sc_specifier_sp),
      m_at_initial_stop(rhs.m_at_initial_stop),
      m_auto_continue(rhs.m_auto_continue),
      m_suppress_output(rhs.m_suppress_output) {
  if (rhs.m_thread_spec_up)
    m_thread_spec_up = std::make_unique<ThreadSpec>(*rhs.m_thread_spec_up);
}

void Target::Hook::SetSCSpecifier(SymbolContextSpecifier *specifier) {
  m_sc_specifier_sp.reset(specifier);
}

void Target::Hook::SetThreadSpecifier(ThreadSpec *specifier) {
  m_thread_spec_up.reset(specifier);
}

bool Target::Hook::ExecutionContextPasses(const ExecutionContext &exc_ctx) {
  SymbolContextSpecifier *specifier = GetSCSpecifier();
  if (!specifier)
    return true;

  bool will_run = true;
  if (exc_ctx.GetFramePtr())
    will_run = specifier->SymbolContextMatches(
        exc_ctx.GetFramePtr()->GetSymbolContext(eSymbolContextEverything));
  if (will_run && GetThreadSpecifier() != nullptr)
    will_run =
        GetThreadSpecifier()->ThreadPassesBasicTests(exc_ctx.GetThreadRef());

  return will_run;
}

void Target::Hook::GetDescription(Stream &s,
                                  lldb::DescriptionLevel level) const {
  s.Printf("Hook: %" PRIu64 "\n", GetID());
  if (level == eDescriptionLevelBrief)
    return;
  s.IndentMore();
  s.Indent();
  s.Printf("State: %s\n", m_enabled ? "enabled" : "disabled");

  {
    std::string fires_on;
    if (m_trigger_mask & kModulesLoaded)
      fires_on += "load";
    if (m_trigger_mask & kModulesUnloaded) {
      if (!fires_on.empty())
        fires_on += ", ";
      fires_on += "unload";
    }
    if (m_trigger_mask & kProcessStop) {
      if (!fires_on.empty())
        fires_on += ", ";
      fires_on += "stop";
    }
    if (!fires_on.empty()) {
      s.Indent();
      s.Printf("Triggers: %s\n", fires_on.c_str());
    }
  }
  // Subclasses add their content (commands or class) then call
  // GetFilterDescription to print filters.
  s.IndentLess();
}

void Target::Hook::GetFilterDescription(Stream &s,
                                        lldb::DescriptionLevel level) const {
  s.IndentMore();

  if (m_auto_continue)
    s.Indent("AutoContinue on\n");

  if (m_sc_specifier_sp) {
    s.Indent();
    s.PutCString("Specifier:\n");
    s.IndentMore();
    m_sc_specifier_sp->GetDescription(&s, level);
    s.IndentLess();
  }

  if (m_thread_spec_up) {
    StreamString tmp;
    s.Indent("Thread:\n");
    m_thread_spec_up->GetDescription(&tmp, level);
    s.IndentMore();
    s.Indent(tmp.GetString());
    s.PutCString("\n");
    s.IndentLess();
  }

  s.IndentLess();
}

void Target::HookCommandLine::GetDescription(
    Stream &s, lldb::DescriptionLevel level) const {
  Hook::GetDescription(s, level);
  if (level == eDescriptionLevelBrief) {
    if (m_commands.GetSize() == 1)
      s.PutCString(m_commands.GetStringAtIndex(0));
    else
      s.Printf("%" PRIu64 " commands", (uint64_t)m_commands.GetSize());
    return;
  }

  // Commands come after the header (ID, State, Triggers) but before filters.
  s.IndentMore();
  s.Indent("Commands: \n");
  s.IndentMore();
  for (uint32_t i = 0; i < m_commands.GetSize(); i++) {
    s.Indent(m_commands.GetStringAtIndex(i));
    s.PutCString("\n");
  }
  s.IndentLess();
  s.IndentLess();

  GetFilterDescription(s, level);
}

// HookCommandLine

void Target::HookCommandLine::SetActionFromString(const std::string &string) {
  GetCommands().SplitIntoLines(string);
}

void Target::HookCommandLine::SetActionFromStrings(
    const std::vector<std::string> &strings) {
  for (const auto &string : strings)
    GetCommands().AppendString(string.c_str());
}

void Target::HookCommandLine::HandleModuleLoaded(StreamSP output_sp) {
  if (!m_commands.GetSize())
    return;

  TargetSP target_sp = GetTarget();
  if (!target_sp)
    return;

  CommandReturnObject result(false);
  result.SetImmediateOutputStream(output_sp);
  result.SetInteractive(false);
  Debugger &debugger = target_sp->GetDebugger();

  ExecutionContext exe_ctx;
  if (target_sp->GetProcessSP())
    exe_ctx.SetContext(target_sp->GetProcessSP());
  else
    exe_ctx.SetContext(target_sp, false);

  CommandInterpreterRunOptions options;
  options.SetStopOnContinue(true);
  options.SetStopOnError(true);
  options.SetEchoCommands(false);
  options.SetPrintResults(true);
  options.SetPrintErrors(true);
  options.SetAddToHistory(false);

  bool old_async = debugger.GetAsyncExecution();
  debugger.SetAsyncExecution(true);
  debugger.GetCommandInterpreter().HandleCommands(GetCommands(), exe_ctx,
                                                  options, result);
  debugger.SetAsyncExecution(old_async);
}

void Target::HookCommandLine::HandleModuleUnloaded(StreamSP output_sp) {
  // Command-based hooks run the same commands on unload as on load.
  HandleModuleLoaded(output_sp);
}

Target::StopHook::StopHookResult
Target::HookCommandLine::HandleStop(ExecutionContext &exc_ctx,
                                    StreamSP output_sp) {
  assert(exc_ctx.GetTargetPtr() && "Can't call HandleStop on a context "
                                   "with no target");

  if (!m_commands.GetSize())
    return StopHook::StopHookResult::KeepStopped;

  CommandReturnObject result(false);
  result.SetImmediateOutputStream(output_sp);
  result.SetImmediateErrorStream(output_sp);
  result.SetInteractive(false);
  Debugger &debugger = exc_ctx.GetTargetPtr()->GetDebugger();
  CommandInterpreterRunOptions options;
  options.SetStopOnContinue(true);
  options.SetStopOnError(true);
  options.SetEchoCommands(false);
  options.SetPrintResults(true);
  options.SetPrintErrors(true);
  options.SetAddToHistory(false);

  bool old_async = debugger.GetAsyncExecution();
  debugger.SetAsyncExecution(true);
  debugger.GetCommandInterpreter().HandleCommands(GetCommands(), exc_ctx,
                                                  options, result);
  debugger.SetAsyncExecution(old_async);
  lldb::ReturnStatus status = result.GetStatus();
  if (status == eReturnStatusSuccessContinuingNoResult ||
      status == eReturnStatusSuccessContinuingResult)
    return StopHook::StopHookResult::AlreadyContinued;
  return StopHook::StopHookResult::KeepStopped;
}

// HookScripted

Status Target::HookScripted::SetScriptCallback(
    const ScriptedMetadata &scripted_metadata) {
  ScriptInterpreter *script_interp =
      GetTarget()->GetDebugger().GetScriptInterpreter();
  if (!script_interp)
    return Status::FromErrorString("No script interpreter installed.");

  m_interface_sp = script_interp->CreateScriptedHookInterface();
  if (!m_interface_sp)
    return Status::FromErrorStringWithFormat(
        "ScriptedHook::%s () - ERROR: %s", __FUNCTION__,
        "Script interpreter couldn't create Scripted Hook Interface");

  auto obj_or_err =
      m_interface_sp->CreatePluginObject(scripted_metadata, GetTarget());
  if (!obj_or_err)
    return Status::FromError(obj_or_err.takeError());

  StructuredData::ObjectSP object_sp = *obj_or_err;
  if (!object_sp || !object_sp->IsValid())
    return Status::FromErrorStringWithFormat(
        "ScriptedHook::%s () - ERROR: %s", __FUNCTION__,
        "Failed to create valid script object");

  // Determine which triggers the class supports by checking which callback
  // methods it implements.
  auto methods = m_interface_sp->GetSupportedMethods();
  if (!methods.any())
    return Status::FromErrorString(
        "hook class implements none of the expected methods "
        "(handle_module_loaded, handle_module_unloaded, handle_stop)");

  if (methods.handle_module_loaded)
    m_trigger_mask |= kModulesLoaded;
  if (methods.handle_module_unloaded)
    m_trigger_mask |= kModulesUnloaded;
  if (methods.handle_stop)
    m_trigger_mask |= kProcessStop;

  return {};
}

void Target::HookScripted::HandleModuleLoaded(StreamSP output_sp) {
  if (!m_interface_sp)
    return;

  TargetSP target_sp = GetTarget();
  if (!target_sp)
    return;

  StreamSP stream = std::make_shared<StreamString>();
  llvm::Error error = m_interface_sp->HandleModuleLoaded(stream);
  output_sp->PutCString(static_cast<StreamString *>(stream.get())->GetData());
  ReportScriptedHookError(std::move(error),
                          llvm::formatv("hook {0}", GetID()).str(),
                          target_sp->GetDebugger());
}

void Target::HookScripted::HandleModuleUnloaded(StreamSP output_sp) {
  if (!m_interface_sp)
    return;

  TargetSP target_sp = GetTarget();
  if (!target_sp)
    return;

  StreamSP stream = std::make_shared<StreamString>();
  llvm::Error error = m_interface_sp->HandleModuleUnloaded(stream);
  output_sp->PutCString(static_cast<StreamString *>(stream.get())->GetData());
  ReportScriptedHookError(std::move(error),
                          llvm::formatv("hook {0}", GetID()).str(),
                          target_sp->GetDebugger());
}

Target::StopHook::StopHookResult
Target::HookScripted::HandleStop(ExecutionContext &exc_ctx,
                                 StreamSP output_sp) {
  assert(exc_ctx.GetTargetPtr() && "Can't call HandleStop on a context "
                                   "with no target");

  if (!m_interface_sp)
    return StopHook::StopHookResult::KeepStopped;

  lldb::StreamSP stream = std::make_shared<lldb_private::StreamString>();
  auto should_stop_or_err = m_interface_sp->HandleStop(exc_ctx, stream);
  output_sp->PutCString(static_cast<StreamString *>(stream.get())->GetData());
  if (!should_stop_or_err) {
    ReportScriptedHookError(should_stop_or_err.takeError(),
                            llvm::formatv("hook {0}", GetID()).str(),
                            exc_ctx.GetTargetPtr()->GetDebugger());
    return StopHook::StopHookResult::KeepStopped;
  }

  return *should_stop_or_err ? StopHook::StopHookResult::KeepStopped
                             : StopHook::StopHookResult::RequestContinue;
}

llvm::StringRef Target::HookScripted::GetScriptClassName() const {
  if (m_interface_sp && m_interface_sp->GetScriptedMetadata())
    return m_interface_sp->GetScriptedMetadata()->GetClassName();
  return "<unknown>";
}

void Target::HookScripted::GetDescription(Stream &s,
                                          lldb::DescriptionLevel level) const {
  Hook::GetDescription(s, level);
  llvm::StringRef class_name = GetScriptClassName();
  if (level == eDescriptionLevelBrief) {
    s.PutCString(class_name);
    return;
  }

  // Class and args come after the header (ID, State, Triggers) but before
  // filters.
  s.IndentMore();
  s.Indent("Class: ");
  s.Format("{0}\n", class_name);

  StructuredData::DictionarySP as_dict =
      (m_interface_sp && m_interface_sp->GetScriptedMetadata())
          ? m_interface_sp->GetScriptedMetadata()->GetArgsSP()
          : nullptr;
  if (as_dict && as_dict->IsValid() && as_dict->GetSize() > 0) {
    s.Indent("Args:\n");
    s.IndentMore();

    auto print_one_element = [&s](llvm::StringRef key,
                                  StructuredData::Object *object) {
      s.Indent();
      s.Format("{0} : {1}\n", key, object->GetStringValue());
      return true;
    };

    as_dict->ForEach(print_one_element);
    s.IndentLess();
  }
  s.IndentLess();

  GetFilterDescription(s, level);
}

// Hook management methods

Target::HookSP Target::CreateHook(Hook::HookKind kind) {
  lldb::user_id_t new_uid = ++m_hook_next_id;
  HookSP hook_sp;
  switch (kind) {
  case Hook::HookKind::CommandBased:
    hook_sp.reset(new HookCommandLine(shared_from_this(), new_uid));
    break;
  case Hook::HookKind::ScriptBased:
    hook_sp.reset(new HookScripted(shared_from_this(), new_uid));
    break;
  }
  m_hooks[new_uid] = hook_sp;
  return hook_sp;
}

void Target::UndoCreateHook(lldb::user_id_t uid) {
  if (!RemoveHookByID(uid))
    return;
  if (uid > 0)
    --m_hook_next_id;
}

bool Target::RemoveHookByID(lldb::user_id_t uid) {
  size_t num_removed = m_hooks.erase(uid);
  return (num_removed != 0);
}

void Target::RemoveAllHooks() { m_hooks.clear(); }

Target::HookSP Target::GetHookByID(lldb::user_id_t uid) {
  auto iter = m_hooks.find(uid);
  if (iter == m_hooks.end())
    return {};
  return iter->second;
}

Target::HookSP Target::GetHookAtIndex(size_t index) {
  if (index >= m_hooks.size())
    return {};
  auto iter = m_hooks.begin();
  std::advance(iter, index);
  return iter->second;
}

bool Target::SetHookEnabledStateByID(lldb::user_id_t uid, bool enabled) {
  auto iter = m_hooks.find(uid);
  if (iter == m_hooks.end())
    return false;
  iter->second->SetIsEnabled(enabled);
  return true;
}

void Target::SetAllHooksEnabledState(bool enabled) {
  for (auto &[_, hook] : m_hooks)
    hook->SetIsEnabled(enabled);
}

void Target::RunModuleHooks(bool is_load) {
  if (m_hooks.empty())
    return;

  uint32_t trigger = is_load ? Hook::kModulesLoaded : Hook::kModulesUnloaded;

  // Copy active hooks into a local vector before iterating, in case a
  // callback modifies m_hooks (same pattern as RunStopHooks).
  std::vector<HookSP> active_hooks;
  for (auto &[_, hook_sp] : m_hooks) {
    if (hook_sp->IsEnabled() && hook_sp->FiresOn(trigger))
      active_hooks.push_back(hook_sp);
  }

  if (active_hooks.empty())
    return;

  StreamSP output_sp = m_debugger.GetAsyncOutputStream();

  for (auto &hook_sp : active_hooks) {
    if (is_load)
      hook_sp->HandleModuleLoaded(output_sp);
    else
      hook_sp->HandleModuleUnloaded(output_sp);
  }

  output_sp->Flush();
}

static constexpr OptionEnumValueElement g_dynamic_value_types[] = {
    {
        eNoDynamicValues,
        "no-dynamic-values",
        "Don't calculate the dynamic type of values",
    },
    {
        eDynamicCanRunTarget,
        "run-target",
        "Calculate the dynamic type of values "
        "even if you have to run the target.",
    },
    {
        eDynamicDontRunTarget,
        "no-run-target",
        "Calculate the dynamic type of values, but don't run the target.",
    },
};

OptionEnumValues lldb_private::GetDynamicValueTypes() {
  return OptionEnumValues(g_dynamic_value_types);
}

static constexpr OptionEnumValueElement g_inline_breakpoint_enums[] = {
    {
        eInlineBreakpointsNever,
        "never",
        "Never look for inline breakpoint locations (fastest). This setting "
        "should only be used if you know that no inlining occurs in your"
        "programs.",
    },
    {
        eInlineBreakpointsHeaders,
        "headers",
        "Only check for inline breakpoint locations when setting breakpoints "
        "in header files, but not when setting breakpoint in implementation "
        "source files (default).",
    },
    {
        eInlineBreakpointsAlways,
        "always",
        "Always look for inline breakpoint locations when setting file and "
        "line breakpoints (slower but most accurate).",
    },
};

enum x86DisassemblyFlavor {
  eX86DisFlavorDefault,
  eX86DisFlavorIntel,
  eX86DisFlavorATT
};

static constexpr OptionEnumValueElement g_x86_dis_flavor_value_types[] = {
    {
        eX86DisFlavorDefault,
        "default",
        "Disassembler default (currently att).",
    },
    {
        eX86DisFlavorIntel,
        "intel",
        "Intel disassembler flavor.",
    },
    {
        eX86DisFlavorATT,
        "att",
        "AT&T disassembler flavor.",
    },
};

static constexpr OptionEnumValueElement g_jit_engine_value_types[] = {
    {
        eJITEngineMCJIT,
        "mcjit",
        "Use LLVM's MCJIT execution engine.",
    },
    {
        eJITEngineORC,
        "orc",
        "Use LLVM's ORC execution engine.",
    },
};

static constexpr OptionEnumValueElement g_import_std_module_value_types[] = {
    {
        eImportStdModuleFalse,
        "false",
        "Never import the 'std' C++ module in the expression parser.",
    },
    {
        eImportStdModuleFallback,
        "fallback",
        "Retry evaluating expressions with an imported 'std' C++ module if they"
        " failed to parse without the module. This allows evaluating more "
        "complex expressions involving C++ standard library types."
    },
    {
        eImportStdModuleTrue,
        "true",
        "Always import the 'std' C++ module. This allows evaluating more "
        "complex expressions involving C++ standard library types. This feature"
        " is experimental."
    },
};

static constexpr OptionEnumValueElement
    g_dynamic_class_info_helper_value_types[] = {
        {
            eDynamicClassInfoHelperAuto,
            "auto",
            "Automatically determine the most appropriate method for the "
            "target OS.",
        },
        {eDynamicClassInfoHelperRealizedClassesStruct, "RealizedClassesStruct",
         "Prefer using the realized classes struct."},
        {eDynamicClassInfoHelperCopyRealizedClassList, "CopyRealizedClassList",
         "Prefer using the CopyRealizedClassList API."},
        {eDynamicClassInfoHelperGetRealizedClassList, "GetRealizedClassList",
         "Prefer using the GetRealizedClassList API."},
};

static constexpr OptionEnumValueElement g_hex_immediate_style_values[] = {
    {
        Disassembler::eHexStyleC,
        "c",
        "C-style (0xffff).",
    },
    {
        Disassembler::eHexStyleAsm,
        "asm",
        "Asm-style (0ffffh).",
    },
};

static constexpr OptionEnumValueElement g_load_script_from_sym_file_values[] = {
    {
        eLoadScriptFromSymFileTrue,
        "true",
        "Load debug scripts inside symbol files",
    },
    {
        eLoadScriptFromSymFileFalse,
        "false",
        "Do not load debug scripts inside symbol files.",
    },
    {
        eLoadScriptFromSymFileWarn,
        "warn",
        "Warn about debug scripts inside symbol files but do not load them.",
    },
    {
        eLoadScriptFromSymFileTrusted,
        "trusted",
        "Load debug scripts inside trusted symbol files, and warn about "
        "scripts from untrusted symbol files.",
    },
};

static constexpr OptionEnumValueElement g_load_cwd_lldbinit_values[] = {
    {
        eLoadCWDlldbinitTrue,
        "true",
        "Load .lldbinit files from current directory",
    },
    {
        eLoadCWDlldbinitFalse,
        "false",
        "Do not load .lldbinit files from current directory",
    },
    {
        eLoadCWDlldbinitWarn,
        "warn",
        "Warn about loading .lldbinit files from current directory",
    },
};

static constexpr OptionEnumValueElement g_memory_module_load_level_values[] = {
    {
        eMemoryModuleLoadLevelMinimal,
        "minimal",
        "Load minimal information when loading modules from memory. Currently "
        "this setting loads sections only.",
    },
    {
        eMemoryModuleLoadLevelPartial,
        "partial",
        "Load partial information when loading modules from memory. Currently "
        "this setting loads sections and function bounds.",
    },
    {
        eMemoryModuleLoadLevelComplete,
        "complete",
        "Load complete information when loading modules from memory. Currently "
        "this setting loads sections and all symbols.",
    },
};

#define LLDB_PROPERTIES_target
#include "TargetProperties.inc"

enum {
#define LLDB_PROPERTIES_target
#include "TargetPropertiesEnum.inc"
  ePropertyExperimental,
};

class TargetOptionValueProperties
    : public Cloneable<TargetOptionValueProperties, OptionValueProperties> {
public:
  TargetOptionValueProperties(llvm::StringRef name) : Cloneable(name) {}

  const Property *
  GetPropertyAtIndex(size_t idx,
                     const ExecutionContext *exe_ctx = nullptr) const override {
    // When getting the value for a key from the target options, we will always
    // try and grab the setting from the current target if there is one. Else
    // we just use the one from this instance.
    if (exe_ctx) {
      Target *target = exe_ctx->GetTargetPtr();
      if (target && !target->IsDummyTarget()) {
        TargetOptionValueProperties *target_properties =
            static_cast<TargetOptionValueProperties *>(
                target->GetValueProperties().get());
        if (this != target_properties)
          return target_properties->ProtectedGetPropertyAtIndex(idx);
      }
    }
    return ProtectedGetPropertyAtIndex(idx);
  }
};

// TargetProperties
#define LLDB_PROPERTIES_target_experimental
#include "TargetProperties.inc"

enum {
#define LLDB_PROPERTIES_target_experimental
#include "TargetPropertiesEnum.inc"
};

class TargetExperimentalOptionValueProperties
    : public Cloneable<TargetExperimentalOptionValueProperties,
                       OptionValueProperties> {
public:
  TargetExperimentalOptionValueProperties()
      : Cloneable(Properties::GetExperimentalSettingsName()) {}
};

TargetExperimentalProperties::TargetExperimentalProperties()
    : Properties(OptionValuePropertiesSP(
          new TargetExperimentalOptionValueProperties())) {
  m_collection_sp->Initialize(g_target_experimental_properties_def);
}

// TargetProperties
TargetProperties::TargetProperties(Target *target)
    : Properties(), m_launch_info(), m_target(target) {
  if (target) {
    m_collection_sp =
        OptionValueProperties::CreateLocalCopy(Target::GetGlobalProperties());

    // Set callbacks to update launch_info whenever "settins set" updated any
    // of these properties
    m_collection_sp->SetValueChangedCallback(
        ePropertyArg0, [this] { Arg0ValueChangedCallback(); });
    m_collection_sp->SetValueChangedCallback(
        ePropertyRunArgs, [this] { RunArgsValueChangedCallback(); });
    m_collection_sp->SetValueChangedCallback(
        ePropertyEnvVars, [this] { EnvVarsValueChangedCallback(); });
    m_collection_sp->SetValueChangedCallback(
        ePropertyUnsetEnvVars, [this] { EnvVarsValueChangedCallback(); });
    m_collection_sp->SetValueChangedCallback(
        ePropertyInheritEnv, [this] { EnvVarsValueChangedCallback(); });
    m_collection_sp->SetValueChangedCallback(
        ePropertyInputPath, [this] { InputPathValueChangedCallback(); });
    m_collection_sp->SetValueChangedCallback(
        ePropertyOutputPath, [this] { OutputPathValueChangedCallback(); });
    m_collection_sp->SetValueChangedCallback(
        ePropertyErrorPath, [this] { ErrorPathValueChangedCallback(); });
    m_collection_sp->SetValueChangedCallback(ePropertyDetachOnError, [this] {
      DetachOnErrorValueChangedCallback();
    });
    m_collection_sp->SetValueChangedCallback(
        ePropertyDisableASLR, [this] { DisableASLRValueChangedCallback(); });
    m_collection_sp->SetValueChangedCallback(
        ePropertyInheritTCC, [this] { InheritTCCValueChangedCallback(); });
    m_collection_sp->SetValueChangedCallback(
        ePropertyDisableSTDIO, [this] { DisableSTDIOValueChangedCallback(); });

    m_collection_sp->SetValueChangedCallback(
        ePropertySaveObjectsDir, [this] { CheckJITObjectsDir(); });
    m_experimental_properties_up =
        std::make_unique<TargetExperimentalProperties>();
    m_collection_sp->AppendProperty(
        Properties::GetExperimentalSettingsName(),
        "Experimental settings - setting these won't produce "
        "errors if the setting is not present.",
        true, m_experimental_properties_up->GetValueProperties());
  } else {
    m_collection_sp = std::make_shared<TargetOptionValueProperties>("target");
    m_collection_sp->Initialize(g_target_properties_def);
    m_experimental_properties_up =
        std::make_unique<TargetExperimentalProperties>();
    m_collection_sp->AppendProperty(
        Properties::GetExperimentalSettingsName(),
        "Experimental settings - setting these won't produce "
        "errors if the setting is not present.",
        true, m_experimental_properties_up->GetValueProperties());
    m_collection_sp->AppendProperty(
        "process", "Settings specific to processes.", true,
        Process::GetGlobalProperties().GetValueProperties());
    m_collection_sp->SetValueChangedCallback(
        ePropertySaveObjectsDir, [this] { CheckJITObjectsDir(); });
  }
}

TargetProperties::~TargetProperties() = default;

void TargetProperties::UpdateLaunchInfoFromProperties() {
  Arg0ValueChangedCallback();
  RunArgsValueChangedCallback();
  EnvVarsValueChangedCallback();
  InputPathValueChangedCallback();
  OutputPathValueChangedCallback();
  ErrorPathValueChangedCallback();
  DetachOnErrorValueChangedCallback();
  DisableASLRValueChangedCallback();
  InheritTCCValueChangedCallback();
  DisableSTDIOValueChangedCallback();
}

std::optional<bool> TargetProperties::GetExperimentalPropertyValue(
    size_t prop_idx, ExecutionContext *exe_ctx) const {
  const Property *exp_property =
      m_collection_sp->GetPropertyAtIndex(ePropertyExperimental, exe_ctx);
  OptionValueProperties *exp_values =
      exp_property->GetValue()->GetAsProperties();
  if (exp_values)
    return exp_values->GetPropertyAtIndexAs<bool>(prop_idx, exe_ctx);
  return std::nullopt;
}

bool TargetProperties::GetInjectLocalVariables(
    ExecutionContext *exe_ctx) const {
  return GetExperimentalPropertyValue(ePropertyInjectLocalVars, exe_ctx)
      .value_or(true);
}

bool TargetProperties::GetUseDIL(ExecutionContext *exe_ctx) const {
  const Property *exp_property =
      m_collection_sp->GetPropertyAtIndex(ePropertyExperimental, exe_ctx);
  OptionValueProperties *exp_values =
      exp_property->GetValue()->GetAsProperties();
  if (exp_values)
    return exp_values->GetPropertyAtIndexAs<bool>(ePropertyUseDIL, exe_ctx)
        .value_or(false);
  else
    return true;
}

void TargetProperties::SetUseDIL(ExecutionContext *exe_ctx, bool b) {
  const Property *exp_property =
      m_collection_sp->GetPropertyAtIndex(ePropertyExperimental, exe_ctx);
  OptionValueProperties *exp_values =
      exp_property->GetValue()->GetAsProperties();
  if (exp_values)
    exp_values->SetPropertyAtIndex(ePropertyUseDIL, true, exe_ctx);
}

bool TargetProperties::GetUseDILForCreatingValues() const {
  const Property *exp_property =
      m_collection_sp->GetPropertyAtIndex(ePropertyExperimental);
  OptionValueProperties *exp_values =
      exp_property->GetValue()->GetAsProperties();
  if (exp_values)
    return exp_values
        ->GetPropertyAtIndexAs<bool>(ePropertyUseDILForCreatingValues)
        .value_or(false);
  else
    return true;
}

void TargetProperties::SetUseDILForCreatingValues(bool b) {
  const Property *exp_property =
      m_collection_sp->GetPropertyAtIndex(ePropertyExperimental);
  OptionValueProperties *exp_values =
      exp_property->GetValue()->GetAsProperties();
  if (exp_values)
    exp_values->SetPropertyAtIndex(ePropertyUseDILForCreatingValues, b);
}

ArchSpec TargetProperties::GetDefaultArchitecture() const {
  const uint32_t idx = ePropertyDefaultArch;
  return GetPropertyAtIndexAs<ArchSpec>(idx, {});
}

void TargetProperties::SetDefaultArchitecture(const ArchSpec &arch) {
  const uint32_t idx = ePropertyDefaultArch;
  SetPropertyAtIndex(idx, arch);
}

bool TargetProperties::GetMoveToNearestCode() const {
  const uint32_t idx = ePropertyMoveToNearestCode;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

lldb::DynamicValueType TargetProperties::GetPreferDynamicValue() const {
  const uint32_t idx = ePropertyPreferDynamic;
  return GetPropertyAtIndexAs<lldb::DynamicValueType>(
      idx, static_cast<lldb::DynamicValueType>(
               g_target_properties[idx].default_uint_value));
}

bool TargetProperties::SetPreferDynamicValue(lldb::DynamicValueType d) {
  const uint32_t idx = ePropertyPreferDynamic;
  return SetPropertyAtIndex(idx, d);
}

bool TargetProperties::GetPreloadSymbols() const {
  if (INTERRUPT_REQUESTED(m_target->GetDebugger(),
                          "Interrupted checking preload symbols")) {
    return false;
  }
  const uint32_t idx = ePropertyPreloadSymbols;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

void TargetProperties::SetPreloadSymbols(bool b) {
  const uint32_t idx = ePropertyPreloadSymbols;
  SetPropertyAtIndex(idx, b);
}

bool TargetProperties::GetDisableASLR() const {
  const uint32_t idx = ePropertyDisableASLR;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

void TargetProperties::SetDisableASLR(bool b) {
  const uint32_t idx = ePropertyDisableASLR;
  SetPropertyAtIndex(idx, b);
}

bool TargetProperties::GetInheritTCC() const {
  const uint32_t idx = ePropertyInheritTCC;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

void TargetProperties::SetInheritTCC(bool b) {
  const uint32_t idx = ePropertyInheritTCC;
  SetPropertyAtIndex(idx, b);
}

bool TargetProperties::GetDetachOnError() const {
  const uint32_t idx = ePropertyDetachOnError;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

void TargetProperties::SetDetachOnError(bool b) {
  const uint32_t idx = ePropertyDetachOnError;
  SetPropertyAtIndex(idx, b);
}

bool TargetProperties::GetDisableSTDIO() const {
  const uint32_t idx = ePropertyDisableSTDIO;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

void TargetProperties::SetDisableSTDIO(bool b) {
  const uint32_t idx = ePropertyDisableSTDIO;
  SetPropertyAtIndex(idx, b);
}
llvm::StringRef TargetProperties::GetLaunchWorkingDirectory() const {
  const uint32_t idx = ePropertyLaunchWorkingDir;
  return GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_target_properties[idx].default_cstr_value);
}

bool TargetProperties::GetParallelModuleLoad() const {
  const uint32_t idx = ePropertyParallelModuleLoad;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

const char *TargetProperties::GetDisassemblyFlavor() const {
  const uint32_t idx = ePropertyDisassemblyFlavor;
  const char *return_value;

  x86DisassemblyFlavor flavor_value =
      GetPropertyAtIndexAs<x86DisassemblyFlavor>(
          idx, static_cast<x86DisassemblyFlavor>(
                   g_target_properties[idx].default_uint_value));

  return_value = g_x86_dis_flavor_value_types[flavor_value].string_value;
  return return_value;
}

const char *TargetProperties::GetDisassemblyCPU() const {
  const uint32_t idx = ePropertyDisassemblyCPU;
  llvm::StringRef str = GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_target_properties[idx].default_cstr_value);
  return str.empty() ? nullptr : str.data();
}

const char *TargetProperties::GetDisassemblyFeatures() const {
  const uint32_t idx = ePropertyDisassemblyFeatures;
  llvm::StringRef str = GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_target_properties[idx].default_cstr_value);
  return str.empty() ? nullptr : str.data();
}

InlineStrategy TargetProperties::GetInlineStrategy() const {
  const uint32_t idx = ePropertyInlineStrategy;
  return GetPropertyAtIndexAs<InlineStrategy>(
      idx,
      static_cast<InlineStrategy>(g_target_properties[idx].default_uint_value));
}

// Returning RealpathPrefixes, but the setting's type is FileSpecList. We do
// this because we want the FileSpecList to normalize the file paths for us.
RealpathPrefixes TargetProperties::GetSourceRealpathPrefixes() const {
  const uint32_t idx = ePropertySourceRealpathPrefixes;
  return RealpathPrefixes(GetPropertyAtIndexAs<FileSpecList>(idx, {}));
}

llvm::StringRef TargetProperties::GetArg0() const {
  const uint32_t idx = ePropertyArg0;
  return GetPropertyAtIndexAs<llvm::StringRef>(
      idx, g_target_properties[idx].default_cstr_value);
}

void TargetProperties::SetArg0(llvm::StringRef arg) {
  const uint32_t idx = ePropertyArg0;
  SetPropertyAtIndex(idx, arg);
  m_launch_info.SetArg0(arg);
}

bool TargetProperties::GetRunArguments(Args &args) const {
  const uint32_t idx = ePropertyRunArgs;
  return m_collection_sp->GetPropertyAtIndexAsArgs(idx, args);
}

void TargetProperties::SetRunArguments(const Args &args) {
  const uint32_t idx = ePropertyRunArgs;
  m_collection_sp->SetPropertyAtIndexFromArgs(idx, args);
  m_launch_info.GetArguments() = args;
}

Environment TargetProperties::ComputeEnvironment() const {
  Environment env;

  if (m_target &&
      GetPropertyAtIndexAs<bool>(
          ePropertyInheritEnv,
          g_target_properties[ePropertyInheritEnv].default_uint_value != 0)) {
    if (auto platform_sp = m_target->GetPlatform()) {
      Environment platform_env = platform_sp->GetEnvironment();
      for (const auto &KV : platform_env)
        env[KV.first()] = KV.second;
    }
  }

  Args property_unset_env;
  m_collection_sp->GetPropertyAtIndexAsArgs(ePropertyUnsetEnvVars,
                                            property_unset_env);
  for (const auto &var : property_unset_env)
    env.erase(var.ref());

  Args property_env;
  m_collection_sp->GetPropertyAtIndexAsArgs(ePropertyEnvVars, property_env);
  for (const auto &KV : Environment(property_env))
    env[KV.first()] = KV.second;

  return env;
}

Environment TargetProperties::GetEnvironment() const {
  return ComputeEnvironment();
}

Environment TargetProperties::GetInheritedEnvironment() const {
  Environment environment;

  if (m_target == nullptr)
    return environment;

  if (!GetPropertyAtIndexAs<bool>(
          ePropertyInheritEnv,
          g_target_properties[ePropertyInheritEnv].default_uint_value != 0))
    return environment;

  PlatformSP platform_sp = m_target->GetPlatform();
  if (platform_sp == nullptr)
    return environment;

  Environment platform_environment = platform_sp->GetEnvironment();
  for (const auto &KV : platform_environment)
    environment[KV.first()] = KV.second;

  Args property_unset_environment;
  m_collection_sp->GetPropertyAtIndexAsArgs(ePropertyUnsetEnvVars,
                                            property_unset_environment);
  for (const auto &var : property_unset_environment)
    environment.erase(var.ref());

  return environment;
}

Environment TargetProperties::GetTargetEnvironment() const {
  Args property_environment;
  m_collection_sp->GetPropertyAtIndexAsArgs(ePropertyEnvVars,
                                            property_environment);
  Environment environment;
  for (const auto &KV : Environment(property_environment))
    environment[KV.first()] = KV.second;

  return environment;
}

void TargetProperties::SetEnvironment(Environment env) {
  // TODO: Get rid of the Args intermediate step
  const uint32_t idx = ePropertyEnvVars;
  m_collection_sp->SetPropertyAtIndexFromArgs(idx, Args(env));
}

bool TargetProperties::GetSkipPrologue() const {
  const uint32_t idx = ePropertySkipPrologue;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

PathMappingList &TargetProperties::GetSourcePathMap() const {
  const uint32_t idx = ePropertySourceMap;
  OptionValuePathMappings *option_value =
      m_collection_sp->GetPropertyAtIndexAsOptionValuePathMappings(idx);
  assert(option_value);
  return option_value->GetCurrentValue();
}

PathMappingList &TargetProperties::GetObjectPathMap() const {
  const uint32_t idx = ePropertyObjectMap;
  OptionValuePathMappings *option_value =
      m_collection_sp->GetPropertyAtIndexAsOptionValuePathMappings(idx);
  assert(option_value);
  return option_value->GetCurrentValue();
}

bool TargetProperties::GetAutoSourceMapRelative() const {
  const uint32_t idx = ePropertyAutoSourceMapRelative;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

void TargetProperties::AppendExecutableSearchPaths(const FileSpec &dir) {
  const uint32_t idx = ePropertyExecutableSearchPaths;
  OptionValueFileSpecList *option_value =
      m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(idx);
  assert(option_value);
  option_value->AppendCurrentValue(dir);
}

FileSpecList TargetProperties::GetExecutableSearchPaths() {
  const uint32_t idx = ePropertyExecutableSearchPaths;
  return GetPropertyAtIndexAs<FileSpecList>(idx, {});
}

FileSpecList TargetProperties::GetDebugFileSearchPaths() {
  const uint32_t idx = ePropertyDebugFileSearchPaths;
  return GetPropertyAtIndexAs<FileSpecList>(idx, {});
}

FileSpecList TargetProperties::GetClangModuleSearchPaths() {
  const uint32_t idx = ePropertyClangModuleSearchPaths;
  return GetPropertyAtIndexAs<FileSpecList>(idx, {});
}

bool TargetProperties::GetEnableAutoImportClangModules() const {
  const uint32_t idx = ePropertyAutoImportClangModules;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

ImportStdModule TargetProperties::GetImportStdModule() const {
  const uint32_t idx = ePropertyImportStdModule;
  return GetPropertyAtIndexAs<ImportStdModule>(
      idx, static_cast<ImportStdModule>(
               g_target_properties[idx].default_uint_value));
}

DynamicClassInfoHelper TargetProperties::GetDynamicClassInfoHelper() const {
  const uint32_t idx = ePropertyDynamicClassInfoHelper;
  return GetPropertyAtIndexAs<DynamicClassInfoHelper>(
      idx, static_cast<DynamicClassInfoHelper>(
               g_target_properties[idx].default_uint_value));
}

bool TargetProperties::GetEnableAutoApplyFixIts() const {
  const uint32_t idx = ePropertyAutoApplyFixIts;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

uint64_t TargetProperties::GetNumberOfRetriesWithFixits() const {
  const uint32_t idx = ePropertyRetriesWithFixIts;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_target_properties[idx].default_uint_value);
}

bool TargetProperties::GetEnableNotifyAboutFixIts() const {
  const uint32_t idx = ePropertyNotifyAboutFixIts;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

FileSpec TargetProperties::GetSaveJITObjectsDir() const {
  const uint32_t idx = ePropertySaveObjectsDir;
  return GetPropertyAtIndexAs<FileSpec>(idx, {});
}

JITEngine TargetProperties::GetJITEngine() const {
  const uint32_t idx = ePropertyJITEngine;
  return GetPropertyAtIndexAs<JITEngine>(
      idx, static_cast<JITEngine>(g_target_properties[idx].default_uint_value));
}

void TargetProperties::CheckJITObjectsDir() {
  FileSpec new_dir = GetSaveJITObjectsDir();
  if (!new_dir)
    return;

  const FileSystem &instance = FileSystem::Instance();
  bool exists = instance.Exists(new_dir);
  bool is_directory = instance.IsDirectory(new_dir);
  std::string path = new_dir.GetPath(true);
  bool writable = llvm::sys::fs::can_write(path);
  if (exists && is_directory && writable)
    return;

  m_collection_sp->GetPropertyAtIndex(ePropertySaveObjectsDir)
      ->GetValue()
      ->Clear();

  std::string buffer;
  llvm::raw_string_ostream os(buffer);
  os << "JIT object dir '" << path << "' ";
  if (!exists)
    os << "does not exist";
  else if (!is_directory)
    os << "is not a directory";
  else if (!writable)
    os << "is not writable";

  std::optional<lldb::user_id_t> debugger_id;
  if (m_target)
    debugger_id = m_target->GetDebugger().GetID();
  Debugger::ReportError(buffer, debugger_id);
}

bool TargetProperties::GetEnableSyntheticValue() const {
  const uint32_t idx = ePropertyEnableSynthetic;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

bool TargetProperties::ShowHexVariableValuesWithLeadingZeroes() const {
  const uint32_t idx = ePropertyShowHexVariableValuesWithLeadingZeroes;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

uint32_t TargetProperties::GetMaxZeroPaddingInFloatFormat() const {
  const uint32_t idx = ePropertyMaxZeroPaddingInFloatFormat;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_target_properties[idx].default_uint_value);
}

uint32_t TargetProperties::GetMaximumNumberOfChildrenToDisplay() const {
  const uint32_t idx = ePropertyMaxChildrenCount;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_target_properties[idx].default_uint_value);
}

std::pair<uint32_t, bool>
TargetProperties::GetMaximumDepthOfChildrenToDisplay() const {
  const uint32_t idx = ePropertyMaxChildrenDepth;
  auto *option_value =
      m_collection_sp->GetPropertyAtIndexAsOptionValueUInt64(idx);
  bool is_default = !option_value->OptionWasSet();
  return {option_value->GetCurrentValue(), is_default};
}

uint32_t TargetProperties::GetMaximumSizeOfStringSummary() const {
  const uint32_t idx = ePropertyMaxSummaryLength;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_target_properties[idx].default_uint_value);
}

uint32_t TargetProperties::GetMaximumMemReadSize() const {
  const uint32_t idx = ePropertyMaxMemReadSize;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_target_properties[idx].default_uint_value);
}

FileSpec TargetProperties::GetStandardInputPath() const {
  const uint32_t idx = ePropertyInputPath;
  return GetPropertyAtIndexAs<FileSpec>(idx, {});
}

void TargetProperties::SetStandardInputPath(llvm::StringRef path) {
  const uint32_t idx = ePropertyInputPath;
  SetPropertyAtIndex(idx, path);
}

FileSpec TargetProperties::GetStandardOutputPath() const {
  const uint32_t idx = ePropertyOutputPath;
  return GetPropertyAtIndexAs<FileSpec>(idx, {});
}

void TargetProperties::SetStandardOutputPath(llvm::StringRef path) {
  const uint32_t idx = ePropertyOutputPath;
  SetPropertyAtIndex(idx, path);
}

FileSpec TargetProperties::GetStandardErrorPath() const {
  const uint32_t idx = ePropertyErrorPath;
  return GetPropertyAtIndexAs<FileSpec>(idx, {});
}

void TargetProperties::SetStandardErrorPath(llvm::StringRef path) {
  const uint32_t idx = ePropertyErrorPath;
  SetPropertyAtIndex(idx, path);
}

SourceLanguage TargetProperties::GetLanguage() const {
  const uint32_t idx = ePropertyLanguage;
  return SourceLanguage{GetPropertyAtIndexAs<LanguageType>(idx, {})};
}

llvm::StringRef TargetProperties::GetExpressionPrefixContents() {
  const uint32_t idx = ePropertyExprPrefix;
  OptionValueFileSpec *file =
      m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpec(idx);
  if (file) {
    DataBufferSP data_sp(file->GetFileContents());
    if (data_sp)
      return llvm::StringRef(
          reinterpret_cast<const char *>(data_sp->GetBytes()),
          data_sp->GetByteSize());
  }
  return "";
}

uint64_t TargetProperties::GetExprErrorLimit() const {
  const uint32_t idx = ePropertyExprErrorLimit;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_target_properties[idx].default_uint_value);
}

uint64_t TargetProperties::GetExprAllocAddress() const {
  const uint32_t idx = ePropertyExprAllocAddress;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_target_properties[idx].default_uint_value);
}

uint64_t TargetProperties::GetExprAllocSize() const {
  const uint32_t idx = ePropertyExprAllocSize;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_target_properties[idx].default_uint_value);
}

uint64_t TargetProperties::GetExprAllocAlign() const {
  const uint32_t idx = ePropertyExprAllocAlign;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_target_properties[idx].default_uint_value);
}

bool TargetProperties::GetBreakpointsConsultPlatformAvoidList() {
  const uint32_t idx = ePropertyBreakpointUseAvoidList;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

BreakpointConditionMode TargetProperties::GetBreakpointsConditionMode() const {
  const uint32_t idx = ePropertyBreakpointsConditionMode;
  return GetPropertyAtIndexAs<BreakpointConditionMode>(
      idx, static_cast<BreakpointConditionMode>(
               g_target_properties[idx].default_uint_value));
}

bool TargetProperties::GetUseHexImmediates() const {
  const uint32_t idx = ePropertyUseHexImmediates;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

bool TargetProperties::GetUseFastStepping() const {
  const uint32_t idx = ePropertyUseFastStepping;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

bool TargetProperties::GetDisplayExpressionsInCrashlogs() const {
  const uint32_t idx = ePropertyDisplayExpressionsInCrashlogs;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

LoadScriptFromSymFile TargetProperties::GetLoadScriptFromSymbolFile() const {
  const uint32_t idx = ePropertyLoadScriptFromSymbolFile;
  return GetPropertyAtIndexAs<LoadScriptFromSymFile>(
      idx, static_cast<LoadScriptFromSymFile>(
               g_target_properties[idx].default_uint_value));
}

void TargetProperties::SetLoadScriptFromSymbolFile(
    LoadScriptFromSymFile load_style) {
  const uint32_t idx = ePropertyLoadScriptFromSymbolFile;
  SetPropertyAtIndex(idx, load_style);
}

LoadCWDlldbinitFile TargetProperties::GetLoadCWDlldbinitFile() const {
  const uint32_t idx = ePropertyLoadCWDlldbinitFile;
  return GetPropertyAtIndexAs<LoadCWDlldbinitFile>(
      idx, static_cast<LoadCWDlldbinitFile>(
               g_target_properties[idx].default_uint_value));
}

Disassembler::HexImmediateStyle TargetProperties::GetHexImmediateStyle() const {
  const uint32_t idx = ePropertyHexImmediateStyle;
  return GetPropertyAtIndexAs<Disassembler::HexImmediateStyle>(
      idx, static_cast<Disassembler::HexImmediateStyle>(
               g_target_properties[idx].default_uint_value));
}

MemoryModuleLoadLevel TargetProperties::GetMemoryModuleLoadLevel() const {
  const uint32_t idx = ePropertyMemoryModuleLoadLevel;
  return GetPropertyAtIndexAs<MemoryModuleLoadLevel>(
      idx, static_cast<MemoryModuleLoadLevel>(
               g_target_properties[idx].default_uint_value));
}

bool TargetProperties::GetUserSpecifiedTrapHandlerNames(Args &args) const {
  const uint32_t idx = ePropertyTrapHandlerNames;
  return m_collection_sp->GetPropertyAtIndexAsArgs(idx, args);
}

void TargetProperties::SetUserSpecifiedTrapHandlerNames(const Args &args) {
  const uint32_t idx = ePropertyTrapHandlerNames;
  m_collection_sp->SetPropertyAtIndexFromArgs(idx, args);
}

bool TargetProperties::GetDisplayRuntimeSupportValues() const {
  const uint32_t idx = ePropertyDisplayRuntimeSupportValues;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

void TargetProperties::SetDisplayRuntimeSupportValues(bool b) {
  const uint32_t idx = ePropertyDisplayRuntimeSupportValues;
  SetPropertyAtIndex(idx, b);
}

bool TargetProperties::GetDisplayRecognizedArguments() const {
  const uint32_t idx = ePropertyDisplayRecognizedArguments;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

void TargetProperties::SetDisplayRecognizedArguments(bool b) {
  const uint32_t idx = ePropertyDisplayRecognizedArguments;
  SetPropertyAtIndex(idx, b);
}

const ProcessLaunchInfo &TargetProperties::GetProcessLaunchInfo() const {
  return m_launch_info;
}

void TargetProperties::SetProcessLaunchInfo(
    const ProcessLaunchInfo &launch_info) {
  m_launch_info = launch_info;
  SetArg0(launch_info.GetArg0());
  SetRunArguments(launch_info.GetArguments());
  SetEnvironment(launch_info.GetEnvironment());
  const FileAction *input_file_action =
      launch_info.GetFileActionForFD(STDIN_FILENO);
  if (input_file_action) {
    SetStandardInputPath(input_file_action->GetFileSpec().GetPath());
  }
  const FileAction *output_file_action =
      launch_info.GetFileActionForFD(STDOUT_FILENO);
  if (output_file_action) {
    SetStandardOutputPath(output_file_action->GetFileSpec().GetPath());
  }
  const FileAction *error_file_action =
      launch_info.GetFileActionForFD(STDERR_FILENO);
  if (error_file_action) {
    SetStandardErrorPath(error_file_action->GetFileSpec().GetPath());
  }
  SetDetachOnError(launch_info.GetFlags().Test(lldb::eLaunchFlagDetachOnError));
  SetDisableASLR(launch_info.GetFlags().Test(lldb::eLaunchFlagDisableASLR));
  SetInheritTCC(
      launch_info.GetFlags().Test(lldb::eLaunchFlagInheritTCCFromParent));
  SetDisableSTDIO(launch_info.GetFlags().Test(lldb::eLaunchFlagDisableSTDIO));
}

bool TargetProperties::GetRequireHardwareBreakpoints() const {
  const uint32_t idx = ePropertyRequireHardwareBreakpoints;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

void TargetProperties::SetRequireHardwareBreakpoints(bool b) {
  const uint32_t idx = ePropertyRequireHardwareBreakpoints;
  m_collection_sp->SetPropertyAtIndex(idx, b);
}

bool TargetProperties::GetAutoInstallMainExecutable() const {
  const uint32_t idx = ePropertyAutoInstallMainExecutable;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

void TargetProperties::Arg0ValueChangedCallback() {
  m_launch_info.SetArg0(GetArg0());
}

void TargetProperties::RunArgsValueChangedCallback() {
  Args args;
  if (GetRunArguments(args))
    m_launch_info.GetArguments() = args;
}

void TargetProperties::EnvVarsValueChangedCallback() {
  m_launch_info.GetEnvironment() = ComputeEnvironment();
}

void TargetProperties::InputPathValueChangedCallback() {
  m_launch_info.AppendOpenFileAction(STDIN_FILENO, GetStandardInputPath(), true,
                                     false);
}

void TargetProperties::OutputPathValueChangedCallback() {
  m_launch_info.AppendOpenFileAction(STDOUT_FILENO, GetStandardOutputPath(),
                                     false, true);
}

void TargetProperties::ErrorPathValueChangedCallback() {
  m_launch_info.AppendOpenFileAction(STDERR_FILENO, GetStandardErrorPath(),
                                     false, true);
}

void TargetProperties::DetachOnErrorValueChangedCallback() {
  if (GetDetachOnError())
    m_launch_info.GetFlags().Set(lldb::eLaunchFlagDetachOnError);
  else
    m_launch_info.GetFlags().Clear(lldb::eLaunchFlagDetachOnError);
}

void TargetProperties::DisableASLRValueChangedCallback() {
  if (GetDisableASLR())
    m_launch_info.GetFlags().Set(lldb::eLaunchFlagDisableASLR);
  else
    m_launch_info.GetFlags().Clear(lldb::eLaunchFlagDisableASLR);
}

void TargetProperties::InheritTCCValueChangedCallback() {
  if (GetInheritTCC())
    m_launch_info.GetFlags().Set(lldb::eLaunchFlagInheritTCCFromParent);
  else
    m_launch_info.GetFlags().Clear(lldb::eLaunchFlagInheritTCCFromParent);
}

void TargetProperties::DisableSTDIOValueChangedCallback() {
  if (GetDisableSTDIO())
    m_launch_info.GetFlags().Set(lldb::eLaunchFlagDisableSTDIO);
  else
    m_launch_info.GetFlags().Clear(lldb::eLaunchFlagDisableSTDIO);
}

bool TargetProperties::GetDebugUtilityExpression() const {
  const uint32_t idx = ePropertyDebugUtilityExpression;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

void TargetProperties::SetDebugUtilityExpression(bool debug) {
  const uint32_t idx = ePropertyDebugUtilityExpression;
  SetPropertyAtIndex(idx, debug);
}

bool TargetProperties::GetCheckValueObjectOwnership() const {
  const uint32_t idx = ePropertyCheckValueObjectOwnership;
  return GetPropertyAtIndexAs<bool>(
      idx, g_target_properties[idx].default_uint_value != 0);
}

void TargetProperties::SetCheckValueObjectOwnership(bool check) {
  const uint32_t idx = ePropertyCheckValueObjectOwnership;
  SetPropertyAtIndex(idx, check);
}

std::optional<LoadScriptFromSymFile>
TargetProperties::GetAutoLoadScriptsForModule(
    llvm::StringRef module_name) const {
  auto *dict = m_collection_sp->GetPropertyAtIndexAsOptionValueDictionary(
      ePropertyAutoLoadScriptsForModules);
  if (!dict)
    return std::nullopt;

  OptionValueSP value_sp = dict->GetValueForKey(module_name);
  if (!value_sp)
    return std::nullopt;

  return value_sp->GetValueAs<LoadScriptFromSymFile>();
}

void TargetProperties::SetAutoLoadScriptsForModule(
    llvm::StringRef module_name, LoadScriptFromSymFile load_style) {
  auto *dict = m_collection_sp->GetPropertyAtIndexAsOptionValueDictionary(
      ePropertyAutoLoadScriptsForModules);
  if (!dict)
    return;

  dict->SetValueForKey(module_name,
                       std::make_shared<OptionValueEnumeration>(
                           g_load_script_from_sym_file_values, load_style));
}

// Target::TargetEventData

Target::TargetEventData::TargetEventData(const lldb::TargetSP &target_sp)
    : EventData(), m_target_sp(target_sp), m_module_list() {}

Target::TargetEventData::TargetEventData(const lldb::TargetSP &target_sp,
                                         const ModuleList &module_list)
    : EventData(), m_target_sp(target_sp), m_module_list(module_list) {}

Target::TargetEventData::TargetEventData(
    const lldb::TargetSP &target_sp, const lldb::TargetSP &created_target_sp)
    : EventData(), m_target_sp(target_sp),
      m_created_target_sp(created_target_sp), m_module_list() {}

Target::TargetEventData::~TargetEventData() = default;

llvm::StringRef Target::TargetEventData::GetFlavorString() {
  return "Target::TargetEventData";
}

void Target::TargetEventData::Dump(Stream *s) const {
  for (size_t i = 0; i < m_module_list.GetSize(); ++i) {
    if (i != 0)
      *s << ", ";
    m_module_list.GetModuleAtIndex(i)->GetDescription(
        s->AsRawOstream(), lldb::eDescriptionLevelBrief);
  }
}

const Target::TargetEventData *
Target::TargetEventData::GetEventDataFromEvent(const Event *event_ptr) {
  if (event_ptr) {
    const EventData *event_data = event_ptr->GetData();
    if (event_data &&
        event_data->GetFlavor() == TargetEventData::GetFlavorString())
      return static_cast<const TargetEventData *>(event_ptr->GetData());
  }
  return nullptr;
}

TargetSP Target::TargetEventData::GetTargetFromEvent(const Event *event_ptr) {
  TargetSP target_sp;
  const TargetEventData *event_data = GetEventDataFromEvent(event_ptr);
  if (event_data)
    target_sp = event_data->m_target_sp;
  return target_sp;
}

TargetSP
Target::TargetEventData::GetCreatedTargetFromEvent(const Event *event_ptr) {
  TargetSP created_target_sp;
  const TargetEventData *event_data = GetEventDataFromEvent(event_ptr);
  if (event_data)
    created_target_sp = event_data->m_created_target_sp;
  return created_target_sp;
}

ModuleList
Target::TargetEventData::GetModuleListFromEvent(const Event *event_ptr) {
  ModuleList module_list;
  const TargetEventData *event_data = GetEventDataFromEvent(event_ptr);
  if (event_data)
    module_list = event_data->m_module_list;
  return module_list;
}

TargetAPIMutex Target::GetAPIMutex() {
  return TargetAPIMutex(shared_from_this());
}

std::recursive_mutex *Target::GetAPIMutexForCurrentPolicy() {
  Policy policy = PolicyStack::Get().Current();
  if (policy.capabilities.can_bypass_target_api_mutex)
    return nullptr;
  return policy.view == Policy::View::Private ? &m_private_mutex : &m_mutex;
}

/// Get metrics associated with this target in JSON format.
llvm::json::Value
Target::ReportStatistics(const lldb_private::StatisticsOptions &options) {
  return m_stats.ToJSON(*this, options);
}

void Target::ResetStatistics() { m_stats.Reset(*this); }

bool Target::HasLoadedSections() { return !GetSectionLoadList().IsEmpty(); }

lldb::addr_t Target::GetSectionLoadAddress(const lldb::SectionSP &section_sp) {
  return GetSectionLoadList().GetSectionLoadAddress(section_sp);
}

void Target::ClearSectionLoadList() { GetSectionLoadList().Clear(); }

void Target::DumpSectionLoadList(Stream &s) {
  GetSectionLoadList().Dump(s, this);
}

void Target::NotifyBreakpointChanged(Breakpoint &bp,
                                     lldb::BreakpointEventType eventKind) {
  if (EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged)) {
    std::shared_ptr<Breakpoint::BreakpointEventData> data_sp =
        std::make_shared<Breakpoint::BreakpointEventData>(
            eventKind, bp.shared_from_this());
    BroadcastEvent(Target::eBroadcastBitBreakpointChanged, data_sp);
  }
}

void Target::NotifyBreakpointChanged(
    Breakpoint &bp, const lldb::EventDataSP &breakpoint_data_sp) {
  if (EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
    BroadcastEvent(Target::eBroadcastBitBreakpointChanged, breakpoint_data_sp);
}

FileSpecList Target::GetSafeAutoLoadPaths() const {
  FileSpecList fspecs = Debugger::GetDefaultSafeAutoLoadPaths();

  // Add platform-specific safe-paths.
  if (m_platform_sp) {
    if (auto platform_fspecs_or_err =
            m_platform_sp->GetSafeAutoLoadPaths(*this))
      fspecs.Append(*platform_fspecs_or_err);
    else
      LLDB_LOG_ERROR(GetLog(LLDBLog::Modules | LLDBLog::Platform),
                     platform_fspecs_or_err.takeError(),
                     "Skipping safe auto-load: {0}");
  }

  // Properties for testing get added last so they take priority.
#ifndef NDEBUG
  for (const auto &fspec :
       TestingProperties::GetGlobalTestingProperties().GetSafeAutoLoadPaths())
    fspecs.Append(fspec);
#endif

  return fspecs;
}

// FIXME: the language plugin should expression options dynamically and
// we should validate here (by asking the language plugin) that the options
// being set/retrieved are actually valid options.

llvm::Error
EvaluateExpressionOptions::SetBooleanLanguageOption(llvm::StringRef option_name,
                                                    bool value) {
  if (option_name.empty())
    return llvm::createStringError("can't set an option with an empty name");

  if (StructuredData::ObjectSP existing_sp =
          GetLanguageOptions().GetValueForKey(option_name);
      existing_sp && existing_sp->GetType() != eStructuredDataTypeBoolean)
    return llvm::createStringErrorV("trying to override existing option '{0}' "
                                    "of type '{1}' with a boolean value",
                                    option_name, existing_sp->GetType());

  GetLanguageOptions().AddBooleanItem(option_name, value);

  return llvm::Error::success();
}

llvm::Expected<bool> EvaluateExpressionOptions::GetBooleanLanguageOption(
    llvm::StringRef option_name) const {
  const StructuredData::Dictionary &opts = GetLanguageOptions();

  if (!opts.HasKey(option_name))
    return llvm::createStringErrorV("option '{0}' does not exist", option_name);

  bool result;
  if (!opts.GetValueForKeyAsBoolean(option_name, result))
    return llvm::createStringErrorV("failed to get option '{0}' as boolean",
                                    option_name);

  return result;
}

const StructuredData::Dictionary &
EvaluateExpressionOptions::GetLanguageOptions() const {
  assert(m_language_options_sp);

  return *m_language_options_sp;
}

StructuredData::Dictionary &EvaluateExpressionOptions::GetLanguageOptions() {
  assert(m_language_options_sp);

  return *m_language_options_sp;
}

// FIXME: this option is C++ plugin specific and should be registered by it,
// instead of hard-coding it here.
constexpr llvm::StringLiteral s_cpp_ignore_context_qualifiers_option =
    "c++-ignore-context-qualifiers";

EvaluateExpressionOptions::EvaluateExpressionOptions()
    : m_language_options_sp(std::make_shared<StructuredData::Dictionary>()) {
  SetCppIgnoreContextQualifiers(false);
}

void EvaluateExpressionOptions::SetCppIgnoreContextQualifiers(bool value) {
  llvm::cantFail(
      SetBooleanLanguageOption(s_cpp_ignore_context_qualifiers_option, value));
}

bool EvaluateExpressionOptions::GetCppIgnoreContextQualifiers() const {
  return llvm::cantFail(
      GetBooleanLanguageOption(s_cpp_ignore_context_qualifiers_option));
}
