[Lldb-commits] [lldb] r134672 - in /lldb/trunk: include/lldb/Target/Target.h lldb.xcodeproj/project.pbxproj source/Plugins/DynamicLoader/MacOSX-Kernel/ source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h source/Plugins/DynamicLoader/MacOSX-Kernel/Makefile source/Target/Target.cpp

Greg Clayton gclayton at apple.com
Thu Jul 7 17:48:10 PDT 2011


Author: gclayton
Date: Thu Jul  7 19:48:09 2011
New Revision: 134672

URL: http://llvm.org/viewvc/llvm-project?rev=134672&view=rev
Log:
Added the start of the darwin dynamic loader plug-in. It isn't hooked up to
be detected yet, but most of the initial code is there and needs to be 
debugged more.


Added:
    lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/
    lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp
    lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h
    lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/Makefile
Modified:
    lldb/trunk/include/lldb/Target/Target.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/Target/Target.cpp

Modified: lldb/trunk/include/lldb/Target/Target.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=134672&r1=134671&r2=134672&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Target.h (original)
+++ lldb/trunk/include/lldb/Target/Target.h Thu Jul  7 19:48:09 2011
@@ -474,6 +474,32 @@
     }
 
 
+    //------------------------------------------------------------------
+    /// Load a module in this target by at the section file addresses
+    /// with an optional constant slide applied to each section.
+    ///
+    /// This function will load all top level sections at their file
+    /// addresses and apply an optional constant slide amount to each 
+    /// section. This can be used to easily load a module at the same 
+    /// addresses that are contained in the object file (trust that
+    /// the addresses in an object file are the correct load addresses).
+    ///
+    /// @param[in] module
+    ///     The module to load.
+    ///
+    /// @param[in] slide
+    ///     A constant slide to add to each file address as each section
+    ///     is being loaded.
+    ///
+    /// @return
+    ///     \b true if loading the module at the specified address 
+    ///     causes a section to be loaded when it previously wasn't, or
+    ///     if a section changes load address. Returns \b false if
+    ///     the sections were all already loaded at these addresses.
+    //------------------------------------------------------------------
+    bool
+    LoadModuleWithSlide (Module *module, lldb::addr_t slide);
+
     static Target *
     GetTargetFromContexts (const ExecutionContext *exe_ctx_ptr, 
                            const SymbolContext *sc_ptr);

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=134672&r1=134671&r2=134672&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Thu Jul  7 19:48:09 2011
@@ -381,6 +381,7 @@
 		26DE20651161904E00A093E2 /* SBSymbol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DE20641161904E00A093E2 /* SBSymbol.cpp */; };
 		26ECA04313665FED008D1F18 /* ARM_DWARF_Registers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26ECA04213665FED008D1F18 /* ARM_DWARF_Registers.cpp */; };
 		26ED3D6D13C563810017D45E /* OptionGroupVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26ED3D6C13C563810017D45E /* OptionGroupVariable.cpp */; };
+		26F4214413C6515B00E04E5E /* DynamicLoaderMacOSXKernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F4214113C6515B00E04E5E /* DynamicLoaderMacOSXKernel.cpp */; };
 		26F5C27710F3D9E4009D5894 /* Driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F5C27310F3D9E4009D5894 /* Driver.cpp */; };
 		26F5C27810F3D9E4009D5894 /* IOChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F5C27510F3D9E4009D5894 /* IOChannel.cpp */; };
 		26F5C32510F3DF23009D5894 /* libpython.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C32410F3DF23009D5894 /* libpython.dylib */; };
@@ -1051,6 +1052,8 @@
 		26ECA04213665FED008D1F18 /* ARM_DWARF_Registers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ARM_DWARF_Registers.cpp; path = source/Utility/ARM_DWARF_Registers.cpp; sourceTree = "<group>"; };
 		26ED3D6C13C563810017D45E /* OptionGroupVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupVariable.cpp; path = source/Interpreter/OptionGroupVariable.cpp; sourceTree = "<group>"; };
 		26ED3D6F13C5638A0017D45E /* OptionGroupVariable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupVariable.h; path = include/lldb/Interpreter/OptionGroupVariable.h; sourceTree = "<group>"; };
+		26F4214113C6515B00E04E5E /* DynamicLoaderMacOSXKernel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLoaderMacOSXKernel.cpp; sourceTree = "<group>"; };
+		26F4214213C6515B00E04E5E /* DynamicLoaderMacOSXKernel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderMacOSXKernel.h; sourceTree = "<group>"; };
 		26F5C26A10F3D9A4009D5894 /* lldb */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = lldb; sourceTree = BUILT_PRODUCTS_DIR; };
 		26F5C27210F3D9E4009D5894 /* lldb-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "lldb-Info.plist"; path = "tools/driver/lldb-Info.plist"; sourceTree = "<group>"; };
 		26F5C27310F3D9E4009D5894 /* Driver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Driver.cpp; path = tools/driver/Driver.cpp; sourceTree = "<group>"; };
@@ -1407,6 +1410,7 @@
 			isa = PBXGroup;
 			children = (
 				260C897910F57C5600BB2B04 /* MacOSX-DYLD */,
+				26F4214013C6515B00E04E5E /* MacOSX-Kernel */,
 				268A683C1321B505000E3FB8 /* Static */,
 			);
 			path = DynamicLoader;
@@ -2473,6 +2477,15 @@
 			name = "lldb-platform";
 			sourceTree = "<group>";
 		};
+		26F4214013C6515B00E04E5E /* MacOSX-Kernel */ = {
+			isa = PBXGroup;
+			children = (
+				26F4214113C6515B00E04E5E /* DynamicLoaderMacOSXKernel.cpp */,
+				26F4214213C6515B00E04E5E /* DynamicLoaderMacOSXKernel.h */,
+			);
+			path = "MacOSX-Kernel";
+			sourceTree = "<group>";
+		};
 		26F5C22410F3D950009D5894 /* Tools */ = {
 			isa = PBXGroup;
 			children = (
@@ -3251,6 +3264,7 @@
 				49D8FB3913B5598F00411094 /* ClangASTImporter.cpp in Sources */,
 				9467E65213C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp in Sources */,
 				26ED3D6D13C563810017D45E /* OptionGroupVariable.cpp in Sources */,
+				26F4214413C6515B00E04E5E /* DynamicLoaderMacOSXKernel.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Added: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp?rev=134672&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp Thu Jul  7 19:48:09 2011
@@ -0,0 +1,1232 @@
+//===-- DynamicLoaderMacOSXKernel.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/DataBuffer.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/State.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlanRunToAddress.h"
+#include "lldb/Target/StackFrame.h"
+
+#include "DynamicLoaderMacOSXKernel.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;
+
+/// FIXME - The ObjC Runtime trampoline handler doesn't really belong here.
+/// I am putting it here so I can invoke it in the Trampoline code here, but
+/// it should be moved to the ObjC Runtime support when it is set up.
+
+
+//----------------------------------------------------------------------
+// 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 *
+DynamicLoaderMacOSXKernel::CreateInstance (Process* process, bool force)
+{
+    bool create = force;
+    if (!create)
+    {
+        const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
+        if (triple_ref.getOS() == llvm::Triple::Darwin && triple_ref.getVendor() == llvm::Triple::Apple)
+            create = true;
+    }
+    
+    if (create)
+        return new DynamicLoaderMacOSXKernel (process);
+    return NULL;
+}
+
+//----------------------------------------------------------------------
+// Constructor
+//----------------------------------------------------------------------
+DynamicLoaderMacOSXKernel::DynamicLoaderMacOSXKernel (Process* process) :
+    DynamicLoader(process),
+    m_kernel(),
+    m_kext_summary_header_addr (LLDB_INVALID_ADDRESS),
+    m_kext_summary_header (),
+    m_kext_summary_header_stop_id (0),
+    m_break_id (LLDB_INVALID_BREAK_ID),
+    m_kext_summaries(),
+    m_kext_summaries_stop_id (UINT32_MAX),
+    m_mutex(Mutex::eMutexTypeRecursive),
+    m_notification_callbacks ()
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+DynamicLoaderMacOSXKernel::~DynamicLoaderMacOSXKernel()
+{
+    Clear(true);
+}
+
+//------------------------------------------------------------------
+/// Called after attaching a process.
+///
+/// Allow DynamicLoader plug-ins to execute some code after
+/// attaching to a process.
+//------------------------------------------------------------------
+void
+DynamicLoaderMacOSXKernel::DidAttach ()
+{
+    PrivateInitialize(m_process);
+    LoadKernelModule();
+    SetNotificationBreakpoint ();
+}
+
+//------------------------------------------------------------------
+/// Called after attaching a process.
+///
+/// Allow DynamicLoader plug-ins to execute some code after
+/// attaching to a process.
+//------------------------------------------------------------------
+void
+DynamicLoaderMacOSXKernel::DidLaunch ()
+{
+    PrivateInitialize(m_process);
+    LoadKernelModule();
+    SetNotificationBreakpoint ();
+}
+
+
+//----------------------------------------------------------------------
+// Clear out the state of this class.
+//----------------------------------------------------------------------
+void
+DynamicLoaderMacOSXKernel::Clear (bool clear_process)
+{
+    Mutex::Locker locker(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(false);
+    m_kext_summary_header_addr = LLDB_INVALID_ADDRESS;
+    m_kext_summaries.clear();
+    m_kext_summaries_stop_id = 0;
+    m_break_id = LLDB_INVALID_BREAK_ID;
+}
+
+//----------------------------------------------------------------------
+// Check if we have found DYLD yet
+//----------------------------------------------------------------------
+bool
+DynamicLoaderMacOSXKernel::DidSetNotificationBreakpoint() const
+{
+    return LLDB_BREAK_ID_IS_VALID (m_break_id);
+}
+
+//----------------------------------------------------------------------
+// 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).
+//----------------------------------------------------------------------
+bool
+DynamicLoaderMacOSXKernel::LoadKernelModule()
+{
+    if (m_kext_summary_header_addr == LLDB_INVALID_ADDRESS)
+    {
+        m_kernel.Clear(false);
+        m_kernel.module_sp = m_process->GetTarget().GetExecutableModule();
+        if (m_kernel.module_sp)
+        {
+            static ConstString mach_header_name ("_mh_execute_header");
+            const Symbol *symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (mach_header_name, eSymbolTypeAbsolute);
+            if (symbol)
+            {
+                m_kernel.address = symbol->GetValue().GetFileAddress();
+                DataExtractor data; // Load command data
+                if (ReadMachHeader (m_kernel.address, &m_kernel.header, &data))
+                {
+                    if (m_kernel.header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor)
+                    {
+                        if (ParseLoadCommands (data, m_kernel))
+                            UpdateImageLoadAddress (m_kernel);
+                                                
+                        // Update all image infos
+                        ReadAllKextSummaries (false);
+                        return true;
+                    }
+                }
+                else
+                {
+                    m_kernel.Clear(false);
+                }
+                return false;
+            }
+        }
+    }
+    return false;
+}
+
+bool
+DynamicLoaderMacOSXKernel::FindTargetModule (OSKextLoadedKextSummary &image_info, bool can_create, bool *did_create_ptr)
+{
+    if (did_create_ptr)
+        *did_create_ptr = false;
+    
+    const bool image_info_uuid_is_valid = image_info.uuid.IsValid();
+
+    if (image_info.module_sp)
+    {
+        if (image_info_uuid_is_valid)
+        {
+            if (image_info.module_sp->GetUUID() == image_info.uuid)
+                return true;
+            else
+                image_info.module_sp.reset();
+        }
+        else
+            return true;
+    }
+
+    ModuleList &target_images = m_process->GetTarget().GetImages();
+    if (image_info_uuid_is_valid)
+        image_info.module_sp = target_images.FindModule(image_info.uuid);
+    
+    if (image_info.module_sp)
+        return true;
+    
+    ArchSpec arch (image_info.GetArchitecture ());
+    if (can_create)
+    {
+        if (image_info_uuid_is_valid)
+        {
+            image_info.module_sp = m_process->GetTarget().GetSharedModule (FileSpec(),
+                                                                arch,
+                                                                &image_info.uuid);
+            if (did_create_ptr)
+                *did_create_ptr = image_info.module_sp;
+        }
+    }
+    return image_info.module_sp;
+}
+
+bool
+DynamicLoaderMacOSXKernel::UpdateCommPageLoadAddress(Module *module)
+{
+    bool changed = false;
+    if (module)
+    {
+        ObjectFile *image_object_file = module->GetObjectFile();
+        if (image_object_file)
+        {
+            SectionList *section_list = image_object_file->GetSectionList ();
+            if (section_list)
+            {
+                uint32_t num_sections = section_list->GetSize();
+                for (uint32_t i=0; i<num_sections; ++i)
+                {
+                    Section* section = section_list->GetSectionAtIndex (i).get();
+                    if (section)
+                    {
+                        const addr_t new_section_load_addr = section->GetFileAddress ();
+                        const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section);
+                        if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
+                            old_section_load_addr != new_section_load_addr)
+                        {
+                            if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress ()))
+                                changed = true;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return changed;
+}
+
+//----------------------------------------------------------------------
+// Update the load addresses for all segments in MODULE using the
+// updated INFO that is passed in.
+//----------------------------------------------------------------------
+bool
+DynamicLoaderMacOSXKernel::UpdateImageLoadAddress (OSKextLoadedKextSummary& info)
+{
+    Module *module = info.module_sp.get();
+    bool changed = false;
+    if (module)
+    {
+        ObjectFile *image_object_file = module->GetObjectFile();
+        if (image_object_file)
+        {
+            SectionList *section_list = image_object_file->GetSectionList ();
+            if (section_list)
+            {
+                // We now know the slide amount, so go through all sections
+                // and update the load addresses with the correct values.
+                uint32_t num_segments = info.segments.size();
+                for (uint32_t i=0; i<num_segments; ++i)
+                {
+                    SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
+                    const addr_t new_section_load_addr = info.segments[i].vmaddr;
+                    if (section_sp)
+                    {
+                        const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get());
+                        if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
+                            old_section_load_addr != new_section_load_addr)
+                        {
+                            if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr))
+                                changed = true;
+                        }
+                    }
+                    else
+                    {
+                        fprintf (stderr, 
+                                 "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n",
+                                 info.segments[i].name.AsCString("<invalid>"),
+                                 (uint64_t)new_section_load_addr,
+                                 image_object_file->GetFileSpec().GetDirectory().AsCString(),
+                                 image_object_file->GetFileSpec().GetFilename().AsCString());
+                    }
+                }
+            }
+        }
+    }
+    return changed;
+}
+
+//----------------------------------------------------------------------
+// Update the load addresses for all segments in MODULE using the
+// updated INFO that is passed in.
+//----------------------------------------------------------------------
+bool
+DynamicLoaderMacOSXKernel::UnloadImageLoadAddress (OSKextLoadedKextSummary& info)
+{
+    Module *module = info.module_sp.get();
+    bool changed = false;
+    if (module)
+    {
+        ObjectFile *image_object_file = module->GetObjectFile();
+        if (image_object_file)
+        {
+            SectionList *section_list = image_object_file->GetSectionList ();
+            if (section_list)
+            {
+                uint32_t num_segments = info.segments.size();
+                for (uint32_t i=0; i<num_segments; ++i)
+                {
+                    SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
+                    if (section_sp)
+                    {
+                        const addr_t old_section_load_addr = info.segments[i].vmaddr;
+                        if (m_process->GetTarget().GetSectionLoadList().SetSectionUnloaded (section_sp.get(), old_section_load_addr))
+                            changed = true;
+                    }
+                    else
+                    {
+                        fprintf (stderr, 
+                                 "warning: unable to find and unload segment named '%s' in '%s/%s' in macosx dynamic loader plug-in.\n",
+                                 info.segments[i].name.AsCString("<invalid>"),
+                                 image_object_file->GetFileSpec().GetDirectory().AsCString(),
+                                 image_object_file->GetFileSpec().GetFilename().AsCString());
+                    }
+                }
+            }
+        }
+    }
+    return changed;
+}
+
+
+//----------------------------------------------------------------------
+// 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
+DynamicLoaderMacOSXKernel::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)
+    
+    DynamicLoaderMacOSXKernel* dyld_instance = (DynamicLoaderMacOSXKernel*) 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.
+    
+    if (!dyld_instance->ReadAllKextSummaries(false))
+    {
+        Process *process = context->exe_ctx.process;
+        const lldb::ABISP &abi = process->GetABI();
+        if (abi != NULL)
+        {
+            // 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;
+            
+            void *clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false);
+            void *clang_uint32_type   = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint, 32);
+            input_value.SetValueType (Value::eValueTypeScalar);
+            input_value.SetContext (Value::eContextTypeClangType, clang_uint32_type);
+            argument_values.PushValue(input_value);
+            argument_values.PushValue(input_value);
+            input_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type);
+            argument_values.PushValue (input_value);
+            
+            if (abi->GetArgumentValues (*context->exe_ctx.thread, argument_values))
+            {
+                uint32_t dyld_mode = argument_values.GetValueAtIndex(0)->GetScalar().UInt (-1);
+                if (dyld_mode != -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 != -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 kext_summary_addr = argument_values.GetValueAtIndex(2)->GetScalar().ULongLong();
+                        if (dyld_mode == 0)
+                        {
+                            // This is add:
+                            dyld_instance->ParseKextSummaries (kext_summary_addr, image_infos_count);
+                        }
+                        else
+                        {
+                            // This is remove:
+                            dyld_instance->RemoveModulesUsingImageInfosAddress (kext_summary_addr, image_infos_count);
+                        }
+                        
+                    }
+                }
+            }
+        }
+    }
+    // Return true to stop the target, false to just let the target run
+    return dyld_instance->GetStopWhenImagesChange();
+}
+
+bool
+DynamicLoaderMacOSXKernel::ReadKextSummaryHeader ()
+{
+    Mutex::Locker locker(m_mutex);
+
+    // the all image infos is already valid for this process stop ID
+    if (m_process->GetStopID() == m_kext_summaries_stop_id)
+        return true;
+
+    m_kext_summaries.clear();
+    if (m_kext_summary_header_addr != LLDB_INVALID_ADDRESS)
+    {
+        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 currenty 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 size_t bytes_read = m_process->ReadMemory (m_kext_summary_header_addr, buf, count, error);
+        if (bytes_read == count)
+        {
+            uint32_t offset = 0;
+            m_kext_summary_header.version       = data.GetU32(&offset);
+            m_kext_summary_header.entry_size    = data.GetU32(&offset);
+            m_kext_summary_header.entry_count   = data.GetU32(&offset);
+            m_kext_summary_header.reserved      = data.GetU32(&offset);
+            m_kext_summary_header_stop_id       = m_process->GetStopID();
+            return true;
+        }
+    }
+    return false;
+}
+
+
+bool
+DynamicLoaderMacOSXKernel::ParseKextSummaries (lldb::addr_t kext_summary_addr, uint32_t count)
+{
+    OSKextLoadedKextSummary::collection kext_summaries;
+    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
+    if (log)
+        log->Printf ("Adding %d modules.\n");
+        
+    Mutex::Locker locker(m_mutex);
+    if (m_process->GetStopID() == m_kext_summaries_stop_id)
+        return true;
+
+    if (!ReadKextSummaries (kext_summary_addr, count, kext_summaries))
+        return false;
+
+    for (uint32_t i = 0; i < count; i++)
+    {
+        if (!kext_summaries[i].UUIDValid())
+        {
+            DataExtractor data; // Load command data
+            if (!ReadMachHeader (kext_summaries[i].address, &kext_summaries[i].header, &data))
+                continue;
+            
+            ParseLoadCommands (data, kext_summaries[i]);
+        }
+    }
+    bool return_value = AddModulesUsingImageInfos (kext_summaries);
+    m_kext_summaries_stop_id = m_process->GetStopID();
+    return return_value;
+}
+
+// Adds the modules in image_infos to m_kext_summaries.  
+// NB don't call this passing in m_kext_summaries.
+
+bool
+DynamicLoaderMacOSXKernel::AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos)
+{
+    // Now add these images to the main list.
+    ModuleList loaded_module_list;
+    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
+    
+    for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
+    {
+        if (log)
+        {
+            log->Printf ("Adding new image at address=0x%16.16llx.", image_infos[idx].address);
+            image_infos[idx].PutToLog (log.get());
+        }
+        
+        m_kext_summaries.push_back(image_infos[idx]);
+        
+        if (FindTargetModule (image_infos[idx], true, NULL))
+        {
+            // UpdateImageLoadAddress will return true if any segments
+            // change load address. We need to check this so we don't
+            // mention that all loaded shared libraries are newly loaded
+            // each time we hit out dyld breakpoint since dyld will list all
+            // shared libraries each time.
+            if (UpdateImageLoadAddress (image_infos[idx]))
+            {
+                loaded_module_list.AppendIfNeeded (image_infos[idx].module_sp);
+            }
+        }
+    }
+    
+    if (loaded_module_list.GetSize() > 0)
+    {
+        // FIXME: This should really be in the Runtime handlers class, which should get
+        // called by the target's ModulesDidLoad, but we're doing it all locally for now 
+        // to save time.
+        // Also, I'm assuming there can be only one libobjc dylib loaded...
+        
+        ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime();
+        if (objc_runtime != NULL && !objc_runtime->HasReadObjCLibrary())
+        {
+            size_t num_modules = loaded_module_list.GetSize();
+            for (int i = 0; i < num_modules; i++)
+            {
+                if (objc_runtime->IsModuleObjCLibrary (loaded_module_list.GetModuleAtIndex (i)))
+                {
+                    objc_runtime->ReadObjCLibrary (loaded_module_list.GetModuleAtIndex (i));
+                    break;
+                }
+            }
+        }
+        if (log)
+            loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXKernel::ModulesDidLoad");
+        m_process->GetTarget().ModulesDidLoad (loaded_module_list);
+    }
+    return true;
+}
+
+bool
+DynamicLoaderMacOSXKernel::RemoveModulesUsingImageInfosAddress (lldb::addr_t kext_summary_addr, uint32_t image_infos_count)
+{
+    OSKextLoadedKextSummary::collection image_infos;
+    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
+    
+    Mutex::Locker locker(m_mutex);
+    if (m_process->GetStopID() == m_kext_summaries_stop_id)
+        return true;
+
+    // First read in the image_infos for the removed modules, and their headers & load commands.
+    if (!ReadKextSummaries (kext_summary_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.16llx.", image_infos[idx].address);
+            image_infos[idx].PutToLog (log.get());
+        }
+            
+        // Remove this image_infos from the m_all_image_infos.  We do the comparision 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.
+        
+        OSKextLoadedKextSummary::collection::iterator pos, end = m_kext_summaries.end();
+        for (pos = m_kext_summaries.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.
+                
+                if (FindTargetModule (image_infos[idx], false, NULL))
+                {
+                    UnloadImageLoadAddress (image_infos[idx]);
+                    unloaded_module_list.AppendIfNeeded (image_infos[idx].module_sp);
+                }
+                else
+                {
+                    if (log)
+                    {
+                        log->Printf ("Could not find module for unloading info entry:");
+                        image_infos[idx].PutToLog(log.get());
+                    }
+                }
+                
+                // Then remove it from the m_kext_summaries:
+                
+                m_kext_summaries.erase(pos);
+                break;
+            }
+        }
+        
+        if (pos == end)
+        {
+            if (log)
+            {
+                log->Printf ("Could not find image_info entry for unloading image:");
+                image_infos[idx].PutToLog(log.get());            
+            }
+        }
+    }
+    if (unloaded_module_list.GetSize() > 0)
+    {
+        if (log)
+        {
+            log->PutCString("Unloaded:");
+            unloaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXKernel::ModulesDidUnload");
+        }
+        m_process->GetTarget().ModulesDidUnload (unloaded_module_list);
+    }
+    m_kext_summaries_stop_id = m_process->GetStopID();
+    return true;
+}
+
+uint32_t
+DynamicLoaderMacOSXKernel::ReadKextSummaries (lldb::addr_t kext_summary_addr, 
+                                              uint32_t image_infos_count, 
+                                              OSKextLoadedKextSummary::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 size_t bytes_read = m_process->ReadMemory (kext_summary_addr, 
+                                                     data.GetBytes(), 
+                                                     data.GetByteSize(),
+                                                     error);
+    if (bytes_read == count)
+    {
+        uint32_t offset = 0;
+        DataExtractor extractor (data.GetBytes(), data.GetByteSize(), endian, addr_size);
+        uint32_t i=0;
+        for (; i < image_infos.size() && extractor.ValidOffsetForDataOfSize(offset, m_kext_summary_header.entry_size); ++i)
+        {
+            const void *name_data = extractor.GetData(&offset, KERNEL_MODULE_MAX_NAME);
+            if (name_data == NULL)
+                break;
+            memcpy (image_infos[i].name, name_data, KERNEL_MODULE_MAX_NAME);
+            image_infos[i].uuid.SetBytes(extractor.GetData (&offset, 16));
+            image_infos[i].address          = extractor.GetU64(&offset);
+            image_infos[i].size             = extractor.GetU64(&offset);
+            image_infos[i].version          = extractor.GetU64(&offset);
+            image_infos[i].load_tag         = extractor.GetU32(&offset);
+            image_infos[i].flags            = extractor.GetU32(&offset);
+            image_infos[i].reference_list   = extractor.GetU64(&offset);
+        }
+        if (i < image_infos.size())
+            image_infos.resize(i);
+    }
+    else
+    {
+        image_infos.clear();
+    }
+    return image_infos.size();
+}
+
+bool
+DynamicLoaderMacOSXKernel::ReadAllKextSummaries (bool force)
+{
+    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
+    
+    Mutex::Locker locker(m_mutex);
+    if (!force)
+    {
+        if (m_process->GetStopID() == m_kext_summaries_stop_id || m_kext_summaries.size() != 0)
+            return false;
+    }
+
+    if (ReadKextSummaryHeader ())
+    {
+        if (m_kext_summary_header.entry_count > 0)
+        {
+            if (!ParseKextSummaries (m_kext_summary_header_addr + 16, m_kext_summary_header.entry_count))
+            {
+                DEBUG_PRINTF( "unable to read all data for all_dylib_infos.");
+                m_kext_summaries.clear();
+            }
+            return true;
+        }
+    }
+    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
+DynamicLoaderMacOSXKernel::ReadMachHeader (lldb::addr_t addr, llvm::MachO::mach_header *header, DataExtractor *load_command_data)
+{
+    DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0);
+    Error error;
+    size_t bytes_read = m_process->ReadMemory (addr, 
+                                               header_bytes.GetBytes(), 
+                                               header_bytes.GetByteSize(), 
+                                               error);
+    if (bytes_read == sizeof(llvm::MachO::mach_header))
+    {
+        uint32_t offset = 0;
+        ::memset (header, 0, sizeof(header));
+
+        // Get the magic byte unswapped so we can figure out what we are dealing with
+        DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), lldb::endian::InlHostByteOrder(), 4);
+        header->magic = data.GetU32(&offset);
+        lldb::addr_t load_cmd_addr = addr;
+        data.SetByteOrder(DynamicLoaderMacOSXKernel::GetByteOrderFromMagic(header->magic));
+        switch (header->magic)
+        {
+        case llvm::MachO::HeaderMagic32:
+        case llvm::MachO::HeaderMagic32Swapped:
+            data.SetAddressByteSize(4);
+            load_cmd_addr += sizeof(llvm::MachO::mach_header);
+            break;
+
+        case llvm::MachO::HeaderMagic64:
+        case llvm::MachO::HeaderMagic64Swapped:
+            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
+DynamicLoaderMacOSXKernel::ParseLoadCommands (const DataExtractor& data, OSKextLoadedKextSummary& dylib_info)
+{
+    uint32_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;
+            uint32_t load_cmd_offset = offset;
+            load_cmd.cmd = data.GetU32 (&offset);
+            load_cmd.cmdsize = data.GetU32 (&offset);
+            switch (load_cmd.cmd)
+            {
+            case llvm::MachO::LoadCommandSegment32:
+                {
+                    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::LoadCommandSegment64:
+                {
+                    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::LoadCommandUUID:
+                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;
+        }
+    }
+#if 0
+    // No slide in the kernel...
+    
+    // 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.slide = dylib_info.address - dylib_info.segments[i].vmaddr;
+            // We have found the slide amount, so we can exit
+            // this for loop.
+            break;
+        }
+    }
+#endif
+    return cmd_idx;
+}
+
+//----------------------------------------------------------------------
+// Dump a Segment to the file handle provided.
+//----------------------------------------------------------------------
+void
+DynamicLoaderMacOSXKernel::Segment::PutToLog (Log *log, lldb::addr_t slide) const
+{
+    if (log)
+    {
+        if (slide == 0)
+            log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx)", 
+                         name.AsCString(""), 
+                         vmaddr + slide, 
+                         vmaddr + slide + vmsize);
+        else
+            log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx) slide = 0x%llx", 
+                         name.AsCString(""), 
+                         vmaddr + slide, 
+                         vmaddr + slide + vmsize, 
+                         slide);
+    }
+}
+
+const DynamicLoaderMacOSXKernel::Segment *
+DynamicLoaderMacOSXKernel::OSKextLoadedKextSummary::FindSegment (const ConstString &name) const
+{
+    const size_t num_segments = segments.size();
+    for (size_t i=0; i<num_segments; ++i)
+    {
+        if (segments[i].name == name)
+            return &segments[i];
+    }
+    return NULL;
+}
+
+
+//----------------------------------------------------------------------
+// Dump an image info structure to the file handle provided.
+//----------------------------------------------------------------------
+void
+DynamicLoaderMacOSXKernel::OSKextLoadedKextSummary::PutToLog (Log *log) const
+{
+    if (log == NULL)
+        return;
+    uint8_t *u = (uint8_t *)uuid.GetBytes();
+//
+//    char                     name[KERNEL_MODULE_MAX_NAME];
+//    lldb::ModuleSP           module_sp;
+//    lldb_private::UUID       uuid;            // UUID for this dylib if it has one, else all zeros
+//    uint64_t                 address;
+//    uint64_t                 size;
+//    uint64_t                 version;
+//    uint32_t                 load_tag;
+//    uint32_t                 flags;
+//    uint64_t                 reference_list;
+//    llvm::MachO::mach_header header;    // The mach header for this image
+//    std::vector<Segment>     segments;      // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
+
+    if (address == LLDB_INVALID_ADDRESS)
+    {
+        if (u)
+        {
+            log->Printf("\t                           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' (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],
+                        name);
+        }
+        else
+            log->Printf("\t                           name='%s' (UNLOADED)", name);
+    }
+    else
+    {
+        if (u)
+        {
+            log->Printf("\taddress=0x%16.16llx 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'",
+                        address,
+                        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],
+                        name);
+        }
+        else
+        {
+            log->Printf("\taddress=0x%16.16llx path='%s/%s'", address, name);
+        }
+        for (uint32_t i=0; i<segments.size(); ++i)
+            segments[i].PutToLog(log, 0);
+    }
+}
+
+//----------------------------------------------------------------------
+// Dump the _dyld_all_image_infos members and all current image infos
+// that we have parsed to the file handle provided.
+//----------------------------------------------------------------------
+void
+DynamicLoaderMacOSXKernel::PutToLog(Log *log) const
+{
+    if (log == NULL)
+        return;
+
+    Mutex::Locker locker(m_mutex);
+    log->Printf("gLoadedKextSummaries = 0x%16.16llx { version=%u, entry_size=%u, entry_count=%u, reserved=%u }",
+                m_kext_summary_header_addr,
+                m_kext_summary_header.version,
+                m_kext_summary_header.entry_size,
+                m_kext_summary_header.entry_count,
+                m_kext_summary_header.reserved);
+
+    size_t i;
+    const size_t count = m_kext_summaries.size();
+    if (count > 0)
+    {
+        log->PutCString("Loaded:");
+        for (i = 0; i<count; i++)
+            m_kext_summaries[i].PutToLog(log);
+    }
+}
+
+void
+DynamicLoaderMacOSXKernel::PrivateInitialize(Process *process)
+{
+    DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
+    Clear(true);
+    m_process = process;
+    m_process->GetTarget().GetSectionLoadList().Clear();
+}
+
+bool
+DynamicLoaderMacOSXKernel::SetNotificationBreakpoint ()
+{
+    // TODO: Add breakpoint to detected dynamic kext loads/unloads. We aren't 
+    // doing any live dynamic checks for kernel kexts being loaded or unloaded 
+    // on the fly yet.
+//    DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
+//    if (m_break_id == LLDB_INVALID_BREAK_ID)
+//    {
+//        if (m_kext_summaries.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.
+//
+//            if (m_process->GetTarget().GetSectionLoadList().ResolveLoadAddress(m_kext_summaries.notification, so_addr))
+//            {
+//                Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true).get();
+//                dyld_break->SetCallback (DynamicLoaderMacOSXKernel::NotifyBreakpointHit, this, true);
+//                m_break_id = dyld_break->GetID();
+//            }
+//        }
+//    }
+    return m_break_id != LLDB_INVALID_BREAK_ID;
+}
+
+//----------------------------------------------------------------------
+// Member function that gets called when the process state changes.
+//----------------------------------------------------------------------
+void
+DynamicLoaderMacOSXKernel::PrivateProcessStateChanged (Process *process, StateType state)
+{
+    DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s(%s)\n", __FUNCTION__, StateAsCString(state));
+    switch (state)
+    {
+    case eStateConnected:
+    case eStateAttaching:
+    case eStateLaunching:
+    case eStateInvalid:
+    case eStateUnloaded:
+    case eStateExited:
+    case eStateDetached:
+        Clear(false);
+        break;
+
+    case eStateStopped:
+        // Keep trying find dyld and set our notification breakpoint each time
+        // we stop until we succeed
+        if (!DidSetNotificationBreakpoint () && m_process->IsAlive())
+        {
+            if (LoadKernelModule())
+            {
+            }
+
+            SetNotificationBreakpoint ();
+        }
+        break;
+
+    case eStateRunning:
+    case eStateStepping:
+    case eStateCrashed:
+    case eStateSuspended:
+        break;
+
+    default:
+        break;
+    }
+}
+
+ThreadPlanSP
+DynamicLoaderMacOSXKernel::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
+{
+    ThreadPlanSP thread_plan_sp;
+    StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get();
+    const SymbolContext &current_context = current_frame->GetSymbolContext(eSymbolContextSymbol);
+    Symbol *current_symbol = current_context.symbol;
+    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+
+    if (current_symbol != NULL)
+    {
+        if (current_symbol->IsTrampoline())
+        {
+            const ConstString &trampoline_name = current_symbol->GetMangled().GetName(Mangled::ePreferMangled);
+            
+            if (trampoline_name)
+            {
+                SymbolContextList target_symbols;
+                ModuleList &images = thread.GetProcess().GetTarget().GetImages();
+                images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols);
+                // FIXME - Make the Run to Address take multiple addresses, and
+                // run to any of them.
+                uint32_t num_symbols = target_symbols.GetSize();
+                if (num_symbols == 1)
+                {
+                    SymbolContext context;
+                    AddressRange addr_range;
+                    if (target_symbols.GetContextAtIndex(0, context))
+                    {
+                        context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
+                        thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addr_range.GetBaseAddress(), stop_others));
+                    }
+                    else
+                    {
+                        if (log)
+                            log->Printf ("Couldn't resolve the symbol context.");
+                    }
+                }
+                else if (num_symbols > 1)
+                {
+                    std::vector<lldb::addr_t>  addresses;
+                    addresses.resize (num_symbols);
+                    for (uint32_t i = 0; i < num_symbols; i++)
+                    {
+                        SymbolContext context;
+                        AddressRange addr_range;
+                        if (target_symbols.GetContextAtIndex(i, context))
+                        {
+                            context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
+                            lldb::addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(&thread.GetProcess().GetTarget());
+                            addresses[i] = load_addr;
+                        }
+                    }
+                    if (addresses.size() > 0)
+                        thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addresses, stop_others));
+                    else
+                    {
+                        if (log)
+                            log->Printf ("Couldn't resolve the symbol contexts.");
+                    }
+                }
+                else
+                {
+                    if (log)
+                    {
+                        log->Printf ("Could not find symbol for trampoline target: \"%s\"", trampoline_name.AsCString());
+                    }
+                }
+            }
+        }
+    }
+    else
+    {
+        if (log)
+            log->Printf ("Could not find symbol for step through.");
+    }
+
+    return thread_plan_sp;
+}
+
+Error
+DynamicLoaderMacOSXKernel::CanLoadImage ()
+{
+    Error error;
+    error.SetErrorString("always unsafe to load or unload shared libraries in the darwin kernel");
+    return error;
+}
+
+void
+DynamicLoaderMacOSXKernel::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+DynamicLoaderMacOSXKernel::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+const char *
+DynamicLoaderMacOSXKernel::GetPluginNameStatic()
+{
+    return "dynamic-loader.macosx-kernel";
+}
+
+const char *
+DynamicLoaderMacOSXKernel::GetPluginDescriptionStatic()
+{
+    return "Dynamic loader plug-in that watches for shared library loads/unloads in the MacOSX kernel.";
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+const char *
+DynamicLoaderMacOSXKernel::GetPluginName()
+{
+    return "DynamicLoaderMacOSXKernel";
+}
+
+const char *
+DynamicLoaderMacOSXKernel::GetShortPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+DynamicLoaderMacOSXKernel::GetPluginVersion()
+{
+    return 1;
+}
+

Added: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h?rev=134672&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h Thu Jul  7 19:48:09 2011
@@ -0,0 +1,418 @@
+//===-- DynamicLoaderMacOSXKernel.h -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_DynamicLoaderMacOSXKernel_h_
+#define liblldb_DynamicLoaderMacOSXKernel_h_
+
+// C Includes
+// C++ Includes
+#include <map>
+#include <vector>
+#include <string>
+
+// Other libraries and framework includes
+#include "llvm/Support/MachO.h"
+
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/TimeValue.h"
+#include "lldb/Core/UUID.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Target/Process.h"
+
+class DynamicLoaderMacOSXKernel : public lldb_private::DynamicLoader
+{
+public:
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static const char *
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::DynamicLoader *
+    CreateInstance (lldb_private::Process *process, bool force);
+
+    DynamicLoaderMacOSXKernel (lldb_private::Process *process);
+
+    virtual
+    ~DynamicLoaderMacOSXKernel ();
+    //------------------------------------------------------------------
+    /// Called after attaching a process.
+    ///
+    /// Allow DynamicLoader plug-ins to execute some code after
+    /// attaching to a process.
+    //------------------------------------------------------------------
+    virtual void
+    DidAttach ();
+
+    virtual void
+    DidLaunch ();
+
+    virtual lldb::ThreadPlanSP
+    GetStepThroughTrampolinePlan (lldb_private::Thread &thread,
+                                  bool stop_others);
+
+    virtual lldb_private::Error
+    CanLoadImage ();
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual const char *
+    GetPluginName();
+
+    virtual const char *
+    GetShortPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+protected:
+    void
+    PrivateInitialize (lldb_private::Process *process);
+
+    void
+    PrivateProcessStateChanged (lldb_private::Process *process,
+                                lldb::StateType state);
+    bool
+    LoadKernelModule ();
+
+    bool
+    DidSetNotificationBreakpoint () const;
+
+    void
+    Clear (bool clear_process);
+
+    void
+    PutToLog (lldb_private::Log *log) const;
+
+    static bool
+    NotifyBreakpointHit (void *baton,
+                         lldb_private::StoppointCallbackContext *context,
+                         lldb::user_id_t break_id,
+                         lldb::user_id_t break_loc_id);
+
+    uint32_t
+    AddrByteSize()
+    {
+        switch (m_kernel.header.magic)
+        {
+            case llvm::MachO::HeaderMagic32:
+            case llvm::MachO::HeaderMagic32Swapped:
+                return 4;
+
+            case llvm::MachO::HeaderMagic64:
+            case llvm::MachO::HeaderMagic64Swapped:
+                return 8;
+
+            default:
+                break;
+        }
+        return 0;
+    }
+
+    static lldb::ByteOrder
+    GetByteOrderFromMagic (uint32_t magic)
+    {
+        switch (magic)
+        {
+            case llvm::MachO::HeaderMagic32:
+            case llvm::MachO::HeaderMagic64:
+                return lldb::endian::InlHostByteOrder();
+
+            case llvm::MachO::HeaderMagic32Swapped:
+            case llvm::MachO::HeaderMagic64Swapped:
+                if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig)
+                    return lldb::eByteOrderLittle;
+                else
+                    return lldb::eByteOrderBig;
+
+            default:
+                break;
+        }
+        return lldb::eByteOrderInvalid;
+    }
+
+    bool
+    ReadMachHeader (lldb::addr_t addr,
+                    llvm::MachO::mach_header *header,
+                    lldb_private::DataExtractor *load_command_data);
+    class Segment
+    {
+    public:
+
+        Segment() :
+            name(),
+            vmaddr(LLDB_INVALID_ADDRESS),
+            vmsize(0),
+            fileoff(0),
+            filesize(0),
+            maxprot(0),
+            initprot(0),
+            nsects(0),
+            flags(0)
+        {
+        }
+
+        lldb_private::ConstString name;
+        lldb::addr_t vmaddr;
+        lldb::addr_t vmsize;
+        lldb::addr_t fileoff;
+        lldb::addr_t filesize;
+        uint32_t maxprot;
+        uint32_t initprot;
+        uint32_t nsects;
+        uint32_t flags;
+
+        bool
+        operator==(const Segment& rhs) const
+        {
+            return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize;
+        }
+
+        void
+        PutToLog (lldb_private::Log *log,
+                  lldb::addr_t slide) const;
+
+    };
+
+    enum { KERNEL_MODULE_MAX_NAME = 64u };
+    
+    struct OSKextLoadedKextSummary
+    {
+        char                     name[KERNEL_MODULE_MAX_NAME];
+        lldb::ModuleSP           module_sp;
+        lldb_private::UUID       uuid;            // UUID for this dylib if it has one, else all zeros
+        uint64_t                 address;
+        uint64_t                 size;
+        uint64_t                 version;
+        uint32_t                 load_tag;
+        uint32_t                 flags;
+        uint64_t                 reference_list;
+        llvm::MachO::mach_header header;    // The mach header for this image
+        std::vector<Segment>     segments;      // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
+
+        OSKextLoadedKextSummary() :
+            module_sp (),
+            uuid (),
+            address (LLDB_INVALID_ADDRESS),
+            size (0),
+            version (0),
+            load_tag (0),
+            flags (0),
+            reference_list (0),
+            header(),
+            segments()
+        {
+            name[0] = '\0';
+        }
+
+        void
+        Clear (bool load_cmd_data_only)
+        {
+            if (!load_cmd_data_only)
+            {
+                address = LLDB_INVALID_ADDRESS;
+                size = 0;
+                version = 0;
+                load_tag = 0;
+                flags = 0;
+                reference_list = 0;
+                name[0] = '\0';
+                ::memset (&header, 0, sizeof(header));
+            }
+            module_sp.reset();
+            uuid.Clear();
+            segments.clear();
+        }
+
+        bool
+        operator == (const OSKextLoadedKextSummary& rhs) const
+        {
+            return  address == rhs.address
+                    && size == rhs.size
+            //&& module_sp.get() == rhs.module_sp.get()
+                    && uuid == rhs.uuid
+                    && version == rhs.version
+                    && load_tag == rhs.load_tag
+                    && flags == rhs.flags
+                    && reference_list == rhs.reference_list
+                    && strncmp (name, rhs.name, KERNEL_MODULE_MAX_NAME) == 0
+                    && memcmp(&header, &rhs.header, sizeof(header)) == 0
+                    && segments == rhs.segments;
+        }
+
+        bool
+        UUIDValid() const
+        {
+            return uuid.IsValid();
+        }
+
+        uint32_t
+        GetAddressByteSize ()
+        {
+            if (header.cputype)
+            {
+                if (header.cputype & llvm::MachO::CPUArchABI64)
+                    return 8;
+                else
+                    return 4;
+            }
+            return 0;
+        }
+
+        lldb::ByteOrder
+        GetByteOrder()
+        {
+            switch (header.magic)
+            {
+            case llvm::MachO::HeaderMagic32:        // MH_MAGIC
+            case llvm::MachO::HeaderMagic64:        // MH_MAGIC_64
+                return lldb::endian::InlHostByteOrder();
+
+            case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM
+            case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64
+                if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle)
+                    return lldb::eByteOrderBig;
+                else
+                    return lldb::eByteOrderLittle;
+            default:
+                assert (!"invalid header.magic value");
+                break;
+            }
+            return lldb::endian::InlHostByteOrder();
+        }
+
+        lldb_private::ArchSpec
+        GetArchitecture () const
+        {
+            return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype);
+        }
+
+        const Segment *
+        FindSegment (const lldb_private::ConstString &name) const;
+
+        void
+        PutToLog (lldb_private::Log *log) const;
+
+        typedef std::vector<OSKextLoadedKextSummary> collection;
+        typedef collection::iterator iterator;
+        typedef collection::const_iterator const_iterator;
+    };
+
+    struct OSKextLoadedKextSummaryHeader
+    {
+        uint32_t version;
+        uint32_t entry_size;
+        uint32_t entry_count;
+        uint32_t reserved; /* explicit alignment for gdb  */
+        lldb::addr_t image_infos_addr;
+
+        OSKextLoadedKextSummaryHeader() :
+            version (0),
+            entry_size (0),
+            entry_count (0),
+            reserved (0),
+            image_infos_addr (LLDB_INVALID_ADDRESS)
+        {
+        }
+
+        void
+        Clear()
+        {
+            version = 0;
+            entry_size = 0;
+            entry_count = 0;
+            reserved = 0;
+            image_infos_addr = LLDB_INVALID_ADDRESS;
+        }
+
+        bool
+        IsValid() const
+        {
+            return version >= 1 || version <= 2;
+        }
+    };
+
+    void
+    RegisterNotificationCallbacks();
+
+    void
+    UnregisterNotificationCallbacks();
+
+    uint32_t
+    ParseLoadCommands (const lldb_private::DataExtractor& data,
+                       OSKextLoadedKextSummary& dylib_info);
+
+    bool
+    UpdateImageLoadAddress(OSKextLoadedKextSummary& info);
+
+    bool
+    FindTargetModule (OSKextLoadedKextSummary &image_info,
+                      bool can_create,
+                      bool *did_create_ptr);
+
+    bool
+    SetNotificationBreakpoint ();
+
+    bool
+    ReadAllKextSummaries (bool force);
+
+    bool
+    ReadKextSummaryHeader ();
+    
+    bool
+    ParseKextSummaries (lldb::addr_t kext_summary_addr, uint32_t count);
+    
+    bool
+    AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos);
+    
+    bool
+    RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count);
+
+    void
+    UpdateImageInfosHeaderAndLoadCommands(OSKextLoadedKextSummary::collection &image_infos, 
+                                          uint32_t infos_count, 
+                                          bool update_executable);
+
+    bool
+    UpdateCommPageLoadAddress (lldb_private::Module *module);
+
+    uint32_t
+    ReadKextSummaries (lldb::addr_t image_infos_addr, 
+                       uint32_t image_infos_count, 
+                       OSKextLoadedKextSummary::collection &image_infos);
+    
+    bool
+    UnloadImageLoadAddress (OSKextLoadedKextSummary& info);
+
+    OSKextLoadedKextSummary m_kernel; // Info about the current kernel image being used
+    lldb::addr_t m_kext_summary_header_addr;
+    OSKextLoadedKextSummaryHeader m_kext_summary_header;
+    uint32_t m_kext_summary_header_stop_id;             // The process stop ID that "m_kext_summary_header" is valid for
+    lldb::user_id_t m_break_id;
+    OSKextLoadedKextSummary::collection m_kext_summaries;
+    uint32_t m_kext_summaries_stop_id;                     // The process stop ID that "m_kext_summaries" is valid for
+    mutable lldb_private::Mutex m_mutex;
+    lldb_private::Process::Notifications m_notification_callbacks;
+
+private:
+    DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXKernel);
+};
+
+#endif  // liblldb_DynamicLoaderMacOSXKernel_h_

Added: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/Makefile?rev=134672&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/Makefile (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/Makefile Thu Jul  7 19:48:09 2011
@@ -0,0 +1,14 @@
+##===- source/Plugins/Disassembler/llvm/Makefile -------------*- Makefile -*-===##
+# 
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+# 
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginDynamicLoaderMacOSXKernel
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile

Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=134672&r1=134671&r2=134672&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Thu Jul  7 19:48:09 2011
@@ -1275,6 +1275,46 @@
     result.GetImmediateErrorStream()->Flush();
 }
 
+bool 
+Target::LoadModuleWithSlide (Module *module, lldb::addr_t slide)
+{
+    bool changed = false;
+    if (module)
+    {
+        ObjectFile *object_file = module->GetObjectFile();
+        if (object_file)
+        {
+            SectionList *section_list = object_file->GetSectionList ();
+            if (section_list)
+            {
+                // 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 = section_list->GetSize();
+                size_t sect_idx = 0;
+                for (sect_idx = 0; sect_idx < num_sections; ++sect_idx)
+                {
+                    // Iterate through the object file sections to find the
+                    // first section that starts of file offset zero and that
+                    // has bytes in the file...
+                    Section *section = section_list->GetSectionAtIndex (sect_idx).get();
+                    if (section)
+                    {
+                        if (m_section_load_list.SetSectionLoadAddress (section, section->GetFileAddress() + slide))
+                            changed = true;
+                    }
+                }
+            }
+        }
+    }
+    return changed;
+}
+
+
 //--------------------------------------------------------------
 // class Target::StopHook
 //--------------------------------------------------------------





More information about the lldb-commits mailing list