<rdar://problem/10560053>

Fixed "target modules list" (aliased to "image list") to output more information
by default. Modified the "target modules list" to have a few new options:

"--header" or "-h" => show the image header address
"--offset" or "-o" => show the image header address offset from the address in the file (the slide applied to the shared library)

Removed the "--symfile-basename" or "-S" option, and repurposed it to 
"--symfile-unique" "-S" which will show the symbol file if it differs from
the executable file.

ObjectFile's can now be loaded from memory for cases where we don't have the
files cached locally in an SDK or net mounted root. ObjectFileMachO can now
read mach files from memory.

Moved the section data reading code into the ObjectFile so that the object
file can get the section data from Process memory if the file is only in
memory.

lldb_private::Module can now load its object file in a target with a rigid 
slide (very common operation for most dynamic linkers) by using:

bool 
Module::SetLoadAddress (Target &target, lldb::addr_t offset, bool &changed)

lldb::SBModule() now has a new constructor in the public interface:

SBModule::SBModule (lldb::SBProcess &process, lldb::addr_t header_addr);

This will find an appropriate ObjectFile plug-in to load an image from memory
where the object file header is at "header_addr".




git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@149804 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Symbol/ObjectFile.cpp b/source/Symbol/ObjectFile.cpp
index 02f176a..862e973 100644
--- a/source/Symbol/ObjectFile.cpp
+++ b/source/Symbol/ObjectFile.cpp
@@ -10,6 +10,7 @@
 #include "lldb/lldb-private.h"
 #include "lldb/lldb-private-log.h"
 #include "lldb/Core/DataBuffer.h"
+#include "lldb/Core/DataBufferHeap.h"
 #include "lldb/Core/Log.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
@@ -18,6 +19,7 @@
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Symbol/ObjectContainer.h"
 #include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Target/Process.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -106,6 +108,40 @@
     return object_file_sp;
 }
 
+ObjectFileSP
+ObjectFile::FindPlugin (Module* module, 
+                        const ProcessSP &process_sp,
+                        lldb::addr_t header_addr,
+                        DataBufferSP &file_data_sp)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "ObjectFile::FindPlugin (module = %s/%s, process = %p, header_addr = 0x%llx)",
+                        module->GetFileSpec().GetDirectory().AsCString(),
+                        module->GetFileSpec().GetFilename().AsCString(),
+                        process_sp.get(), header_addr);
+    ObjectFileSP object_file_sp;
+    
+    if (module != NULL)
+    {
+        uint32_t idx;
+        
+        // Check if this is a normal object file by iterating through
+        // all object file plugin instances.
+        ObjectFileCreateMemoryInstance create_callback;
+        for (idx = 0; (create_callback = PluginManager::GetObjectFileCreateMemoryCallbackAtIndex(idx)) != NULL; ++idx)
+        {
+            object_file_sp.reset (create_callback(module, file_data_sp, process_sp, header_addr));
+            if (object_file_sp.get())
+                return object_file_sp;
+        }
+        
+    }
+    // We didn't find it, so clear our shared pointer in case it
+    // contains anything and return an empty shared pointer
+    object_file_sp.reset();
+    return object_file_sp;
+}
+
 ObjectFile::ObjectFile (Module* module, 
                         const FileSpec *file_spec_ptr, 
                         addr_t file_offset, 
@@ -118,7 +154,9 @@
     m_offset (file_offset),
     m_length (file_size),
     m_data (),
-    m_unwind_table (*this)
+    m_unwind_table (*this),
+    m_process_wp(),
+    m_in_memory (false)
 {    
     if (file_spec_ptr)
         m_file = *file_spec_ptr;
@@ -150,6 +188,37 @@
     }
 }
 
+
+ObjectFile::ObjectFile (Module* module, 
+                        const ProcessSP &process_sp,
+                        lldb::addr_t header_addr, 
+                        DataBufferSP& header_data_sp) :
+    ModuleChild (module),
+    m_file (),
+    m_type (eTypeInvalid),
+    m_strata (eStrataInvalid),
+    m_offset (header_addr),
+    m_length (0),
+    m_data (),
+    m_unwind_table (*this),
+    m_process_wp (process_sp),
+    m_in_memory (true)
+{    
+    if (header_data_sp)
+        m_data.SetData (header_data_sp, 0, header_data_sp->GetByteSize());
+    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
+    if (log)
+    {
+        log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, process = %p, header_addr = 0x%llx\n",
+                     this,
+                     m_module->GetFileSpec().GetDirectory().AsCString(),
+                     m_module->GetFileSpec().GetFilename().AsCString(),
+                     process_sp.get(),
+                     m_offset);
+    }
+}
+
+
 ObjectFile::~ObjectFile()
 {
     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
@@ -276,6 +345,24 @@
     return eAddressClassUnknown;
 }
 
+DataBufferSP
+ObjectFile::ReadMemory (const ProcessSP &process_sp, lldb::addr_t addr, size_t byte_size)
+{
+    DataBufferSP data_sp;
+    if (process_sp)
+    {
+        std::auto_ptr<DataBufferHeap> data_ap (new DataBufferHeap (byte_size, 0));
+        Error error;
+        const size_t bytes_read = process_sp->ReadMemory (addr, 
+                                                          data_ap->GetBytes(), 
+                                                          data_ap->GetByteSize(), 
+                                                          error);
+        if (bytes_read == byte_size)
+            data_sp.reset (data_ap.release());
+    }
+    return data_sp;
+}
+
 size_t
 ObjectFile::GetData (off_t offset, size_t length, DataExtractor &data) const
 {
@@ -291,3 +378,69 @@
     return m_data.CopyByteOrderedData (offset, length, dst, length, lldb::endian::InlHostByteOrder());
 }
 
+
+size_t
+ObjectFile::ReadSectionData (const Section *section, off_t section_offset, void *dst, size_t dst_len) const
+{
+    if (m_in_memory)
+    {
+        ProcessSP process_sp (m_process_wp.lock());
+        if (process_sp)
+        {
+            Error error;
+            return process_sp->ReadMemory (section->GetLoadBaseAddress (&process_sp->GetTarget()) + section_offset, dst, dst_len, error);
+        }
+    }
+    else
+    {
+        return CopyData (section->GetFileOffset() + section_offset, dst_len, dst);
+    }
+    return 0;
+}
+
+//----------------------------------------------------------------------
+// Get the section data the file on disk
+//----------------------------------------------------------------------
+size_t
+ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data) const
+{
+    if (m_in_memory)
+    {
+        ProcessSP process_sp (m_process_wp.lock());
+        if (process_sp)
+        {
+            DataBufferSP data_sp (ReadMemory (process_sp, section->GetLoadBaseAddress (&process_sp->GetTarget()), section->GetByteSize()));
+            if (data_sp)
+            {
+                section_data.SetData (data_sp, 0, data_sp->GetByteSize());
+                section_data.SetByteOrder (process_sp->GetByteOrder());
+                section_data.SetAddressByteSize (process_sp->GetAddressByteSize());
+                return section_data.GetByteSize();
+            }
+        }
+    }
+    else
+    {
+        // The object file now contains a full mmap'ed copy of the object file data, so just use this
+        return MemoryMapSectionData (section, section_data);
+    }
+    section_data.Clear();
+    return 0;
+}
+
+size_t
+ObjectFile::MemoryMapSectionData (const Section *section, DataExtractor& section_data) const
+{
+    if (m_in_memory)
+    {
+        return ReadSectionData (section, section_data);
+    }
+    else
+    {
+        // The object file now contains a full mmap'ed copy of the object file data, so just use this
+        return GetData(section->GetFileOffset(), section->GetByteSize(), section_data);
+    }
+    section_data.Clear();
+    return 0;
+}
+