//===-- DynamicLoaderDarwin.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 "DynamicLoaderDarwin.h"

#include "DynamicLoaderDarwinProperties.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.h"
#include "llvm/Support/ThreadPool.h"

#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"

//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
#ifdef ENABLE_DEBUG_PRINTF
#include <cstdio>
#define DEBUG_PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define DEBUG_PRINTF(fmt, ...)
#endif

#include <memory>

using namespace lldb;
using namespace lldb_private;

// Constructor
DynamicLoaderDarwin::DynamicLoaderDarwin(Process *process)
    : DynamicLoader(process), m_dyld_module_wp(), m_libpthread_module_wp(),
      m_pthread_getspecific_addr(), m_tid_to_tls_map(), m_dyld_image_infos(),
      m_dyld_image_infos_stop_id(UINT32_MAX), m_dyld(), m_mutex() {}

// Destructor
DynamicLoaderDarwin::~DynamicLoaderDarwin() = default;

/// Called after attaching a process.
///
/// Allow DynamicLoader plug-ins to execute some code after
/// attaching to a process.
void DynamicLoaderDarwin::DidAttach() {
  PrivateInitialize(m_process);
  DoInitialImageFetch();
  SetNotificationBreakpoint();
}

/// Called after attaching a process.
///
/// Allow DynamicLoader plug-ins to execute some code after
/// attaching to a process.
void DynamicLoaderDarwin::DidLaunch() {
  PrivateInitialize(m_process);
  DoInitialImageFetch();
  SetNotificationBreakpoint();
}

void DynamicLoaderDarwin::CreateSettings(lldb_private::Debugger &debugger) {
  if (!PluginManager::GetSettingForDynamicLoaderPlugin(
          debugger, DynamicLoaderDarwinProperties::GetSettingName())) {
    const bool is_global_setting = true;
    PluginManager::CreateSettingForDynamicLoaderPlugin(
        debugger,
        DynamicLoaderDarwinProperties::GetGlobal().GetValueProperties(),
        "Properties for the DynamicLoaderDarwin plug-in.", is_global_setting);
  }
}

// Clear out the state of this class.
void DynamicLoaderDarwin::Clear(bool clear_process) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  if (clear_process)
    m_process = nullptr;
  m_dyld_image_infos.clear();
  m_dyld_image_infos_stop_id = UINT32_MAX;
  m_dyld.Clear(false);
}

ModuleSP DynamicLoaderDarwin::FindTargetModuleForImageInfo(
    const ImageInfo &image_info, bool can_create, bool *did_create_ptr) {
  if (did_create_ptr)
    *did_create_ptr = false;

  Target &target = m_process->GetTarget();
  const ModuleList &target_images = target.GetImages();
  ModuleSpec module_spec(image_info.file_spec);
  module_spec.GetUUID() = image_info.uuid;

  // macCatalyst support: Request matching os/environment.
  {
    auto &target_triple = target.GetArchitecture().GetTriple();
    if (target_triple.getOS() == llvm::Triple::IOS &&
        target_triple.getEnvironment() == llvm::Triple::MacABI) {
      // Request the macCatalyst variant of frameworks that have both
      // a PLATFORM_MACOS and a PLATFORM_MACCATALYST load command.
      module_spec.GetArchitecture() = ArchSpec(target_triple);
    }
  }

  ModuleSP module_sp(target_images.FindFirstModule(module_spec));

  if (module_sp && !module_spec.GetUUID().IsValid() &&
      !module_sp->GetUUID().IsValid()) {
    // No UUID, we must rely upon the cached module modification time and the
    // modification time of the file on disk
    if (module_sp->GetModificationTime() !=
        FileSystem::Instance().GetModificationTime(module_sp->GetFileSpec()))
      module_sp.reset();
  }

  if (module_sp || !can_create)
    return module_sp;

  if (HostInfo::GetArchitecture().IsCompatibleMatch(target.GetArchitecture())) {
    // When debugging on the host, we are most likely using the same shared
    // cache as our inferior. The dylibs from the shared cache might not
    // exist on the filesystem, so let's use the images in our own memory
    // to create the modules.
    // Check if the requested image is in our shared cache.
    SharedCacheImageInfo image_info =
        HostInfo::GetSharedCacheImageInfo(module_spec.GetFileSpec().GetPath());

    // If we found it and it has the correct UUID, let's proceed with
    // creating a module from the memory contents.
    if (image_info.uuid &&
        (!module_spec.GetUUID() || module_spec.GetUUID() == image_info.uuid)) {
      ModuleSpec shared_cache_spec(module_spec.GetFileSpec(), image_info.uuid,
                                   image_info.data_sp);
      module_sp =
          target.GetOrCreateModule(shared_cache_spec, false /* notify */);
    }
  }
  // We'll call Target::ModulesDidLoad after all the modules have been
  // added to the target, don't let it be called for every one.
  if (!module_sp)
    module_sp = target.GetOrCreateModule(module_spec, false /* notify */);
  if (!module_sp || module_sp->GetObjectFile() == nullptr)
    module_sp = m_process->ReadModuleFromMemory(image_info.file_spec,
                                                image_info.address);

  if (did_create_ptr)
    *did_create_ptr = (bool)module_sp;

  return module_sp;
}

void DynamicLoaderDarwin::UnloadImages(
    const std::vector<lldb::addr_t> &solib_addresses) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
    return;

  Log *log = GetLog(LLDBLog::DynamicLoader);
  Target &target = m_process->GetTarget();
  LLDB_LOGF(log, "Removing %" PRId64 " modules.",
            (uint64_t)solib_addresses.size());

  ModuleList unloaded_module_list;

  for (addr_t solib_addr : solib_addresses) {
    Address header;
    if (header.SetLoadAddress(solib_addr, &target)) {
      if (header.GetOffset() == 0) {
        ModuleSP module_to_remove(header.GetModule());
        if (module_to_remove.get()) {
          LLDB_LOGF(log, "Removing module at address 0x%" PRIx64, solib_addr);
          // remove the sections from the Target
          UnloadSections(module_to_remove);
          // add this to the list of modules to remove
          unloaded_module_list.AppendIfNeeded(module_to_remove);
          // remove the entry from the m_dyld_image_infos
          ImageInfo::collection::iterator pos, end = m_dyld_image_infos.end();
          for (pos = m_dyld_image_infos.begin(); pos != end; pos++) {
            if (solib_addr == (*pos).address) {
              m_dyld_image_infos.erase(pos);
              break;
            }
          }
        }
      }
    }
  }

  if (unloaded_module_list.GetSize() > 0) {
    if (log) {
      log->PutCString("Unloaded:");
      unloaded_module_list.LogUUIDAndPaths(
          log, "DynamicLoaderDarwin::UnloadModules");
    }
    m_process->GetTarget().GetImages().Remove(unloaded_module_list);
    m_dyld_image_infos_stop_id = m_process->GetStopID();
  }
}

void DynamicLoaderDarwin::UnloadAllImages() {
  Log *log = GetLog(LLDBLog::DynamicLoader);
  ModuleList unloaded_modules_list;

  Target &target = m_process->GetTarget();
  const ModuleList &target_modules = target.GetImages();
  std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());

  ModuleSP dyld_sp(GetDYLDModule());
  for (ModuleSP module_sp : target_modules.Modules()) {
    // Don't remove dyld - else we'll lose our breakpoint notifying us about
    // libraries being re-loaded...
    if (module_sp && module_sp != dyld_sp) {
      UnloadSections(module_sp);
      unloaded_modules_list.Append(module_sp);
    }
  }

  if (unloaded_modules_list.GetSize() != 0) {
    if (log) {
      log->PutCString("Unloaded:");
      unloaded_modules_list.LogUUIDAndPaths(
          log, "DynamicLoaderDarwin::UnloadAllImages");
    }
    target.GetImages().Remove(unloaded_modules_list);
    m_dyld_image_infos.clear();
    m_dyld_image_infos_stop_id = m_process->GetStopID();
  }
}

// Update the load addresses for all segments in MODULE using the updated INFO
// that is passed in.
bool DynamicLoaderDarwin::UpdateImageLoadAddress(Module *module,
                                                 ImageInfo &info) {
  bool changed = false;
  if (module) {
    ObjectFile *image_object_file = module->GetObjectFile();
    if (image_object_file) {
      SectionList *section_list = image_object_file->GetSectionList();
      if (section_list) {
        std::vector<uint32_t> inaccessible_segment_indexes;
        // We now know the slide amount, so go through all sections and update
        // the load addresses with the correct values.
        const size_t num_segments = info.segments.size();
        for (size_t i = 0; i < num_segments; ++i) {
          // Only load a segment if it has protections. Things like __PAGEZERO
          // don't have any protections, and they shouldn't be slid
          SectionSP section_sp(
              section_list->FindSectionByName(info.segments[i].name));

          if (info.segments[i].maxprot == 0) {
            inaccessible_segment_indexes.push_back(i);
          } else {
            const addr_t new_section_load_addr =
                info.segments[i].vmaddr + info.slide;
            static ConstString g_section_name_LINKEDIT("__LINKEDIT");

            if (section_sp) {
              // __LINKEDIT sections from files in the shared cache can overlap
              // so check to see what the segment name is and pass "false" so
              // we don't warn of overlapping "Section" objects, and "true" for
              // all other sections.
              const bool warn_multiple =
                  section_sp->GetName() != g_section_name_LINKEDIT;

              changed = m_process->GetTarget().SetSectionLoadAddress(
                  section_sp, new_section_load_addr, warn_multiple);
            }
          }
        }

        // If the loaded the file (it changed) and we have segments that are
        // not readable or writeable, add them to the invalid memory region
        // cache for the process. This will typically only be the __PAGEZERO
        // segment in the main executable. We might be able to apply this more
        // generally to more sections that have no protections in the future,
        // but for now we are going to just do __PAGEZERO.
        if (changed && !inaccessible_segment_indexes.empty()) {
          for (uint32_t i = 0; i < inaccessible_segment_indexes.size(); ++i) {
            const uint32_t seg_idx = inaccessible_segment_indexes[i];
            SectionSP section_sp(
                section_list->FindSectionByName(info.segments[seg_idx].name));

            if (section_sp) {
              static ConstString g_pagezero_section_name("__PAGEZERO");
              if (g_pagezero_section_name == section_sp->GetName()) {
                // __PAGEZERO never slides...
                const lldb::addr_t vmaddr = info.segments[seg_idx].vmaddr;
                const lldb::addr_t vmsize = info.segments[seg_idx].vmsize;
                Process::LoadRange pagezero_range(vmaddr, vmsize);
                m_process->AddInvalidMemoryRegion(pagezero_range);
              }
            }
          }
        }
      }
    }
  }
  // We might have an in memory image that was loaded as soon as it was created
  if (info.load_stop_id == m_process->GetStopID())
    changed = true;
  else if (changed) {
    // Update the stop ID when this library was updated
    info.load_stop_id = m_process->GetStopID();
  }
  return changed;
}

// Unload the segments in MODULE using the INFO that is passed in.
bool DynamicLoaderDarwin::UnloadModuleSections(Module *module,
                                               ImageInfo &info) {
  bool changed = false;
  if (module) {
    ObjectFile *image_object_file = module->GetObjectFile();
    if (image_object_file) {
      SectionList *section_list = image_object_file->GetSectionList();
      if (section_list) {
        const size_t num_segments = info.segments.size();
        for (size_t i = 0; i < num_segments; ++i) {
          SectionSP section_sp(
              section_list->FindSectionByName(info.segments[i].name));
          if (section_sp) {
            const addr_t old_section_load_addr =
                info.segments[i].vmaddr + info.slide;
            if (m_process->GetTarget().SetSectionUnloaded(
                    section_sp, old_section_load_addr))
              changed = true;
          } else {
            Debugger::ReportWarning(
                llvm::formatv("unable to find and unload segment named "
                              "'{0}' in '{1}' in macosx dynamic loader plug-in",
                              info.segments[i].name.AsCString("<invalid>"),
                              image_object_file->GetFileSpec().GetPath()));
          }
        }
      }
    }
  }
  return changed;
}

// Given a JSON dictionary (from debugserver, most likely) of binary images
// loaded in the inferior process, add the images to the ImageInfo collection.

bool DynamicLoaderDarwin::JSONImageInformationIntoImageInfo(
    StructuredData::ObjectSP image_details,
    ImageInfo::collection &image_infos) {
  StructuredData::ObjectSP images_sp =
      image_details->GetAsDictionary()->GetValueForKey("images");
  if (images_sp.get() == nullptr)
    return false;

  image_infos.resize(images_sp->GetAsArray()->GetSize());

  for (size_t i = 0; i < image_infos.size(); i++) {
    StructuredData::ObjectSP image_sp =
        images_sp->GetAsArray()->GetItemAtIndex(i);
    if (image_sp.get() == nullptr || image_sp->GetAsDictionary() == nullptr)
      return false;
    StructuredData::Dictionary *image = image_sp->GetAsDictionary();
    // clang-format off
    if (!image->HasKey("load_address") ||
        !image->HasKey("pathname") ||
        !image->HasKey("mach_header") ||
        image->GetValueForKey("mach_header")->GetAsDictionary() == nullptr ||
        !image->HasKey("segments") ||
        image->GetValueForKey("segments")->GetAsArray() == nullptr ||
        !image->HasKey("uuid")) {
      return false;
    }
    // clang-format on
    image_infos[i].address =
        image->GetValueForKey("load_address")->GetUnsignedIntegerValue();
    image_infos[i].file_spec.SetFile(
        image->GetValueForKey("pathname")->GetAsString()->GetValue(),
        FileSpec::Style::native);

    StructuredData::Dictionary *mh =
        image->GetValueForKey("mach_header")->GetAsDictionary();
    image_infos[i].header.magic =
        mh->GetValueForKey("magic")->GetUnsignedIntegerValue();
    image_infos[i].header.cputype =
        mh->GetValueForKey("cputype")->GetUnsignedIntegerValue();
    image_infos[i].header.cpusubtype =
        mh->GetValueForKey("cpusubtype")->GetUnsignedIntegerValue();
    image_infos[i].header.filetype =
        mh->GetValueForKey("filetype")->GetUnsignedIntegerValue();

    if (image->HasKey("min_version_os_name")) {
      std::string os_name =
          std::string(image->GetValueForKey("min_version_os_name")
                          ->GetAsString()
                          ->GetValue());
      if (os_name == "macosx")
        image_infos[i].os_type = llvm::Triple::MacOSX;
      else if (os_name == "ios" || os_name == "iphoneos")
        image_infos[i].os_type = llvm::Triple::IOS;
      else if (os_name == "tvos")
        image_infos[i].os_type = llvm::Triple::TvOS;
      else if (os_name == "watchos")
        image_infos[i].os_type = llvm::Triple::WatchOS;
      else if (os_name == "bridgeos")
        image_infos[i].os_type = llvm::Triple::BridgeOS;
      else if (os_name == "maccatalyst") {
        image_infos[i].os_type = llvm::Triple::IOS;
        image_infos[i].os_env = llvm::Triple::MacABI;
      } else if (os_name == "iossimulator") {
        image_infos[i].os_type = llvm::Triple::IOS;
        image_infos[i].os_env = llvm::Triple::Simulator;
      } else if (os_name == "tvossimulator") {
        image_infos[i].os_type = llvm::Triple::TvOS;
        image_infos[i].os_env = llvm::Triple::Simulator;
      } else if (os_name == "watchossimulator") {
        image_infos[i].os_type = llvm::Triple::WatchOS;
        image_infos[i].os_env = llvm::Triple::Simulator;
      }
    }
    if (image->HasKey("min_version_os_sdk")) {
      image_infos[i].min_version_os_sdk =
          std::string(image->GetValueForKey("min_version_os_sdk")
                          ->GetAsString()
                          ->GetValue());
    }

    // Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't
    // currently send them in the reply.

    if (mh->HasKey("flags"))
      image_infos[i].header.flags =
          mh->GetValueForKey("flags")->GetUnsignedIntegerValue();
    else
      image_infos[i].header.flags = 0;

    if (mh->HasKey("ncmds"))
      image_infos[i].header.ncmds =
          mh->GetValueForKey("ncmds")->GetUnsignedIntegerValue();
    else
      image_infos[i].header.ncmds = 0;

    if (mh->HasKey("sizeofcmds"))
      image_infos[i].header.sizeofcmds =
          mh->GetValueForKey("sizeofcmds")->GetUnsignedIntegerValue();
    else
      image_infos[i].header.sizeofcmds = 0;

    StructuredData::Array *segments =
        image->GetValueForKey("segments")->GetAsArray();
    uint32_t segcount = segments->GetSize();
    for (size_t j = 0; j < segcount; j++) {
      Segment segment;
      StructuredData::Dictionary *seg =
          segments->GetItemAtIndex(j)->GetAsDictionary();
      segment.name =
          ConstString(seg->GetValueForKey("name")->GetAsString()->GetValue());
      segment.vmaddr = seg->GetValueForKey("vmaddr")->GetUnsignedIntegerValue();
      segment.vmsize = seg->GetValueForKey("vmsize")->GetUnsignedIntegerValue();
      segment.fileoff =
          seg->GetValueForKey("fileoff")->GetUnsignedIntegerValue();
      segment.filesize =
          seg->GetValueForKey("filesize")->GetUnsignedIntegerValue();
      segment.maxprot =
          seg->GetValueForKey("maxprot")->GetUnsignedIntegerValue();

      // Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't
      // currently send them in the reply.

      if (seg->HasKey("initprot"))
        segment.initprot =
            seg->GetValueForKey("initprot")->GetUnsignedIntegerValue();
      else
        segment.initprot = 0;

      if (seg->HasKey("flags"))
        segment.flags = seg->GetValueForKey("flags")->GetUnsignedIntegerValue();
      else
        segment.flags = 0;

      if (seg->HasKey("nsects"))
        segment.nsects =
            seg->GetValueForKey("nsects")->GetUnsignedIntegerValue();
      else
        segment.nsects = 0;

      image_infos[i].segments.push_back(segment);
    }

    image_infos[i].uuid.SetFromStringRef(
        image->GetValueForKey("uuid")->GetAsString()->GetValue());

    // All sections listed in the dyld image info structure will all either be
    // fixed up already, or they will all be off by a single slide amount that
    // is determined by finding the first segment that is at file offset zero
    // which also has bytes (a file size that is greater than zero) in the
    // object file.

    // Determine the slide amount (if any)
    const size_t num_sections = image_infos[i].segments.size();
    for (size_t k = 0; k < num_sections; ++k) {
      // Iterate through the object file sections to find the first section
      // that starts of file offset zero and that has bytes in the file...
      if ((image_infos[i].segments[k].fileoff == 0 &&
           image_infos[i].segments[k].filesize > 0) ||
          (image_infos[i].segments[k].name == "__TEXT")) {
        image_infos[i].slide =
            image_infos[i].address - image_infos[i].segments[k].vmaddr;
        // We have found the slide amount, so we can exit this for loop.
        break;
      }
    }
  }

  return true;
}

void DynamicLoaderDarwin::UpdateSpecialBinariesFromPreloadedModules(
    std::vector<std::pair<ImageInfo, ModuleSP>> &images) {
  uint32_t exe_idx = UINT32_MAX;
  uint32_t dyld_idx = UINT32_MAX;
  Target &target = m_process->GetTarget();
  Log *log = GetLog(LLDBLog::DynamicLoader);
  ConstString g_dyld_sim_filename("dyld_sim");

  ArchSpec target_arch = target.GetArchitecture();
  const size_t images_size = images.size();
  for (size_t i = 0; i < images_size; i++) {
    const auto &image_info = images[i].first;
    if (image_info.header.filetype == llvm::MachO::MH_DYLINKER) {
      // In a "simulator" process we will have two dyld modules --
      // a "dyld" that we want to keep track of, and a "dyld_sim" which
      // we don't need to keep track of here.  dyld_sim will have a non-macosx
      // OS.
      if (target_arch.GetTriple().getEnvironment() == llvm::Triple::Simulator &&
          image_info.os_type != llvm::Triple::OSType::MacOSX) {
        continue;
      }

      dyld_idx = i;
    }
    if (image_info.header.filetype == llvm::MachO::MH_EXECUTE) {
      exe_idx = i;
    }
  }

  // Set the target executable if we haven't found one so far.
  if (exe_idx != UINT32_MAX && !target.GetExecutableModule()) {
    ModuleSP exe_module_sp = images[exe_idx].second;
    if (exe_module_sp) {
      LLDB_LOGF(log, "Found executable module: %s",
                exe_module_sp->GetFileSpec().GetPath().c_str());
      target.GetImages().AppendIfNeeded(exe_module_sp);
      UpdateImageLoadAddress(exe_module_sp.get(), images[exe_idx].first);
      if (exe_module_sp.get() != target.GetExecutableModulePointer())
        target.SetExecutableModule(exe_module_sp, eLoadDependentsNo);

      // Update the target executable's arch if necessary.
      auto exe_triple = exe_module_sp->GetArchitecture().GetTriple();
      if (target_arch.GetTriple().isArm64e() &&
          exe_triple.getArch() == llvm::Triple::aarch64 &&
          !exe_triple.isArm64e()) {
        // On arm64e-capable Apple platforms, the system libraries are
        // always arm64e, but applications often are arm64. When a
        // target is created from a file, LLDB recognizes it as an
        // arm64 target, but debugserver will still (technically
        // correct) report the process as being arm64e. For
        // consistency, set the target to arm64 here, so attaching to
        // a live process behaves the same as creating a process from
        // file.
        auto triple = target_arch.GetTriple();
        triple.setArchName(exe_triple.getArchName());
        target_arch.SetTriple(triple);
        target.SetArchitecture(target_arch, /*set_platform=*/false,
                               /*merge=*/false);
      }
    }
  }

  if (dyld_idx != UINT32_MAX) {
    ModuleSP dyld_sp = images[dyld_idx].second;
    if (dyld_sp.get()) {
      LLDB_LOGF(log, "Found dyld module: %s",
                dyld_sp->GetFileSpec().GetPath().c_str());
      target.GetImages().AppendIfNeeded(dyld_sp);
      UpdateImageLoadAddress(dyld_sp.get(), images[dyld_idx].first);
      SetDYLDModule(dyld_sp);
    }
  }
}

bool DynamicLoaderDarwin::UpdateDYLDImageInfoFromNewImageInfo(
    ImageInfo &image_info) {
  if (image_info.header.filetype == llvm::MachO::MH_DYLINKER) {
    const bool can_create = true;
    ModuleSP dyld_sp =
        FindTargetModuleForImageInfo(image_info, can_create, nullptr);
    if (dyld_sp.get()) {
      Target &target = m_process->GetTarget();
      target.GetImages().AppendIfNeeded(dyld_sp);
      UpdateImageLoadAddress(dyld_sp.get(), image_info);
      SetDYLDModule(dyld_sp);
      return true;
    }
  }
  return false;
}

std::optional<lldb_private::Address> DynamicLoaderDarwin::GetStartAddress() {
  Log *log = GetLog(LLDBLog::DynamicLoader);

  auto log_err = [log](llvm::StringLiteral err_msg) -> std::nullopt_t {
    LLDB_LOGV(log, "{}", err_msg);
    return std::nullopt;
  };

  ModuleSP dyld_sp = GetDYLDModule();
  if (!dyld_sp)
    return log_err("Couldn't retrieve DYLD module. Cannot get `start` symbol.");

  const Symbol *symbol =
      dyld_sp->FindFirstSymbolWithNameAndType(ConstString("_dyld_start"));
  if (!symbol)
    return log_err("Cannot find `start` symbol in DYLD module.");

  return symbol->GetAddress();
}

void DynamicLoaderDarwin::SetDYLDModule(lldb::ModuleSP &dyld_module_sp) {
  m_dyld_module_wp = dyld_module_sp;
}

ModuleSP DynamicLoaderDarwin::GetDYLDModule() {
  ModuleSP dyld_sp(m_dyld_module_wp.lock());
  return dyld_sp;
}

void DynamicLoaderDarwin::ClearDYLDModule() { m_dyld_module_wp.reset(); }

std::vector<std::pair<DynamicLoaderDarwin::ImageInfo, ModuleSP>>
DynamicLoaderDarwin::PreloadModulesFromImageInfos(
    const ImageInfo::collection &image_infos) {
  const auto size = image_infos.size();
  std::vector<std::pair<DynamicLoaderDarwin::ImageInfo, ModuleSP>> images(size);
  auto LoadImage = [&](size_t i, ImageInfo::collection::const_iterator it) {
    const auto &image_info = *it;
    images[i] = std::make_pair(
        image_info, FindTargetModuleForImageInfo(image_info, true, nullptr));
  };
  auto it = image_infos.begin();
  bool is_parallel_load =
      DynamicLoaderDarwinProperties::GetGlobal().GetEnableParallelImageLoad();
  if (is_parallel_load) {
    llvm::ThreadPoolTaskGroup taskGroup(Debugger::GetThreadPool());
    for (size_t i = 0; i < size; ++i, ++it) {
      taskGroup.async(LoadImage, i, it);
    }
    taskGroup.wait();
  } else {
    for (size_t i = 0; i < size; ++i, ++it) {
      LoadImage(i, it);
    }
  }
  return images;
}

bool DynamicLoaderDarwin::AddModulesUsingImageInfos(
    ImageInfo::collection &image_infos) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  auto images = PreloadModulesFromImageInfos(image_infos);
  return AddModulesUsingPreloadedModules(images);
}

bool DynamicLoaderDarwin::AddModulesUsingPreloadedModules(
    std::vector<std::pair<ImageInfo, ModuleSP>> &images) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  // Now add these images to the main list.
  ModuleList loaded_module_list;
  Log *log = GetLog(LLDBLog::DynamicLoader);
  Target &target = m_process->GetTarget();
  ModuleList &target_images = target.GetImages();

  for (uint32_t idx = 0; idx < images.size(); ++idx) {
    auto &image_info = images[idx].first;
    const auto &image_module_sp = images[idx].second;
    if (log) {
      LLDB_LOGF(log, "Adding new image at address=0x%16.16" PRIx64 ".",
                image_info.address);
      image_info.PutToLog(log);
    }
    m_dyld_image_infos.push_back(image_info);

    if (image_module_sp) {
      ObjectFile *objfile = image_module_sp->GetObjectFile();
      if (objfile) {
        SectionList *sections = objfile->GetSectionList();
        if (sections) {
          ConstString commpage_dbstr("__commpage");
          Section *commpage_section =
              sections->FindSectionByName(commpage_dbstr).get();
          if (commpage_section) {
            ModuleSpec module_spec(objfile->GetFileSpec(),
                                   image_info.GetArchitecture());
            module_spec.GetObjectName() = commpage_dbstr;
            ModuleSP commpage_image_module_sp(
                target_images.FindFirstModule(module_spec));
            if (!commpage_image_module_sp) {
              module_spec.SetObjectOffset(objfile->GetFileOffset() +
                                          commpage_section->GetFileOffset());
              module_spec.SetObjectSize(objfile->GetByteSize());
              commpage_image_module_sp = target.GetOrCreateModule(module_spec,
                                                               true /* notify */);
              if (!commpage_image_module_sp ||
                  commpage_image_module_sp->GetObjectFile() == nullptr) {
                commpage_image_module_sp = m_process->ReadModuleFromMemory(
                    image_info.file_spec, image_info.address);
                // Always load a memory image right away in the target in case
                // we end up trying to read the symbol table from memory... The
                // __LINKEDIT will need to be mapped so we can figure out where
                // the symbol table bits are...
                bool changed = false;
                UpdateImageLoadAddress(commpage_image_module_sp.get(),
                                       image_info);
                target.GetImages().Append(commpage_image_module_sp);
                if (changed) {
                  image_info.load_stop_id = m_process->GetStopID();
                  loaded_module_list.AppendIfNeeded(commpage_image_module_sp);
                }
              }
            }
          }
        }
      }

      // UpdateImageLoadAddress will return true if any segments change load
      // address. We need to check this so we don't mention that all loaded
      // shared libraries are newly loaded each time we hit out dyld breakpoint
      // since dyld will list all shared libraries each time.
      if (UpdateImageLoadAddress(image_module_sp.get(), image_info)) {
        target_images.AppendIfNeeded(image_module_sp);
        loaded_module_list.AppendIfNeeded(image_module_sp);
      }

      // To support macCatalyst and legacy iOS simulator,
      // update the module's platform with the DYLD info.
      ArchSpec dyld_spec = image_info.GetArchitecture();
      auto &dyld_triple = dyld_spec.GetTriple();
      if ((dyld_triple.getEnvironment() == llvm::Triple::MacABI &&
           dyld_triple.getOS() == llvm::Triple::IOS) ||
          (dyld_triple.getEnvironment() == llvm::Triple::Simulator &&
           (dyld_triple.getOS() == llvm::Triple::IOS ||
            dyld_triple.getOS() == llvm::Triple::TvOS ||
            dyld_triple.getOS() == llvm::Triple::WatchOS)))
        image_module_sp->MergeArchitecture(dyld_spec);
    }
  }

  if (loaded_module_list.GetSize() > 0) {
    if (log)
      loaded_module_list.LogUUIDAndPaths(log,
                                         "DynamicLoaderDarwin::ModulesDidLoad");
    m_process->GetTarget().ModulesDidLoad(loaded_module_list);
  }
  return true;
}

// On Mac OS X libobjc (the Objective-C runtime) has several critical dispatch
// functions written in hand-written assembly, and also have hand-written
// unwind information in the eh_frame section.  Normally we prefer analyzing
// the assembly instructions of a currently executing frame to unwind from that
// frame -- but on hand-written functions this profiling can fail.  We should
// use the eh_frame instructions for these functions all the time.
//
// As an aside, it would be better if the eh_frame entries had a flag (or were
// extensible so they could have an Apple-specific flag) which indicates that
// the instructions are asynchronous -- accurate at every instruction, instead
// of our normal default assumption that they are not.

bool DynamicLoaderDarwin::AlwaysRelyOnEHUnwindInfo(SymbolContext &sym_ctx) {
  ModuleSP module_sp;
  if (sym_ctx.symbol) {
    module_sp = sym_ctx.symbol->GetAddressRef().GetModule();
  }
  if (module_sp.get() == nullptr && sym_ctx.function)
    module_sp = sym_ctx.function->GetAddress().GetModule();
  if (module_sp.get() == nullptr)
    return false;

  ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*m_process);
  return objc_runtime != nullptr &&
         objc_runtime->IsModuleObjCLibrary(module_sp);
}

// Dump a Segment to the file handle provided.
void DynamicLoaderDarwin::Segment::PutToLog(Log *log,
                                            lldb::addr_t slide) const {
  if (log) {
    if (slide == 0)
      LLDB_LOGF(log, "\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")",
                name.AsCString(""), vmaddr + slide, vmaddr + slide + vmsize);
    else
      LLDB_LOGF(log,
                "\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64
                ") slide = 0x%" PRIx64,
                name.AsCString(""), vmaddr + slide, vmaddr + slide + vmsize,
                slide);
  }
}

lldb_private::ArchSpec DynamicLoaderDarwin::ImageInfo::GetArchitecture() const {
  // Update the module's platform with the DYLD info.
  lldb_private::ArchSpec arch_spec(lldb_private::eArchTypeMachO, header.cputype,
                                   header.cpusubtype);
  if (os_env == llvm::Triple::MacABI && os_type == llvm::Triple::IOS) {
    llvm::Triple triple(llvm::Twine(arch_spec.GetArchitectureName()) +
                        "-apple-ios" + min_version_os_sdk + "-macabi");
    ArchSpec maccatalyst_spec(triple);
    if (arch_spec.IsCompatibleMatch(maccatalyst_spec))
      arch_spec.MergeFrom(maccatalyst_spec);
  }
  if (os_env == llvm::Triple::Simulator &&
      (os_type == llvm::Triple::IOS || os_type == llvm::Triple::TvOS ||
       os_type == llvm::Triple::WatchOS)) {
    llvm::Triple triple(llvm::Twine(arch_spec.GetArchitectureName()) +
                        "-apple-" + llvm::Triple::getOSTypeName(os_type) +
                        min_version_os_sdk + "-simulator");
    ArchSpec sim_spec(triple);
    if (arch_spec.IsCompatibleMatch(sim_spec))
      arch_spec.MergeFrom(sim_spec);
  }
  return arch_spec;
}

const DynamicLoaderDarwin::Segment *
DynamicLoaderDarwin::ImageInfo::FindSegment(ConstString name) const {
  const size_t num_segments = segments.size();
  for (size_t i = 0; i < num_segments; ++i) {
    if (segments[i].name == name)
      return &segments[i];
  }
  return nullptr;
}

// Dump an image info structure to the file handle provided.
void DynamicLoaderDarwin::ImageInfo::PutToLog(Log *log) const {
  if (!log)
    return;
  if (address == LLDB_INVALID_ADDRESS) {
    LLDB_LOG(log, "uuid={1} path='{2}' (UNLOADED)", uuid.GetAsString(),
             file_spec.GetPath());
  } else {
    LLDB_LOG(log, "address={0:x+16} uuid={1} path='{2}'", address,
             uuid.GetAsString(), file_spec.GetPath());
    for (uint32_t i = 0; i < segments.size(); ++i)
      segments[i].PutToLog(log, slide);
  }
}

void DynamicLoaderDarwin::PrivateInitialize(Process *process) {
  DEBUG_PRINTF("DynamicLoaderDarwin::%s() process state = %s\n", __FUNCTION__,
               StateAsCString(m_process->GetState()));
  Clear(true);
  m_process = process;
  m_process->GetTarget().ClearAllLoadedSections();
}

// Member function that gets called when the process state changes.
void DynamicLoaderDarwin::PrivateProcessStateChanged(Process *process,
                                                     StateType state) {
  DEBUG_PRINTF("DynamicLoaderDarwin::%s(%s)\n", __FUNCTION__,
               StateAsCString(state));
  switch (state) {
  case eStateConnected:
  case eStateAttaching:
  case eStateLaunching:
  case eStateInvalid:
  case eStateUnloaded:
  case eStateExited:
  case eStateDetached:
    Clear(false);
    break;

  case eStateStopped:
    // Keep trying find dyld and set our notification breakpoint each time we
    // stop until we succeed
    if (!DidSetNotificationBreakpoint() && m_process->IsAlive()) {
      if (NeedToDoInitialImageFetch())
        DoInitialImageFetch();

      SetNotificationBreakpoint();
    }
    break;

  case eStateRunning:
  case eStateStepping:
  case eStateCrashed:
  case eStateSuspended:
    break;
  }
}

ThreadPlanSP
DynamicLoaderDarwin::GetStepThroughTrampolinePlan(Thread &thread,
                                                  bool stop_others) {
  ThreadPlanSP thread_plan_sp;
  StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get();
  const SymbolContext &current_context =
      current_frame->GetSymbolContext(eSymbolContextSymbol);
  Symbol *current_symbol = current_context.symbol;
  Log *log = GetLog(LLDBLog::Step);
  TargetSP target_sp(thread.CalculateTarget());

  if (current_symbol != nullptr) {
    std::vector<Address> addresses;

    if (current_symbol->IsTrampoline()) {
      ConstString trampoline_name =
          current_symbol->GetMangled().GetName(Mangled::ePreferMangled);

      if (trampoline_name) {
        const ModuleList &images = target_sp->GetImages();

        SymbolContextList code_symbols;
        images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode,
                                          code_symbols);
        for (const SymbolContext &context : code_symbols) {
          AddressRange addr_range;
          context.GetAddressRange(eSymbolContextEverything, 0, false,
                                  addr_range);
          addresses.push_back(addr_range.GetBaseAddress());
          if (log) {
            addr_t load_addr =
                addr_range.GetBaseAddress().GetLoadAddress(target_sp.get());

            LLDB_LOGF(log, "Found a trampoline target symbol at 0x%" PRIx64 ".",
                      load_addr);
          }
        }

        SymbolContextList reexported_symbols;
        images.FindSymbolsWithNameAndType(
            trampoline_name, eSymbolTypeReExported, reexported_symbols);
        for (const SymbolContext &context : reexported_symbols) {
          if (context.symbol) {
            Symbol *actual_symbol =
                context.symbol->ResolveReExportedSymbol(*target_sp.get());
            if (actual_symbol) {
              const Address actual_symbol_addr = actual_symbol->GetAddress();
              if (actual_symbol_addr.IsValid()) {
                addresses.push_back(actual_symbol_addr);
                if (log) {
                  lldb::addr_t load_addr =
                      actual_symbol_addr.GetLoadAddress(target_sp.get());
                  LLDB_LOGF(log,
                            "Found a re-exported symbol: %s at 0x%" PRIx64 ".",
                            actual_symbol->GetName().GetCString(), load_addr);
                }
              }
            }
          }
        }

        SymbolContextList indirect_symbols;
        images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeResolver,
                                          indirect_symbols);

        for (const SymbolContext &context : indirect_symbols) {
          AddressRange addr_range;
          context.GetAddressRange(eSymbolContextEverything, 0, false,
                                  addr_range);
          addresses.push_back(addr_range.GetBaseAddress());
          if (log) {
            addr_t load_addr =
                addr_range.GetBaseAddress().GetLoadAddress(target_sp.get());

            LLDB_LOGF(log, "Found an indirect target symbol at 0x%" PRIx64 ".",
                      load_addr);
          }
        }
      }
    } else if (current_symbol->GetType() == eSymbolTypeReExported) {
      // I am not sure we could ever end up stopped AT a re-exported symbol.
      // But just in case:

      const Symbol *actual_symbol =
          current_symbol->ResolveReExportedSymbol(*(target_sp.get()));
      if (actual_symbol) {
        Address target_addr(actual_symbol->GetAddress());
        if (target_addr.IsValid()) {
          LLDB_LOGF(
              log,
              "Found a re-exported symbol: %s pointing to: %s at 0x%" PRIx64
              ".",
              current_symbol->GetName().GetCString(),
              actual_symbol->GetName().GetCString(),
              target_addr.GetLoadAddress(target_sp.get()));
          addresses.push_back(target_addr.GetLoadAddress(target_sp.get()));
        }
      }
    }

    if (addresses.size() > 0) {
      // First check whether any of the addresses point to Indirect symbols,
      // and if they do, resolve them:
      std::vector<lldb::addr_t> load_addrs;
      for (Address address : addresses) {
        Symbol *symbol = address.CalculateSymbolContextSymbol();
        if (symbol && symbol->IsIndirect()) {
          Status error;
          Address symbol_address = symbol->GetAddress();
          addr_t resolved_addr = thread.GetProcess()->ResolveIndirectFunction(
              &symbol_address, error);
          if (error.Success()) {
            load_addrs.push_back(resolved_addr);
            LLDB_LOGF(log,
                      "ResolveIndirectFunction found resolved target for "
                      "%s at 0x%" PRIx64 ".",
                      symbol->GetName().GetCString(), resolved_addr);
          }
        } else {
          load_addrs.push_back(address.GetLoadAddress(target_sp.get()));
        }
      }
      thread_plan_sp = std::make_shared<ThreadPlanRunToAddress>(
          thread, load_addrs, stop_others);
    }
  } else {
    LLDB_LOGF(log, "Could not find symbol for step through.");
  }

  return thread_plan_sp;
}

void DynamicLoaderDarwin::FindEquivalentSymbols(
    lldb_private::Symbol *original_symbol, lldb_private::ModuleList &images,
    lldb_private::SymbolContextList &equivalent_symbols) {
  ConstString trampoline_name =
      original_symbol->GetMangled().GetName(Mangled::ePreferMangled);
  if (!trampoline_name)
    return;

  static const char *resolver_name_regex = "(_gc|_non_gc|\\$[A-Za-z0-9\\$]+)$";
  std::string equivalent_regex_buf("^");
  equivalent_regex_buf.append(trampoline_name.GetCString());
  equivalent_regex_buf.append(resolver_name_regex);

  RegularExpression equivalent_name_regex(equivalent_regex_buf);
  images.FindSymbolsMatchingRegExAndType(equivalent_name_regex, eSymbolTypeCode,
                                         equivalent_symbols);

}

lldb::ModuleSP DynamicLoaderDarwin::GetPThreadLibraryModule() {
  ModuleSP module_sp = m_libpthread_module_wp.lock();
  if (!module_sp) {
    SymbolContextList sc_list;
    ModuleSpec module_spec;
    module_spec.GetFileSpec().SetFilename("libsystem_pthread.dylib");
    ModuleList module_list;
    m_process->GetTarget().GetImages().FindModules(module_spec, module_list);
    if (!module_list.IsEmpty()) {
      if (module_list.GetSize() == 1) {
        module_sp = module_list.GetModuleAtIndex(0);
        if (module_sp)
          m_libpthread_module_wp = module_sp;
      }
    }
  }
  return module_sp;
}

Address DynamicLoaderDarwin::GetPthreadSetSpecificAddress() {
  if (!m_pthread_getspecific_addr.IsValid()) {
    ModuleSP module_sp = GetPThreadLibraryModule();
    if (module_sp) {
      lldb_private::SymbolContextList sc_list;
      module_sp->FindSymbolsWithNameAndType(ConstString("pthread_getspecific"),
                                            eSymbolTypeCode, sc_list);
      SymbolContext sc;
      if (sc_list.GetContextAtIndex(0, sc)) {
        if (sc.symbol)
          m_pthread_getspecific_addr = sc.symbol->GetAddress();
      }
    }
  }
  return m_pthread_getspecific_addr;
}

lldb::addr_t
DynamicLoaderDarwin::GetThreadLocalData(const lldb::ModuleSP module_sp,
                                        const lldb::ThreadSP thread_sp,
                                        lldb::addr_t tls_file_addr) {
  if (!thread_sp || !module_sp)
    return LLDB_INVALID_ADDRESS;

  std::lock_guard<std::recursive_mutex> guard(m_mutex);

  lldb_private::Address tls_addr;
  if (!module_sp->ResolveFileAddress(tls_file_addr, tls_addr))
    return LLDB_INVALID_ADDRESS;

  Target &target = m_process->GetTarget();
  TypeSystemClangSP scratch_ts_sp =
      ScratchTypeSystemClang::GetForTarget(target);
  if (!scratch_ts_sp)
    return LLDB_INVALID_ADDRESS;

  CompilerType clang_void_ptr_type =
      scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType();

  auto evaluate_tls_address = [this, &thread_sp, &clang_void_ptr_type](
                                  Address func_ptr,
                                  llvm::ArrayRef<addr_t> args) -> addr_t {
    EvaluateExpressionOptions options;

    lldb::ThreadPlanSP thread_plan_sp(new ThreadPlanCallFunction(
        *thread_sp, func_ptr, clang_void_ptr_type, args, options));

    DiagnosticManager execution_errors;
    ExecutionContext exe_ctx(thread_sp);
    lldb::ExpressionResults results = m_process->RunThreadPlan(
        exe_ctx, thread_plan_sp, options, execution_errors);

    if (results == lldb::eExpressionCompleted) {
      if (lldb::ValueObjectSP result_valobj_sp =
              thread_plan_sp->GetReturnValueObject()) {
        return result_valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
      }
    }
    return LLDB_INVALID_ADDRESS;
  };

  // On modern apple platforms, there is a small data structure that looks
  // approximately like this:
  // struct TLS_Thunk {
  //  void *(*get_addr)(struct TLS_Thunk *);
  //  size_t key;
  //  size_t offset;
  // }
  //
  // The strategy is to take get_addr, call it with the address of the
  // containing TLS_Thunk structure, and add the offset to the resulting
  // pointer to get the data block.
  //
  // On older apple platforms, the key is treated as a pthread_key_t and passed
  // to pthread_getspecific. The pointer returned from that call is added to
  // offset to get the relevant data block.

  const uint32_t addr_size = m_process->GetAddressByteSize();
  uint8_t buf[sizeof(addr_t) * 3];
  Status error;
  const size_t tls_data_size = addr_size * 3;
  const size_t bytes_read = target.ReadMemory(
      tls_addr, buf, tls_data_size, error, /*force_live_memory = */ true);
  if (bytes_read != tls_data_size || error.Fail())
    return LLDB_INVALID_ADDRESS;

  DataExtractor data(buf, sizeof(buf), m_process->GetByteOrder(), addr_size);
  lldb::offset_t offset = 0;
  const addr_t tls_thunk = data.GetAddress(&offset);
  const addr_t key = data.GetAddress(&offset);
  const addr_t tls_offset = data.GetAddress(&offset);

  if (tls_thunk != 0) {
    const addr_t fixed_tls_thunk = m_process->FixCodeAddress(tls_thunk);
    Address thunk_load_addr;
    if (target.ResolveLoadAddress(fixed_tls_thunk, thunk_load_addr)) {
      const addr_t tls_load_addr = tls_addr.GetLoadAddress(&target);
      const addr_t tls_data = evaluate_tls_address(
          thunk_load_addr, llvm::ArrayRef<addr_t>(tls_load_addr));
      if (tls_data != LLDB_INVALID_ADDRESS)
        return tls_data + tls_offset;
    }
  }

  if (key != 0) {
    // First check to see if we have already figured out the location of
    // TLS data for the pthread_key on a specific thread yet. If we have we
    // can re-use it since its location will not change unless the process
    // execs.
    const lldb::tid_t tid = thread_sp->GetID();
    auto tid_pos = m_tid_to_tls_map.find(tid);
    if (tid_pos != m_tid_to_tls_map.end()) {
      auto tls_pos = tid_pos->second.find(key);
      if (tls_pos != tid_pos->second.end()) {
        return tls_pos->second + tls_offset;
      }
    }
    Address pthread_getspecific_addr = GetPthreadSetSpecificAddress();
    if (pthread_getspecific_addr.IsValid()) {
      const addr_t tls_data = evaluate_tls_address(pthread_getspecific_addr,
                                                   llvm::ArrayRef<addr_t>(key));
      if (tls_data != LLDB_INVALID_ADDRESS)
        return tls_data + tls_offset;
    }
  }
  return LLDB_INVALID_ADDRESS;
}

bool DynamicLoaderDarwin::UseDYLDSPI(Process *process) {
  Log *log = GetLog(LLDBLog::DynamicLoader);
  bool use_new_spi_interface = false;

  llvm::VersionTuple version = process->GetHostOSVersion();
  if (!version.empty()) {
    const llvm::Triple::OSType os_type =
        process->GetTarget().GetArchitecture().GetTriple().getOS();

    // macOS 10.12 and newer
    if (os_type == llvm::Triple::MacOSX &&
        version >= llvm::VersionTuple(10, 12))
      use_new_spi_interface = true;

    // iOS 10 and newer
    if (os_type == llvm::Triple::IOS && version >= llvm::VersionTuple(10))
      use_new_spi_interface = true;

    // tvOS 10 and newer
    if (os_type == llvm::Triple::TvOS && version >= llvm::VersionTuple(10))
      use_new_spi_interface = true;

    // watchOS 3 and newer
    if (os_type == llvm::Triple::WatchOS && version >= llvm::VersionTuple(3))
      use_new_spi_interface = true;

    // NEED_BRIDGEOS_TRIPLE // Any BridgeOS
    // NEED_BRIDGEOS_TRIPLE if (os_type == llvm::Triple::BridgeOS)
    // NEED_BRIDGEOS_TRIPLE   use_new_spi_interface = true;
  }

  if (log) {
    if (use_new_spi_interface)
      LLDB_LOGF(
          log, "DynamicLoaderDarwin::UseDYLDSPI: Use new DynamicLoader plugin");
    else
      LLDB_LOGF(
          log, "DynamicLoaderDarwin::UseDYLDSPI: Use old DynamicLoader plugin");
  }
  return use_new_spi_interface;
}
