[Lldb-commits] [lldb] r276254 - Add a new DynamicLoader plugin that uses SPI that are in development

Jason Molenda via lldb-commits lldb-commits at lists.llvm.org
Thu Jul 21 01:30:55 PDT 2016


Author: jmolenda
Date: Thu Jul 21 03:30:55 2016
New Revision: 276254

URL: http://llvm.org/viewvc/llvm-project?rev=276254&view=rev
Log:
Add a new DynamicLoader plugin that uses SPI that are in development
for the fall (northern hemisphere) 2016 Darwin platforms to learn
about loaded images, instead of reading dyld internal data structures.
These new SPI don't exist on older releases, and new packets are
needed from debugserver to use them (those changes are already committed).

I had to change the minimum deployment target for debugserver in the xcode
project file to macOS 10.10 so that debugserver will use the 
[[NSProcessInfo processInfo] operatingSystemVersion]
call in MachProcess::GetOSVersionNumbers to get the operarting system
version # -- this API is only available in macOS 10.10 and newer
("OS X Yosemite", released Oct 2014).  If we have many people building
llvm.org lldb on older systems still, we can back off on this for the
llvm.org sources.

There should be no change in behavior with this commit, either to
older darwin systems or newer darwin systems.

For now the new DynamicLoader plugin is never activated - I'm forcing
the old plugin to be used in DynamicLoaderDarwin::UseDYLDSPI.
I'll remove that unconditional use of the old plugin soon, so the
newer plugin is used on the newest Darwin platforms.

<rdar://problem/25251243> 


Added:
    lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
    lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h
Modified:
    lldb/trunk/include/lldb/Target/Process.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/API/SystemInitializerFull.cpp
    lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt
    lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
    lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h
    lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
    lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
    lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj

Modified: lldb/trunk/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=276254&r1=276253&r2=276254&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Process.h (original)
+++ lldb/trunk/include/lldb/Target/Process.h Thu Jul 21 03:30:55 2016
@@ -1918,6 +1918,9 @@ public:
 
     //------------------------------------------------------------------
     /// Retrieve the list of shared libraries that are loaded for this process
+    /// This method is used on pre-macOS 10.12, pre-iOS 10, pre-tvOS 10, 
+    /// pre-watchOS 3 systems.  The following two methods are for newer versions
+    /// of those OSes.
     /// 
     /// For certain platforms, the time it takes for the DynamicLoader plugin to
     /// read all of the shared libraries out of memory over a slow communication
@@ -1945,6 +1948,22 @@ public:
     {
         return StructuredData::ObjectSP();
     }
+
+    // On macOS 10.12, tvOS 10, iOS 10, watchOS 3 and newer, debugserver can return
+    // the full list of loaded shared libraries without needing any input.
+    virtual lldb_private::StructuredData::ObjectSP
+    GetLoadedDynamicLibrariesInfos ()
+    {
+        return StructuredData::ObjectSP();
+    }
+
+    // On macOS 10.12, tvOS 10, iOS 10, watchOS 3 and newer, debugserver can return
+    // information about binaries given their load addresses.
+    virtual lldb_private::StructuredData::ObjectSP
+    GetLoadedDynamicLibrariesInfos (const std::vector<lldb::addr_t> &load_addresses)
+    {
+        return StructuredData::ObjectSP();
+    }
 
     //------------------------------------------------------------------
     /// Print a user-visible warning about a module being built with optimization

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=276254&r1=276253&r2=276254&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Thu Jul 21 03:30:55 2016
@@ -894,6 +894,8 @@
 		AF26703B1852D01E00B6CC36 /* QueueList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF2670391852D01E00B6CC36 /* QueueList.cpp */; };
 		AF27AD551D3603EA00CF2833 /* DynamicLoaderDarwin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF27AD531D3603EA00CF2833 /* DynamicLoaderDarwin.cpp */; };
 		AF27AD561D3603EA00CF2833 /* DynamicLoaderDarwin.h in Headers */ = {isa = PBXBuildFile; fileRef = AF27AD541D3603EA00CF2833 /* DynamicLoaderDarwin.h */; };
+		AF2907BF1D3F082400E10654 /* DynamicLoaderMacOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF2907BD1D3F082400E10654 /* DynamicLoaderMacOS.cpp */; };
+		AF2907C01D3F082400E10654 /* DynamicLoaderMacOS.h in Headers */ = {isa = PBXBuildFile; fileRef = AF2907BE1D3F082400E10654 /* DynamicLoaderMacOS.h */; };
 		AF2BA6EC1A707E3400C5248A /* UriParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33064C991A5C7A330033D415 /* UriParser.cpp */; };
 		AF2BCA6C18C7EFDE005B4526 /* JITLoaderGDB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF2BCA6918C7EFDE005B4526 /* JITLoaderGDB.cpp */; };
 		AF33B4BE1C1FA441001B28D9 /* NetBSDSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF33B4BC1C1FA441001B28D9 /* NetBSDSignals.cpp */; };
@@ -2817,6 +2819,8 @@
 		AF2670391852D01E00B6CC36 /* QueueList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = QueueList.cpp; path = source/Target/QueueList.cpp; sourceTree = "<group>"; };
 		AF27AD531D3603EA00CF2833 /* DynamicLoaderDarwin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLoaderDarwin.cpp; sourceTree = "<group>"; };
 		AF27AD541D3603EA00CF2833 /* DynamicLoaderDarwin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderDarwin.h; sourceTree = "<group>"; };
+		AF2907BD1D3F082400E10654 /* DynamicLoaderMacOS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLoaderMacOS.cpp; sourceTree = "<group>"; };
+		AF2907BE1D3F082400E10654 /* DynamicLoaderMacOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderMacOS.h; sourceTree = "<group>"; };
 		AF2BCA6918C7EFDE005B4526 /* JITLoaderGDB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITLoaderGDB.cpp; sourceTree = "<group>"; };
 		AF2BCA6A18C7EFDE005B4526 /* JITLoaderGDB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITLoaderGDB.h; sourceTree = "<group>"; };
 		AF33B4BC1C1FA441001B28D9 /* NetBSDSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetBSDSignals.cpp; path = Utility/NetBSDSignals.cpp; sourceTree = "<group>"; };
@@ -3297,6 +3301,8 @@
 			children = (
 				AF27AD531D3603EA00CF2833 /* DynamicLoaderDarwin.cpp */,
 				AF27AD541D3603EA00CF2833 /* DynamicLoaderDarwin.h */,
+				AF2907BD1D3F082400E10654 /* DynamicLoaderMacOS.cpp */,
+				AF2907BE1D3F082400E10654 /* DynamicLoaderMacOS.h */,
 				260C897A10F57C5600BB2B04 /* DynamicLoaderMacOSXDYLD.cpp */,
 				260C897B10F57C5600BB2B04 /* DynamicLoaderMacOSXDYLD.h */,
 			);
@@ -6950,6 +6956,7 @@
 				268900ED13353E6F00698AC0 /* ObjCLanguageRuntime.cpp in Sources */,
 				268900EE13353E6F00698AC0 /* PathMappingList.cpp in Sources */,
 				4C2479BD1BA39295009C9A7B /* FunctionCaller.cpp in Sources */,
+				AF2907BF1D3F082400E10654 /* DynamicLoaderMacOS.cpp in Sources */,
 				268900EF13353E6F00698AC0 /* Platform.cpp in Sources */,
 				268900F013353E6F00698AC0 /* Process.cpp in Sources */,
 				26BC17AD18C7F4CB00D2196D /* RegisterContextPOSIXCore_mips64.cpp in Sources */,

Modified: lldb/trunk/source/API/SystemInitializerFull.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SystemInitializerFull.cpp?rev=276254&r1=276253&r2=276254&view=diff
==============================================================================
--- lldb/trunk/source/API/SystemInitializerFull.cpp (original)
+++ lldb/trunk/source/API/SystemInitializerFull.cpp Thu Jul 21 03:30:55 2016
@@ -43,6 +43,7 @@
 #include "Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h"
 #include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h"
 #include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"
+#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h"
 #include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
 #include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"
 #include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h"
@@ -383,6 +384,7 @@ SystemInitializerFull::Initialize()
 
     process_gdb_remote::ProcessGDBRemote::Initialize();
     DynamicLoaderMacOSXDYLD::Initialize();
+    DynamicLoaderMacOS::Initialize();
     DynamicLoaderPOSIXDYLD::Initialize();
     DynamicLoaderStatic::Initialize();
     DynamicLoaderWindowsDYLD::Initialize();
@@ -506,6 +508,7 @@ SystemInitializerFull::Terminate()
     platform_gdb_server::PlatformRemoteGDBServer::Terminate();
     process_gdb_remote::ProcessGDBRemote::Terminate();
     DynamicLoaderMacOSXDYLD::Terminate();
+    DynamicLoaderMacOS::Terminate();
     DynamicLoaderPOSIXDYLD::Terminate();
     DynamicLoaderStatic::Terminate();
     DynamicLoaderWindowsDYLD::Terminate();

Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt?rev=276254&r1=276253&r2=276254&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt Thu Jul 21 03:30:55 2016
@@ -1,4 +1,5 @@
 add_lldb_library(lldbPluginDynamicLoaderMacOSXDYLD
   DynamicLoaderMacOSXDYLD.cpp
+  DynamicLoaderMacOS.cpp
   DynamicLoaderDarwin.cpp
   )

Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp?rev=276254&r1=276253&r2=276254&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp (original)
+++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp Thu Jul 21 03:30:55 2016
@@ -151,21 +151,6 @@ DynamicLoaderDarwin::FindTargetModuleFor
     return module_sp;
 }
 
-DynamicLoaderDarwin::ImageInfo *
-DynamicLoaderDarwin::FindImageInfoForAddress (addr_t load_address)
-{
-    std::lock_guard<std::recursive_mutex> guard(m_mutex);
-    const size_t image_count = m_dyld_image_infos.size();
-    for (size_t i = 0; i < image_count; i++)
-    {
-        if (load_address == m_dyld_image_infos[i].address)
-        {
-            return &m_dyld_image_infos[i];
-        }
-    }
-    return NULL;
-}
-
 void
 DynamicLoaderDarwin::UnloadImages (const std::vector<lldb::addr_t> &solib_addresses)
 {
@@ -223,6 +208,46 @@ DynamicLoaderDarwin::UnloadImages (const
     }
 }
 
+void
+DynamicLoaderDarwin::UnloadAllImages ()
+{
+    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
+    ModuleList unloaded_modules_list;
+
+    Target &target = m_process->GetTarget();
+    const ModuleList &target_modules = target.GetImages();
+    std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
+
+    size_t num_modules = target_modules.GetSize();
+    ModuleSP dyld_sp (GetDYLDModule());
+
+    for (size_t i = 0; i < num_modules; i++)
+    {
+        ModuleSP module_sp = target_modules.GetModuleAtIndexUnlocked (i);
+
+        // Don't remove dyld - else we'll lose our breakpoint notifying us about libraries
+        // being re-loaded...
+        if (module_sp.get() != nullptr
+            && module_sp.get() != dyld_sp.get())
+        {
+            UnloadSections (module_sp);
+            unloaded_modules_list.Append (module_sp);
+        }
+    }
+
+    if (unloaded_modules_list.GetSize() != 0)
+    {
+        if (log)
+        {
+            log->PutCString("Unloaded:");
+            unloaded_modules_list.LogUUIDAndPaths (log, "DynamicLoaderDarwin::UnloadAllImages");
+        }
+        target.GetImages().Remove(unloaded_modules_list);
+        m_dyld_image_infos.clear();
+        m_dyld_image_infos_stop_id = m_process->GetStopID();
+    }
+}
+
 //----------------------------------------------------------------------
 // Update the load addresses for all segments in MODULE using the
 // updated INFO that is passed in.
@@ -401,6 +426,23 @@ DynamicLoaderDarwin::JSONImageInformatio
         image_infos[i].header.cpusubtype = mh->GetValueForKey("cpusubtype")->GetAsInteger()->GetValue();
         image_infos[i].header.filetype = mh->GetValueForKey("filetype")->GetAsInteger()->GetValue();
 
+        if (image->HasKey("min_version_os_name"))
+        {
+            std::string os_name = image->GetValueForKey("min_version_os_name")->GetAsString()->GetValue();
+            if (os_name == "macosx")
+                image_infos[i].os_type = llvm::Triple::MacOSX;
+            else if (os_name == "ios" || os_name == "iphoneos")
+                image_infos[i].os_type = llvm::Triple::IOS;
+            else if (os_name == "tvos")
+                image_infos[i].os_type = llvm::Triple::TvOS;
+            else if (os_name == "watchos")
+                image_infos[i].os_type = llvm::Triple::WatchOS;
+        }
+        if (image->HasKey("min_version_os_sdk"))
+        {
+            image_infos[i].min_version_os_sdk = image->GetValueForKey("min_version_os_sdk")->GetAsString()->GetValue();
+        }
+
         // Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't currently send them
         // in the reply.
 
@@ -483,71 +525,99 @@ DynamicLoaderDarwin::JSONImageInformatio
 }
 
 void
-DynamicLoaderDarwin::UpdateDYLDImageInfoFromNewImageInfos (ImageInfo::collection &image_infos)
+DynamicLoaderDarwin::UpdateSpecialBinariesFromNewImageInfos (ImageInfo::collection &image_infos)
 {
+    uint32_t exe_idx = UINT32_MAX;
+    uint32_t dyld_idx = UINT32_MAX;
+    Target &target = m_process->GetTarget();
+    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
+    ConstString g_dyld_sim_filename ("dyld_sim");
+
+    ArchSpec target_arch = target.GetArchitecture();
     const size_t image_infos_size = image_infos.size();
     for (size_t i = 0; i < image_infos_size; i++)
     {
         if (image_infos[i].header.filetype == llvm::MachO::MH_DYLINKER)
         {
-            UpdateDYLDImageInfoFromNewImageInfo (image_infos[i]);
-            break; // FIXME simulator debugging w/ multiple dylds
+            // In a "simulator" process (an x86 process that is ios/tvos/watchos)
+            // we will have two dyld modules -- a "dyld" that we want to keep track of,
+            // and a "dyld_sim" which we don't need to keep track of here.  
+            // If the target is an x86 system and the OS of the dyld binary is 
+            // ios/tvos/watchos, then we are looking at dyld_sym.
+
+            // debugserver has only recently (late 2016) started sending up the
+            // os type for each binary it sees -- so if we don't have an os
+            // type, use a filename check as our next best guess.
+            if (image_infos[i].os_type == llvm::Triple::OSType::UnknownOS)
+            {
+                if (image_infos[i].file_spec.GetFilename() != g_dyld_sim_filename)
+                {
+                    dyld_idx = i;
+                }
+            }
+            else if (target_arch.GetTriple().getArch() == llvm::Triple::x86 
+                     || target_arch.GetTriple().getArch() == llvm::Triple::x86_64)
+            {
+                if (image_infos[i].os_type != llvm::Triple::OSType::IOS
+                    && image_infos[i].os_type != llvm::Triple::TvOS
+                    && image_infos[i].os_type != llvm::Triple::WatchOS)
+                {
+                    dyld_idx = i;
+                }
+            }
+        }
+        else if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE)
+        {
+            exe_idx = i;
         }
     }
-}
 
-void
-DynamicLoaderDarwin::UpdateDYLDImageInfoFromNewImageInfo (ImageInfo &image_info)
-{
-    // FIXME simulator debugging w/ multiple dylds
-    if (image_info.header.filetype == llvm::MachO::MH_DYLINKER)
+    if (exe_idx != UINT32_MAX)
     {
         const bool can_create = true;
-        ModuleSP dyld_sp = FindTargetModuleForImageInfo (image_info, can_create, NULL);
+        ModuleSP exe_module_sp (FindTargetModuleForImageInfo (image_infos[exe_idx], can_create, NULL));
+        if (exe_module_sp)
+        {
+            if (log)
+                log->Printf ("Found executable module: %s", exe_module_sp->GetFileSpec().GetPath().c_str());
+            target.GetImages().AppendIfNeeded (exe_module_sp);
+            UpdateImageLoadAddress (exe_module_sp.get(), image_infos[exe_idx]);
+            if (exe_module_sp.get() != target.GetExecutableModulePointer())
+            {
+                const bool get_dependent_images = false;
+                target.SetExecutableModule (exe_module_sp, get_dependent_images);
+            }
+        }
+    }
+
+    if (dyld_idx != UINT32_MAX)
+    {
+        const bool can_create = true;
+        ModuleSP dyld_sp = FindTargetModuleForImageInfo (image_infos[dyld_idx], can_create, NULL);
         if (dyld_sp.get())
         {
-            Target &target = m_process->GetTarget();
+            if (log)
+                log->Printf ("Found dyld module: %s", dyld_sp->GetFileSpec().GetPath().c_str());
             target.GetImages().AppendIfNeeded (dyld_sp);
-            UpdateImageLoadAddress (dyld_sp.get(), image_info);
+            UpdateImageLoadAddress (dyld_sp.get(), image_infos[dyld_idx]);
             SetDYLDModule (dyld_sp);
         }
     }
 }
 
 void
-DynamicLoaderDarwin::AddExecutableModuleIfInImageInfos (ImageInfo::collection &image_infos)
+DynamicLoaderDarwin::UpdateDYLDImageInfoFromNewImageInfo (ImageInfo &image_info)
 {
-    const size_t image_infos_size = image_infos.size();
-    for (size_t i = 0; i < image_infos_size; i++)
+    if (image_info.header.filetype == llvm::MachO::MH_DYLINKER)
     {
-        if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE)
+        const bool can_create = true;
+        ModuleSP dyld_sp = FindTargetModuleForImageInfo (image_info, can_create, NULL);
+        if (dyld_sp.get())
         {
             Target &target = m_process->GetTarget();
-            const bool can_create = true;
-            ModuleSP exe_module_sp (FindTargetModuleForImageInfo (image_infos[i], can_create, NULL));
-    
-            if (exe_module_sp)
-            {
-                UpdateImageLoadAddress (exe_module_sp.get(), image_infos[i]);
-    
-                if (exe_module_sp.get() != target.GetExecutableModulePointer())
-                {
-                    // Don't load dependent images since we are in dyld where we will know
-                    // and find out about all images that are loaded. Also when setting the
-                    // executable module, it will clear the targets module list, and if we
-                    // have an in memory dyld module, it will get removed from the list
-                    // so we will need to add it back after setting the executable module,
-                    // so we first try and see if we already have a weak pointer to the
-                    // dyld module, make it into a shared pointer, then add the executable,
-                    // then re-add it back to make sure it is always in the list.
-                    
-                    const bool get_dependent_images = false;
-                    m_process->GetTarget().SetExecutableModule (exe_module_sp, 
-                                                                get_dependent_images);
-    
-                    UpdateDYLDImageInfoFromNewImageInfos (image_infos);
-                }
-            }
+            target.GetImages().AppendIfNeeded (dyld_sp);
+            UpdateImageLoadAddress (dyld_sp.get(), image_info);
+            SetDYLDModule (dyld_sp);
         }
     }
 }
@@ -1141,3 +1211,57 @@ DynamicLoaderDarwin::GetThreadLocalData(
     return LLDB_INVALID_ADDRESS;
 }
 
+bool
+DynamicLoaderDarwin::UseDYLDSPI (Process *process)
+{
+    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
+    uint32_t major, minor, update;
+
+    bool use_new_spi_interface = false;
+
+    if (process->GetHostOSVersion (major, minor, update))
+    {
+        const llvm::Triple::OSType os_type = process->GetTarget().GetArchitecture().GetTriple().getOS();
+
+        // macOS 10.12 and newer
+        if (os_type == llvm::Triple::MacOSX
+            && (major >= 10 || (major == 10 && minor >= 12)))
+        {
+            use_new_spi_interface = true;
+        }
+
+        // iOS 10 and newer
+        if (os_type == llvm::Triple::IOS && major >= 10)
+        {
+            use_new_spi_interface = true;
+        }
+
+        // tvOS 10 and newer
+        if (os_type == llvm::Triple::TvOS && major >= 10)
+        {
+            use_new_spi_interface = true;
+        }
+
+        // watchOS 3 and newer
+        if (os_type == llvm::Triple::WatchOS && major >= 3)
+        {
+            use_new_spi_interface = true;
+        }
+    }
+
+
+    // FIXME: Temporarily force the use of the old DynamicLoader plugin until all
+    // the different use cases have been tested & the updated SPIs are available 
+    // everywhere.
+    use_new_spi_interface = false;
+
+    if (log)
+    {
+        if (use_new_spi_interface)
+            log->Printf ("DynamicLoaderDarwin::UseDYLDSPI: Use new DynamicLoader plugin");
+        else
+            log->Printf ("DynamicLoaderDarwin::UseDYLDSPI: Use old DynamicLoader plugin");
+
+    }
+	return use_new_spi_interface;
+}

Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h?rev=276254&r1=276253&r2=276254&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h (original)
+++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h Thu Jul 21 03:30:55 2016
@@ -26,6 +26,8 @@
 #include "lldb/Target/Process.h"
 #include "lldb/Utility/SafeMachO.h"
 
+#include "llvm/ADT/Triple.h"
+
 namespace lldb_private {
 
 class DynamicLoaderDarwin : public lldb_private::DynamicLoader
@@ -137,6 +139,8 @@ protected:
         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)
         uint32_t load_stop_id;              // The process stop ID that the sections for this image were loaded
+        llvm::Triple::OSType os_type;       // LC_VERSION_MIN_... load command os type
+        std::string min_version_os_sdk;     // LC_VERSION_MIN_... sdk value
 
         ImageInfo() :
             address(LLDB_INVALID_ADDRESS),
@@ -146,7 +150,9 @@ protected:
             uuid(),
             header(),
             segments(),
-            load_stop_id(0)
+            load_stop_id(0),
+            os_type (llvm::Triple::OSType::UnknownOS),
+            min_version_os_sdk()
         {
         }
 
@@ -164,6 +170,8 @@ protected:
             uuid.Clear();
             segments.clear();
             load_stop_id = 0;
+            os_type = llvm::Triple::OSType::UnknownOS;
+            min_version_os_sdk.clear();
         }
 
         bool
@@ -175,7 +183,8 @@ protected:
                 && file_spec == rhs.file_spec
                 && uuid == rhs.uuid
                 && memcmp(&header, &rhs.header, sizeof(header)) == 0
-                && segments == rhs.segments;
+                && segments == rhs.segments
+                && os_type == rhs.os_type;
         }
 
         bool
@@ -220,9 +229,6 @@ protected:
     bool
     UnloadModuleSections (lldb_private::Module *module, ImageInfo& info);
 
-    ImageInfo *
-    FindImageInfoForAddress (lldb::addr_t load_address);
-
     lldb::ModuleSP
     FindTargetModuleForImageInfo (ImageInfo &image_info,
                                   bool can_create,
@@ -231,6 +237,9 @@ protected:
     void
     UnloadImages (const std::vector<lldb::addr_t> &solib_addresses);
 
+    void
+    UnloadAllImages ();
+
     virtual bool
     SetNotificationBreakpoint () = 0;
 
@@ -258,10 +267,10 @@ protected:
     bool
     JSONImageInformationIntoImageInfo (lldb_private::StructuredData::ObjectSP image_details, ImageInfo::collection &image_infos);
 
-    // If image_infos contains / may contain dyld image, call this method
-    // to keep our internal record keeping of the special dyld binary up-to-date.
+    // If image_infos contains / may contain dyld or executable image, call this method
+    // to keep our internal record keeping of the special binaries up-to-date.
     void
-    UpdateDYLDImageInfoFromNewImageInfos (ImageInfo::collection &image_infos);
+    UpdateSpecialBinariesFromNewImageInfos (ImageInfo::collection &image_infos);
 
     // if image_info is a dyld binary, call this method
     void
@@ -275,7 +284,13 @@ protected:
     bool
     AddModulesUsingImageInfos (ImageInfo::collection &image_infos);
 
-    lldb::ModuleWP m_dyld_module_wp;
+    // Whether we should use the new dyld SPI to get shared library information, or read
+    // it directly out of the dyld_all_image_infos.  Whether we use the (newer) DynamicLoaderMacOS
+    // plugin or the (older) DynamicLoaderMacOSX plugin.
+    static bool
+    UseDYLDSPI (lldb_private::Process *process);
+
+    lldb::ModuleWP m_dyld_module_wp;     // the dyld whose file type (mac, ios, etc) matches the process
     lldb::ModuleWP m_libpthread_module_wp;
     lldb_private::Address m_pthread_getspecific_addr;
     ThreadIDToTLSMap m_tid_to_tls_map;

Added: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp?rev=276254&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp Thu Jul 21 03:30:55 2016
@@ -0,0 +1,528 @@
+//===-- DynamicLoaderMacOS.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/State.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/ABI.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/StackFrame.h"
+
+#include "DynamicLoaderMacOS.h"
+#include "DynamicLoaderDarwin.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+//----------------------------------------------------------------------
+// Create an instance of this class. This function is filled into
+// the plugin info class that gets handed out by the plugin factory and
+// allows the lldb to instantiate an instance of this class.
+//----------------------------------------------------------------------
+DynamicLoader *
+DynamicLoaderMacOS::CreateInstance (Process* process, bool force)
+{
+    bool create = force;
+    if (!create)
+    {
+        create = true;
+        Module* exe_module = process->GetTarget().GetExecutableModulePointer();
+        if (exe_module)
+        {
+            ObjectFile *object_file = exe_module->GetObjectFile();
+            if (object_file)
+            {
+                create = (object_file->GetStrata() == ObjectFile::eStrataUser);
+            }
+        }
+        
+        if (create)
+        {
+            const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
+            switch (triple_ref.getOS())
+            {
+                case llvm::Triple::Darwin:
+                case llvm::Triple::MacOSX:
+                case llvm::Triple::IOS:
+                case llvm::Triple::TvOS:
+                case llvm::Triple::WatchOS:
+                    create = triple_ref.getVendor() == llvm::Triple::Apple;
+                    break;
+                default:
+                    create = false;
+                    break;
+            }
+        }
+    }
+
+	if (UseDYLDSPI (process) == false)
+	{
+		create = false;
+	}
+    
+    if (create)
+        return new DynamicLoaderMacOS (process);
+    return NULL;
+}
+
+//----------------------------------------------------------------------
+// Constructor
+//----------------------------------------------------------------------
+DynamicLoaderMacOS::DynamicLoaderMacOS (Process* process) :
+    DynamicLoaderDarwin(process),
+    m_image_infos_stop_id (UINT32_MAX),
+    m_break_id(LLDB_INVALID_BREAK_ID),
+    m_mutex()
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+DynamicLoaderMacOS::~DynamicLoaderMacOS()
+{
+    if (LLDB_BREAK_ID_IS_VALID(m_break_id))
+        m_process->GetTarget().RemoveBreakpointByID (m_break_id);
+}
+
+bool
+DynamicLoaderMacOS::ProcessDidExec ()
+{
+    std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
+    bool did_exec = false;
+    if (m_process)
+    {
+        // If we are stopped after an exec, we will have only one thread...
+        if (m_process->GetThreadList().GetSize() == 1)
+        {
+            // See if we are stopped at '_dyld_start'
+            ThreadSP thread_sp (m_process->GetThreadList().GetThreadAtIndex(0));
+            if (thread_sp)
+            {
+                lldb::StackFrameSP frame_sp (thread_sp->GetStackFrameAtIndex(0));
+                if (frame_sp)
+                {
+                    const Symbol *symbol = frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
+                    if (symbol)
+                    {
+                        if (symbol->GetName() == ConstString("_dyld_start"))
+                            did_exec = true;
+                    }
+                }
+            }
+
+        }
+    }
+
+    if (did_exec)
+    {
+        m_libpthread_module_wp.reset();
+        m_pthread_getspecific_addr.Clear();
+    }
+    return did_exec;
+}
+
+//----------------------------------------------------------------------
+// Clear out the state of this class.
+//----------------------------------------------------------------------
+void
+DynamicLoaderMacOS::DoClear ()
+{
+    std::lock_guard<std::recursive_mutex> guard(m_mutex);
+
+    if (LLDB_BREAK_ID_IS_VALID(m_break_id))
+        m_process->GetTarget().RemoveBreakpointByID (m_break_id);
+
+    m_break_id = LLDB_INVALID_BREAK_ID;
+}
+
+//----------------------------------------------------------------------
+// Check if we have found DYLD yet
+//----------------------------------------------------------------------
+bool
+DynamicLoaderMacOS::DidSetNotificationBreakpoint()
+{
+    return LLDB_BREAK_ID_IS_VALID (m_break_id);
+}
+
+void
+DynamicLoaderMacOS::ClearNotificationBreakpoint ()
+{
+    if (LLDB_BREAK_ID_IS_VALID (m_break_id))
+    {
+        m_process->GetTarget().RemoveBreakpointByID (m_break_id);
+    }
+}
+
+//----------------------------------------------------------------------
+// Try and figure out where dyld is by first asking the Process
+// if it knows (which currently calls down in the lldb::Process
+// to get the DYLD info (available on SnowLeopard only). If that fails,
+// then check in the default addresses.
+//----------------------------------------------------------------------
+void
+DynamicLoaderMacOS::DoInitialImageFetch()
+{
+    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
+
+    StructuredData::ObjectSP all_image_info_json_sp (m_process->GetLoadedDynamicLibrariesInfos ());
+    ImageInfo::collection image_infos;
+    if (all_image_info_json_sp.get() 
+        && all_image_info_json_sp->GetAsDictionary() 
+        && all_image_info_json_sp->GetAsDictionary()->HasKey("images")
+        && all_image_info_json_sp->GetAsDictionary()->GetValueForKey("images")->GetAsArray())
+    {
+        if (JSONImageInformationIntoImageInfo (all_image_info_json_sp, image_infos))
+        {
+    	    if (log)
+        	    log->Printf ("Initial module fetch:  Adding %" PRId64 " modules.\n", (uint64_t) image_infos.size());
+
+            UpdateSpecialBinariesFromNewImageInfos (image_infos);
+            AddModulesUsingImageInfos (image_infos);
+        }
+    }
+    
+    m_dyld_image_infos_stop_id = m_process->GetStopID();
+}
+
+bool
+DynamicLoaderMacOS::NeedToDoInitialImageFetch ()
+{
+    return true;
+}
+
+//----------------------------------------------------------------------
+// Static callback function that gets called when our DYLD notification
+// breakpoint gets hit. We update all of our image infos and then
+// let our super class DynamicLoader class decide if we should stop
+// or not (based on global preference).
+//----------------------------------------------------------------------
+bool
+DynamicLoaderMacOS::NotifyBreakpointHit (void *baton, 
+                                              StoppointCallbackContext *context, 
+                                              lldb::user_id_t break_id, 
+                                              lldb::user_id_t break_loc_id)
+{
+    // Let the event know that the images have changed
+    // DYLD passes three arguments to the notification breakpoint.
+    // Arg1: enum dyld_notify_mode mode - 0 = adding, 1 = removing, 2 = remove all
+    // Arg2: unsigned long icount        - Number of shared libraries added/removed
+    // Arg3: uint64_t mach_headers[]     - Array of load addresses of binaries added/removed
+
+    DynamicLoaderMacOS* dyld_instance = (DynamicLoaderMacOS*) baton;
+    
+    ExecutionContext exe_ctx (context->exe_ctx_ref);
+    Process *process = exe_ctx.GetProcessPtr();
+
+    // This is a sanity check just in case this dyld_instance is an old dyld plugin's breakpoint still lying around.
+    if (process != dyld_instance->m_process)
+        return false;
+
+	if (dyld_instance->m_image_infos_stop_id != UINT32_MAX 
+        && process->GetStopID() < dyld_instance->m_image_infos_stop_id)
+	{
+		return false;
+	}
+
+    const lldb::ABISP &abi = process->GetABI();
+    if (abi)
+    {
+        // Build up the value array to store the three arguments given above, then get the values from the ABI:
+        
+        ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
+        ValueList argument_values;
+
+        Value mode_value;  // enum dyld_notify_mode { dyld_notify_adding=0, dyld_notify_removing=1, dyld_notify_remove_all=2 };
+        Value count_value;  // unsigned long count
+		Value headers_value; // uint64_t machHeaders[] (aka void*) 
+        
+        CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+        CompilerType clang_uint32_type = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint, 32);
+        CompilerType clang_uint64_type = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint, 32);
+
+        mode_value.SetValueType (Value::eValueTypeScalar);
+        mode_value.SetCompilerType (clang_uint32_type);
+
+		if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 4)
+        {
+            count_value.SetValueType (Value::eValueTypeScalar);
+            count_value.SetCompilerType (clang_uint32_type);
+        }
+        else
+        {
+            count_value.SetValueType (Value::eValueTypeScalar);
+            count_value.SetCompilerType (clang_uint64_type);
+        }
+
+        headers_value.SetValueType (Value::eValueTypeScalar);
+        headers_value.SetCompilerType (clang_void_ptr_type);
+
+        argument_values.PushValue (mode_value);
+        argument_values.PushValue (count_value);
+        argument_values.PushValue (headers_value);
+        
+        if (abi->GetArgumentValues (exe_ctx.GetThreadRef(), argument_values))
+        {
+            uint32_t dyld_mode = argument_values.GetValueAtIndex(0)->GetScalar().UInt (-1);
+            if (dyld_mode != static_cast<uint32_t>(-1))
+            {
+                // Okay the mode was right, now get the number of elements, and the array of new elements...
+                uint32_t image_infos_count = argument_values.GetValueAtIndex(1)->GetScalar().UInt (-1);
+                if (image_infos_count != static_cast<uint32_t>(-1))
+                {
+                    addr_t header_array = argument_values.GetValueAtIndex(2)->GetScalar().ULongLong(-1);
+                    if (header_array != static_cast<uint64_t>(-1))
+                    {
+                        std::vector<addr_t> image_load_addresses;
+                        for (uint64_t i = 0; i < image_infos_count ; i++)
+                        {
+                            Error error;
+                            addr_t addr = process->ReadUnsignedIntegerFromMemory (header_array + (8 * i), 8, LLDB_INVALID_ADDRESS, error);
+                            if (addr != LLDB_INVALID_ADDRESS)
+                            {
+                                image_load_addresses.push_back (addr);
+                            }
+                        }
+                        if (dyld_mode == 0)
+                        {
+                            // dyld_notify_adding
+                            dyld_instance->AddBinaries (image_load_addresses);
+                        }
+                        else if (dyld_mode == 1)
+                        {
+                            // dyld_notify_removing
+                            dyld_instance->UnloadImages (image_load_addresses);
+                        }
+                        else if (dyld_mode == 2)
+                        {
+                            // dyld_notify_remove_all
+                            dyld_instance->UnloadAllImages ();
+                        }
+                    }
+                }
+            }
+        }
+    }
+    else
+    {
+        process->GetTarget().GetDebugger().GetAsyncErrorStream()->Printf("No ABI plugin located for triple %s -- shared libraries will not be registered!\n", process->GetTarget().GetArchitecture().GetTriple().getTriple().c_str());
+    }
+    
+    // Return true to stop the target, false to just let the target run
+    return dyld_instance->GetStopWhenImagesChange();
+}
+
+void
+DynamicLoaderMacOS::AddBinaries (const std::vector<lldb::addr_t> &load_addresses)
+{
+    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
+    ImageInfo::collection image_infos;
+
+    if (log)
+        log->Printf ("Adding %" PRId64 " modules.", (uint64_t) load_addresses.size());
+    StructuredData::ObjectSP binaries_info_sp = m_process->GetLoadedDynamicLibrariesInfos (load_addresses);
+    if (binaries_info_sp.get() 
+        && binaries_info_sp->GetAsDictionary() 
+        && binaries_info_sp->GetAsDictionary()->HasKey("images")
+        && binaries_info_sp->GetAsDictionary()->GetValueForKey("images")->GetAsArray()
+        && binaries_info_sp->GetAsDictionary()->GetValueForKey("images")->GetAsArray()->GetSize() == load_addresses.size())
+    {
+        if (JSONImageInformationIntoImageInfo (binaries_info_sp, image_infos))
+        {
+            UpdateSpecialBinariesFromNewImageInfos (image_infos);
+            AddModulesUsingImageInfos (image_infos);
+        }
+        m_dyld_image_infos_stop_id = m_process->GetStopID();
+    }
+}
+
+
+// Dump the _dyld_all_image_infos members and all current image infos
+// that we have parsed to the file handle provided.
+//----------------------------------------------------------------------
+void
+DynamicLoaderMacOS::PutToLog(Log *log) const
+{
+    if (log == NULL)
+        return;
+}
+
+bool
+DynamicLoaderMacOS::SetNotificationBreakpoint ()
+{
+    if (m_break_id == LLDB_INVALID_BREAK_ID)
+    {
+        ConstString g_symbol_name ("_dyld_debugger_notification");
+        const Symbol *symbol = nullptr;
+        ModuleSP dyld_sp (GetDYLDModule());
+        if (dyld_sp)
+        {
+            symbol = dyld_sp->FindFirstSymbolWithNameAndType (g_symbol_name, eSymbolTypeCode);
+        }
+        if (symbol && (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid()))
+        {
+            addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&m_process->GetTarget());
+            if (symbol_address != LLDB_INVALID_ADDRESS)
+            {
+                bool internal = true;
+                bool hardware = false;
+                Breakpoint *breakpoint = m_process->GetTarget().CreateBreakpoint(symbol_address, internal, hardware).get();
+                breakpoint->SetCallback (DynamicLoaderMacOS::NotifyBreakpointHit, this, true);
+                breakpoint->SetBreakpointKind ("shared-library-event");
+                m_break_id = breakpoint->GetID();
+            }
+        }
+    }
+    return m_break_id != LLDB_INVALID_BREAK_ID;
+}
+
+
+addr_t
+DynamicLoaderMacOS::GetDyldLockVariableAddressFromModule (Module *module)
+{
+    SymbolContext sc;
+    SymbolVendor *sym_vendor = module->GetSymbolVendor ();
+    Target &target = m_process->GetTarget ();
+    if (sym_vendor)
+    {
+        Symtab *symtab = sym_vendor->GetSymtab();
+        if (symtab)
+        {
+            std::vector<uint32_t> match_indexes;
+            ConstString g_symbol_name ("_dyld_global_lock_held");
+            uint32_t num_matches = 0;
+            num_matches = symtab->AppendSymbolIndexesWithName (g_symbol_name, match_indexes);
+            if (num_matches == 1)
+            {
+                Symbol *symbol = symtab->SymbolAtIndex (match_indexes[0]);
+                if (symbol && (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid()))
+                {
+                    return symbol->GetAddressRef().GetOpcodeLoadAddress(&target);
+                }
+            }
+        }
+    }
+    return LLDB_INVALID_ADDRESS;
+}
+
+//  Look for this symbol:
+//
+//  int	__attribute__((visibility("hidden")))			_dyld_global_lock_held = 0;
+//
+//  in libdyld.dylib.
+Error
+DynamicLoaderMacOS::CanLoadImage ()
+{
+    Error error;
+    addr_t symbol_address = LLDB_INVALID_ADDRESS;
+    Target &target = m_process->GetTarget ();
+    const ModuleList &target_modules = target.GetImages();
+    std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
+    const size_t num_modules = target_modules.GetSize();
+    ConstString g_libdyld_name ("libdyld.dylib");
+
+    // Find any modules named "libdyld.dylib" and look for the symbol there first
+    for (size_t i = 0; i < num_modules; i++)
+    {
+        Module *module_pointer = target_modules.GetModulePointerAtIndexUnlocked (i);
+        if (module_pointer)
+        {
+            if (module_pointer->GetFileSpec().GetFilename() == g_libdyld_name)
+            {
+                symbol_address = GetDyldLockVariableAddressFromModule (module_pointer);
+                if (symbol_address != LLDB_INVALID_ADDRESS)
+                    break;
+            }
+        }
+    }
+
+    // Search through all modules looking for the symbol in them
+    if (symbol_address == LLDB_INVALID_ADDRESS)
+    {
+        for (size_t i = 0; i < num_modules; i++) 
+        {
+            Module *module_pointer = target_modules.GetModulePointerAtIndexUnlocked (i);
+            if (module_pointer)
+            {
+                addr_t symbol_address = GetDyldLockVariableAddressFromModule (module_pointer);
+                if (symbol_address != LLDB_INVALID_ADDRESS)
+                    break;
+            }
+        }
+    }
+
+    // Default assumption is that it is OK to load images.
+    // Only say that we cannot load images if we find the symbol in libdyld and it indicates that
+    // we cannot.
+
+    if (symbol_address != LLDB_INVALID_ADDRESS)
+    {
+        {
+            int lock_held = m_process->ReadUnsignedIntegerFromMemory (symbol_address, 4, 0, error);
+            if (lock_held != 0)
+            {
+                error.SetErrorToGenericError();
+            }
+        }
+    }
+    return error;
+}
+
+void
+DynamicLoaderMacOS::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+DynamicLoaderMacOS::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+lldb_private::ConstString
+DynamicLoaderMacOS::GetPluginNameStatic()
+{
+    static ConstString g_name("macos-dyld");
+    return g_name;
+}
+
+const char *
+DynamicLoaderMacOS::GetPluginDescriptionStatic()
+{
+    return "Dynamic loader plug-in that watches for shared library loads/unloads in MacOSX user processes.";
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+DynamicLoaderMacOS::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+DynamicLoaderMacOS::GetPluginVersion()
+{
+    return 1;
+}

Added: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h?rev=276254&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h Thu Jul 21 03:30:55 2016
@@ -0,0 +1,129 @@
+//===-- DynamicLoaderMacOS.h -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// This is the DynamicLoader plugin for Darwin (macOS / iPhoneOS / tvOS / watchOS)
+// platforms late 2016 and newer, where lldb will call dyld SPI functions to get
+// information about shared libraries, information about the shared cache, and
+// the _dyld_debugger_notification function we put a breakpoint on give us an
+// array of load addresses for solibs loaded and unloaded.  The SPI will tell us
+// about both dyld and the executable, in addition to all of the usual solibs.
+
+#ifndef liblldb_DynamicLoaderMacOS_h_
+#define liblldb_DynamicLoaderMacOS_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+#include <mutex>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Core/StructuredData.h"
+#include "lldb/Core/UUID.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/SafeMachO.h"
+
+#include "DynamicLoaderDarwin.h"
+
+class DynamicLoaderMacOS : public lldb_private::DynamicLoaderDarwin
+{
+public:
+    DynamicLoaderMacOS(lldb_private::Process *process);
+
+    virtual ~DynamicLoaderMacOS() override;
+
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::DynamicLoader *
+    CreateInstance (lldb_private::Process *process, bool force);
+
+    //------------------------------------------------------------------
+    /// Called after attaching a process.
+    ///
+    /// Allow DynamicLoader plug-ins to execute some code after
+    /// attaching to a process.
+    //------------------------------------------------------------------
+    bool
+    ProcessDidExec() override;
+
+    lldb_private::Error
+    CanLoadImage() override;
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    lldb_private::ConstString
+    GetPluginName() override;
+
+    uint32_t
+    GetPluginVersion() override;
+
+protected:
+    void
+    PutToLog(lldb_private::Log *log) const;
+
+    void
+    DoInitialImageFetch () override;
+
+    bool
+    NeedToDoInitialImageFetch () override;
+
+    bool
+    DidSetNotificationBreakpoint () override;
+
+    void
+    AddBinaries (const std::vector<lldb::addr_t> &load_addresses);
+
+    void
+    DoClear () override;
+
+    static bool
+    NotifyBreakpointHit (void *baton,
+                         lldb_private::StoppointCallbackContext *context,
+                         lldb::user_id_t break_id,
+                         lldb::user_id_t break_loc_id);
+
+    bool
+    SetNotificationBreakpoint () override;
+
+    void
+    ClearNotificationBreakpoint () override;
+
+    void
+    UpdateImageInfosHeaderAndLoadCommands(ImageInfo::collection &image_infos, 
+                                          uint32_t infos_count, 
+                                          bool update_executable);
+
+    lldb::addr_t
+    GetDyldLockVariableAddressFromModule (lldb_private::Module *module);
+
+    uint32_t m_image_infos_stop_id;        // The Stop ID the last time we loaded/unloaded images
+    lldb::user_id_t m_break_id;
+    mutable std::recursive_mutex m_mutex;
+
+private:
+    DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOS);
+};
+
+#endif // liblldb_DynamicLoaderMacOS_h_

Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp?rev=276254&r1=276253&r2=276254&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp (original)
+++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp Thu Jul 21 03:30:55 2016
@@ -89,6 +89,11 @@ DynamicLoaderMacOSXDYLD::CreateInstance
             }
         }
     }
+
+    if (UseDYLDSPI (process) == true)
+    {
+        create = false;
+    }
     
     if (create)
         return new DynamicLoaderMacOSXDYLD (process);
@@ -296,6 +301,7 @@ DynamicLoaderMacOSXDYLD::ReadDYLDInfoFro
 {
     std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
     DataExtractor data; // Load command data
+    static ConstString g_dyld_all_image_infos ("dyld_all_image_infos");
     if (ReadMachHeader (addr, &m_dyld.header, &data))
     {
         if (m_dyld.header.filetype == llvm::MachO::MH_DYLINKER)
@@ -316,7 +322,6 @@ DynamicLoaderMacOSXDYLD::ReadDYLDInfoFro
 
             if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS && dyld_module_sp.get())
             {
-                static ConstString g_dyld_all_image_infos ("dyld_all_image_infos");
                 const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType (g_dyld_all_image_infos, eSymbolTypeData);
                 if (symbol)
                     m_dyld_all_image_infos_addr = symbol->GetLoadAddress(&target);
@@ -340,6 +345,7 @@ DynamicLoaderMacOSXDYLD::ReadDYLDInfoFro
                 target.ModulesDidLoad(modules);
                 SetDYLDModule (dyld_module_sp);
             }
+
             return true;
         }
     }
@@ -592,7 +598,7 @@ DynamicLoaderMacOSXDYLD::AddModulesUsing
         bool return_value = false;
         if (JSONImageInformationIntoImageInfo (image_infos_json_sp, image_infos))
         {
-            AddExecutableModuleIfInImageInfos (image_infos);
+            UpdateSpecialBinariesFromNewImageInfos (image_infos);
             return_value = AddModulesUsingImageInfos (image_infos);
         }
         m_dyld_image_infos_stop_id = m_process->GetStopID();
@@ -1105,7 +1111,7 @@ DynamicLoaderMacOSXDYLD::SetNotification
             bool resolved = m_process->GetTarget().ResolveLoadAddress(m_dyld_all_image_infos.notification, so_addr);
             if (!resolved)
             {
-                ModuleSP dyld_module_sp = m_dyld_module_wp.lock();
+                ModuleSP dyld_module_sp = GetDYLDModule();
                 if (dyld_module_sp)
                 {
                     std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());

Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h?rev=276254&r1=276253&r2=276254&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h (original)
+++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h Thu Jul 21 03:30:55 2016
@@ -7,6 +7,17 @@
 //
 //===----------------------------------------------------------------------===//
 
+
+// This is the DynamicLoader plugin for Darwin (macOS / iPhoneOS / tvOS / watchOS)
+// platforms earlier than 2016, where lldb would read the "dyld_all_image_infos"
+// dyld internal structure to understand where things were loaded and the 
+// solib loaded/unloaded notification function we put a breakpoint on gives us
+// an array of (load address, mod time, file path) tuples.
+//
+// As of late 2016, the new DynamicLoaderMacOS plugin should be used, which uses
+// dyld SPI functions to get the same information without reading internal dyld
+// data structures.
+
 #ifndef liblldb_DynamicLoaderMacOSXDYLD_h_
 #define liblldb_DynamicLoaderMacOSXDYLD_h_
 

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=276254&r1=276253&r2=276254&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Thu Jul 21 03:30:55 2016
@@ -4165,7 +4165,7 @@ ProcessGDBRemote::GetExtendedInfoForThre
 
         StreamString packet;
         packet << "jThreadExtendedInfo:";
-        args_dict->Dump (packet);
+        args_dict->Dump (packet, false);
 
         // FIXME the final character of a JSON dictionary, '}', is the escape
         // character in gdb-remote binary mode.  lldb currently doesn't escape
@@ -4194,6 +4194,44 @@ ProcessGDBRemote::GetExtendedInfoForThre
 StructuredData::ObjectSP
 ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_address, lldb::addr_t image_count)
 {
+
+    StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
+    args_dict->GetAsDictionary()->AddIntegerItem ("image_list_address", image_list_address);
+    args_dict->GetAsDictionary()->AddIntegerItem ("image_count", image_count);
+
+    return GetLoadedDynamicLibrariesInfos_sender (args_dict);
+}
+
+StructuredData::ObjectSP
+ProcessGDBRemote::GetLoadedDynamicLibrariesInfos ()
+{
+    StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
+
+    args_dict->GetAsDictionary()->AddBooleanItem ("fetch_all_solibs", true);
+
+    return GetLoadedDynamicLibrariesInfos_sender (args_dict);
+}
+
+StructuredData::ObjectSP
+ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (const std::vector<lldb::addr_t> &load_addresses)
+{
+    StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
+    StructuredData::ArraySP addresses(new StructuredData::Array);
+
+    for (auto addr : load_addresses)
+    {
+        StructuredData::ObjectSP addr_sp (new StructuredData::Integer (addr));
+        addresses->AddItem (addr_sp);
+    }
+
+    args_dict->GetAsDictionary()->AddItem ("solib_addresses", addresses);
+
+    return GetLoadedDynamicLibrariesInfos_sender (args_dict);
+}
+
+StructuredData::ObjectSP
+ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender (StructuredData::ObjectSP args_dict)
+{
     StructuredData::ObjectSP object_sp;
 
     if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported())
@@ -4201,13 +4239,9 @@ ProcessGDBRemote::GetLoadedDynamicLibrar
         // Scope for the scoped timeout object
         GDBRemoteCommunication::ScopedTimeout timeout (m_gdb_comm, 10);
 
-        StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
-        args_dict->GetAsDictionary()->AddIntegerItem ("image_list_address", image_list_address);
-        args_dict->GetAsDictionary()->AddIntegerItem ("image_count", image_count);
-
         StreamString packet;
         packet << "jGetLoadedDynamicLibrariesInfos:";
-        args_dict->Dump (packet);
+        args_dict->Dump (packet, false);
 
         // FIXME the final character of a JSON dictionary, '}', is the escape
         // character in gdb-remote binary mode.  lldb currently doesn't escape
@@ -4233,6 +4267,9 @@ ProcessGDBRemote::GetLoadedDynamicLibrar
     return object_sp;
 }
 
+
+
+
 // Establish the largest memory read/write payloads we should use.
 // If the remote stub has a max packet size, stay under that size.
 //

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=276254&r1=276253&r2=276254&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Thu Jul 21 03:30:55 2016
@@ -261,6 +261,15 @@ public:
     StructuredData::ObjectSP
     GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_address, lldb::addr_t image_count) override;
 
+    StructuredData::ObjectSP
+    GetLoadedDynamicLibrariesInfos () override;
+
+    StructuredData::ObjectSP
+    GetLoadedDynamicLibrariesInfos (const std::vector<lldb::addr_t> &load_addresses) override;
+
+    StructuredData::ObjectSP
+    GetLoadedDynamicLibrariesInfos_sender (StructuredData::ObjectSP args);
+
 protected:
     friend class ThreadGDBRemote;
     friend class GDBRemoteCommunicationClient;

Modified: lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj?rev=276254&r1=276253&r2=276254&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj Thu Jul 21 03:30:55 2016
@@ -610,6 +610,7 @@
 				"LLDB_COMPRESSION_LDFLAGS[sdk=macosx10.11]" = "-weak-lcompression";
 				LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
 				LLDB_ZLIB_LDFLAGS = "-lz";
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				ONLY_ACTIVE_ARCH = YES;
 				OTHER_CFLAGS = "";
 				STRIP_INSTALLED_PRODUCT = NO;
@@ -651,6 +652,7 @@
 				"LLDB_COMPRESSION_LDFLAGS[sdk=macosx10.11]" = "-weak-lcompression";
 				LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
 				LLDB_ZLIB_LDFLAGS = "-lz";
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				ONLY_ACTIVE_ARCH = YES;
 				OTHER_CFLAGS = "";
 				STRIPFLAGS = "-x";
@@ -690,6 +692,7 @@
 				"LLDB_COMPRESSION_LDFLAGS[sdk=macosx10.11]" = "-weak-lcompression";
 				LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
 				LLDB_ZLIB_LDFLAGS = "-lz";
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				OTHER_CFLAGS = "";
 				STRIPFLAGS = "-x";
 				STRIP_STYLE = debugging;
@@ -1317,6 +1320,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = macosx.internal;
 				"SDKROOT[arch=i386]" = macosx;
@@ -1455,6 +1459,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = macosx.internal;
 				"SDKROOT[arch=i386]" = macosx;
@@ -1672,6 +1677,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = macosx.internal;
 				"SDKROOT[arch=i386]" = macosx;
@@ -1800,6 +1806,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = macosx.internal;
 				"SDKROOT[arch=i386]" = macosx;




More information about the lldb-commits mailing list