<rdar://problem/13159777> 

lldb was mmap'ing archive files once per .o file it loads, now it correctly shares the archive between modules.

LLDB was also always mapping entire contents of universal mach-o files, now it maps just the slice that is required.

Added a new logging channel for "lldb" called "mmap" to help track future regressions.

Modified the ObjectFile and ObjectContainer plugin interfaces to take a data offset along with the file offset and size so we can implement the correct caching and efficient reading of parts of files without mmap'ing the entire file like we used to.

The current implementation still keeps entire .a files mmaped (once) and entire slices from universal files mmaped to ensure that if a client builds their binaries during a debug session we don't lose our data and get corrupt object file info and debug info.

llvm-svn: 174524
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index a430c26..6d6d1ec 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -173,19 +173,30 @@
 ObjectFile *
 ObjectFileELF::CreateInstance (const lldb::ModuleSP &module_sp,
                                DataBufferSP &data_sp,
-                               const FileSpec *file, 
-                               addr_t offset,
-                               addr_t length)
+                               lldb::offset_t data_offset,
+                               const lldb_private::FileSpec* file,
+                               lldb::offset_t file_offset,
+                               lldb::offset_t length)
 {
-    if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT + offset))
+    if (!data_sp)
     {
-        const uint8_t *magic = data_sp->GetBytes() + offset;
+        data_sp = file->MemoryMapFileContents(file_offset, length);
+        data_offset = 0;
+    }
+
+    if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT + data_offset))
+    {
+        const uint8_t *magic = data_sp->GetBytes() + data_offset;
         if (ELFHeader::MagicBytesMatch(magic))
         {
+            // Update the data to contain the entire file
+            // Update the data to contain the entire file if it doesn't already
+            if (data_sp->GetByteSize() < length)
+                data_sp = file->MemoryMapFileContents(file_offset, length);
             unsigned address_size = ELFHeader::AddressSizeInBytes(magic);
             if (address_size == 4 || address_size == 8)
             {
-                std::auto_ptr<ObjectFileELF> objfile_ap(new ObjectFileELF(module_sp, data_sp, file, offset, length));
+                std::auto_ptr<ObjectFileELF> objfile_ap(new ObjectFileELF(module_sp, data_sp, data_offset, file, file_offset, length));
                 ArchSpec spec;
                 if (objfile_ap->GetArchitecture(spec) &&
                     objfile_ap->SetModulesArchitecture(spec))
@@ -232,11 +243,12 @@
 //------------------------------------------------------------------
 
 ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp, 
-                              DataBufferSP& dataSP,
+                              DataBufferSP& data_sp,
+                              lldb::offset_t data_offset,
                               const FileSpec* file, 
-                              addr_t offset,
-                              addr_t length) : 
-    ObjectFile(module_sp, file, offset, length, dataSP),
+                              lldb::offset_t file_offset,
+                              lldb::offset_t length) : 
+    ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
     m_header(),
     m_program_headers(),
     m_section_headers(),
@@ -291,7 +303,7 @@
 bool
 ObjectFileELF::ParseHeader()
 {
-    lldb::offset_t offset = GetOffset();
+    lldb::offset_t offset = GetFileOffset();
     return m_header.Parse(m_data, &offset);
 }
 
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index f347c7b..2c1ff6c 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -46,10 +46,11 @@
 
     static lldb_private::ObjectFile *
     CreateInstance(const lldb::ModuleSP &module_sp,
-                   lldb::DataBufferSP& dataSP,
+                   lldb::DataBufferSP& data_sp,
+                   lldb::offset_t data_offset,
                    const lldb_private::FileSpec* file,
-                   lldb::addr_t offset,
-                   lldb::addr_t length);
+                   lldb::offset_t file_offset,
+                   lldb::offset_t length);
 
     static lldb_private::ObjectFile *
     CreateMemoryInstance (const lldb::ModuleSP &module_sp, 
@@ -119,10 +120,11 @@
 
 private:
     ObjectFileELF(const lldb::ModuleSP &module_sp,
-                  lldb::DataBufferSP& dataSP,
+                  lldb::DataBufferSP& data_sp,
+                  lldb::offset_t data_offset,
                   const lldb_private::FileSpec* file,
-                  lldb::addr_t offset,
-                  lldb::addr_t length);
+                  lldb::offset_t offset,
+                  lldb::offset_t length);
 
     typedef std::vector<elf::ELFProgramHeader>  ProgramHeaderColl;
     typedef ProgramHeaderColl::iterator         ProgramHeaderCollIter;
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index ad219c7..9249a8d 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -378,13 +378,29 @@
     return "Mach-o object file reader (32 and 64 bit)";
 }
 
-
 ObjectFile *
-ObjectFileMachO::CreateInstance (const lldb::ModuleSP &module_sp, DataBufferSP& data_sp, const FileSpec* file, addr_t offset, addr_t length)
+ObjectFileMachO::CreateInstance (const lldb::ModuleSP &module_sp,
+                                 DataBufferSP& data_sp,
+                                 lldb::offset_t data_offset,
+                                 const FileSpec* file,
+                                 lldb::offset_t file_offset,
+                                 lldb::offset_t length)
 {
-    if (ObjectFileMachO::MagicBytesMatch(data_sp, offset, length))
+    if (!data_sp)
     {
-        std::auto_ptr<ObjectFile> objfile_ap(new ObjectFileMachO (module_sp, data_sp, file, offset, length));
+        data_sp = file->MemoryMapFileContents(file_offset, length);
+        data_offset = 0;
+    }
+
+    if (ObjectFileMachO::MagicBytesMatch(data_sp, data_offset, length))
+    {
+        // Update the data to contain the entire file if it doesn't already
+        if (data_sp->GetByteSize() < length)
+        {
+            data_sp = file->MemoryMapFileContents(file_offset, length);
+            data_offset = 0;
+        }
+        std::auto_ptr<ObjectFile> objfile_ap(new ObjectFileMachO (module_sp, data_sp, data_offset, file, file_offset, length));
         if (objfile_ap.get() && objfile_ap->ParseHeader())
             return objfile_ap.release();
     }
@@ -478,8 +494,13 @@
 }
 
 
-ObjectFileMachO::ObjectFileMachO(const lldb::ModuleSP &module_sp, DataBufferSP& data_sp, const FileSpec* file, addr_t offset, addr_t length) :
-    ObjectFile(module_sp, file, offset, length, data_sp),
+ObjectFileMachO::ObjectFileMachO(const lldb::ModuleSP &module_sp,
+                                 DataBufferSP& data_sp,
+                                 lldb::offset_t data_offset,
+                                 const FileSpec* file,
+                                 lldb::offset_t file_offset,
+                                 lldb::offset_t length) :
+    ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
     m_sections_ap(),
     m_symtab_ap(),
     m_mach_segments(),
@@ -576,12 +597,12 @@
                     ProcessSP process_sp (m_process_wp.lock());
                     if (process_sp)
                     {
-                        data_sp = ReadMemory (process_sp, m_offset, header_and_lc_size);
+                        data_sp = ReadMemory (process_sp, m_memory_addr, header_and_lc_size);
                     }
                     else
                     {
                         // Read in all only the load command data from the file on disk
-                        data_sp = m_file.ReadFileContents(m_offset, header_and_lc_size);
+                        data_sp = m_file.ReadFileContents(m_file_offset, header_and_lc_size);
                         if (data_sp->GetByteSize() != header_and_lc_size)
                             return false;
                     }
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
index 6075bb5..1d04437 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
@@ -43,10 +43,11 @@
 
     static lldb_private::ObjectFile *
     CreateInstance (const lldb::ModuleSP &module_sp,
-                    lldb::DataBufferSP& dataSP,
+                    lldb::DataBufferSP& data_sp,
+                    lldb::offset_t data_offset,
                     const lldb_private::FileSpec* file,
-                    lldb::addr_t offset,
-                    lldb::addr_t length);
+                    lldb::offset_t file_offset,
+                    lldb::offset_t length);
 
     static lldb_private::ObjectFile *
     CreateMemoryInstance (const lldb::ModuleSP &module_sp, 
@@ -55,7 +56,7 @@
                           lldb::addr_t header_addr);
 
     static bool
-    MagicBytesMatch (lldb::DataBufferSP& dataSP, 
+    MagicBytesMatch (lldb::DataBufferSP& data_sp,
                      lldb::addr_t offset, 
                      lldb::addr_t length);
 
@@ -63,13 +64,14 @@
     // Member Functions
     //------------------------------------------------------------------
     ObjectFileMachO (const lldb::ModuleSP &module_sp,
-                     lldb::DataBufferSP& dataSP,
+                     lldb::DataBufferSP& data_sp,
+                     lldb::offset_t data_offset,
                      const lldb_private::FileSpec* file,
-                     lldb::addr_t offset,
-                     lldb::addr_t length);
+                     lldb::offset_t offset,
+                     lldb::offset_t length);
 
     ObjectFileMachO (const lldb::ModuleSP &module_sp,
-                     lldb::DataBufferSP& dataSP,
+                     lldb::DataBufferSP& data_sp,
                      const lldb::ProcessSP &process_sp,
                      lldb::addr_t header_addr);
 
diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index 6bfe695..78af661 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -145,11 +145,25 @@
 
 
 ObjectFile *
-ObjectFilePECOFF::CreateInstance (const lldb::ModuleSP &module_sp, DataBufferSP& dataSP, const FileSpec* file, addr_t offset, addr_t length)
+ObjectFilePECOFF::CreateInstance (const lldb::ModuleSP &module_sp,
+                                  DataBufferSP& data_sp,
+                                  lldb::offset_t data_offset,
+                                  const lldb_private::FileSpec* file,
+                                  lldb::offset_t file_offset,
+                                  lldb::offset_t length)
 {
-    if (ObjectFilePECOFF::MagicBytesMatch(dataSP))
+    if (!data_sp)
     {
-        std::auto_ptr<ObjectFile> objfile_ap(new ObjectFilePECOFF (module_sp, dataSP, file, offset, length));
+        data_sp = file->MemoryMapFileContents(file_offset, length);
+        data_offset = 0;
+    }
+
+    if (ObjectFilePECOFF::MagicBytesMatch(data_sp))
+    {
+        // Update the data to contain the entire file if it doesn't already
+        if (data_sp->GetByteSize() < length)
+            data_sp = file->MemoryMapFileContents(file_offset, length);
+        std::auto_ptr<ObjectFile> objfile_ap(new ObjectFilePECOFF (module_sp, data_sp, data_offset, file, file_offset, length));
         if (objfile_ap.get() && objfile_ap->ParseHeader())
             return objfile_ap.release();
     }
@@ -166,9 +180,9 @@
 }
 
 bool
-ObjectFilePECOFF::MagicBytesMatch (DataBufferSP& dataSP)
+ObjectFilePECOFF::MagicBytesMatch (DataBufferSP& data_sp)
 {
-    DataExtractor data(dataSP, eByteOrderLittle, 4);
+    DataExtractor data(data_sp, eByteOrderLittle, 4);
     lldb::offset_t offset = 0;
     uint16_t magic = data.GetU16 (&offset);
     return magic == IMAGE_DOS_SIGNATURE;
@@ -176,11 +190,12 @@
 
 
 ObjectFilePECOFF::ObjectFilePECOFF (const lldb::ModuleSP &module_sp, 
-                                    DataBufferSP& dataSP, 
+                                    DataBufferSP& data_sp,
+                                    lldb::offset_t data_offset,
                                     const FileSpec* file, 
-                                    addr_t offset, 
-                                    addr_t length) :
-    ObjectFile (module_sp, file, offset, length, dataSP),
+                                    lldb::offset_t file_offset,
+                                    lldb::offset_t length) :
+    ObjectFile (module_sp, file, file_offset, length, data_sp, data_offset),
     m_dos_header (),
     m_coff_header (),
     m_coff_header_opt (),
diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
index 446999c..aad2696 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
@@ -36,10 +36,11 @@
     
     static ObjectFile *
     CreateInstance (const lldb::ModuleSP &module_sp,
-                    lldb::DataBufferSP& dataSP,
+                    lldb::DataBufferSP& data_sp,
+                    lldb::offset_t data_offset,
                     const lldb_private::FileSpec* file,
-                    lldb::addr_t offset,
-                    lldb::addr_t length);
+                    lldb::offset_t offset,
+                    lldb::offset_t length);
     
     static lldb_private::ObjectFile *
     CreateMemoryInstance (const lldb::ModuleSP &module_sp, 
@@ -47,14 +48,15 @@
                           const lldb::ProcessSP &process_sp, 
                           lldb::addr_t header_addr);
     static bool
-    MagicBytesMatch (lldb::DataBufferSP& dataSP);
+    MagicBytesMatch (lldb::DataBufferSP& data_sp);
     
     
     ObjectFilePECOFF (const lldb::ModuleSP &module_sp,
-                      lldb::DataBufferSP& dataSP,
+                      lldb::DataBufferSP& data_sp,
+                      lldb::offset_t data_offset,
                       const lldb_private::FileSpec* file,
-                      lldb::addr_t offset,
-                      lldb::addr_t length);
+                      lldb::offset_t file_offset,
+                      lldb::offset_t length);
     
 	virtual 
     ~ObjectFilePECOFF();