//===-- 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 "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/Target/ThreadPlanStepInstruction.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();
}

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

  // See if we have this binary in the Target or the global Module
  // cache already.
  module_sp = target.GetOrCreateModule(module_spec, /*notify=*/false);

  if (!module_sp &&
      HostInfo::GetArchitecture().IsCompatibleMatch(target.GetArchitecture())) {

    SharedCacheImageInfo image_info;

    // If we have a shared cache filepath and UUID, ask HostInfo
    // if it can provide the SourceCacheImageInfo for the binary
    // out of that shared cache.  Search by the Module's UUID if
    // available, else the filepath.
    addr_t sc_base_addr;
    UUID sc_uuid;
    LazyBool using_sc;
    LazyBool private_sc;
    FileSpec sc_path;
    std::optional<uint64_t> size;
    SymbolSharedCacheUse sc_mode = ModuleList::GetGlobalModuleListProperties()
                                       .GetSharedCacheBinaryLoading();
    if (GetSharedCacheInformation(sc_base_addr, sc_uuid, using_sc, private_sc,
                                  sc_path, size) &&
        sc_uuid) {
      if (module_spec.GetUUID())
        image_info = HostInfo::GetSharedCacheImageInfo(module_spec.GetUUID(),
                                                       sc_uuid, sc_mode);

      else
        image_info = HostInfo::GetSharedCacheImageInfo(
            module_spec.GetFileSpec().GetPathAsConstString(), sc_uuid, sc_mode);
    } else {
      // Fall back to looking lldb's own shared cache by filename
      image_info = HostInfo::GetSharedCacheImageInfo(
          module_spec.GetFileSpec().GetPathAsConstString(), sc_mode);
    }

    // If we found it and it has the correct UUID, let's proceed with
    // creating a module from the memory contents.
    if (image_info.GetUUID() &&
        (!module_spec.GetUUID() ||
         module_spec.GetUUID() == image_info.GetUUID())) {
      ModuleSpec shared_cache_spec(module_spec.GetFileSpec(),
                                   image_info.GetUUID(),
                                   image_info.GetExtractor());
      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->GetObjectFile() == nullptr) {
    llvm::Expected<ModuleSP> module_sp_or_err = m_process->ReadModuleFromMemory(
        image_info.file_spec, image_info.address,
        image_info.mh_and_load_cmd_size);
    if (auto err = module_sp_or_err.takeError()) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::DynamicLoader), std::move(err),
                     "Failed to load module from memory: {0}");
      return {};
    }
    module_sp = *module_sp_or_err;
  }

  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;
  Log *log = GetLog(LLDBLog::DynamicLoader);
  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;

              // If a segment was eliminated for the in-memory image,
              // don't map it into lldb's target section load list.
              if (info.segments[i].vmsize == 0) {
                LLDB_LOGF(log, "%s: Omitting zero-size segment %s",
                          info.file_spec.GetFilename().AsCString(""),
                          info.segments[i].name.AsCString(""));
                continue;
              }

              if (info.segments[i].vmsize != section_sp->GetByteSize())
                LLDB_LOGF(log,
                          "%s: In-memory segment size for %s is 0x%" PRIx64
                          " but file segment size is 0x%" PRIx64,
                          info.file_spec.GetFilename().AsCString(""),
                          info.segments[i].name.AsCString(""),
                          info.segments[i].vmsize, section_sp->GetByteSize());

              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 (mh->HasKey("sizeof_mh_and_loadcmds"))
      image_infos[i].mh_and_load_cmd_size =
          mh->GetValueForKey("sizeof_mh_and_loadcmds")
              ->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 == "driverkit")
        image_infos[i].os_type = llvm::Triple::DriverKit;
      else if (os_name == "xros")
        image_infos[i].os_type = llvm::Triple::XROS;
      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;
      } else if (os_name == "xrsimulator") {
        image_infos[i].os_type = llvm::Triple::XROS;
        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_LOG_VERBOSE(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 = m_process->GetTarget().GetParallelModuleLoad();
  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) {
                llvm::Expected<ModuleSP> module_sp_or_err =
                    m_process->ReadModuleFromMemory(image_info.file_spec,
                                                    image_info.address);
                if (auto err = module_sp_or_err.takeError()) {
                  LLDB_LOG_ERROR(log, std::move(err),
                                 "Failed to read module from memory: {0}");
                } else {
                  // 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...
                  commpage_image_module_sp = *module_sp_or_err;
                  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 ||
            dyld_triple.getOS() == llvm::Triple::XROS)))
        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 (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 || os_type == llvm::Triple::XROS)) {
    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={} path='{}' (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;
}

// 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);
  const Symbol *current_symbol = current_context.symbol;
  Log *log = GetLog(LLDBLog::Step);
  TargetSP target_sp(thread.CalculateTarget());

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

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

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

        SymbolContextList code_symbols;
        images.FindSymbolsWithNameAndType(current_name, eSymbolTypeCode,
                                          code_symbols);
        for (const SymbolContext &context : code_symbols) {
          Address addr = context.GetFunctionOrSymbolAddress();
          addresses.push_back(addr);
          if (log) {
            addr_t load_addr = addr.GetLoadAddress(target_sp.get());

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

        SymbolContextList reexported_symbols;
        images.FindSymbolsWithNameAndType(current_name, eSymbolTypeReExported,
                                          reexported_symbols);
        for (const SymbolContext &context : reexported_symbols) {
          if (context.symbol) {
            const 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(current_name, eSymbolTypeResolver,
                                          indirect_symbols);

        for (const SymbolContext &context : indirect_symbols) {
          Address addr = context.GetFunctionOrSymbolAddress();
          addresses.push_back(addr);
          if (log) {
            addr_t load_addr = addr.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(
              Address(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) {
        const 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);
    }
    // One more case we have to consider is "branch islands".  These are regular
    // TEXT symbols but their names end in .island plus maybe a .digit suffix.
    // They are to allow arm64 code to branch further than the size of the
    // address slot allows.  We just need to single-instruction step in that
    // case.
    static const char *g_branch_island_pattern = "\\.island\\.?[0-9]*$";
    static RegularExpression g_branch_island_regex(g_branch_island_pattern);

    bool is_branch_island = g_branch_island_regex.Execute(current_name);
    if (!thread_plan_sp && is_branch_island) {
      thread_plan_sp = std::make_shared<ThreadPlanStepInstruction>(
          thread,
          /* step_over= */ false, /* stop_others */ false, eVoteNoOpinion,
          eVoteNoOpinion);
      LLDB_LOG(log, "Stepping one instruction over branch island: '{0}'.",
               current_name);
    }
  } else {
    LLDB_LOGF(log, "Could not find symbol for step through.");
  }

  return thread_plan_sp;
}

void DynamicLoaderDarwin::FindEquivalentSymbols(
    const 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 and call it with the address of the
  // containing TLS_Thunk structure.
  //
  // 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;
    }
  }

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

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

    auto OlderThan = [os_type, version](llvm::Triple::OSType o,
                                        llvm::VersionTuple v) -> bool {
      return os_type == o && version < v;
    };

    if (OlderThan(Triple::MacOSX, VersionTuple(10, 12)))
      use_new_spi_interface = false;

    if (OlderThan(Triple::IOS, VersionTuple(10)))
      use_new_spi_interface = false;

    if (OlderThan(Triple::TvOS, VersionTuple(10)))
      use_new_spi_interface = false;

    if (OlderThan(Triple::WatchOS, VersionTuple(3)))
      use_new_spi_interface = false;

    // llvm::Triple::BridgeOS and llvm::Triple::XROS always use the new
    // libdyld SPI interface.
  } else {
    // We could not get an OS version string, we are likely not
    // connected to debugserver and the packets to call the libdyld SPI
    // will not exist.
    use_new_spi_interface = false;
  }

  // Corefiles cannot use the libdyld SPI to get the inferior's
  // binaries, we must find it through metadata or a scan
  // of the corefile memory.
  if (!process->IsLiveDebugSession())
    use_new_spi_interface = false;

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