Added the ability to extract a ModuleSpecList (a new class) from an ObjectFile. This is designed to be used when you have an object file that contains one or more architectures (MacOSX universal (fat) files) and/or one or more objects (BSD archive (.a files)).

There is a new static ObjectFile function you can call:

size_t
ObjectFile::GetModuleSpecifications (const FileSpec &file,
                                     lldb::offset_t file_offset,
                                     ModuleSpecList &specs)

This will fill in "specs" which the details of all the module specs (file + arch + UUID (if there is one) + object name (for BSD archive objects eventually) + file offset to the object in question).

This helps us when a user specifies a file that contains a single architecture, and also helps us when we are given a debug symbol file (like a dSYM file on MacOSX) that contains one or more architectures and we need to be able to match it up to an existing Module that has no debug info.



git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@180224 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index 90e5605..7bd6020 100644
--- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -19,6 +19,7 @@
 #include "lldb/Core/FileSpecList.h"
 #include "lldb/Core/Log.h"
 #include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/RangeMap.h"
 #include "lldb/Core/Section.h"
@@ -367,7 +368,8 @@
     PluginManager::RegisterPlugin (GetPluginNameStatic(),
                                    GetPluginDescriptionStatic(),
                                    CreateInstance,
-                                   CreateMemoryInstance);
+                                   CreateMemoryInstance,
+                                   GetModuleSpecifications);
 }
 
 void
@@ -433,6 +435,47 @@
     return NULL;
 }
 
+size_t
+ObjectFileMachO::GetModuleSpecifications (const lldb_private::FileSpec& file,
+                                          lldb::DataBufferSP& data_sp,
+                                          lldb::offset_t data_offset,
+                                          lldb::offset_t file_offset,
+                                          lldb::offset_t length,
+                                          lldb_private::ModuleSpecList &specs)
+{
+    const size_t initial_count = specs.GetSize();
+    
+    if (ObjectFileMachO::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize()))
+    {
+        DataExtractor data;
+        data.SetData(data_sp);
+        llvm::MachO::mach_header header;
+        if (ParseHeader (data, &data_offset, header))
+        {
+            if (header.sizeofcmds >= data_sp->GetByteSize())
+            {
+                data_sp = file.ReadFileContents(file_offset, header.sizeofcmds);
+                data_offset = 0;
+            }
+            if (data_sp)
+            {
+                ModuleSpec spec;
+                spec.GetFileSpec() = file;
+                spec.GetArchitecture().SetArchitecture(eArchTypeMachO,
+                                                       header.cputype,
+                                                       header.cpusubtype);
+                if (spec.GetArchitecture().IsValid())
+                {
+                    GetUUID (header, data, data_offset, spec.GetUUID());
+                    specs.Append(spec);
+                }
+            }
+        }
+    }
+    return specs.GetSize() - initial_count;
+}
+
+
 
 const ConstString &
 ObjectFileMachO::GetSegmentNameTEXT()
@@ -541,6 +584,61 @@
 {
 }
 
+bool
+ObjectFileMachO::ParseHeader (DataExtractor &data,
+                              lldb::offset_t *data_offset_ptr,
+                              llvm::MachO::mach_header &header)
+{
+    data.SetByteOrder (lldb::endian::InlHostByteOrder());
+    // Leave magic in the original byte order
+    header.magic = data.GetU32(data_offset_ptr);
+    bool can_parse = false;
+    bool is_64_bit = false;
+    switch (header.magic)
+    {
+        case HeaderMagic32:
+            data.SetByteOrder (lldb::endian::InlHostByteOrder());
+            data.SetAddressByteSize(4);
+            can_parse = true;
+            break;
+            
+        case HeaderMagic64:
+            data.SetByteOrder (lldb::endian::InlHostByteOrder());
+            data.SetAddressByteSize(8);
+            can_parse = true;
+            is_64_bit = true;
+            break;
+            
+        case HeaderMagic32Swapped:
+            data.SetByteOrder(lldb::endian::InlHostByteOrder() == eByteOrderBig ? eByteOrderLittle : eByteOrderBig);
+            data.SetAddressByteSize(4);
+            can_parse = true;
+            break;
+            
+        case HeaderMagic64Swapped:
+            data.SetByteOrder(lldb::endian::InlHostByteOrder() == eByteOrderBig ? eByteOrderLittle : eByteOrderBig);
+            data.SetAddressByteSize(8);
+            is_64_bit = true;
+            can_parse = true;
+            break;
+            
+        default:
+            break;
+    }
+    
+    if (can_parse)
+    {
+        data.GetU32(data_offset_ptr, &header.cputype, 6);
+        if (is_64_bit)
+            *data_offset_ptr += 4;
+        return true;
+    }
+    else
+    {
+        memset(&header, 0, sizeof(header));
+    }
+    return false;
+}
 
 bool
 ObjectFileMachO::ParseHeader ()
@@ -3481,6 +3579,49 @@
     }
 }
 
+bool
+ObjectFileMachO::GetUUID (const llvm::MachO::mach_header &header,
+                          const lldb_private::DataExtractor &data,
+                          lldb::offset_t lc_offset,
+                          lldb_private::UUID& uuid)
+{
+    uint32_t i;
+    struct uuid_command load_cmd;
+
+    lldb::offset_t offset = lc_offset;
+    for (i=0; i<header.ncmds; ++i)
+    {
+        const lldb::offset_t cmd_offset = offset;
+        if (data.GetU32(&offset, &load_cmd, 2) == NULL)
+            break;
+        
+        if (load_cmd.cmd == LoadCommandUUID)
+        {
+            const uint8_t *uuid_bytes = data.PeekData(offset, 16);
+            
+            if (uuid_bytes)
+            {
+                // OpenCL on Mac OS X uses the same UUID for each of its object files.
+                // We pretend these object files have no UUID to prevent crashing.
+                
+                const uint8_t opencl_uuid[] = { 0x8c, 0x8e, 0xb3, 0x9b,
+                    0x3b, 0xa8,
+                    0x4b, 0x16,
+                    0xb6, 0xa4,
+                    0x27, 0x63, 0xbb, 0x14, 0xf0, 0x0d };
+                
+                if (!memcmp(uuid_bytes, opencl_uuid, 16))
+                    return false;
+                
+                uuid.SetBytes (uuid_bytes);
+                return true;
+            }
+            return false;
+        }
+        offset = cmd_offset + load_cmd.cmdsize;
+    }
+    return false;
+}
 
 bool
 ObjectFileMachO::GetUUID (lldb_private::UUID* uuid)
@@ -3489,40 +3630,8 @@
     if (module_sp)
     {
         lldb_private::Mutex::Locker locker(module_sp->GetMutex());
-        struct uuid_command load_cmd;
         lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
-        uint32_t i;
-        for (i=0; i<m_header.ncmds; ++i)
-        {
-            const lldb::offset_t cmd_offset = offset;
-            if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
-                break;
-
-            if (load_cmd.cmd == LoadCommandUUID)
-            {
-                const uint8_t *uuid_bytes = m_data.PeekData(offset, 16);
-
-                if (uuid_bytes)
-                {
-                    // OpenCL on Mac OS X uses the same UUID for each of its object files.
-                    // We pretend these object files have no UUID to prevent crashing.
-
-                    const uint8_t opencl_uuid[] = { 0x8c, 0x8e, 0xb3, 0x9b,
-                                                    0x3b, 0xa8,
-                                                    0x4b, 0x16,
-                                                    0xb6, 0xa4,
-                                                    0x27, 0x63, 0xbb, 0x14, 0xf0, 0x0d };
-
-                    if (!memcmp(uuid_bytes, opencl_uuid, 16))
-                        return false;
-
-                    uuid->SetBytes (uuid_bytes);
-                    return true;
-                }
-                return false;
-            }
-            offset = cmd_offset + load_cmd.cmdsize;
-        }
+        return GetUUID (m_header, m_data, offset, *uuid);
     }
     return false;
 }