//===-- 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/Utility/DataBuffer.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.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

#ifndef __APPLE__
#include "Utility/UuidCompatibility.h"
#else
#include <uuid/uuid.h>
#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(
    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("mod_date") ||
        !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")->GetAsInteger()->GetValue();
    image_infos[i].mod_date =
        image->GetValueForKey("mod_date")->GetAsInteger()->GetValue();
    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")->GetAsInteger()->GetValue();
    image_infos[i].header.cputype =
        mh->GetValueForKey("cputype")->GetAsInteger()->GetValue();
    image_infos[i].header.cpusubtype =
        mh->GetValueForKey("cpusubtype")->GetAsInteger()->GetValue();
    image_infos[i].header.filetype =
        mh->GetValueForKey("filetype")->GetAsInteger()->GetValue();

    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;
      // NEED_BRIDGEOS_TRIPLE else if (os_name == "bridgeos")
      // NEED_BRIDGEOS_TRIPLE   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")->GetAsInteger()->GetValue();
    else
      image_infos[i].header.flags = 0;

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

    if (mh->HasKey("sizeofcmds"))
      image_infos[i].header.sizeofcmds =
          mh->GetValueForKey("sizeofcmds")->GetAsInteger()->GetValue();
    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")->GetAsInteger()->GetValue();
      segment.vmsize =
          seg->GetValueForKey("vmsize")->GetAsInteger()->GetValue();
      segment.fileoff =
          seg->GetValueForKey("fileoff")->GetAsInteger()->GetValue();
      segment.filesize =
          seg->GetValueForKey("filesize")->GetAsInteger()->GetValue();
      segment.maxprot =
          seg->GetValueForKey("maxprot")->GetAsInteger()->GetValue();

      // 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")->GetAsInteger()->GetValue();
      else
        segment.initprot = 0;

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

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

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

    image_infos[i].uuid.SetFromOptionalStringRef(
        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::UpdateSpecialBinariesFromNewImageInfos(
    ImageInfo::collection &image_infos) {
  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 image_infos_size = image_infos.size();
  for (size_t i = 0; i < image_infos_size; i++) {
    if (image_infos[i].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_infos[i].os_type != llvm::Triple::OSType::MacOSX) {
        continue;
      }

      dyld_idx = i;
    } 
    if (image_infos[i].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()) {
    const bool can_create = true;
    ModuleSP exe_module_sp(FindTargetModuleForImageInfo(image_infos[exe_idx],
                                                        can_create, nullptr));
    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(), image_infos[exe_idx]);
      if (exe_module_sp.get() != target.GetExecutableModulePointer()) {
        target.SetExecutableModule(exe_module_sp, eLoadDependentsNo);
      }
    }
  }

  if (dyld_idx != UINT32_MAX) {
    const bool can_create = true;
    ModuleSP dyld_sp = FindTargetModuleForImageInfo(image_infos[dyld_idx],
                                                    can_create, nullptr);
    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(), image_infos[dyld_idx]);
      SetDYLDModule(dyld_sp);
    }
  }
}

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

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

bool DynamicLoaderDarwin::AddModulesUsingImageInfos(
    ImageInfo::collection &image_infos) {
  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 < image_infos.size(); ++idx) {
    if (log) {
      LLDB_LOGF(log, "Adding new image at address=0x%16.16" PRIx64 ".",
                image_infos[idx].address);
      image_infos[idx].PutToLog(log);
    }

    m_dyld_image_infos.push_back(image_infos[idx]);

    ModuleSP image_module_sp(
        FindTargetModuleForImageInfo(image_infos[idx], true, nullptr));

    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_infos[idx].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_infos[idx].file_spec, image_infos[idx].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_infos[idx]);
                target.GetImages().Append(commpage_image_module_sp);
                if (changed) {
                  image_infos[idx].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_infos[idx])) {
        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_infos[idx].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->GetAddressRange().GetBaseAddress().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, "modtime={0:x+8} uuid={1} path='{2}' (UNLOADED)", mod_date,
             uuid.GetAsString(), file_spec.GetPath());
  } else {
    LLDB_LOG(log, "address={0:x+16} modtime={1:x+8} uuid={2} path='{3}'",
             address, mod_date, 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);
        size_t num_code_symbols = code_symbols.GetSize();

        if (num_code_symbols > 0) {
          for (uint32_t i = 0; i < num_code_symbols; i++) {
            SymbolContext context;
            AddressRange addr_range;
            if (code_symbols.GetContextAtIndex(i, context)) {
              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);
        size_t num_reexported_symbols = reexported_symbols.GetSize();
        if (num_reexported_symbols > 0) {
          for (uint32_t i = 0; i < num_reexported_symbols; i++) {
            SymbolContext context;
            if (reexported_symbols.GetContextAtIndex(i, context)) {
              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);
        size_t num_indirect_symbols = indirect_symbols.GetSize();
        if (num_indirect_symbols > 0) {
          for (uint32_t i = 0; i < num_indirect_symbols; i++) {
            SymbolContext context;
            AddressRange addr_range;
            if (indirect_symbols.GetContextAtIndex(i, context)) {
              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().GetFilename().SetCString(
        "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);

  const uint32_t addr_size = m_process->GetAddressByteSize();
  uint8_t buf[sizeof(lldb::addr_t) * 3];

  lldb_private::Address tls_addr;
  if (module_sp->ResolveFileAddress(tls_file_addr, tls_addr)) {
    Status error;
    const size_t tsl_data_size = addr_size * 3;
    Target &target = m_process->GetTarget();
    if (target.ReadMemory(tls_addr, buf, tsl_data_size, error, true) ==
        tsl_data_size) {
      const ByteOrder byte_order = m_process->GetByteOrder();
      DataExtractor data(buf, sizeof(buf), byte_order, addr_size);
      lldb::offset_t offset = addr_size; // Skip the first pointer
      const lldb::addr_t pthread_key = data.GetAddress(&offset);
      const lldb::addr_t tls_offset = data.GetAddress(&offset);
      if (pthread_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 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(pthread_key);
          if (tls_pos != tid_pos->second.end()) {
            return tls_pos->second + tls_offset;
          }
        }
        StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(0);
        if (frame_sp) {
          TypeSystemClang *clang_ast_context =
              ScratchTypeSystemClang::GetForTarget(target);

          if (!clang_ast_context)
            return LLDB_INVALID_ADDRESS;

          CompilerType clang_void_ptr_type =
              clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
          Address pthread_getspecific_addr = GetPthreadSetSpecificAddress();
          if (pthread_getspecific_addr.IsValid()) {
            EvaluateExpressionOptions options;

            lldb::ThreadPlanSP thread_plan_sp(new ThreadPlanCallFunction(
                *thread_sp, pthread_getspecific_addr, clang_void_ptr_type,
                llvm::ArrayRef<lldb::addr_t>(pthread_key), 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) {
              lldb::ValueObjectSP result_valobj_sp =
                  thread_plan_sp->GetReturnValueObject();
              if (result_valobj_sp) {
                const lldb::addr_t pthread_key_data =
                    result_valobj_sp->GetValueAsUnsigned(0);
                if (pthread_key_data) {
                  m_tid_to_tls_map[tid].insert(
                      std::make_pair(pthread_key, pthread_key_data));
                  return pthread_key_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;
}
