//===-- DynamicLoaderDarwinKernel.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/Utility/SafeMachO.h"

#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.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/Core/StreamFile.h"
#include "lldb/Host/Symbols.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Symbol/ObjectFile.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 "Plugins/Platform/MacOSX/PlatformDarwinKernel.h"

#include "DynamicLoaderDarwinKernel.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

using namespace lldb;
using namespace lldb_private;

// Progressively greater amounts of scanning we will allow
// For some targets very early in startup, we can't do any random reads of memory or we can crash the device
// so a setting is needed that can completely disable the KASLR scans.

enum KASLRScanType
{
    eKASLRScanNone = 0,         // No reading into the inferior at all
    eKASLRScanLowgloAddresses,  // Check one word of memory for a possible kernel addr, then see if a kernel is there
    eKASLRScanNearPC,           // Scan backwards from the current $pc looking for kernel; checking at 96 locations total
    eKASLRScanExhaustiveScan    // Scan through the entire possible kernel address range looking for a kernel
};

OptionEnumValueElement
g_kaslr_kernel_scan_enum_values[] =
{
    { eKASLRScanNone,            "none",            "Do not read memory looking for a Darwin kernel when attaching." },
    { eKASLRScanLowgloAddresses, "basic",           "Check for the Darwin kernel's load addr in the lowglo page (boot-args=debug) only." },
    { eKASLRScanNearPC,          "fast-scan",       "Scan near the pc value on attach to find the Darwin kernel's load address."},
    { eKASLRScanExhaustiveScan,  "exhaustive-scan", "Scan through the entire potential address range of Darwin kernel (only on 32-bit targets)."},
    { 0, NULL, NULL }
};

static PropertyDefinition
g_properties[] =
{
    { "load-kexts" , OptionValue::eTypeBoolean, true, true, NULL, NULL, "Automatically loads kext images when attaching to a kernel." },
    { "scan-type",   OptionValue::eTypeEnum,    true, eKASLRScanNearPC, NULL, g_kaslr_kernel_scan_enum_values, "Control how many reads lldb will make while searching for a Darwin kernel on attach." },
    {  NULL        , OptionValue::eTypeInvalid, false, 0  , NULL, NULL, NULL  }
};

enum {
    ePropertyLoadKexts,
    ePropertyScanType
};

class DynamicLoaderDarwinKernelProperties : public Properties
{
public:
    
    static ConstString &
    GetSettingName ()
    {
        static ConstString g_setting_name("darwin-kernel");
        return g_setting_name;
    }

    DynamicLoaderDarwinKernelProperties() :
        Properties ()
    {
        m_collection_sp.reset (new OptionValueProperties(GetSettingName()));
        m_collection_sp->Initialize(g_properties);
    }

    virtual
    ~DynamicLoaderDarwinKernelProperties()
    {
    }

    bool
    GetLoadKexts() const
    {
        const uint32_t idx = ePropertyLoadKexts;
        return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
    }

    KASLRScanType
    GetScanType() const
    {
        const uint32_t idx = ePropertyScanType;
        return (KASLRScanType) m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value);
    }


};

typedef std::shared_ptr<DynamicLoaderDarwinKernelProperties> DynamicLoaderDarwinKernelPropertiesSP;

static const DynamicLoaderDarwinKernelPropertiesSP &
GetGlobalProperties()
{
    static DynamicLoaderDarwinKernelPropertiesSP g_settings_sp;
    if (!g_settings_sp)
        g_settings_sp.reset (new DynamicLoaderDarwinKernelProperties ());
    return g_settings_sp;
}

//----------------------------------------------------------------------
// 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 *
DynamicLoaderDarwinKernel::CreateInstance (Process* process, bool force)
{
    if (!force)
    {
        // If the user provided an executable binary and it is not a kernel,
        // this plugin should not create an instance.
        Module* exe_module = process->GetTarget().GetExecutableModulePointer();
        if (exe_module)
        {
            ObjectFile *object_file = exe_module->GetObjectFile();
            if (object_file)
            {
                if (object_file->GetStrata() != ObjectFile::eStrataKernel)
                {
                    return NULL;
                }
            }
        }

        // If the target's architecture does not look like an Apple environment,
        // this plugin should not create an instance.
        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:
                if (triple_ref.getVendor() != llvm::Triple::Apple)
                {
                   return NULL;
                }
                break;
            // If we have triple like armv7-unknown-unknown, we should try looking for a Darwin kernel.
            case llvm::Triple::UnknownOS:
                break;
            default:
                return NULL;
                break;
        }
    }

    // At this point if there is an ExecutableModule, it is a kernel and the Target is some variant of an Apple system.  
    // If the Process hasn't provided the kernel load address, we need to look around in memory to find it.

    const addr_t kernel_load_address = SearchForDarwinKernel (process);
    if (CheckForKernelImageAtAddress (kernel_load_address, process).IsValid())
    {
        process->SetCanRunCode(false);
        return new DynamicLoaderDarwinKernel (process, kernel_load_address);
    }
    return NULL;
}

lldb::addr_t
DynamicLoaderDarwinKernel::SearchForDarwinKernel (Process *process)
{
    addr_t kernel_load_address = process->GetImageInfoAddress();
    if (kernel_load_address == LLDB_INVALID_ADDRESS)
    {
        kernel_load_address = SearchForKernelAtSameLoadAddr (process);
        if (kernel_load_address == LLDB_INVALID_ADDRESS)
        {
            kernel_load_address = SearchForKernelWithDebugHints (process);
            if (kernel_load_address == LLDB_INVALID_ADDRESS)
            {
                kernel_load_address = SearchForKernelNearPC (process);
                if (kernel_load_address == LLDB_INVALID_ADDRESS)
                {
                    kernel_load_address = SearchForKernelViaExhaustiveSearch (process);
                }
            }
        }
    }
    return kernel_load_address;
}

//----------------------------------------------------------------------
// Check if the kernel binary is loaded in memory without a slide.
// First verify that the ExecutableModule is a kernel before we proceed.
// Returns the address of the kernel if one was found, else LLDB_INVALID_ADDRESS.
//----------------------------------------------------------------------
lldb::addr_t
DynamicLoaderDarwinKernel::SearchForKernelAtSameLoadAddr (Process *process)
{
    Module *exe_module = process->GetTarget().GetExecutableModulePointer();
    if (exe_module == NULL)
        return LLDB_INVALID_ADDRESS;

    ObjectFile *exe_objfile = exe_module->GetObjectFile();
    if (exe_objfile == NULL)
        return LLDB_INVALID_ADDRESS;

    if (exe_objfile->GetType() != ObjectFile::eTypeExecutable || exe_objfile->GetStrata() != ObjectFile::eStrataKernel)
        return LLDB_INVALID_ADDRESS;

    if (!exe_objfile->GetHeaderAddress().IsValid())
        return LLDB_INVALID_ADDRESS;

    if (CheckForKernelImageAtAddress (exe_objfile->GetHeaderAddress().GetFileAddress(), process) == exe_module->GetUUID())
        return exe_objfile->GetHeaderAddress().GetFileAddress();

    return LLDB_INVALID_ADDRESS;
}

//----------------------------------------------------------------------
// If the debug flag is included in the boot-args nvram setting, the kernel's load address
// will be noted in the lowglo page at a fixed address
// Returns the address of the kernel if one was found, else LLDB_INVALID_ADDRESS.
//----------------------------------------------------------------------
lldb::addr_t
DynamicLoaderDarwinKernel::SearchForKernelWithDebugHints (Process *process)
{
    if (GetGlobalProperties()->GetScanType() == eKASLRScanNone)
        return LLDB_INVALID_ADDRESS;

    Error read_err;
    addr_t addr = LLDB_INVALID_ADDRESS;
    addr_t kernel_addresses_64[] = { 0xffffff8000002010ULL, 0xffffff8000004010ULL, 
                                     0xfffffff000002010ULL, 0xfffffff000004010ULL, 
                                     LLDB_INVALID_ADDRESS };
    addr_t kernel_addresses_32[] = { 0xffff0110,
                                     LLDB_INVALID_ADDRESS };
    for (size_t i = 0; kernel_addresses_64[i] != LLDB_INVALID_ADDRESS; i++)
    {
        addr = process->ReadUnsignedIntegerFromMemory (kernel_addresses_64[i], 8, LLDB_INVALID_ADDRESS, read_err);
        if (CheckForKernelImageAtAddress (addr, process).IsValid())
        {
            return addr;
        }
    }

    for (size_t i = 0; kernel_addresses_32[i] != LLDB_INVALID_ADDRESS; i++)
    {
        addr = process->ReadUnsignedIntegerFromMemory (kernel_addresses_32[i], 4, LLDB_INVALID_ADDRESS, read_err);
        if (CheckForKernelImageAtAddress (addr, process).IsValid())
        {
            return addr;
        }
    }

    return LLDB_INVALID_ADDRESS;
}

//----------------------------------------------------------------------
// If the kernel is currently executing when lldb attaches, and we don't have
// a better way of finding the kernel's load address, try searching backwards
// from the current pc value looking for the kernel's Mach header in memory.
// Returns the address of the kernel if one was found, else LLDB_INVALID_ADDRESS.
//----------------------------------------------------------------------
lldb::addr_t
DynamicLoaderDarwinKernel::SearchForKernelNearPC (Process *process)
{
    if (GetGlobalProperties()->GetScanType() == eKASLRScanNone 
        || GetGlobalProperties()->GetScanType() == eKASLRScanLowgloAddresses)
    {
        return LLDB_INVALID_ADDRESS;
    }

    ThreadSP thread = process->GetThreadList().GetSelectedThread ();
    if (thread.get() == NULL)
        return LLDB_INVALID_ADDRESS;
    addr_t pc = thread->GetRegisterContext ()->GetPC(LLDB_INVALID_ADDRESS);

    if (pc == LLDB_INVALID_ADDRESS)
        return LLDB_INVALID_ADDRESS;

    // The kernel will load at at one megabyte boundary (0x100000), or at that boundary plus 
    // an offset of one page (0x1000) or two, or four (0x4000), depending on the device.

    // Round the current pc down to the nearest one megabyte boundary - the place where we will start searching.
    addr_t addr = pc & ~0xfffff;

    // Search backwards 32 megabytes, looking for the start of the kernel at each one-megabyte boundary.
    for (int i = 0; i < 32; i++, addr -= 0x100000)
    {
        if (CheckForKernelImageAtAddress (addr, process).IsValid())
            return addr;
        if (CheckForKernelImageAtAddress (addr + 0x1000, process).IsValid())
            return addr + 0x1000;
        if (CheckForKernelImageAtAddress (addr + 0x2000, process).IsValid())
            return addr + 0x2000;
        if (CheckForKernelImageAtAddress (addr + 0x4000, process).IsValid())
            return addr + 0x4000;
    }

    return LLDB_INVALID_ADDRESS;
}

//----------------------------------------------------------------------
// Scan through the valid address range for a kernel binary.
// This is uselessly slow in 64-bit environments so we don't even try it.
// This scan is not enabled by default even for 32-bit targets.
// Returns the address of the kernel if one was found, else LLDB_INVALID_ADDRESS.
//----------------------------------------------------------------------
lldb::addr_t
DynamicLoaderDarwinKernel::SearchForKernelViaExhaustiveSearch (Process *process)
{
    if (GetGlobalProperties()->GetScanType() != eKASLRScanExhaustiveScan)
    {
        return LLDB_INVALID_ADDRESS;
    }

    addr_t kernel_range_low, kernel_range_high;
    if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 8)
    {
        kernel_range_low = 1ULL << 63;
        kernel_range_high = UINT64_MAX;
    }
    else
    {
        kernel_range_low = 1ULL << 31;
        kernel_range_high = UINT32_MAX;
    }

    // Stepping through memory at one-megabyte resolution looking for a kernel
    // rarely works (fast enough) with a 64-bit address space -- for now, let's
    // not even bother.  We may be attaching to something which *isn't* a kernel
    // and we don't want to spin for minutes on-end looking for a kernel.
    if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 8)
        return LLDB_INVALID_ADDRESS;

    addr_t addr = kernel_range_low;

    while (addr >= kernel_range_low && addr < kernel_range_high)
    {
        if (CheckForKernelImageAtAddress (addr, process).IsValid())
            return addr;
        if (CheckForKernelImageAtAddress (addr + 0x1000, process).IsValid())
            return addr + 0x1000;
        if (CheckForKernelImageAtAddress (addr + 0x2000, process).IsValid())
            return addr + 0x2000;
        if (CheckForKernelImageAtAddress (addr + 0x4000, process).IsValid())
            return addr + 0x4000;
        addr += 0x100000;
    }
    return LLDB_INVALID_ADDRESS;
}

//----------------------------------------------------------------------
// Given an address in memory, look to see if there is a kernel image at that
// address.  
// Returns a UUID; if a kernel was not found at that address, UUID.IsValid() will be false.
//----------------------------------------------------------------------
lldb_private::UUID
DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress (lldb::addr_t addr, Process *process)
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
    if (addr == LLDB_INVALID_ADDRESS)
        return UUID();

    if (log)
        log->Printf ("DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress: looking for kernel binary at 0x%" PRIx64, addr);

    // First try a quick test -- read the first 4 bytes and see if there is a valid Mach-O magic field there
    // (the first field of the mach_header/mach_header_64 struct).

    Error read_error;
    uint64_t result = process->ReadUnsignedIntegerFromMemory (addr, 4, LLDB_INVALID_ADDRESS, read_error);
    if (result != llvm::MachO::MH_MAGIC_64
        && result != llvm::MachO::MH_MAGIC
        && result != llvm::MachO::MH_CIGAM
        && result != llvm::MachO::MH_CIGAM_64)
    {
        return UUID();
    }

    // Read the mach header and see whether it looks like a kernel
    llvm::MachO::mach_header header;
    if (process->DoReadMemory (addr, &header, sizeof (header), read_error) != sizeof (header))
        return UUID();

    if (header.magic == llvm::MachO::MH_CIGAM ||
        header.magic == llvm::MachO::MH_CIGAM_64)
    {
        header.magic        = llvm::ByteSwap_32 (header.magic);
        header.cputype      = llvm::ByteSwap_32 (header.cputype);
        header.cpusubtype   = llvm::ByteSwap_32 (header.cpusubtype);
        header.filetype     = llvm::ByteSwap_32 (header.filetype);
        header.ncmds        = llvm::ByteSwap_32 (header.ncmds);
        header.sizeofcmds   = llvm::ByteSwap_32 (header.sizeofcmds);
        header.flags        = llvm::ByteSwap_32 (header.flags);
    }

    // A kernel is an executable which does not have the dynamic link object flag set.
    if (header.filetype == llvm::MachO::MH_EXECUTE
        && (header.flags & llvm::MachO::MH_DYLDLINK) == 0)
    {
        // Create a full module to get the UUID
        ModuleSP memory_module_sp = process->ReadModuleFromMemory (FileSpec ("temp_mach_kernel", false), addr);
        if (!memory_module_sp.get())
            return UUID();

        ObjectFile *exe_objfile = memory_module_sp->GetObjectFile();
        if (exe_objfile == NULL)
            return UUID();

        if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && exe_objfile->GetStrata() == ObjectFile::eStrataKernel)
        {
            ArchSpec kernel_arch (eArchTypeMachO, header.cputype, header.cpusubtype);
            if (!process->GetTarget().GetArchitecture().IsCompatibleMatch(kernel_arch))
            {
                process->GetTarget().SetArchitecture (kernel_arch);
            }
            if (log)
                log->Printf ("DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress: kernel binary image found at 0x%" PRIx64, addr);
            return memory_module_sp->GetUUID();
        }
    }

    return UUID();
}

//----------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------
DynamicLoaderDarwinKernel::DynamicLoaderDarwinKernel(Process *process, lldb::addr_t kernel_addr)
    : DynamicLoader(process),
      m_kernel_load_address(kernel_addr),
      m_kernel(),
      m_kext_summary_header_ptr_addr(),
      m_kext_summary_header_addr(),
      m_kext_summary_header(),
      m_known_kexts(),
      m_mutex(),
      m_break_id(LLDB_INVALID_BREAK_ID)
{
    Error error;
    PlatformSP platform_sp(Platform::Create(PlatformDarwinKernel::GetPluginNameStatic(), error));
    // Only select the darwin-kernel Platform if we've been asked to load kexts.
    // It can take some time to scan over all of the kext info.plists and that
    // shouldn't be done if kext loading is explicitly disabled.
    if (platform_sp.get() && GetGlobalProperties()->GetLoadKexts())
    {
        process->GetTarget().SetPlatform(platform_sp);
    }
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
DynamicLoaderDarwinKernel::~DynamicLoaderDarwinKernel()
{
    Clear(true);
}

void
DynamicLoaderDarwinKernel::UpdateIfNeeded()
{
    LoadKernelModuleIfNeeded();
    SetNotificationBreakpointIfNeeded ();
}
//------------------------------------------------------------------
/// Called after attaching a process.
///
/// Allow DynamicLoader plug-ins to execute some code after
/// attaching to a process.
//------------------------------------------------------------------
void
DynamicLoaderDarwinKernel::DidAttach ()
{
    PrivateInitialize(m_process);
    UpdateIfNeeded();
}

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


//----------------------------------------------------------------------
// Clear out the state of this class.
//----------------------------------------------------------------------
void
DynamicLoaderDarwinKernel::Clear (bool clear_process)
{
    std::lock_guard<std::recursive_mutex> guard(m_mutex);

    if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
        m_process->ClearBreakpointSiteByID(m_break_id);

    if (clear_process)
        m_process = NULL;
    m_kernel.Clear();
    m_known_kexts.clear();
    m_kext_summary_header_ptr_addr.Clear();
    m_kext_summary_header_addr.Clear();
    m_break_id = LLDB_INVALID_BREAK_ID;
}


bool
DynamicLoaderDarwinKernel::KextImageInfo::LoadImageAtFileAddress (Process *process)
{
    if (IsLoaded())
        return true;

    if (m_module_sp)
    {
        bool changed = false;
        if (m_module_sp->SetLoadAddress (process->GetTarget(), 0, true, changed))
            m_load_process_stop_id = process->GetStopID();
    }
    return false;
}

void
DynamicLoaderDarwinKernel::KextImageInfo::SetModule (ModuleSP module_sp)
{
    m_module_sp = module_sp;
    if (module_sp.get() && module_sp->GetObjectFile())
    {
        if (module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeExecutable
            && module_sp->GetObjectFile()->GetStrata() == ObjectFile::eStrataKernel)
        {
            m_kernel_image = true;
        }
        else
        {
            m_kernel_image = false;
        }
    }
}

ModuleSP
DynamicLoaderDarwinKernel::KextImageInfo::GetModule ()
{
    return m_module_sp;
}

void
DynamicLoaderDarwinKernel::KextImageInfo::SetLoadAddress (addr_t load_addr)
{ 
    m_load_address = load_addr;
}

addr_t
DynamicLoaderDarwinKernel::KextImageInfo::GetLoadAddress () const
{ 
    return m_load_address;
}

uint64_t 
DynamicLoaderDarwinKernel::KextImageInfo::GetSize () const
{
    return m_size;
}

void
DynamicLoaderDarwinKernel::KextImageInfo::SetSize (uint64_t size)
{
    m_size = size;
}

uint32_t
DynamicLoaderDarwinKernel::KextImageInfo::GetProcessStopId () const
{
    return m_load_process_stop_id;
}

void
DynamicLoaderDarwinKernel::KextImageInfo::SetProcessStopId (uint32_t stop_id)
{
    m_load_process_stop_id = stop_id;
}

bool
DynamicLoaderDarwinKernel::KextImageInfo::operator== (const KextImageInfo &rhs)
{
    if (m_uuid.IsValid() || rhs.GetUUID().IsValid())
    {
        if (m_uuid == rhs.GetUUID())
        {
            return true;
        }
        return false;
    }

    if (m_name == rhs.GetName() && m_load_address == rhs.GetLoadAddress())
        return true;

    return false;
}

void
DynamicLoaderDarwinKernel::KextImageInfo::SetName (const char *name)
{
    m_name = name;
}

std::string
DynamicLoaderDarwinKernel::KextImageInfo::GetName () const
{
    return m_name;
}

void
DynamicLoaderDarwinKernel::KextImageInfo::SetUUID (const UUID &uuid)
{
    m_uuid = uuid;
}

UUID
DynamicLoaderDarwinKernel::KextImageInfo::GetUUID () const
{
    return m_uuid;
}

// Given the m_load_address from the kext summaries, and a UUID, try to create an in-memory
// Module at that address.  Require that the MemoryModule have a matching UUID and detect
// if this MemoryModule is a kernel or a kext.
//
// Returns true if m_memory_module_sp is now set to a valid Module.  

bool
DynamicLoaderDarwinKernel::KextImageInfo::ReadMemoryModule (Process *process)
{
    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
    if (m_memory_module_sp.get() != NULL)
        return true;
    if (m_load_address == LLDB_INVALID_ADDRESS)
        return false;

    FileSpec file_spec;
    file_spec.SetFile (m_name.c_str(), false);

    ModuleSP memory_module_sp = process->ReadModuleFromMemory (file_spec, m_load_address);

    if (memory_module_sp.get() == NULL)
        return false;

    bool is_kernel = false;
    if (memory_module_sp->GetObjectFile())
    {
        if (memory_module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeExecutable
            && memory_module_sp->GetObjectFile()->GetStrata() == ObjectFile::eStrataKernel)
        {
            is_kernel = true;
        }
        else if (memory_module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeSharedLibrary)
        {
            is_kernel = false;
        }
    }

    // If this is a kext, and the kernel specified what UUID we should find at this 
    // load address, require that the memory module have a matching UUID or something 
    // has gone wrong and we should discard it.
    if (m_uuid.IsValid())
    {
        if (m_uuid != memory_module_sp->GetUUID())
        {
            if (log)
            {
                log->Printf ("KextImageInfo::ReadMemoryModule the kernel said to find uuid %s at 0x%" PRIx64 " but instead we found uuid %s, throwing it away", m_uuid.GetAsString().c_str(), m_load_address, memory_module_sp->GetUUID().GetAsString().c_str());
            }
            return false;
        }
    }

    // If the in-memory Module has a UUID, let's use that.
    if (!m_uuid.IsValid() && memory_module_sp->GetUUID().IsValid())
    {
        m_uuid = memory_module_sp->GetUUID();
    }

    m_memory_module_sp = memory_module_sp;
    m_kernel_image = is_kernel;
    if (is_kernel)
    {
        if (log)
        {
            // This is unusual and probably not intended
            log->Printf ("KextImageInfo::ReadMemoryModule read the kernel binary out of memory");
        }
        if (memory_module_sp->GetArchitecture().IsValid())
        {
            process->GetTarget().SetArchitecture(memory_module_sp->GetArchitecture());
        }
        if (m_uuid.IsValid())
        {
            ModuleSP exe_module_sp = process->GetTarget().GetExecutableModule();
            if (exe_module_sp.get() && exe_module_sp->GetUUID().IsValid())
            {
                if (m_uuid != exe_module_sp->GetUUID())
                {
                    // The user specified a kernel binary that has a different UUID than
                    // the kernel actually running in memory.  This never ends well; 
                    // clear the user specified kernel binary from the Target.

                    m_module_sp.reset();

                    ModuleList user_specified_kernel_list;
                    user_specified_kernel_list.Append (exe_module_sp);
                    process->GetTarget().GetImages().Remove (user_specified_kernel_list);
                }
            }
        }
    }

    return true;
}

bool
DynamicLoaderDarwinKernel::KextImageInfo::IsKernel () const
{
    return m_kernel_image == true;
}

void
DynamicLoaderDarwinKernel::KextImageInfo::SetIsKernel (bool is_kernel) 
{
    m_kernel_image = is_kernel;
}

bool
DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule (Process *process)
{
    if (IsLoaded())
        return true;


    Target &target = process->GetTarget();

    // If we don't have / can't create a memory module for this kext, don't try to load it - we won't
    // have the correct segment load addresses.
    if (!ReadMemoryModule (process))
    {
        return false;
    }

    bool uuid_is_valid = m_uuid.IsValid();

    if (IsKernel() && uuid_is_valid && m_memory_module_sp.get())
    {
        Stream *s = target.GetDebugger().GetOutputFile().get();
        if (s)
        {
            s->Printf ("Kernel UUID: %s\n", m_memory_module_sp->GetUUID().GetAsString().c_str());
            s->Printf ("Load Address: 0x%" PRIx64 "\n", m_load_address);
        }
    }

    if (!m_module_sp)
    {
        // See if the kext has already been loaded into the target, probably by the user doing target modules add.
        const ModuleList &target_images = target.GetImages();
        m_module_sp = target_images.FindModule(m_uuid);

        // Search for the kext on the local filesystem via the UUID
        if (!m_module_sp && uuid_is_valid)
        {
            ModuleSpec module_spec;
            module_spec.GetUUID() = m_uuid;
            module_spec.GetArchitecture() = target.GetArchitecture();

            // For the kernel, we really do need an on-disk file copy of the binary to do anything useful.
            // This will force a clal to 
            if (IsKernel())
            {
                if (Symbols::DownloadObjectAndSymbolFile (module_spec, true))
                {
                    if (module_spec.GetFileSpec().Exists())
                    {
                        m_module_sp.reset(new Module (module_spec.GetFileSpec(), target.GetArchitecture()));
                        if (m_module_sp.get() && m_module_sp->MatchesModuleSpec (module_spec))
                        {
                            ModuleList loaded_module_list;
                            loaded_module_list.Append (m_module_sp);
                            target.ModulesDidLoad (loaded_module_list);
                        }
                    }
                }
            }

            // If the current platform is PlatformDarwinKernel, create a ModuleSpec with the filename set 
            // to be the bundle ID for this kext, e.g. "com.apple.filesystems.msdosfs", and ask the platform
            // to find it.
            PlatformSP platform_sp (target.GetPlatform());
            if (!m_module_sp && platform_sp)
            {
                ConstString platform_name (platform_sp->GetPluginName());
                static ConstString g_platform_name (PlatformDarwinKernel::GetPluginNameStatic());
                if (platform_name == g_platform_name)
                {
                    ModuleSpec kext_bundle_module_spec(module_spec);
                    FileSpec kext_filespec(m_name.c_str(), false);
                    kext_bundle_module_spec.GetFileSpec() = kext_filespec;
                    platform_sp->GetSharedModule (kext_bundle_module_spec, process, m_module_sp, &target.GetExecutableSearchPaths(), NULL, NULL);
                }
            }

            // Ask the Target to find this file on the local system, if possible.
            // This will search in the list of currently-loaded files, look in the 
            // standard search paths on the system, and on a Mac it will try calling
            // the DebugSymbols framework with the UUID to find the binary via its
            // search methods.
            if (!m_module_sp)
            {
                m_module_sp = target.GetSharedModule (module_spec);
            }

            if (IsKernel() && !m_module_sp)
            {
                Stream *s = target.GetDebugger().GetOutputFile().get();
                if (s)
                {
                    s->Printf ("WARNING: Unable to locate kernel binary on the debugger system.\n");
                }
            }
        }

        // If we managed to find a module, append it to the target's list of images.
        // If we also have a memory module, require that they have matching UUIDs
        if (m_module_sp)
        {
            bool uuid_match_ok = true;
            if (m_memory_module_sp)
            {
                if (m_module_sp->GetUUID() != m_memory_module_sp->GetUUID())
                {
                    uuid_match_ok = false;
                }
            }
            if (uuid_match_ok)
            {
                target.GetImages().AppendIfNeeded(m_module_sp);
                if (IsKernel() && target.GetExecutableModulePointer() != m_module_sp.get())
                {
                    target.SetExecutableModule (m_module_sp, false);
                }
            }
        }
    }
    
    if (!m_module_sp && !IsKernel() && m_uuid.IsValid() && !m_name.empty())
    {
        Stream *s = target.GetDebugger().GetOutputFile().get();
        if (s)
        {
            s->Printf ("warning: Can't find binary/dSYM for %s (%s)\n", 
                       m_name.c_str(), m_uuid.GetAsString().c_str());
        }
    }

    static ConstString g_section_name_LINKEDIT ("__LINKEDIT");

    if (m_memory_module_sp && m_module_sp)
    {
        if (m_module_sp->GetUUID() == m_memory_module_sp->GetUUID())
        {
            ObjectFile *ondisk_object_file = m_module_sp->GetObjectFile();
            ObjectFile *memory_object_file = m_memory_module_sp->GetObjectFile();
            
            if (memory_object_file && ondisk_object_file)
            {
                // The memory_module for kexts may have an invalid __LINKEDIT seg; skip it.
                const bool ignore_linkedit = !IsKernel ();
                
                SectionList *ondisk_section_list = ondisk_object_file->GetSectionList ();
                SectionList *memory_section_list = memory_object_file->GetSectionList ();
                if (memory_section_list && ondisk_section_list)
                {
                    const uint32_t num_ondisk_sections = ondisk_section_list->GetSize();
                    // There may be CTF sections in the memory image so we can't
                    // always just compare the number of sections (which are actually
                    // segments in mach-o parlance)
                    uint32_t sect_idx = 0;
                    
                    // Use the memory_module's addresses for each section to set the 
                    // file module's load address as appropriate.  We don't want to use
                    // a single slide value for the entire kext - different segments may
                    // be slid different amounts by the kext loader.

                    uint32_t num_sections_loaded = 0;
                    for (sect_idx=0; sect_idx<num_ondisk_sections; ++sect_idx)
                    {
                        SectionSP ondisk_section_sp(ondisk_section_list->GetSectionAtIndex(sect_idx));
                        if (ondisk_section_sp)
                        {
                            // Don't ever load __LINKEDIT as it may or may not be actually
                            // mapped into memory and there is no current way to tell.
                            // I filed rdar://problem/12851706 to track being able to tell
                            // if the __LINKEDIT is actually mapped, but until then, we need
                            // to not load the __LINKEDIT
                            if (ignore_linkedit && ondisk_section_sp->GetName() == g_section_name_LINKEDIT)
                                continue;

                            const Section *memory_section = memory_section_list->FindSectionByName(ondisk_section_sp->GetName()).get();
                            if (memory_section)
                            {
                                target.SetSectionLoadAddress (ondisk_section_sp, memory_section->GetFileAddress());
                                ++num_sections_loaded;
                            }
                        }
                    }
                    if (num_sections_loaded > 0)
                        m_load_process_stop_id = process->GetStopID();
                    else
                        m_module_sp.reset(); // No sections were loaded
                }
                else
                    m_module_sp.reset(); // One or both section lists
            }
            else
                m_module_sp.reset(); // One or both object files missing
        }
        else
            m_module_sp.reset(); // UUID mismatch
    }

    bool is_loaded = IsLoaded();
    
    if (is_loaded && m_module_sp && IsKernel())
    {
        Stream *s = target.GetDebugger().GetOutputFile().get();
        if (s)
        {
            ObjectFile *kernel_object_file = m_module_sp->GetObjectFile();
            if (kernel_object_file)
            {
                addr_t file_address = kernel_object_file->GetHeaderAddress().GetFileAddress();
                if (m_load_address != LLDB_INVALID_ADDRESS && file_address != LLDB_INVALID_ADDRESS)
                {
                    s->Printf ("Kernel slid 0x%" PRIx64 " in memory.\n", m_load_address - file_address);
                }
            }
            {
                s->Printf ("Loaded kernel file %s\n",
                           m_module_sp->GetFileSpec().GetPath().c_str());
            }
            s->Flush ();
        }
    }
    return is_loaded;
}

uint32_t
DynamicLoaderDarwinKernel::KextImageInfo::GetAddressByteSize ()
{
    if (m_memory_module_sp)
        return m_memory_module_sp->GetArchitecture().GetAddressByteSize();
    if (m_module_sp)
        return m_module_sp->GetArchitecture().GetAddressByteSize();
    return 0;
}

lldb::ByteOrder
DynamicLoaderDarwinKernel::KextImageInfo::GetByteOrder()
{
    if (m_memory_module_sp)
        return m_memory_module_sp->GetArchitecture().GetByteOrder();
    if (m_module_sp)
        return m_module_sp->GetArchitecture().GetByteOrder();
    return endian::InlHostByteOrder();
}

lldb_private::ArchSpec
DynamicLoaderDarwinKernel::KextImageInfo::GetArchitecture () const
{
    if (m_memory_module_sp)
        return m_memory_module_sp->GetArchitecture();
    if (m_module_sp)
        return m_module_sp->GetArchitecture();
    return lldb_private::ArchSpec ();
}


//----------------------------------------------------------------------
// Load the kernel module and initialize the "m_kernel" member. Return
// true _only_ if the kernel is loaded the first time through (subsequent
// calls to this function should return false after the kernel has been
// already loaded).
//----------------------------------------------------------------------
void
DynamicLoaderDarwinKernel::LoadKernelModuleIfNeeded()
{
    if (!m_kext_summary_header_ptr_addr.IsValid())
    {
        m_kernel.Clear();
        m_kernel.SetModule (m_process->GetTarget().GetExecutableModule());
        m_kernel.SetIsKernel(true);

        ConstString kernel_name("mach_kernel");
        if (m_kernel.GetModule().get()
            && m_kernel.GetModule()->GetObjectFile()
            && !m_kernel.GetModule()->GetObjectFile()->GetFileSpec().GetFilename().IsEmpty())
        {
            kernel_name = m_kernel.GetModule()->GetObjectFile()->GetFileSpec().GetFilename();
        }
        m_kernel.SetName (kernel_name.AsCString());

        if (m_kernel.GetLoadAddress() == LLDB_INVALID_ADDRESS)
        {
            m_kernel.SetLoadAddress(m_kernel_load_address);
            if (m_kernel.GetLoadAddress() == LLDB_INVALID_ADDRESS && m_kernel.GetModule())
            {
                // We didn't get a hint from the process, so we will
                // try the kernel at the address that it exists at in
                // the file if we have one
                ObjectFile *kernel_object_file = m_kernel.GetModule()->GetObjectFile();
                if (kernel_object_file)
                {
                    addr_t load_address = kernel_object_file->GetHeaderAddress().GetLoadAddress(&m_process->GetTarget());
                    addr_t file_address = kernel_object_file->GetHeaderAddress().GetFileAddress();
                    if (load_address != LLDB_INVALID_ADDRESS && load_address != 0)
                    {
                        m_kernel.SetLoadAddress (load_address);
                        if (load_address != file_address)
                        {
                            // Don't accidentally relocate the kernel to the File address -- 
                            // the Load address has already been set to its actual in-memory address.  
                            // Mark it as IsLoaded.
                            m_kernel.SetProcessStopId (m_process->GetStopID());
                        }
                    }
                    else
                    {
                        m_kernel.SetLoadAddress(file_address);
                    }
                }
            }
        }
        
        if (m_kernel.GetLoadAddress() != LLDB_INVALID_ADDRESS)
        {
            if (!m_kernel.LoadImageUsingMemoryModule (m_process))
            {
                m_kernel.LoadImageAtFileAddress (m_process);
            }
        }

        if (m_kernel.IsLoaded() && m_kernel.GetModule())
        {
            static ConstString kext_summary_symbol ("gLoadedKextSummaries");
            const Symbol *symbol = m_kernel.GetModule()->FindFirstSymbolWithNameAndType (kext_summary_symbol, eSymbolTypeData);
            if (symbol)
            {
                m_kext_summary_header_ptr_addr = symbol->GetAddress();
                // Update all image infos
                ReadAllKextSummaries ();
            }
        }
        else
        {
            m_kernel.Clear();
        }
    }
}

//----------------------------------------------------------------------
// 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
DynamicLoaderDarwinKernel::BreakpointHitCallback (void *baton, 
                                                  StoppointCallbackContext *context, 
                                                  user_id_t break_id, 
                                                  user_id_t break_loc_id)
{    
    return static_cast<DynamicLoaderDarwinKernel*>(baton)->BreakpointHit (context, break_id, break_loc_id);    
}

bool
DynamicLoaderDarwinKernel::BreakpointHit (StoppointCallbackContext *context, 
                                          user_id_t break_id, 
                                          user_id_t break_loc_id)
{    
    Log *log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
    if (log)
        log->Printf ("DynamicLoaderDarwinKernel::BreakpointHit (...)\n");

    ReadAllKextSummaries ();
    
    if (log)
        PutToLog(log);

    return GetStopWhenImagesChange();
}


bool
DynamicLoaderDarwinKernel::ReadKextSummaryHeader ()
{
    std::lock_guard<std::recursive_mutex> guard(m_mutex);

    // the all image infos is already valid for this process stop ID

    if (m_kext_summary_header_ptr_addr.IsValid())
    {
        const uint32_t addr_size = m_kernel.GetAddressByteSize ();
        const ByteOrder byte_order = m_kernel.GetByteOrder();
        Error error;
        // Read enough bytes for a "OSKextLoadedKextSummaryHeader" structure
        // which is currently 4 uint32_t and a pointer.
        uint8_t buf[24];
        DataExtractor data (buf, sizeof(buf), byte_order, addr_size);
        const size_t count = 4 * sizeof(uint32_t) + addr_size;
        const bool prefer_file_cache = false;
        if (m_process->GetTarget().ReadPointerFromMemory (m_kext_summary_header_ptr_addr, 
                                                          prefer_file_cache,
                                                          error,
                                                          m_kext_summary_header_addr))
        {
            // We got a valid address for our kext summary header and make sure it isn't NULL
            if (m_kext_summary_header_addr.IsValid() && 
                m_kext_summary_header_addr.GetFileAddress() != 0)
            {
                const size_t bytes_read = m_process->GetTarget().ReadMemory (m_kext_summary_header_addr, prefer_file_cache, buf, count, error);
                if (bytes_read == count)
                {
                    lldb::offset_t offset = 0;
                    m_kext_summary_header.version = data.GetU32(&offset);
                    if (m_kext_summary_header.version > 128)
                    {
                        Stream *s = m_process->GetTarget().GetDebugger().GetOutputFile().get();
                        s->Printf ("WARNING: Unable to read kext summary header, got improbable version number %u\n", m_kext_summary_header.version);
                        // If we get an improbably large version number, we're probably getting bad memory.
                        m_kext_summary_header_addr.Clear();
                        return false;
                    }
                    if (m_kext_summary_header.version >= 2)
                    {
                        m_kext_summary_header.entry_size = data.GetU32(&offset);
                        if (m_kext_summary_header.entry_size > 4096)
                        {
                            // If we get an improbably large entry_size, we're probably getting bad memory.
                            Stream *s = m_process->GetTarget().GetDebugger().GetOutputFile().get();
                            s->Printf ("WARNING: Unable to read kext summary header, got improbable entry_size %u\n", m_kext_summary_header.entry_size);
                            m_kext_summary_header_addr.Clear();
                            return false;
                        }
                    }
                    else
                    {
                        // Versions less than 2 didn't have an entry size, it was hard coded
                        m_kext_summary_header.entry_size = KERNEL_MODULE_ENTRY_SIZE_VERSION_1;
                    }
                    m_kext_summary_header.entry_count = data.GetU32(&offset);
                    if (m_kext_summary_header.entry_count > 10000)
                    {
                        // If we get an improbably large number of kexts, we're probably getting bad memory.
                        Stream *s = m_process->GetTarget().GetDebugger().GetOutputFile().get();
                        s->Printf ("WARNING: Unable to read kext summary header, got improbable number of kexts %u\n", m_kext_summary_header.entry_count);
                        m_kext_summary_header_addr.Clear();
                        return false;
                    }
                    return true;
                }
            }
        }
    }
    m_kext_summary_header_addr.Clear();
    return false;
}

// We've either (a) just attached to a new kernel, or (b) the kexts-changed breakpoint was hit
// and we need to figure out what kexts have been added or removed.
// Read the kext summaries from the inferior kernel memory, compare them against the
// m_known_kexts vector and update the m_known_kexts vector as needed to keep in sync with the
// inferior.

bool
DynamicLoaderDarwinKernel::ParseKextSummaries (const Address &kext_summary_addr, uint32_t count)
{
    KextImageInfo::collection kext_summaries;
    Log *log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
    if (log)
        log->Printf ("Kexts-changed breakpoint hit, there are %d kexts currently.\n", count);

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

    if (!ReadKextSummaries (kext_summary_addr, count, kext_summaries))
        return false;

    // read the plugin.dynamic-loader.darwin-kernel.load-kexts setting -- if the user requested no 
    // kext loading, don't print any messages about kexts & don't try to read them.
    const bool load_kexts = GetGlobalProperties()->GetLoadKexts();

    // By default, all kexts we've loaded in the past are marked as "remove" and all of the kexts
    // we just found out about from ReadKextSummaries are marked as "add".
    std::vector<bool> to_be_removed(m_known_kexts.size(), true);
    std::vector<bool> to_be_added(count, true);

    int number_of_new_kexts_being_added = 0;
    int number_of_old_kexts_being_removed = m_known_kexts.size();

    const uint32_t new_kexts_size = kext_summaries.size();
    const uint32_t old_kexts_size = m_known_kexts.size();

    // The m_known_kexts vector may have entries that have been Cleared,
    // or are a kernel.  
    for (uint32_t old_kext = 0; old_kext < old_kexts_size; old_kext++)
    {
        bool ignore = false;
        KextImageInfo &image_info = m_known_kexts[old_kext];
        if (image_info.IsKernel())
        {
            ignore = true;
        }
        else if (image_info.GetLoadAddress() == LLDB_INVALID_ADDRESS && !image_info.GetModule())
        {
            ignore = true;
        }

        if (ignore)
        {
            number_of_old_kexts_being_removed--;
            to_be_removed[old_kext] = false;
        }
    }

    // Scan over the list of kexts we just read from the kernel, note those that
    // need to be added and those already loaded.
    for (uint32_t new_kext = 0; new_kext < new_kexts_size; new_kext++)
    {
        bool add_this_one = true;
        for (uint32_t old_kext = 0; old_kext < old_kexts_size; old_kext++)
        {
            if (m_known_kexts[old_kext] == kext_summaries[new_kext])
            {
                // We already have this kext, don't re-load it.
                to_be_added[new_kext] = false;
                // This kext is still present, do not remove it.
                to_be_removed[old_kext] = false;

                number_of_old_kexts_being_removed--;
                add_this_one = false;
                break;
            }
        }
        if (add_this_one)
        {
            number_of_new_kexts_being_added++;
        }
    }

    if (number_of_new_kexts_being_added == 0 && number_of_old_kexts_being_removed == 0)
        return true;

    Stream *s = m_process->GetTarget().GetDebugger().GetOutputFile().get();
    if (s && load_kexts)
    {
        if (number_of_new_kexts_being_added > 0 && number_of_old_kexts_being_removed > 0)
        {
            s->Printf ("Loading %d kext modules and unloading %d kext modules ", number_of_new_kexts_being_added, number_of_old_kexts_being_removed);
        }
        else if (number_of_new_kexts_being_added > 0)
        {
            s->Printf ("Loading %d kext modules ", number_of_new_kexts_being_added);
        }
        else if (number_of_old_kexts_being_removed > 0)
        {
            s->Printf ("Unloading %d kext modules ", number_of_old_kexts_being_removed);
        }
    }

    if (log)
    {
        if (load_kexts)
        {
            log->Printf ("DynamicLoaderDarwinKernel::ParseKextSummaries: %d kexts added, %d kexts removed", number_of_new_kexts_being_added, number_of_old_kexts_being_removed);
        }
        else
        {
            log->Printf ("DynamicLoaderDarwinKernel::ParseKextSummaries kext loading is disabled, else would have %d kexts added, %d kexts removed", number_of_new_kexts_being_added, number_of_old_kexts_being_removed);
        }
    }


    if (number_of_new_kexts_being_added > 0)
    {
        ModuleList loaded_module_list;

        const uint32_t num_of_new_kexts = kext_summaries.size();
        for (uint32_t new_kext = 0; new_kext < num_of_new_kexts; new_kext++)
        {
            if (to_be_added[new_kext] == true)
            {
                KextImageInfo &image_info = kext_summaries[new_kext];
                if (load_kexts)
                {
                    if (!image_info.LoadImageUsingMemoryModule (m_process))
                    {
                        image_info.LoadImageAtFileAddress (m_process);
                    }
                }

                m_known_kexts.push_back(image_info);

                if (image_info.GetModule() && m_process->GetStopID() == image_info.GetProcessStopId())
                    loaded_module_list.AppendIfNeeded (image_info.GetModule());

                if (s && load_kexts)
                    s->Printf (".");

                if (log)
                    kext_summaries[new_kext].PutToLog (log);
            }
        }
        m_process->GetTarget().ModulesDidLoad (loaded_module_list);
    }

    if (number_of_old_kexts_being_removed > 0)
    {
        ModuleList loaded_module_list;
        const uint32_t num_of_old_kexts = m_known_kexts.size();
        for (uint32_t old_kext = 0; old_kext < num_of_old_kexts; old_kext++)
        {
            ModuleList unloaded_module_list;
            if (to_be_removed[old_kext])
            {
                KextImageInfo &image_info = m_known_kexts[old_kext];
                // You can't unload the kernel.
                if (!image_info.IsKernel())
                {
                    if (image_info.GetModule())
                    {
                        unloaded_module_list.AppendIfNeeded (image_info.GetModule());
                    }
                    if (s)
                        s->Printf (".");
                    image_info.Clear();
                    // should pull it out of the KextImageInfos vector but that would mutate the list and invalidate
                    // the to_be_removed bool vector; leaving it in place once Cleared() is relatively harmless.
                }
            }
            m_process->GetTarget().ModulesDidUnload (unloaded_module_list, false);
        }
    }

    if (s && load_kexts)
    {
        s->Printf (" done.\n");
        s->Flush ();
    }

    return true;
}

uint32_t
DynamicLoaderDarwinKernel::ReadKextSummaries (const Address &kext_summary_addr,
                                              uint32_t image_infos_count, 
                                              KextImageInfo::collection &image_infos)
{
    const ByteOrder endian = m_kernel.GetByteOrder();
    const uint32_t addr_size = m_kernel.GetAddressByteSize();

    image_infos.resize(image_infos_count);
    const size_t count = image_infos.size() * m_kext_summary_header.entry_size;
    DataBufferHeap data(count, 0);
    Error error;
    
    const bool prefer_file_cache = false;
    const size_t bytes_read = m_process->GetTarget().ReadMemory (kext_summary_addr, 
                                                                 prefer_file_cache,
                                                                 data.GetBytes(), 
                                                                 data.GetByteSize(),
                                                                 error);
    if (bytes_read == count)
    {
        
        DataExtractor extractor (data.GetBytes(), data.GetByteSize(), endian, addr_size);
        uint32_t i=0;
        for (uint32_t kext_summary_offset = 0;
             i < image_infos.size() && extractor.ValidOffsetForDataOfSize(kext_summary_offset, m_kext_summary_header.entry_size); 
             ++i, kext_summary_offset += m_kext_summary_header.entry_size)
        {
            lldb::offset_t offset = kext_summary_offset;
            const void *name_data = extractor.GetData(&offset, KERNEL_MODULE_MAX_NAME);
            if (name_data == NULL)
                break;
            image_infos[i].SetName ((const char *) name_data);
            UUID uuid (extractor.GetData (&offset, 16), 16);
            image_infos[i].SetUUID (uuid);
            image_infos[i].SetLoadAddress (extractor.GetU64(&offset));
            image_infos[i].SetSize (extractor.GetU64(&offset));
        }
        if (i < image_infos.size())
            image_infos.resize(i);
    }
    else
    {
        image_infos.clear();
    }
    return image_infos.size();
}

bool
DynamicLoaderDarwinKernel::ReadAllKextSummaries ()
{
    std::lock_guard<std::recursive_mutex> guard(m_mutex);

    if (ReadKextSummaryHeader ())
    {
        if (m_kext_summary_header.entry_count > 0 && m_kext_summary_header_addr.IsValid())
        {
            Address summary_addr (m_kext_summary_header_addr);
            summary_addr.Slide(m_kext_summary_header.GetSize());
            if (!ParseKextSummaries (summary_addr, m_kext_summary_header.entry_count))
            {
                m_known_kexts.clear();
            }
            return true;
        }
    }
    return false;
}

//----------------------------------------------------------------------
// Dump an image info structure to the file handle provided.
//----------------------------------------------------------------------
void
DynamicLoaderDarwinKernel::KextImageInfo::PutToLog (Log *log) const
{
    if (log == NULL)
        return;
    const uint8_t *u = (uint8_t *) m_uuid.GetBytes();

    if (m_load_address == LLDB_INVALID_ADDRESS)
    {
        if (u)
        {
            log->Printf("\tuuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name=\"%s\" (UNLOADED)",
                        u[ 0], u[ 1], u[ 2], u[ 3],
                        u[ 4], u[ 5], u[ 6], u[ 7],
                        u[ 8], u[ 9], u[10], u[11],
                        u[12], u[13], u[14], u[15],
                        m_name.c_str());
        }
        else
            log->Printf("\tname=\"%s\" (UNLOADED)", m_name.c_str());
    }
    else
    {
        if (u)
        {
            log->Printf("\taddr=0x%16.16" PRIx64 " size=0x%16.16" PRIx64 " uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name=\"%s\"",
                        m_load_address, m_size, 
                        u[ 0], u[ 1], u[ 2], u[ 3], u[ 4], u[ 5], u[ 6], u[ 7],
                        u[ 8], u[ 9], u[10], u[11], u[12], u[13], u[14], u[15],
                        m_name.c_str());
        }
        else
        {
            log->Printf("\t[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ") name=\"%s\"",
                        m_load_address, m_load_address+m_size, m_name.c_str());
        }
    }
}

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

    std::lock_guard<std::recursive_mutex> guard(m_mutex);
    log->Printf("gLoadedKextSummaries = 0x%16.16" PRIx64 " { version=%u, entry_size=%u, entry_count=%u }",
                m_kext_summary_header_addr.GetFileAddress(),
                m_kext_summary_header.version,
                m_kext_summary_header.entry_size,
                m_kext_summary_header.entry_count);

    size_t i;
    const size_t count = m_known_kexts.size();
    if (count > 0)
    {
        log->PutCString("Loaded:");
        for (i = 0; i<count; i++)
            m_known_kexts[i].PutToLog(log);
    }
}

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

void
DynamicLoaderDarwinKernel::SetNotificationBreakpointIfNeeded ()
{
    if (m_break_id == LLDB_INVALID_BREAK_ID && m_kernel.GetModule())
    {
        DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));

        
        const bool internal_bp = true;
        const bool hardware = false;
        const LazyBool skip_prologue = eLazyBoolNo;
        FileSpecList module_spec_list;
        module_spec_list.Append (m_kernel.GetModule()->GetFileSpec());
        Breakpoint *bp = m_process->GetTarget().CreateBreakpoint (&module_spec_list,
                                                                  NULL,
                                                                  "OSKextLoadedKextSummariesUpdated",
                                                                  eFunctionNameTypeFull,
                                                                  eLanguageTypeUnknown,
                                                                  0,
                                                                  skip_prologue,
                                                                  internal_bp,
                                                                  hardware).get();

        bp->SetCallback (DynamicLoaderDarwinKernel::BreakpointHitCallback, this, true);
        m_break_id = bp->GetID();
    }
}

//----------------------------------------------------------------------
// Member function that gets called when the process state changes.
//----------------------------------------------------------------------
void
DynamicLoaderDarwinKernel::PrivateProcessStateChanged (Process *process, StateType state)
{
    DEBUG_PRINTF("DynamicLoaderDarwinKernel::%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:
        UpdateIfNeeded();
        break;

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

ThreadPlanSP
DynamicLoaderDarwinKernel::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
{
    ThreadPlanSP thread_plan_sp;
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    if (log)
        log->Printf ("Could not find symbol for step through.");
    return thread_plan_sp;
}

Error
DynamicLoaderDarwinKernel::CanLoadImage ()
{
    Error error;
    error.SetErrorString("always unsafe to load or unload shared libraries in the darwin kernel");
    return error;
}

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

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

void
DynamicLoaderDarwinKernel::DebuggerInitialize (lldb_private::Debugger &debugger)
{
    if (!PluginManager::GetSettingForDynamicLoaderPlugin (debugger, DynamicLoaderDarwinKernelProperties::GetSettingName()))
    {
        const bool is_global_setting = true;
        PluginManager::CreateSettingForDynamicLoaderPlugin (debugger,
                                                            GetGlobalProperties()->GetValueProperties(),
                                                            ConstString ("Properties for the DynamicLoaderDarwinKernel plug-in."),
                                                            is_global_setting);
    }
}

lldb_private::ConstString
DynamicLoaderDarwinKernel::GetPluginNameStatic()
{
    static ConstString g_name("darwin-kernel");
    return g_name;
}

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


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

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

lldb::ByteOrder
DynamicLoaderDarwinKernel::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;
}

