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

#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.h"

#include "DynamicLoaderDarwin.h"
#include "DynamicLoaderMacOS.h"

#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"

using namespace lldb;
using namespace lldb_private;

// Create an instance of this class. This function is filled into the plugin
// info class that gets handed out by the plugin factory and allows the lldb to
// instantiate an instance of this class.
DynamicLoader *DynamicLoaderMacOS::CreateInstance(Process *process,
                                                  bool force) {
  bool create = force;
  if (!create) {
    create = true;
    Module *exe_module = process->GetTarget().GetExecutableModulePointer();
    if (exe_module) {
      ObjectFile *object_file = exe_module->GetObjectFile();
      if (object_file) {
        create = (object_file->GetStrata() == ObjectFile::eStrataUser);
      }
    }

    if (create) {
      const llvm::Triple &triple_ref =
          process->GetTarget().GetArchitecture().GetTriple();
      switch (triple_ref.getOS()) {
      case llvm::Triple::Darwin:
      case llvm::Triple::MacOSX:
      case llvm::Triple::IOS:
      case llvm::Triple::TvOS:
      case llvm::Triple::WatchOS:
      case llvm::Triple::BridgeOS:
      case llvm::Triple::DriverKit:
      case llvm::Triple::XROS:
        create = triple_ref.getVendor() == llvm::Triple::Apple;
        break;
      default:
        create = false;
        break;
      }
    }
  }

  if (!UseDYLDSPI(process)) {
    create = false;
  }

  if (create)
    return new DynamicLoaderMacOS(process);
  return nullptr;
}

// Constructor
DynamicLoaderMacOS::DynamicLoaderMacOS(Process *process)
    : DynamicLoaderDarwin(process), m_image_infos_stop_id(UINT32_MAX),
      m_break_id(LLDB_INVALID_BREAK_ID),
      m_dyld_handover_break_id(LLDB_INVALID_BREAK_ID), m_mutex(),
      m_maybe_image_infos_address(LLDB_INVALID_ADDRESS),
      m_libsystem_fully_initalized(false) {}

// Destructor
DynamicLoaderMacOS::~DynamicLoaderMacOS() {
  if (LLDB_BREAK_ID_IS_VALID(m_break_id))
    m_process->GetTarget().RemoveBreakpointByID(m_break_id);
  if (LLDB_BREAK_ID_IS_VALID(m_dyld_handover_break_id))
    m_process->GetTarget().RemoveBreakpointByID(m_dyld_handover_break_id);
}

bool DynamicLoaderMacOS::ProcessDidExec() {
  std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
  bool did_exec = false;
  if (m_process) {
    // If we are stopped after an exec, we will have only one thread...
    if (m_process->GetThreadList().GetSize() == 1) {
      // Maybe we still have an image infos address around?  If so see
      // if that has changed, and if so we have exec'ed.
      if (m_maybe_image_infos_address != LLDB_INVALID_ADDRESS) {
        lldb::addr_t image_infos_address = m_process->GetImageInfoAddress();
        if (image_infos_address != m_maybe_image_infos_address) {
          // We don't really have to reset this here, since we are going to
          // call DoInitialImageFetch right away to handle the exec.  But in
          // case anybody looks at it in the meantime, it can't hurt.
          m_maybe_image_infos_address = image_infos_address;
          did_exec = true;
        }
      }

      if (!did_exec) {
        // See if we are stopped at '_dyld_start'
        ThreadSP thread_sp(m_process->GetThreadList().GetThreadAtIndex(0));
        if (thread_sp) {
          lldb::StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0));
          if (frame_sp) {
            const Symbol *symbol =
                frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
            if (symbol) {
              if (symbol->GetName() == "_dyld_start")
                did_exec = true;
            }
          }
        }
      }
    }
  }

  if (did_exec) {
    m_libpthread_module_wp.reset();
    m_pthread_getspecific_addr.Clear();
    m_libsystem_fully_initalized = false;
  }
  return did_exec;
}

// Clear out the state of this class.
void DynamicLoaderMacOS::DoClear() {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);

  if (LLDB_BREAK_ID_IS_VALID(m_break_id))
    m_process->GetTarget().RemoveBreakpointByID(m_break_id);
  if (LLDB_BREAK_ID_IS_VALID(m_dyld_handover_break_id))
    m_process->GetTarget().RemoveBreakpointByID(m_dyld_handover_break_id);

  m_break_id = LLDB_INVALID_BREAK_ID;
  m_dyld_handover_break_id = LLDB_INVALID_BREAK_ID;
  m_libsystem_fully_initalized = false;
}

bool DynamicLoaderMacOS::IsFullyInitialized() {
  if (m_libsystem_fully_initalized)
    return true;

  StructuredData::ObjectSP process_state_sp(
      m_process->GetDynamicLoaderProcessState());
  if (!process_state_sp)
    return true;
  if (process_state_sp->GetAsDictionary()->HasKey("error"))
    return true;
  if (!process_state_sp->GetAsDictionary()->HasKey("process_state string"))
    return true;
  std::string proc_state = process_state_sp->GetAsDictionary()
                               ->GetValueForKey("process_state string")
                               ->GetAsString()
                               ->GetValue()
                               .str();
  if (proc_state == "dyld_process_state_not_started" ||
      proc_state == "dyld_process_state_dyld_initialized" ||
      proc_state == "dyld_process_state_terminated_before_inits") {
    return false;
  }
  m_libsystem_fully_initalized = true;
  return true;
}

// Check if we have found DYLD yet
bool DynamicLoaderMacOS::DidSetNotificationBreakpoint() {
  return LLDB_BREAK_ID_IS_VALID(m_break_id);
}

void DynamicLoaderMacOS::ClearNotificationBreakpoint() {
  if (LLDB_BREAK_ID_IS_VALID(m_break_id)) {
    m_process->GetTarget().RemoveBreakpointByID(m_break_id);
    m_break_id = LLDB_INVALID_BREAK_ID;
  }
}

void DynamicLoaderMacOS::DoInitialImageFetch() {
  Log *log = GetLog(LLDBLog::DynamicLoader);

  // Remove any binaries we pre-loaded in the Target before
  // launching/attaching. If the same binaries are present in the process,
  // we'll get them from the shared module cache, we won't need to re-load them
  // from disk.
  UnloadAllImages();

  StructuredData::ObjectSP all_image_info_json_sp(
      m_process->GetLoadedDynamicLibrariesInfos(
          eBinaryInformationLevelAddrOnly));
  ImageInfo::collection image_infos;
  if (all_image_info_json_sp.get() &&
      all_image_info_json_sp->GetAsDictionary() &&
      all_image_info_json_sp->GetAsDictionary()->HasKey("images") &&
      all_image_info_json_sp->GetAsDictionary()
          ->GetValueForKey("images")
          ->GetAsArray()) {

    // Older debugserver (pre-2024-ish) will not recognize the
    // eBinaryInformationLevelAddrOnly enum above, and
    // will return the full binary information including mach
    // header and segments/load commands.  The response includes
    // the full information on all binaries.
    StructuredData::Array *images = all_image_info_json_sp->GetAsDictionary()
                                        ->GetValueForKey("images")
                                        ->GetAsArray();
    if (images->GetSize() > 0 && images->GetItemAtIndex(0)->GetAsDictionary() &&
        images->GetItemAtIndex(0)->GetAsDictionary()->HasKey("mach_header")) {
      if (JSONImageInformationIntoImageInfo(all_image_info_json_sp,
                                            image_infos)) {
        LLDB_LOGF(log, "Initial module fetch:  Adding %" PRIu64 " modules.\n",
                  (uint64_t)image_infos.size());

        auto new_images = PreloadModulesFromImageInfos(image_infos);
        UpdateSpecialBinariesFromPreloadedModules(new_images);
        AddModulesUsingPreloadedModules(new_images);
      }
    } else {
      // This is a newer debugserver which only replied with
      // `load_address` for all binaries loaded in the process.
      // We can request detailed information in smaller chunks,
      // instead of one gigantic packet.
      size_t image_count = images->GetSize();
      std::vector<addr_t> load_addresses;
      for (size_t i = 0; i < image_count; i++) {
        StructuredData::Dictionary *image =
            images->GetItemAtIndex(i)->GetAsDictionary();
        if (image && image->HasKey("load_address")) {
          addr_t val = image->GetValueForKey("load_address")
                           ->GetUnsignedIntegerValue(LLDB_INVALID_ADDRESS);
          if (val != LLDB_INVALID_ADDRESS)
            load_addresses.push_back(val);
        }
      }
      AddBinaries(load_addresses);
    }
  }

  m_dyld_image_infos_stop_id = m_process->GetStopID();
  m_maybe_image_infos_address = m_process->GetImageInfoAddress();
}

bool DynamicLoaderMacOS::NeedToDoInitialImageFetch() { return true; }

// Static callback function that gets called when our DYLD notification
// breakpoint gets hit. We update all of our image infos and then let our super
// class DynamicLoader class decide if we should stop or not (based on global
// preference).
bool DynamicLoaderMacOS::NotifyBreakpointHit(void *baton,
                                             StoppointCallbackContext *context,
                                             lldb::user_id_t break_id,
                                             lldb::user_id_t break_loc_id) {
  //
  // Our breakpoint on
  //
  // void lldb_image_notifier(enum dyld_image_mode mode, uint32_t infoCount,
  // const dyld_image_info info[])
  //
  // has been hit.  We need to read the arguments.

  DynamicLoaderMacOS *dyld_instance = (DynamicLoaderMacOS *)baton;

  ExecutionContext exe_ctx(context->exe_ctx_ref);
  Process *process = exe_ctx.GetProcessPtr();

  // This is a sanity check just in case this dyld_instance is an old dyld
  // plugin's breakpoint still lying around.
  if (process != dyld_instance->m_process)
    return false;

  if (dyld_instance->m_image_infos_stop_id != UINT32_MAX &&
      process->GetStopID() < dyld_instance->m_image_infos_stop_id) {
    return false;
  }

  const lldb::ABISP &abi = process->GetABI();
  if (abi) {
    // Build up the value array to store the three arguments given above, then
    // get the values from the ABI:

    TypeSystemClangSP scratch_ts_sp =
        ScratchTypeSystemClang::GetForTarget(process->GetTarget());
    if (!scratch_ts_sp)
      return false;

    ValueList argument_values;

    Value mode_value;    // enum dyld_notify_mode { dyld_notify_adding=0,
                         // dyld_notify_removing=1, dyld_notify_remove_all=2,
                         // dyld_notify_dyld_moved=3 };
    Value count_value;   // uint32_t
    Value headers_value; // struct dyld_image_info machHeaders[]

    CompilerType clang_void_ptr_type =
        scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType();
    CompilerType clang_uint32_type =
        scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint,
                                                           32);
    CompilerType clang_uint64_type =
        scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint,
                                                           32);

    mode_value.SetValueType(Value::ValueType::Scalar);
    mode_value.SetCompilerType(clang_uint32_type);

    count_value.SetValueType(Value::ValueType::Scalar);
    count_value.SetCompilerType(clang_uint32_type);

    headers_value.SetValueType(Value::ValueType::Scalar);
    headers_value.SetCompilerType(clang_void_ptr_type);

    argument_values.PushValue(mode_value);
    argument_values.PushValue(count_value);
    argument_values.PushValue(headers_value);

    if (abi->GetArgumentValues(exe_ctx.GetThreadRef(), argument_values)) {
      uint32_t dyld_mode =
          argument_values.GetValueAtIndex(0)->GetScalar().UInt(-1);
      if (dyld_mode != static_cast<uint32_t>(-1)) {
        // Okay the mode was right, now get the number of elements, and the
        // array of new elements...
        uint32_t image_infos_count =
            argument_values.GetValueAtIndex(1)->GetScalar().UInt(-1);
        if (image_infos_count != static_cast<uint32_t>(-1)) {
          addr_t header_array =
              argument_values.GetValueAtIndex(2)->GetScalar().ULongLong(-1);
          if (header_array != static_cast<uint64_t>(-1)) {
            std::vector<addr_t> image_load_addresses;
            // header_array points to an array of image_infos_count elements,
            // each is
            // struct dyld_image_info {
            //   const struct mach_header* imageLoadAddress;
            //   const char*               imageFilePath;
            //   uintptr_t                 imageFileModDate;
            // };
            //
            // and we only need the imageLoadAddress fields.

            const int addrsize =
                process->GetTarget().GetArchitecture().GetAddressByteSize();
            for (uint64_t i = 0; i < image_infos_count; i++) {
              Status error;
              addr_t dyld_image_info = header_array + (addrsize * 3 * i);
              addr_t addr =
                  process->ReadPointerFromMemory(dyld_image_info, error);
              if (error.Success()) {
                image_load_addresses.push_back(addr);
              } else {
                Debugger::ReportWarning(
                    "DynamicLoaderMacOS::NotifyBreakpointHit unable "
                    "to read binary mach-o load address at 0x%" PRIx64,
                    addr);
              }
            }
            if (dyld_mode == 0) {
              // dyld_notify_adding
              if (process->GetTarget().GetImages().GetSize() == 0) {
                // When all images have been removed, we're doing the
                // dyld handover from a launch-dyld to a shared-cache-dyld,
                // and we've just hit our one-shot address breakpoint in
                // the sc-dyld.  Note that the image addresses passed to
                // this function are inferior sizeof(void*) not uint64_t's
                // like our normal notification, so don't even look at
                // image_load_addresses.

                dyld_instance->ClearDYLDHandoverBreakpoint();

                dyld_instance->DoInitialImageFetch();
                dyld_instance->SetNotificationBreakpoint();
              } else {
                dyld_instance->AddBinaries(image_load_addresses);
              }
            } else if (dyld_mode == 1) {
              // dyld_notify_removing
              dyld_instance->UnloadImages(image_load_addresses);
            } else if (dyld_mode == 2) {
              // dyld_notify_remove_all
              dyld_instance->UnloadAllImages();
            } else if (dyld_mode == 3 && image_infos_count == 1) {
              // dyld_image_dyld_moved

              dyld_instance->ClearNotificationBreakpoint();
              dyld_instance->UnloadAllImages();
              dyld_instance->ClearDYLDModule();
              process->GetTarget().GetImages().Clear();
              process->GetTarget().ClearSectionLoadList();

              addr_t all_image_infos = process->GetImageInfoAddress();
              int addr_size =
                  process->GetTarget().GetArchitecture().GetAddressByteSize();
              addr_t notification_location = all_image_infos + 4 + // version
                                             4 +        // infoArrayCount
                                             addr_size; // infoArray
              Status error;
              addr_t notification_addr =
                  process->ReadPointerFromMemory(notification_location, error);
              if (!error.Success()) {
                Debugger::ReportWarning(
                    "DynamicLoaderMacOS::NotifyBreakpointHit unable "
                    "to read address of dyld-handover notification function at "
                    "0x%" PRIx64,
                    notification_location);
              } else {
                notification_addr = process->FixCodeAddress(notification_addr);
                dyld_instance->SetDYLDHandoverBreakpoint(notification_addr);
              }
            }
          }
        }
      }
    }
  } else {
    Target &target = process->GetTarget();
    Debugger::ReportWarning(
        "no ABI plugin located for triple " +
            target.GetArchitecture().GetTriple().getTriple() +
            ": shared libraries will not be registered",
        target.GetDebugger().GetID());
  }

  // Return true to stop the target, false to just let the target run
  return dyld_instance->GetStopWhenImagesChange();
}

void DynamicLoaderMacOS::AddBinaries(
    const std::vector<lldb::addr_t> &load_addresses) {
  Log *log = GetLog(LLDBLog::DynamicLoader);
  ImageInfo::collection image_infos;

  // For now, hardcode a limit of fetching 600 binaries at once.
  // Fetching the full binary information for a large number of
  // binaries can cause debugserver to use too much memory on
  // memory-limited environments, and get killed.
  const size_t image_fetch_max = 600;
  size_t fetched = 0;
  size_t total_image_size = load_addresses.size();
  while (fetched < total_image_size) {
    size_t this_fetch_amt =
        std::min(image_fetch_max, total_image_size - fetched);
    std::vector<addr_t> fetch_binaries(load_addresses.begin() + fetched,
                                       load_addresses.begin() + fetched +
                                           this_fetch_amt);

    LLDB_LOGF(log, "Adding %" PRId64 " modules.",
              (uint64_t)fetch_binaries.size());
    image_infos.clear();
    StructuredData::ObjectSP binaries_info_sp =
        m_process->GetLoadedDynamicLibrariesInfos(eBinaryInformationLevelFull,
                                                  fetch_binaries);
    if (binaries_info_sp && binaries_info_sp->GetAsDictionary() &&
        binaries_info_sp->GetAsDictionary()->HasKey("images") &&
        binaries_info_sp->GetAsDictionary()
            ->GetValueForKey("images")
            ->GetAsArray()) {
      StructuredData::Array *images = binaries_info_sp->GetAsDictionary()
                                          ->GetValueForKey("images")
                                          ->GetAsArray();
      if (images->GetSize() == fetch_binaries.size() &&
          JSONImageInformationIntoImageInfo(binaries_info_sp, image_infos)) {
        auto new_images = PreloadModulesFromImageInfos(image_infos);
        UpdateSpecialBinariesFromPreloadedModules(new_images);
        AddModulesUsingPreloadedModules(new_images);
      }
    }
    fetched += this_fetch_amt;
  }
  m_dyld_image_infos_stop_id = m_process->GetStopID();
}

// Dump the _dyld_all_image_infos members and all current image infos that we
// have parsed to the file handle provided.
void DynamicLoaderMacOS::PutToLog(Log *log) const {
  if (log == nullptr)
    return;
}

// Look in dyld's dyld_all_image_infos structure for the address
// of the notification function.
// We can find the address of dyld_all_image_infos by a system
// call, even if we don't have a dyld binary registered in lldb's
// image list.
// At process launch time - before dyld has executed any instructions -
// the address of the notification function is not a resolved vm address
// yet.  dyld_all_image_infos also has a field with its own address
// in it, and this will also be unresolved when we're at this state.
// So we can compare the address of the object with this field and if
// they differ, dyld hasn't started executing yet and we can't get the
// notification address this way.
addr_t DynamicLoaderMacOS::GetNotificationFuncAddrFromImageInfos() {
  addr_t notification_addr = LLDB_INVALID_ADDRESS;
  if (!m_process)
    return notification_addr;

  addr_t all_image_infos_addr = m_process->GetImageInfoAddress();
  if (all_image_infos_addr == LLDB_INVALID_ADDRESS)
    return notification_addr;

  const uint32_t addr_size =
      m_process->GetTarget().GetArchitecture().GetAddressByteSize();
  offset_t registered_infos_addr_offset =
      sizeof(uint32_t) + // version
      sizeof(uint32_t) + // infoArrayCount
      addr_size +        // infoArray
      addr_size +        // notification
      addr_size +        // processDetachedFromSharedRegion +
                         // libSystemInitialized + pad
      addr_size +        // dyldImageLoadAddress
      addr_size +        // jitInfo
      addr_size +        // dyldVersion
      addr_size +        // errorMessage
      addr_size +        // terminationFlags
      addr_size +        // coreSymbolicationShmPage
      addr_size +        // systemOrderFlag
      addr_size +        // uuidArrayCount
      addr_size;         // uuidArray
                         // dyldAllImageInfosAddress

  // If the dyldAllImageInfosAddress does not match
  // the actual address of this struct, dyld has not started
  // executing yet.  The 'notification' field can't be used by
  // lldb until it's resolved to an actual address.
  Status error;
  addr_t registered_infos_addr = m_process->ReadPointerFromMemory(
      all_image_infos_addr + registered_infos_addr_offset, error);
  if (!error.Success())
    return notification_addr;
  if (registered_infos_addr != all_image_infos_addr)
    return notification_addr;

  offset_t notification_fptr_offset = sizeof(uint32_t) + // version
                                      sizeof(uint32_t) + // infoArrayCount
                                      addr_size;         // infoArray

  addr_t notification_fptr = m_process->ReadPointerFromMemory(
      all_image_infos_addr + notification_fptr_offset, error);
  if (error.Success())
    notification_addr = m_process->FixCodeAddress(notification_fptr);
  return notification_addr;
}

// We want to put a breakpoint on dyld's lldb_image_notifier()
// but we may have attached to the process during the
// transition from on-disk-dyld to shared-cache-dyld, so there's
// officially no dyld binary loaded in the process (libdyld will
// report none when asked), but the kernel can find the dyld_all_image_infos
// struct and the function pointer for lldb_image_notifier is in
// that struct.
bool DynamicLoaderMacOS::SetNotificationBreakpoint() {

  // First try to find the notification breakpoint function by name
  if (m_break_id == LLDB_INVALID_BREAK_ID) {
    ModuleSP dyld_sp(GetDYLDModule());
    if (dyld_sp) {
      bool internal = true;
      bool hardware = false;
      LazyBool skip_prologue = eLazyBoolNo;
      FileSpecList *source_files = nullptr;
      FileSpecList dyld_filelist;
      dyld_filelist.Append(dyld_sp->GetFileSpec());

      Breakpoint *breakpoint =
          m_process->GetTarget()
              .CreateBreakpoint(&dyld_filelist, source_files,
                                "lldb_image_notifier", eFunctionNameTypeFull,
                                eLanguageTypeUnknown, 0, false, skip_prologue,
                                internal, hardware)
              .get();
      breakpoint->SetCallback(DynamicLoaderMacOS::NotifyBreakpointHit, this,
                              true);
      breakpoint->SetBreakpointKind("shared-library-event");
      if (breakpoint->HasResolvedLocations())
        m_break_id = breakpoint->GetID();
      else
        m_process->GetTarget().RemoveBreakpointByID(breakpoint->GetID());

      if (m_break_id == LLDB_INVALID_BREAK_ID) {
        Breakpoint *breakpoint =
            m_process->GetTarget()
                .CreateBreakpoint(&dyld_filelist, source_files,
                                  "gdb_image_notifier", eFunctionNameTypeFull,
                                  eLanguageTypeUnknown, 0,
                                  /*offset_is_insn_count = */ false,
                                  skip_prologue, internal, hardware)
                .get();
        breakpoint->SetCallback(DynamicLoaderMacOS::NotifyBreakpointHit, this,
                                true);
        breakpoint->SetBreakpointKind("shared-library-event");
        if (breakpoint->HasResolvedLocations())
          m_break_id = breakpoint->GetID();
        else
          m_process->GetTarget().RemoveBreakpointByID(breakpoint->GetID());
      }
    }
  }

  // Failing that, find dyld_all_image_infos struct in memory,
  // read the notification function pointer at the offset.
  if (m_break_id == LLDB_INVALID_BREAK_ID) {
    addr_t notification_addr = GetNotificationFuncAddrFromImageInfos();
    if (notification_addr != LLDB_INVALID_ADDRESS) {
      Address so_addr;
      // We may not have a dyld binary mapped to this address yet;
      // don't try to express the Address object as section+offset,
      // only as a raw load address.
      so_addr.SetRawAddress(notification_addr);
      Breakpoint *dyld_break =
          m_process->GetTarget().CreateBreakpoint(so_addr, true, false).get();
      dyld_break->SetCallback(DynamicLoaderMacOS::NotifyBreakpointHit, this,
                              true);
      dyld_break->SetBreakpointKind("shared-library-event");
      if (dyld_break->HasResolvedLocations())
        m_break_id = dyld_break->GetID();
      else
        m_process->GetTarget().RemoveBreakpointByID(dyld_break->GetID());
    }
  }
  return m_break_id != LLDB_INVALID_BREAK_ID;
}

bool DynamicLoaderMacOS::SetDYLDHandoverBreakpoint(
    addr_t notification_address) {
  if (m_dyld_handover_break_id == LLDB_INVALID_BREAK_ID) {
    BreakpointSP dyld_handover_bp = m_process->GetTarget().CreateBreakpoint(
        notification_address, true, false);
    dyld_handover_bp->SetCallback(DynamicLoaderMacOS::NotifyBreakpointHit, this,
                                  true);
    dyld_handover_bp->SetOneShot(true);
    m_dyld_handover_break_id = dyld_handover_bp->GetID();
    return true;
  }
  return false;
}

void DynamicLoaderMacOS::ClearDYLDHandoverBreakpoint() {
  if (LLDB_BREAK_ID_IS_VALID(m_dyld_handover_break_id))
    m_process->GetTarget().RemoveBreakpointByID(m_dyld_handover_break_id);
  m_dyld_handover_break_id = LLDB_INVALID_BREAK_ID;
}

addr_t
DynamicLoaderMacOS::GetDyldLockVariableAddressFromModule(Module *module) {
  SymbolContext sc;
  Target &target = m_process->GetTarget();
  if (Symtab *symtab = module->GetSymtab()) {
    std::vector<uint32_t> match_indexes;
    ConstString g_symbol_name("_dyld_global_lock_held");
    uint32_t num_matches = 0;
    num_matches =
        symtab->AppendSymbolIndexesWithName(g_symbol_name, match_indexes);
    if (num_matches == 1) {
      const Symbol *symbol = symtab->SymbolAtIndex(match_indexes[0]);
      if (symbol &&
          (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())) {
        return symbol->GetAddressRef().GetOpcodeLoadAddress(&target);
      }
    }
  }
  return LLDB_INVALID_ADDRESS;
}

//  Look for this symbol:
//
//  int __attribute__((visibility("hidden")))           _dyld_global_lock_held =
//  0;
//
//  in libdyld.dylib.
Status DynamicLoaderMacOS::CanLoadImage() {
  Status error;
  addr_t symbol_address = LLDB_INVALID_ADDRESS;
  ConstString g_libdyld_name("libdyld.dylib");
  Target &target = m_process->GetTarget();
  const ModuleList &target_modules = target.GetImages();
  std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());

  // Find any modules named "libdyld.dylib" and look for the symbol there first
  for (ModuleSP module_sp : target.GetImages().ModulesNoLocking()) {
    if (module_sp) {
      if (module_sp->GetFileSpec().GetFilename() == g_libdyld_name) {
        symbol_address = GetDyldLockVariableAddressFromModule(module_sp.get());
        if (symbol_address != LLDB_INVALID_ADDRESS)
          break;
      }
    }
  }

  // Search through all modules looking for the symbol in them
  if (symbol_address == LLDB_INVALID_ADDRESS) {
    for (ModuleSP module_sp : target.GetImages().Modules()) {
      if (module_sp) {
        addr_t symbol_address =
            GetDyldLockVariableAddressFromModule(module_sp.get());
        if (symbol_address != LLDB_INVALID_ADDRESS)
          break;
      }
    }
  }

  // Default assumption is that it is OK to load images. Only say that we
  // cannot load images if we find the symbol in libdyld and it indicates that
  // we cannot.

  if (symbol_address != LLDB_INVALID_ADDRESS) {
    {
      int lock_held =
          m_process->ReadUnsignedIntegerFromMemory(symbol_address, 4, 0, error);
      if (lock_held != 0) {
        error =
            Status::FromErrorString("dyld lock held - unsafe to load images.");
      }
    }
  } else {
    // If we were unable to find _dyld_global_lock_held in any modules, or it
    // is not loaded into memory yet, we may be at process startup (sitting  at
    // _dyld_start) - so we should not allow dlopen calls. But if we found more
    // than one module then we are clearly past _dyld_start so in that case
    // we'll default to "it's safe".
    if (target.GetImages().GetSize() <= 1)
      error = Status::FromErrorString("could not find the dyld library or "
                                      "the dyld lock symbol");
  }
  return error;
}

bool DynamicLoaderMacOS::GetSharedCacheInformation(
    lldb::addr_t &base_address, UUID &uuid, LazyBool &using_shared_cache,
    LazyBool &private_shared_cache, FileSpec &shared_cache_path,
    std::optional<uint64_t> &size) {
  base_address = LLDB_INVALID_ADDRESS;
  uuid.Clear();
  using_shared_cache = eLazyBoolCalculate;
  private_shared_cache = eLazyBoolCalculate;
  size.reset();

  if (m_process) {
    StructuredData::ObjectSP info = m_process->GetSharedCacheInfo();
    StructuredData::Dictionary *info_dict = nullptr;
    if (info.get() && info->GetAsDictionary()) {
      info_dict = info->GetAsDictionary();
    }

    // { "shared_cache_base_address":6580879360,
    //   "shared_cache_uuid":"71E62C65-D8D9-32D0-9A0B-7F5154C8049F",
    //   "no_shared_cache":false,
    //   "shared_cache_private_cache":false,
    //   "shared_cache_path":"/S/V/P/C/OS/Sm/L/dyld/dyld_shared_cache_arm64e",
    //   "shared_cache_size":6012010496
    // }

    if (info_dict && info_dict->HasKey("shared_cache_uuid") &&
        info_dict->HasKey("no_shared_cache") &&
        info_dict->HasKey("shared_cache_private_cache") &&
        info_dict->HasKey("shared_cache_base_address")) {
      base_address = info_dict->GetValueForKey("shared_cache_base_address")
                         ->GetUnsignedIntegerValue(LLDB_INVALID_ADDRESS);
      std::string uuid_str = std::string(
          info_dict->GetValueForKey("shared_cache_uuid")->GetStringValue());
      if (!uuid_str.empty())
        uuid.SetFromStringRef(uuid_str);
      if (!info_dict->GetValueForKey("no_shared_cache")->GetBooleanValue())
        using_shared_cache = eLazyBoolYes;
      else
        using_shared_cache = eLazyBoolNo;
      if (info_dict->GetValueForKey("shared_cache_private_cache")
              ->GetBooleanValue())
        private_shared_cache = eLazyBoolYes;
      else
        private_shared_cache = eLazyBoolNo;
      if (info_dict->HasKey("shared_cache_path")) {
        llvm::StringRef filepath =
            info_dict->GetValueForKey("shared_cache_path")->GetStringValue();
        shared_cache_path.SetPath(filepath);
      }
      if (info_dict->HasKey("shared_cache_size")) {
        uint64_t val = info_dict->GetValueForKey("shared_cache_size")
                           ->GetUnsignedIntegerValue(LLDB_INVALID_ADDRESS);
        if (val != LLDB_INVALID_ADDRESS)
          size = val;
      }
      return true;
    }
  }
  return false;
}

void DynamicLoaderMacOS::Initialize() {
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                GetPluginDescriptionStatic(), CreateInstance);
}

void DynamicLoaderMacOS::Terminate() {
  PluginManager::UnregisterPlugin(CreateInstance);
}

llvm::StringRef DynamicLoaderMacOS::GetPluginDescriptionStatic() {
  return "Dynamic loader plug-in that watches for shared library loads/unloads "
         "in MacOSX user processes.";
}
