[Lldb-commits] [lldb] r179583 - The dyld_all_image_infos structure, at version 13 and higher, has

Jason Molenda jmolenda at apple.com
Mon Apr 15 23:24:42 PDT 2013


Author: jmolenda
Date: Tue Apr 16 01:24:42 2013
New Revision: 179583

URL: http://llvm.org/viewvc/llvm-project?rev=179583&view=rev
Log:
The dyld_all_image_infos structure, at version 13 and higher, has
a UUID for the shared cache libraries that can be used to confirm
that one process' shared cache is the same as another, or that a
process' in-memory shared cache is a match for a given on-disk
dyld_shared_cache binary file.  Use these UUIDs to catch some
uncommon problems when the shared caches are being changed for debug
purposes.
<rdar://problem/13524467>

Modified:
    lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
    lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h

Modified: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp?rev=179583&r1=179582&r2=179583&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Tue Apr 16 01:24:42 2013
@@ -38,6 +38,11 @@
 #include "Plugins/Process/Utility/RegisterContextDarwin_i386.h"
 #include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h"
 
+#if defined (__APPLE__) && defined (__arm__)
+// GetLLDBSharedCacheUUID() needs to call dlsym()
+#include <dlfcn.h>
+#endif
+
 using namespace lldb;
 using namespace lldb_private;
 using namespace llvm::MachO;
@@ -1372,8 +1377,17 @@ ObjectFileMachO::ParseSymtab (bool minim
                     // symbol and string table. Reading all of this symbol and string table
                     // data across can slow down debug launch times, so we optimize this by
                     // reading the memory for the __LINKEDIT section from this process.
+
+                    UUID lldb_shared_cache(GetLLDBSharedCacheUUID());
+                    UUID process_shared_cache(GetProcessSharedCacheUUID(process));
+                    bool use_lldb_cache = true;
+                    if (lldb_shared_cache.IsValid() && process_shared_cache.IsValid() && lldb_shared_cache != process_shared_cache)
+                    {
+                            use_lldb_cache = false;
+                    }
+
                     PlatformSP platform_sp (target.GetPlatform());
-                    if (platform_sp && platform_sp->IsHost())
+                    if (platform_sp && platform_sp->IsHost() && use_lldb_cache)
                     {
                         data_was_read = true;
                         nlist_data.SetData((void *)symoff_addr, nlist_data_byte_size, eByteOrderLittle);
@@ -1571,16 +1585,6 @@ ObjectFileMachO::ParseSymtab (bool minim
             // Before we can start mapping the DSC, we need to make certain the target process is actually
             // using the cache we can find.
 
-            /*
-             * TODO (FIXME!)
-             *
-             * Consider the case of testing with a separate DSC file.
-             * If we go through the normal code paths, we will give symbols for the wrong DSC, and
-             * that is bad.  We need to read the target process' all_image_infos struct, and look
-             * at the values of the processDetachedFromSharedRegion field. If that is set, we should skip
-             * this code section.
-             */
-
             // Next we need to determine the correct path for the dyld shared cache.
 
             ArchSpec header_arch(eArchTypeMachO, m_header.cputype, m_header.cpusubtype);
@@ -1688,14 +1692,35 @@ ObjectFileMachO::ParseSymtab (bool minim
                     }
                 }
 
+                UUID dsc_uuid;
+                if (version >= 1)
+                {
+                    offset = offsetof (struct lldb_copy_dyld_cache_header_v1, uuid);
+                    uint8_t uuid_bytes[sizeof (uuid_t)];
+                    memcpy (uuid_bytes, dsc_header_data.GetData (&offset, sizeof (uuid_t)), sizeof (uuid_t));
+                    dsc_uuid.SetBytes (uuid_bytes);
+                }
+
+                bool uuid_match = true;
+                if (dsc_uuid.IsValid() && process)
+                {
+                    UUID shared_cache_uuid(GetProcessSharedCacheUUID(process));
+
+                    if (shared_cache_uuid.IsValid() && dsc_uuid != shared_cache_uuid)
+                    {
+                        // The on-disk dyld_shared_cache file is not the same as the one in this
+                        // process' memory, don't use it.
+                        uuid_match = false;
+                    }
+                }
+
                 offset = offsetof (struct lldb_copy_dyld_cache_header_v1, mappingOffset);
 
                 uint32_t mappingOffset = dsc_header_data.GetU32(&offset);
 
                 // If the mappingOffset points to a location inside the header, we've
                 // opened an old dyld shared cache, and should not proceed further.
-                if ((version == 0 && mappingOffset >= sizeof(struct lldb_copy_dyld_cache_header_v0))
-                    || (version >= 1 && mappingOffset >= sizeof(struct lldb_copy_dyld_cache_header_v1)))
+                if (uuid_match && mappingOffset >= sizeof(struct lldb_copy_dyld_cache_header_v0))
                 {
 
                     DataBufferSP dsc_mapping_info_data_sp = dsc_filespec.MemoryMapFileContents(mappingOffset, sizeof (struct lldb_copy_dyld_cache_mapping_info));
@@ -3942,6 +3967,78 @@ ObjectFileMachO::GetArchitecture (ArchSp
 }
 
 
+UUID
+ObjectFileMachO::GetProcessSharedCacheUUID (Process *process)
+{
+    UUID uuid;
+    if (process)
+    {
+        addr_t all_image_infos = process->GetImageInfoAddress();
+
+        // The address returned by GetImageInfoAddress may be the address of dyld (don't want)
+        // or it may be the address of the dyld_all_image_infos structure (want).  The first four
+        // bytes will be either the version field (all_image_infos) or a Mach-O file magic constant.
+        // Version 13 and higher of dyld_all_image_infos is required to get the sharedCacheUUID field.
+
+        Error err;
+        uint32_t version_or_magic = process->ReadUnsignedIntegerFromMemory (all_image_infos, 4, -1, err);
+        if (version_or_magic != -1 
+            && version_or_magic != HeaderMagic32
+            && version_or_magic != HeaderMagic32Swapped
+            && version_or_magic != HeaderMagic64
+            && version_or_magic != HeaderMagic64Swapped
+            && version_or_magic >= 13)
+        {
+            addr_t sharedCacheUUID_address = LLDB_INVALID_ADDRESS;
+            int wordsize = process->GetAddressByteSize();
+            if (wordsize == 8)
+            {
+                sharedCacheUUID_address = all_image_infos + 160;  // sharedCacheUUID <mach-o/dyld_images.h>
+            }
+            if (wordsize == 4)
+            {
+                sharedCacheUUID_address = all_image_infos + 84;   // sharedCacheUUID <mach-o/dyld_images.h>
+            }
+            if (sharedCacheUUID_address != LLDB_INVALID_ADDRESS)
+            {
+                uuid_t shared_cache_uuid;
+                if (process->ReadMemory (sharedCacheUUID_address, shared_cache_uuid, sizeof (uuid_t), err) == sizeof (uuid_t))
+                {
+                    uuid.SetBytes (shared_cache_uuid);
+                }
+            }
+        }
+    }
+    return uuid;
+}
+
+UUID
+ObjectFileMachO::GetLLDBSharedCacheUUID ()
+{
+    UUID uuid;
+#if defined (__APPLE__) && defined (__arm__)
+    uint8_t *(*dyld_get_all_image_infos)(void);
+    dyld_get_all_image_infos = (uint8_t*(*)()) dlsym (RTLD_DEFAULT, "_dyld_get_all_image_infos");
+    if (dyld_get_all_image_infos)
+    {
+        uint8_t *dyld_all_image_infos_address = dyld_get_all_image_infos();
+        if (dyld_all_image_infos_address)
+        {
+            uint32_t version;
+            memcpy (&version, dyld_all_image_infos_address, 4);
+            if (version >= 13)
+            {
+                uint8_t *sharedCacheUUID_address = 0;
+                sharedCacheUUID_address = dyld_all_image_infos_address + 84;  // sharedCacheUUID <mach-o/dyld_images.h>
+                uuid.SetBytes (sharedCacheUUID_address);
+            }
+        }
+    }
+#endif
+    return uuid;
+}
+
+
 //------------------------------------------------------------------
 // PluginInterface protocol
 //------------------------------------------------------------------

Modified: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h?rev=179583&r1=179582&r2=179583&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h (original)
+++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h Tue Apr 16 01:24:42 2013
@@ -145,6 +145,23 @@ public:
     GetVersion (uint32_t *versions, uint32_t num_versions);
 
 protected:
+
+    // Intended for same-host arm device debugging where lldb needs to 
+    // detect libraries in the shared cache and augment the nlist entries
+    // with an on-disk dyld_shared_cache file.  The process will record
+    // the shared cache UUID so the on-disk cache can be matched or rejected
+    // correctly.
+    lldb_private::UUID
+    GetProcessSharedCacheUUID (lldb_private::Process *);
+
+    // Intended for same-host arm device debugging where lldb will read
+    // shared cache libraries out of its own memory instead of the remote
+    // process' memory as an optimization.  If lldb's shared cache UUID 
+    // does not match the process' shared cache UUID, this optimization
+    // should not be used.
+    lldb_private::UUID
+    GetLLDBSharedCacheUUID ();
+
     llvm::MachO::mach_header m_header;
     static const lldb_private::ConstString &GetSegmentNameTEXT();
     static const lldb_private::ConstString &GetSegmentNameDATA();





More information about the lldb-commits mailing list