//===-- DynamicLoaderMacOSXDYLD.cpp -----------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#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/Core/State.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"

#include "DynamicLoaderDarwin.h"
#include "DynamicLoaderMacOSXDYLD.h"

//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
#ifdef ENABLE_DEBUG_PRINTF
#include <stdio.h>
#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

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 *DynamicLoaderMacOSXDYLD::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:
        create = triple_ref.getVendor() == llvm::Triple::Apple;
        break;
      default:
        create = false;
        break;
      }
    }
  }

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

  if (create)
    return new DynamicLoaderMacOSXDYLD(process);
  return NULL;
}

//----------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------
DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD(Process *process)
    : DynamicLoaderDarwin(process),
      m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS),
      m_dyld_all_image_infos(), m_dyld_all_image_infos_stop_id(UINT32_MAX),
      m_break_id(LLDB_INVALID_BREAK_ID), m_mutex(),
      m_process_image_addr_is_all_images_infos(false) {}

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

bool DynamicLoaderMacOSXDYLD::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) {
      // We know if a process has exec'ed if our "m_dyld_all_image_infos_addr"
      // value differs from the Process' image info address. When a process
      // execs itself it might cause a change if ASLR is enabled.
      const addr_t shlib_addr = m_process->GetImageInfoAddress();
      if (m_process_image_addr_is_all_images_infos == true &&
          shlib_addr != m_dyld_all_image_infos_addr) {
        // The image info address from the process is the 'dyld_all_image_infos'
        // address and it has changed.
        did_exec = true;
      } else if (m_process_image_addr_is_all_images_infos == false &&
                 shlib_addr == m_dyld.address) {
        // The image info address from the process is the mach_header
        // address for dyld and it has changed.
        did_exec = true;
      } else {
        // ASLR might be disabled and dyld could have ended up in the same
        // location. We should try and detect 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() == ConstString("_dyld_start"))
                did_exec = true;
            }
          }
        }
      }

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

//----------------------------------------------------------------------
// Clear out the state of this class.
//----------------------------------------------------------------------
void DynamicLoaderMacOSXDYLD::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);

  m_dyld_all_image_infos_addr = LLDB_INVALID_ADDRESS;
  m_dyld_all_image_infos.Clear();
  m_break_id = LLDB_INVALID_BREAK_ID;
}

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

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

//----------------------------------------------------------------------
// Try and figure out where dyld is by first asking the Process
// if it knows (which currently calls down in the lldb::Process
// to get the DYLD info (available on SnowLeopard only). If that fails,
// then check in the default addresses.
//----------------------------------------------------------------------
void DynamicLoaderMacOSXDYLD::DoInitialImageFetch() {
  if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS) {
    // Check the image info addr as it might point to the
    // mach header for dyld, or it might point to the
    // dyld_all_image_infos struct
    const addr_t shlib_addr = m_process->GetImageInfoAddress();
    if (shlib_addr != LLDB_INVALID_ADDRESS) {
      ByteOrder byte_order =
          m_process->GetTarget().GetArchitecture().GetByteOrder();
      uint8_t buf[4];
      DataExtractor data(buf, sizeof(buf), byte_order, 4);
      Status error;
      if (m_process->ReadMemory(shlib_addr, buf, 4, error) == 4) {
        lldb::offset_t offset = 0;
        uint32_t magic = data.GetU32(&offset);
        switch (magic) {
        case llvm::MachO::MH_MAGIC:
        case llvm::MachO::MH_MAGIC_64:
        case llvm::MachO::MH_CIGAM:
        case llvm::MachO::MH_CIGAM_64:
          m_process_image_addr_is_all_images_infos = false;
          ReadDYLDInfoFromMemoryAndSetNotificationCallback(shlib_addr);
          return;

        default:
          break;
        }
      }
      // Maybe it points to the all image infos?
      m_dyld_all_image_infos_addr = shlib_addr;
      m_process_image_addr_is_all_images_infos = true;
    }
  }

  if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) {
    if (ReadAllImageInfosStructure()) {
      if (m_dyld_all_image_infos.dyldImageLoadAddress != LLDB_INVALID_ADDRESS)
        ReadDYLDInfoFromMemoryAndSetNotificationCallback(
            m_dyld_all_image_infos.dyldImageLoadAddress);
      else
        ReadDYLDInfoFromMemoryAndSetNotificationCallback(
            m_dyld_all_image_infos_addr & 0xfffffffffff00000ull);
      return;
    }
  }

  // Check some default values
  Module *executable = m_process->GetTarget().GetExecutableModulePointer();

  if (executable) {
    const ArchSpec &exe_arch = executable->GetArchitecture();
    if (exe_arch.GetAddressByteSize() == 8) {
      ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull);
    } else if (exe_arch.GetMachine() == llvm::Triple::arm ||
               exe_arch.GetMachine() == llvm::Triple::thumb ||
               exe_arch.GetMachine() == llvm::Triple::aarch64) {
      ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000);
    } else {
      ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000);
    }
  }
  return;
}

//----------------------------------------------------------------------
// Assume that dyld is in memory at ADDR and try to parse it's load
// commands
//----------------------------------------------------------------------
bool DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(
    lldb::addr_t addr) {
  std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
  DataExtractor data; // Load command data
  static ConstString g_dyld_all_image_infos("dyld_all_image_infos");
  if (ReadMachHeader(addr, &m_dyld.header, &data)) {
    if (m_dyld.header.filetype == llvm::MachO::MH_DYLINKER) {
      m_dyld.address = addr;
      ModuleSP dyld_module_sp;
      if (ParseLoadCommands(data, m_dyld, &m_dyld.file_spec)) {
        if (m_dyld.file_spec) {
          UpdateDYLDImageInfoFromNewImageInfo(m_dyld);
        }
      }
      dyld_module_sp = GetDYLDModule();

      Target &target = m_process->GetTarget();

      if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS &&
          dyld_module_sp.get()) {
        const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType(
            g_dyld_all_image_infos, eSymbolTypeData);
        if (symbol)
          m_dyld_all_image_infos_addr = symbol->GetLoadAddress(&target);
      }

      // Update all image infos
      InitializeFromAllImageInfos();

      // If we didn't have an executable before, but now we do, then the
      // dyld module shared pointer might be unique and we may need to add
      // it again (since Target::SetExecutableModule() will clear the
      // images). So append the dyld module back to the list if it is
      /// unique!
      if (dyld_module_sp) {
        target.GetImages().AppendIfNeeded(dyld_module_sp);

        // At this point we should have read in dyld's module, and so we should
        // set breakpoints in it:
        ModuleList modules;
        modules.Append(dyld_module_sp);
        target.ModulesDidLoad(modules);
        SetDYLDModule(dyld_module_sp);
      }

      return true;
    }
  }
  return false;
}

bool DynamicLoaderMacOSXDYLD::NeedToDoInitialImageFetch() {
  return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS;
}

//----------------------------------------------------------------------
// 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 DynamicLoaderMacOSXDYLD::NotifyBreakpointHit(
    void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id,
    lldb::user_id_t break_loc_id) {
  // Let the event know that the images have changed
  // DYLD passes three arguments to the notification breakpoint.
  // Arg1: enum dyld_image_mode mode - 0 = adding, 1 = removing
  // Arg2: uint32_t infoCount        - Number of shared libraries added
  // Arg3: dyld_image_info info[]    - Array of structs of the form:
  //                                     const struct mach_header
  //                                     *imageLoadAddress
  //                                     const char               *imageFilePath
  //                                     uintptr_t imageFileModDate (a time_t)

  DynamicLoaderMacOSXDYLD *dyld_instance = (DynamicLoaderMacOSXDYLD *)baton;

  // First step is to see if we've already initialized the all image infos.  If
  // we haven't then this function
  // will do so and return true.  In the course of initializing the
  // all_image_infos it will read the complete
  // current state, so we don't need to figure out what has changed from the
  // data passed in to us.

  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->InitializeFromAllImageInfos())
    return dyld_instance->GetStopWhenImagesChange();

  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:

    ClangASTContext *clang_ast_context =
        process->GetTarget().GetScratchClangASTContext();
    ValueList argument_values;
    Value input_value;

    CompilerType clang_void_ptr_type =
        clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
    CompilerType clang_uint32_type =
        clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(
            lldb::eEncodingUint, 32);
    input_value.SetValueType(Value::eValueTypeScalar);
    input_value.SetCompilerType(clang_uint32_type);
    //        input_value.SetContext (Value::eContextTypeClangType,
    //        clang_uint32_type);
    argument_values.PushValue(input_value);
    argument_values.PushValue(input_value);
    input_value.SetCompilerType(clang_void_ptr_type);
    //        input_value.SetContext (Value::eContextTypeClangType,
    //        clang_void_ptr_type);
    argument_values.PushValue(input_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)) {
          // Got the number added, now go through the array of added elements,
          // putting out the mach header
          // address, and adding the image.
          // Note, I'm not putting in logging here, since the AddModules &
          // RemoveModules functions do
          // all the logging internally.

          lldb::addr_t image_infos_addr =
              argument_values.GetValueAtIndex(2)->GetScalar().ULongLong();
          if (dyld_mode == 0) {
            // This is add:
            dyld_instance->AddModulesUsingImageInfosAddress(image_infos_addr,
                                                            image_infos_count);
          } else {
            // This is remove:
            dyld_instance->RemoveModulesUsingImageInfosAddress(
                image_infos_addr, image_infos_count);
          }
        }
      }
    }
  } else {
    process->GetTarget().GetDebugger().GetAsyncErrorStream()->Printf(
        "No ABI plugin located for triple %s -- shared libraries will not be "
        "registered!\n",
        process->GetTarget().GetArchitecture().GetTriple().getTriple().c_str());
  }

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

bool DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure() {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);

  // the all image infos is already valid for this process stop ID
  if (m_process->GetStopID() == m_dyld_all_image_infos_stop_id)
    return true;

  m_dyld_all_image_infos.Clear();
  if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) {
    ByteOrder byte_order =
        m_process->GetTarget().GetArchitecture().GetByteOrder();
    uint32_t addr_size =
        m_process->GetTarget().GetArchitecture().GetAddressByteSize();

    uint8_t buf[256];
    DataExtractor data(buf, sizeof(buf), byte_order, addr_size);
    lldb::offset_t offset = 0;

    const size_t count_v2 = sizeof(uint32_t) + // version
                            sizeof(uint32_t) + // infoArrayCount
                            addr_size +        // infoArray
                            addr_size +        // notification
                            addr_size + // processDetachedFromSharedRegion +
                                        // libSystemInitialized + pad
                            addr_size;  // dyldImageLoadAddress
    const size_t count_v11 = count_v2 + addr_size +  // jitInfo
                             addr_size +             // dyldVersion
                             addr_size +             // errorMessage
                             addr_size +             // terminationFlags
                             addr_size +             // coreSymbolicationShmPage
                             addr_size +             // systemOrderFlag
                             addr_size +             // uuidArrayCount
                             addr_size +             // uuidArray
                             addr_size +             // dyldAllImageInfosAddress
                             addr_size +             // initialImageCount
                             addr_size +             // errorKind
                             addr_size +             // errorClientOfDylibPath
                             addr_size +             // errorTargetDylibPath
                             addr_size;              // errorSymbol
    const size_t count_v13 = count_v11 + addr_size + // sharedCacheSlide
                             sizeof(uuid_t);         // sharedCacheUUID
    UNUSED_IF_ASSERT_DISABLED(count_v13);
    assert(sizeof(buf) >= count_v13);

    Status error;
    if (m_process->ReadMemory(m_dyld_all_image_infos_addr, buf, 4, error) ==
        4) {
      m_dyld_all_image_infos.version = data.GetU32(&offset);
      // If anything in the high byte is set, we probably got the byte
      // order incorrect (the process might not have it set correctly
      // yet due to attaching to a program without a specified file).
      if (m_dyld_all_image_infos.version & 0xff000000) {
        // We have guessed the wrong byte order. Swap it and try
        // reading the version again.
        if (byte_order == eByteOrderLittle)
          byte_order = eByteOrderBig;
        else
          byte_order = eByteOrderLittle;

        data.SetByteOrder(byte_order);
        offset = 0;
        m_dyld_all_image_infos.version = data.GetU32(&offset);
      }
    } else {
      return false;
    }

    const size_t count =
        (m_dyld_all_image_infos.version >= 11) ? count_v11 : count_v2;

    const size_t bytes_read =
        m_process->ReadMemory(m_dyld_all_image_infos_addr, buf, count, error);
    if (bytes_read == count) {
      offset = 0;
      m_dyld_all_image_infos.version = data.GetU32(&offset);
      m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset);
      m_dyld_all_image_infos.dylib_info_addr = data.GetPointer(&offset);
      m_dyld_all_image_infos.notification = data.GetPointer(&offset);
      m_dyld_all_image_infos.processDetachedFromSharedRegion =
          data.GetU8(&offset);
      m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset);
      // Adjust for padding.
      offset += addr_size - 2;
      m_dyld_all_image_infos.dyldImageLoadAddress = data.GetPointer(&offset);
      if (m_dyld_all_image_infos.version >= 11) {
        offset += addr_size * 8;
        uint64_t dyld_all_image_infos_addr = data.GetPointer(&offset);

        // When we started, we were given the actual address of the
        // all_image_infos
        // struct (probably via TASK_DYLD_INFO) in memory - this address is
        // stored in
        // m_dyld_all_image_infos_addr and is the most accurate address we have.

        // We read the dyld_all_image_infos struct from memory; it contains its
        // own address.
        // If the address in the struct does not match the actual address,
        // the dyld we're looking at has been loaded at a different location
        // (slid) from
        // where it intended to load.  The addresses in the dyld_all_image_infos
        // struct
        // are the original, non-slid addresses, and need to be adjusted.  Most
        // importantly
        // the address of dyld and the notification address need to be adjusted.

        if (dyld_all_image_infos_addr != m_dyld_all_image_infos_addr) {
          uint64_t image_infos_offset =
              dyld_all_image_infos_addr -
              m_dyld_all_image_infos.dyldImageLoadAddress;
          uint64_t notification_offset =
              m_dyld_all_image_infos.notification -
              m_dyld_all_image_infos.dyldImageLoadAddress;
          m_dyld_all_image_infos.dyldImageLoadAddress =
              m_dyld_all_image_infos_addr - image_infos_offset;
          m_dyld_all_image_infos.notification =
              m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset;
        }
      }
      m_dyld_all_image_infos_stop_id = m_process->GetStopID();
      return true;
    }
  }
  return false;
}

bool DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfosAddress(
    lldb::addr_t image_infos_addr, uint32_t image_infos_count) {
  ImageInfo::collection image_infos;
  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
  if (log)
    log->Printf("Adding %d modules.\n", image_infos_count);

  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
  if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
    return true;

  StructuredData::ObjectSP image_infos_json_sp =
      m_process->GetLoadedDynamicLibrariesInfos(image_infos_addr,
                                                image_infos_count);
  if (image_infos_json_sp.get() && image_infos_json_sp->GetAsDictionary() &&
      image_infos_json_sp->GetAsDictionary()->HasKey("images") &&
      image_infos_json_sp->GetAsDictionary()
          ->GetValueForKey("images")
          ->GetAsArray() &&
      image_infos_json_sp->GetAsDictionary()
              ->GetValueForKey("images")
              ->GetAsArray()
              ->GetSize() == image_infos_count) {
    bool return_value = false;
    if (JSONImageInformationIntoImageInfo(image_infos_json_sp, image_infos)) {
      UpdateSpecialBinariesFromNewImageInfos(image_infos);
      return_value = AddModulesUsingImageInfos(image_infos);
    }
    m_dyld_image_infos_stop_id = m_process->GetStopID();
    return return_value;
  }

  if (!ReadImageInfos(image_infos_addr, image_infos_count, image_infos))
    return false;

  UpdateImageInfosHeaderAndLoadCommands(image_infos, image_infos_count, false);
  bool return_value = AddModulesUsingImageInfos(image_infos);
  m_dyld_image_infos_stop_id = m_process->GetStopID();
  return return_value;
}

bool DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress(
    lldb::addr_t image_infos_addr, uint32_t image_infos_count) {
  ImageInfo::collection image_infos;
  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));

  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
  if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
    return true;

  // First read in the image_infos for the removed modules, and their headers &
  // load commands.
  if (!ReadImageInfos(image_infos_addr, image_infos_count, image_infos)) {
    if (log)
      log->PutCString("Failed reading image infos array.");
    return false;
  }

  if (log)
    log->Printf("Removing %d modules.", image_infos_count);

  ModuleList unloaded_module_list;
  for (uint32_t idx = 0; idx < image_infos.size(); ++idx) {
    if (log) {
      log->Printf("Removing module at address=0x%16.16" PRIx64 ".",
                  image_infos[idx].address);
      image_infos[idx].PutToLog(log);
    }

    // Remove this image_infos from the m_all_image_infos.  We do the comparison
    // by address
    // rather than by file spec because we can have many modules with the same
    // "file spec" in the
    // case that they are modules loaded from memory.
    //
    // Also copy over the uuid from the old entry to the removed entry so we can
    // use it to lookup the module in the module list.

    ImageInfo::collection::iterator pos, end = m_dyld_image_infos.end();
    for (pos = m_dyld_image_infos.begin(); pos != end; pos++) {
      if (image_infos[idx].address == (*pos).address) {
        image_infos[idx].uuid = (*pos).uuid;

        // Add the module from this image_info to the "unloaded_module_list".
        // We'll remove them all at
        // one go later on.

        ModuleSP unload_image_module_sp(
            FindTargetModuleForImageInfo(image_infos[idx], false, NULL));
        if (unload_image_module_sp.get()) {
          // When we unload, be sure to use the image info from the old list,
          // since that has sections correctly filled in.
          UnloadModuleSections(unload_image_module_sp.get(), *pos);
          unloaded_module_list.AppendIfNeeded(unload_image_module_sp);
        } else {
          if (log) {
            log->Printf("Could not find module for unloading info entry:");
            image_infos[idx].PutToLog(log);
          }
        }

        // Then remove it from the m_dyld_image_infos:

        m_dyld_image_infos.erase(pos);
        break;
      }
    }

    if (pos == end) {
      if (log) {
        log->Printf("Could not find image_info entry for unloading image:");
        image_infos[idx].PutToLog(log);
      }
    }
  }
  if (unloaded_module_list.GetSize() > 0) {
    if (log) {
      log->PutCString("Unloaded:");
      unloaded_module_list.LogUUIDAndPaths(
          log, "DynamicLoaderMacOSXDYLD::ModulesDidUnload");
    }
    m_process->GetTarget().GetImages().Remove(unloaded_module_list);
  }
  m_dyld_image_infos_stop_id = m_process->GetStopID();
  return true;
}

bool DynamicLoaderMacOSXDYLD::ReadImageInfos(
    lldb::addr_t image_infos_addr, uint32_t image_infos_count,
    ImageInfo::collection &image_infos) {
  std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
  const ByteOrder endian = GetByteOrderFromMagic(m_dyld.header.magic);
  const uint32_t addr_size = m_dyld.GetAddressByteSize();

  image_infos.resize(image_infos_count);
  const size_t count = image_infos.size() * 3 * addr_size;
  DataBufferHeap info_data(count, 0);
  Status error;
  const size_t bytes_read = m_process->ReadMemory(
      image_infos_addr, info_data.GetBytes(), info_data.GetByteSize(), error);
  if (bytes_read == count) {
    lldb::offset_t info_data_offset = 0;
    DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(),
                                endian, addr_size);
    for (size_t i = 0;
         i < image_infos.size() && info_data_ref.ValidOffset(info_data_offset);
         i++) {
      image_infos[i].address = info_data_ref.GetPointer(&info_data_offset);
      lldb::addr_t path_addr = info_data_ref.GetPointer(&info_data_offset);
      image_infos[i].mod_date = info_data_ref.GetPointer(&info_data_offset);

      char raw_path[PATH_MAX];
      m_process->ReadCStringFromMemory(path_addr, raw_path, sizeof(raw_path),
                                       error);
      // don't resolve the path
      if (error.Success()) {
        const bool resolve_path = false;
        image_infos[i].file_spec.SetFile(raw_path, resolve_path);
      }
    }
    return true;
  } else {
    return false;
  }
}

//----------------------------------------------------------------------
// If we have found where the "_dyld_all_image_infos" lives in memory,
// read the current info from it, and then update all image load
// addresses (or lack thereof).  Only do this if this is the first time
// we're reading the dyld infos.  Return true if we actually read anything,
// and false otherwise.
//----------------------------------------------------------------------
bool DynamicLoaderMacOSXDYLD::InitializeFromAllImageInfos() {
  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));

  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
  if (m_process->GetStopID() == m_dyld_image_infos_stop_id ||
      m_dyld_image_infos.size() != 0)
    return false;

  if (ReadAllImageInfosStructure()) {
    // Nothing to load or unload?
    if (m_dyld_all_image_infos.dylib_info_count == 0)
      return true;

    if (m_dyld_all_image_infos.dylib_info_addr == 0) {
      // DYLD is updating the images now.  So we should say we have no images,
      // and then we'll
      // figure it out when we hit the added breakpoint.
      return false;
    } else {
      if (!AddModulesUsingImageInfosAddress(
              m_dyld_all_image_infos.dylib_info_addr,
              m_dyld_all_image_infos.dylib_info_count)) {
        DEBUG_PRINTF("%s", "unable to read all data for all_dylib_infos.");
        m_dyld_image_infos.clear();
      }
    }

    // Now we have one more bit of business.  If there is a library left in the
    // images for our target that
    // doesn't have a load address, then it must be something that we were
    // expecting to load (for instance we
    // read a load command for it) but it didn't in fact load - probably because
    // DYLD_*_PATH pointed
    // to an equivalent version.  We don't want it to stay in the target's
    // module list or it will confuse
    // us, so unload it here.
    Target &target = m_process->GetTarget();
    const ModuleList &target_modules = target.GetImages();
    ModuleList not_loaded_modules;
    std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());

    size_t num_modules = target_modules.GetSize();
    for (size_t i = 0; i < num_modules; i++) {
      ModuleSP module_sp = target_modules.GetModuleAtIndexUnlocked(i);
      if (!module_sp->IsLoadedInTarget(&target)) {
        if (log) {
          StreamString s;
          module_sp->GetDescription(&s);
          log->Printf("Unloading pre-run module: %s.", s.GetData());
        }
        not_loaded_modules.Append(module_sp);
      }
    }

    if (not_loaded_modules.GetSize() != 0) {
      target.GetImages().Remove(not_loaded_modules);
    }

    return true;
  } else
    return false;
}

//----------------------------------------------------------------------
// Read a mach_header at ADDR into HEADER, and also fill in the load
// command data into LOAD_COMMAND_DATA if it is non-NULL.
//
// Returns true if we succeed, false if we fail for any reason.
//----------------------------------------------------------------------
bool DynamicLoaderMacOSXDYLD::ReadMachHeader(lldb::addr_t addr,
                                             llvm::MachO::mach_header *header,
                                             DataExtractor *load_command_data) {
  DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0);
  Status error;
  size_t bytes_read = m_process->ReadMemory(addr, header_bytes.GetBytes(),
                                            header_bytes.GetByteSize(), error);
  if (bytes_read == sizeof(llvm::MachO::mach_header)) {
    lldb::offset_t offset = 0;
    ::memset(header, 0, sizeof(llvm::MachO::mach_header));

    // Get the magic byte unswapped so we can figure out what we are dealing
    // with
    DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(),
                       endian::InlHostByteOrder(), 4);
    header->magic = data.GetU32(&offset);
    lldb::addr_t load_cmd_addr = addr;
    data.SetByteOrder(
        DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header->magic));
    switch (header->magic) {
    case llvm::MachO::MH_MAGIC:
    case llvm::MachO::MH_CIGAM:
      data.SetAddressByteSize(4);
      load_cmd_addr += sizeof(llvm::MachO::mach_header);
      break;

    case llvm::MachO::MH_MAGIC_64:
    case llvm::MachO::MH_CIGAM_64:
      data.SetAddressByteSize(8);
      load_cmd_addr += sizeof(llvm::MachO::mach_header_64);
      break;

    default:
      return false;
    }

    // Read the rest of dyld's mach header
    if (data.GetU32(&offset, &header->cputype,
                    (sizeof(llvm::MachO::mach_header) / sizeof(uint32_t)) -
                        1)) {
      if (load_command_data == NULL)
        return true; // We were able to read the mach_header and weren't asked
                     // to read the load command bytes

      DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0));

      size_t load_cmd_bytes_read =
          m_process->ReadMemory(load_cmd_addr, load_cmd_data_sp->GetBytes(),
                                load_cmd_data_sp->GetByteSize(), error);

      if (load_cmd_bytes_read == header->sizeofcmds) {
        // Set the load command data and also set the correct endian
        // swap settings and the correct address size
        load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds);
        load_command_data->SetByteOrder(data.GetByteOrder());
        load_command_data->SetAddressByteSize(data.GetAddressByteSize());
        return true; // We successfully read the mach_header and the load
                     // command data
      }

      return false; // We weren't able to read the load command data
    }
  }
  return false; // We failed the read the mach_header
}

//----------------------------------------------------------------------
// Parse the load commands for an image
//----------------------------------------------------------------------
uint32_t DynamicLoaderMacOSXDYLD::ParseLoadCommands(const DataExtractor &data,
                                                    ImageInfo &dylib_info,
                                                    FileSpec *lc_id_dylinker) {
  lldb::offset_t offset = 0;
  uint32_t cmd_idx;
  Segment segment;
  dylib_info.Clear(true);

  for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++) {
    // Clear out any load command specific data from DYLIB_INFO since
    // we are about to read it.

    if (data.ValidOffsetForDataOfSize(offset,
                                      sizeof(llvm::MachO::load_command))) {
      llvm::MachO::load_command load_cmd;
      lldb::offset_t load_cmd_offset = offset;
      load_cmd.cmd = data.GetU32(&offset);
      load_cmd.cmdsize = data.GetU32(&offset);
      switch (load_cmd.cmd) {
      case llvm::MachO::LC_SEGMENT: {
        segment.name.SetTrimmedCStringWithLength(
            (const char *)data.GetData(&offset, 16), 16);
        // We are putting 4 uint32_t values 4 uint64_t values so
        // we have to use multiple 32 bit gets below.
        segment.vmaddr = data.GetU32(&offset);
        segment.vmsize = data.GetU32(&offset);
        segment.fileoff = data.GetU32(&offset);
        segment.filesize = data.GetU32(&offset);
        // Extract maxprot, initprot, nsects and flags all at once
        data.GetU32(&offset, &segment.maxprot, 4);
        dylib_info.segments.push_back(segment);
      } break;

      case llvm::MachO::LC_SEGMENT_64: {
        segment.name.SetTrimmedCStringWithLength(
            (const char *)data.GetData(&offset, 16), 16);
        // Extract vmaddr, vmsize, fileoff, and filesize all at once
        data.GetU64(&offset, &segment.vmaddr, 4);
        // Extract maxprot, initprot, nsects and flags all at once
        data.GetU32(&offset, &segment.maxprot, 4);
        dylib_info.segments.push_back(segment);
      } break;

      case llvm::MachO::LC_ID_DYLINKER:
        if (lc_id_dylinker) {
          const lldb::offset_t name_offset =
              load_cmd_offset + data.GetU32(&offset);
          const char *path = data.PeekCStr(name_offset);
          lc_id_dylinker->SetFile(path, true);
        }
        break;

      case llvm::MachO::LC_UUID:
        dylib_info.uuid.SetBytes(data.GetData(&offset, 16));
        break;

      default:
        break;
      }
      // Set offset to be the beginning of the next load command.
      offset = load_cmd_offset + load_cmd.cmdsize;
    }
  }

  // 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 = dylib_info.segments.size();
  for (size_t i = 0; i < num_sections; ++i) {
    // 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 ((dylib_info.segments[i].fileoff == 0 &&
         dylib_info.segments[i].filesize > 0) ||
        (dylib_info.segments[i].name == ConstString("__TEXT"))) {
      dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr;
      // We have found the slide amount, so we can exit
      // this for loop.
      break;
    }
  }
  return cmd_idx;
}

//----------------------------------------------------------------------
// Read the mach_header and load commands for each image that the
// _dyld_all_image_infos structure points to and cache the results.
//----------------------------------------------------------------------

void DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(
    ImageInfo::collection &image_infos, uint32_t infos_count,
    bool update_executable) {
  uint32_t exe_idx = UINT32_MAX;
  // Read any UUID values that we can get
  for (uint32_t i = 0; i < infos_count; i++) {
    if (!image_infos[i].UUIDValid()) {
      DataExtractor data; // Load command data
      if (!ReadMachHeader(image_infos[i].address, &image_infos[i].header,
                          &data))
        continue;

      ParseLoadCommands(data, image_infos[i], NULL);

      if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE)
        exe_idx = i;
    }
  }

  Target &target = m_process->GetTarget();

  if (exe_idx < image_infos.size()) {
    const bool can_create = true;
    ModuleSP exe_module_sp(
        FindTargetModuleForImageInfo(image_infos[exe_idx], can_create, NULL));

    if (exe_module_sp) {
      UpdateImageLoadAddress(exe_module_sp.get(), image_infos[exe_idx]);

      if (exe_module_sp.get() != target.GetExecutableModulePointer()) {
        // Don't load dependent images since we are in dyld where we will know
        // and find out about all images that are loaded. Also when setting the
        // executable module, it will clear the targets module list, and if we
        // have an in memory dyld module, it will get removed from the list
        // so we will need to add it back after setting the executable module,
        // so we first try and see if we already have a weak pointer to the
        // dyld module, make it into a shared pointer, then add the executable,
        // then re-add it back to make sure it is always in the list.
        ModuleSP dyld_module_sp(GetDYLDModule());

        const bool get_dependent_images = false;
        m_process->GetTarget().SetExecutableModule(exe_module_sp,
                                                   get_dependent_images);

        if (dyld_module_sp) {
          if (target.GetImages().AppendIfNeeded(dyld_module_sp)) {
            std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());

            // Also add it to the section list.
            UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
          }
        }
      }
    }
  }
}

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

  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
  log->Printf(
      "dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8" PRIx64
      ", notify=0x%8.8" PRIx64 " }",
      m_dyld_all_image_infos.version, m_dyld_all_image_infos.dylib_info_count,
      (uint64_t)m_dyld_all_image_infos.dylib_info_addr,
      (uint64_t)m_dyld_all_image_infos.notification);
  size_t i;
  const size_t count = m_dyld_image_infos.size();
  if (count > 0) {
    log->PutCString("Loaded:");
    for (i = 0; i < count; i++)
      m_dyld_image_infos[i].PutToLog(log);
  }
}

bool DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint() {
  DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n",
               __FUNCTION__, StateAsCString(m_process->GetState()));
  if (m_break_id == LLDB_INVALID_BREAK_ID) {
    if (m_dyld_all_image_infos.notification != LLDB_INVALID_ADDRESS) {
      Address so_addr;
      // Set the notification breakpoint and install a breakpoint
      // callback function that will get called each time the
      // breakpoint gets hit. We will use this to track when shared
      // libraries get loaded/unloaded.
      bool resolved = m_process->GetTarget().ResolveLoadAddress(
          m_dyld_all_image_infos.notification, so_addr);
      if (!resolved) {
        ModuleSP dyld_module_sp = GetDYLDModule();
        if (dyld_module_sp) {
          std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());

          UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
          resolved = m_process->GetTarget().ResolveLoadAddress(
              m_dyld_all_image_infos.notification, so_addr);
        }
      }

      if (resolved) {
        Breakpoint *dyld_break =
            m_process->GetTarget().CreateBreakpoint(so_addr, true, false).get();
        dyld_break->SetCallback(DynamicLoaderMacOSXDYLD::NotifyBreakpointHit,
                                this, true);
        dyld_break->SetBreakpointKind("shared-library-event");
        m_break_id = dyld_break->GetID();
      }
    }
  }
  return m_break_id != LLDB_INVALID_BREAK_ID;
}

Status DynamicLoaderMacOSXDYLD::CanLoadImage() {
  Status error;
  // In order for us to tell if we can load a shared library we verify that
  // the dylib_info_addr isn't zero (which means no shared libraries have
  // been set yet, or dyld is currently mucking with the shared library list).
  if (ReadAllImageInfosStructure()) {
    // TODO: also check the _dyld_global_lock_held variable in
    // libSystem.B.dylib?
    // TODO: check the malloc lock?
    // TODO: check the objective C lock?
    if (m_dyld_all_image_infos.dylib_info_addr != 0)
      return error; // Success
  }

  error.SetErrorString("unsafe to load or unload shared libraries");
  return error;
}

bool DynamicLoaderMacOSXDYLD::GetSharedCacheInformation(
    lldb::addr_t &base_address, UUID &uuid, LazyBool &using_shared_cache,
    LazyBool &private_shared_cache) {
  base_address = LLDB_INVALID_ADDRESS;
  uuid.Clear();
  using_shared_cache = eLazyBoolCalculate;
  private_shared_cache = eLazyBoolCalculate;

  if (m_process) {
    addr_t all_image_infos = m_process->GetImageInfoAddress();

    // The address returned by GetImageInfoAddress may be the address of dyld
    // (don't want)
    // or it may be the address of the dyld_all_image_infos structure (want).
    // The first four
    // bytes will be either the version field (all_image_infos) or a Mach-O file
    // magic constant.
    // Version 13 and higher of dyld_all_image_infos is required to get the
    // sharedCacheUUID field.

    Status err;
    uint32_t version_or_magic =
        m_process->ReadUnsignedIntegerFromMemory(all_image_infos, 4, -1, err);
    if (version_or_magic != static_cast<uint32_t>(-1) &&
        version_or_magic != llvm::MachO::MH_MAGIC &&
        version_or_magic != llvm::MachO::MH_CIGAM &&
        version_or_magic != llvm::MachO::MH_MAGIC_64 &&
        version_or_magic != llvm::MachO::MH_CIGAM_64 &&
        version_or_magic >= 13) {
      addr_t sharedCacheUUID_address = LLDB_INVALID_ADDRESS;
      int wordsize = m_process->GetAddressByteSize();
      if (wordsize == 8) {
        sharedCacheUUID_address =
            all_image_infos + 160; // sharedCacheUUID <mach-o/dyld_images.h>
      }
      if (wordsize == 4) {
        sharedCacheUUID_address =
            all_image_infos + 84; // sharedCacheUUID <mach-o/dyld_images.h>
      }
      if (sharedCacheUUID_address != LLDB_INVALID_ADDRESS) {
        uuid_t shared_cache_uuid;
        if (m_process->ReadMemory(sharedCacheUUID_address, shared_cache_uuid,
                                  sizeof(uuid_t), err) == sizeof(uuid_t)) {
          uuid.SetBytes(shared_cache_uuid);
          if (uuid.IsValid()) {
            using_shared_cache = eLazyBoolYes;
          }
        }

        if (version_or_magic >= 15) {
          // The sharedCacheBaseAddress field is the next one in the
          // dyld_all_image_infos struct.
          addr_t sharedCacheBaseAddr_address = sharedCacheUUID_address + 16;
          Status error;
          base_address = m_process->ReadUnsignedIntegerFromMemory(
              sharedCacheBaseAddr_address, wordsize, LLDB_INVALID_ADDRESS,
              error);
          if (error.Fail())
            base_address = LLDB_INVALID_ADDRESS;
        }

        return true;
      }

      //
      // add
      // NB: sharedCacheBaseAddress is the next field in dyld_all_image_infos
      // after
      // sharedCacheUUID -- that is, 16 bytes after it, if we wanted to fetch
      // it.
    }
  }
  return false;
}

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

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

lldb_private::ConstString DynamicLoaderMacOSXDYLD::GetPluginNameStatic() {
  static ConstString g_name("macosx-dyld");
  return g_name;
}

const char *DynamicLoaderMacOSXDYLD::GetPluginDescriptionStatic() {
  return "Dynamic loader plug-in that watches for shared library loads/unloads "
         "in MacOSX user processes.";
}

//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
lldb_private::ConstString DynamicLoaderMacOSXDYLD::GetPluginName() {
  return GetPluginNameStatic();
}

uint32_t DynamicLoaderMacOSXDYLD::GetPluginVersion() { return 1; }

uint32_t DynamicLoaderMacOSXDYLD::AddrByteSize() {
  std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());

  switch (m_dyld.header.magic) {
  case llvm::MachO::MH_MAGIC:
  case llvm::MachO::MH_CIGAM:
    return 4;

  case llvm::MachO::MH_MAGIC_64:
  case llvm::MachO::MH_CIGAM_64:
    return 8;

  default:
    break;
  }
  return 0;
}

lldb::ByteOrder DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(uint32_t magic) {
  switch (magic) {
  case llvm::MachO::MH_MAGIC:
  case llvm::MachO::MH_MAGIC_64:
    return endian::InlHostByteOrder();

  case llvm::MachO::MH_CIGAM:
  case llvm::MachO::MH_CIGAM_64:
    if (endian::InlHostByteOrder() == lldb::eByteOrderBig)
      return lldb::eByteOrderLittle;
    else
      return lldb::eByteOrderBig;

  default:
    break;
  }
  return lldb::eByteOrderInvalid;
}
