<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/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 81126f6..09bdff8 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -148,7 +148,8 @@
 {
     PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                   GetPluginDescriptionStatic(),
-                                  CreateInstance);
+                                  CreateInstance,
+                                  CreateMemoryInstance);
 }
 
 void
@@ -196,6 +197,13 @@
 }
 
 
+ObjectFile*
+ObjectFileELF::CreateMemoryInstance(Module* module, DataBufferSP& data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr)
+{
+    return NULL;
+}
+
+
 //------------------------------------------------------------------
 // PluginInterface protocol
 //------------------------------------------------------------------
@@ -428,8 +436,8 @@
 
     DataExtractor dynsym_data;
     DataExtractor dynstr_data;
-    if (dynsym->ReadSectionDataFromObjectFile(this, dynsym_data) &&
-        dynstr->ReadSectionDataFromObjectFile(this, dynstr_data))
+    if (ReadSectionData(dynsym, dynsym_data) &&
+        ReadSectionData(dynstr, dynstr_data))
     {
         ELFDynamic symbol;
         const unsigned section_size = dynsym_data.GetByteSize();
@@ -812,8 +820,8 @@
     {
         DataExtractor symtab_data;
         DataExtractor strtab_data;
-        if (symtab->ReadSectionDataFromObjectFile(this, symtab_data) &&
-            strtab->ReadSectionDataFromObjectFile(this, strtab_data))
+        if (ReadSectionData(symtab, symtab_data) &&
+            ReadSectionData(strtab, strtab_data))
         {
             num_symbols = ParseSymbols(symbol_table, start_id, 
                                        section_list, symtab_hdr,
@@ -844,7 +852,7 @@
 
     ELFDynamic symbol;
     DataExtractor dynsym_data;
-    if (dynsym->ReadSectionDataFromObjectFile(this, dynsym_data))
+    if (ReadSectionData(dynsym, dynsym_data))
     {
 
         const unsigned section_size = dynsym_data.GetByteSize();
@@ -1034,15 +1042,15 @@
         return 0;
 
     DataExtractor rel_data;
-    if (!rel_section->ReadSectionDataFromObjectFile(this, rel_data))
+    if (!ReadSectionData(rel_section, rel_data))
         return 0;
 
     DataExtractor symtab_data;
-    if (!symtab->ReadSectionDataFromObjectFile(this, symtab_data))
+    if (!ReadSectionData(symtab, symtab_data))
         return 0;
 
     DataExtractor strtab_data;
-    if (!strtab->ReadSectionDataFromObjectFile(this, strtab_data))
+    if (!ReadSectionData(strtab, strtab_data))
         return 0;
 
     unsigned rel_type = PLTRelocationType();
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 78d2b5d..f20b0bd 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -51,6 +51,12 @@
                    lldb::addr_t offset,
                    lldb::addr_t length);
 
+    static lldb_private::ObjectFile *
+    CreateMemoryInstance (lldb_private::Module* module, 
+                          lldb::DataBufferSP& data_sp, 
+                          const lldb::ProcessSP &process_sp, 
+                          lldb::addr_t header_addr);
+
     //------------------------------------------------------------------
     // PluginInterface protocol
     //------------------------------------------------------------------
diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index de889ee..67773e7 100644
--- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -26,6 +26,7 @@
 #include "lldb/Host/FileSpec.h"
 #include "lldb/Symbol/ClangNamespaceDecl.h"
 #include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/Process.h"
 
 
 using namespace lldb;
@@ -39,7 +40,8 @@
 {
     PluginManager::RegisterPlugin (GetPluginNameStatic(),
                                    GetPluginDescriptionStatic(),
-                                   CreateInstance);
+                                   CreateInstance,
+                                   CreateMemoryInstance);
 }
 
 void
@@ -74,6 +76,58 @@
     return NULL;
 }
 
+ObjectFile *
+ObjectFileMachO::CreateMemoryInstance (Module* module, 
+                                       DataBufferSP& data_sp, 
+                                       const ProcessSP &process_sp, 
+                                       lldb::addr_t header_addr)
+{
+    if (ObjectFileMachO::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize()))
+    {
+        std::auto_ptr<ObjectFile> objfile_ap(new ObjectFileMachO (module, data_sp, process_sp, header_addr));
+        if (objfile_ap.get() && objfile_ap->ParseHeader())
+            return objfile_ap.release();
+    }
+    return NULL;    
+}
+
+
+const ConstString &
+ObjectFileMachO::GetSegmentNameTEXT()
+{
+    static ConstString g_segment_name_TEXT ("__TEXT");
+    return g_segment_name_TEXT;
+}
+
+const ConstString &
+ObjectFileMachO::GetSegmentNameDATA()
+{
+    static ConstString g_segment_name_DATA ("__DATA");
+    return g_segment_name_DATA;
+}
+
+const ConstString &
+ObjectFileMachO::GetSegmentNameOBJC()
+{
+    static ConstString g_segment_name_OBJC ("__OBJC");
+    return g_segment_name_OBJC;
+}
+
+const ConstString &
+ObjectFileMachO::GetSegmentNameLINKEDIT()
+{
+    static ConstString g_section_name_LINKEDIT ("__LINKEDIT");
+    return g_section_name_LINKEDIT;
+}
+
+const ConstString &
+ObjectFileMachO::GetSectionNameEHFrame()
+{
+    static ConstString g_section_name_eh_frame ("__eh_frame");
+    return g_section_name_eh_frame;
+}
+
+
 
 static uint32_t
 MachHeaderSizeFromMagic(uint32_t magic)
@@ -121,6 +175,20 @@
     ::memset (&m_dysymtab, 0, sizeof(m_dysymtab));
 }
 
+ObjectFileMachO::ObjectFileMachO (lldb_private::Module* module,
+                                  lldb::DataBufferSP& header_data_sp,
+                                  const lldb::ProcessSP &process_sp,
+                                  lldb::addr_t header_addr) :
+    ObjectFile(module, process_sp, header_addr, header_data_sp),
+    m_mutex (Mutex::eMutexTypeRecursive),
+    m_header(),
+    m_sections_ap(),
+    m_symtab_ap(),
+    m_entry_point_address ()
+{
+    ::memset (&m_header, 0, sizeof(m_header));
+    ::memset (&m_dysymtab, 0, sizeof(m_dysymtab));
+}
 
 ObjectFileMachO::~ObjectFileMachO()
 {
@@ -173,7 +241,28 @@
         ArchSpec mach_arch(eArchTypeMachO, m_header.cputype, m_header.cpusubtype);
         
         if (SetModulesArchitecture (mach_arch))
-            return true;
+        {
+            const size_t header_and_lc_size = m_header.sizeofcmds + MachHeaderSizeFromMagic(m_header.magic);
+            if (m_data.GetByteSize() < header_and_lc_size)
+            {
+                DataBufferSP data_sp;
+                ProcessSP process_sp (m_process_wp.lock());
+                if (process_sp)
+                {
+                    data_sp = ReadMemory (process_sp, m_offset, 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);
+                    if (data_sp->GetByteSize() != header_and_lc_size)
+                        return false;
+                }
+                if (data_sp)
+                    m_data.SetData (data_sp);
+            }
+        }
+        return true;
     }
     else
     {
@@ -799,11 +888,45 @@
                 if (section_list == NULL)
                     return 0;
 
+                ProcessSP process_sp (m_process_wp.lock());
+
                 const size_t addr_byte_size = m_data.GetAddressByteSize();
                 bool bit_width_32 = addr_byte_size == 4;
                 const size_t nlist_byte_size = bit_width_32 ? sizeof(struct nlist) : sizeof(struct nlist_64);
 
-                DataExtractor nlist_data (m_data, symtab_load_command.symoff, symtab_load_command.nsyms * nlist_byte_size);
+                DataExtractor nlist_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize());
+                DataExtractor strtab_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize());
+
+                const addr_t nlist_data_byte_size = symtab_load_command.nsyms * nlist_byte_size;
+                const addr_t strtab_data_byte_size = symtab_load_command.strsize;
+                if (process_sp)
+                {
+                    Target &target = process_sp->GetTarget();
+                    SectionSP linkedit_section_sp(section_list->FindSectionByName(GetSegmentNameLINKEDIT()));
+                    // Reading mach file from memory in a process or core file...
+
+                    if (linkedit_section_sp)
+                    {
+                        const addr_t linkedit_load_addr = linkedit_section_sp->GetLoadBaseAddress(&target);
+                        const addr_t linkedit_file_offset = linkedit_section_sp->GetFileOffset();
+                        const addr_t symoff_addr = linkedit_load_addr + symtab_load_command.symoff - linkedit_file_offset;
+                        const addr_t stroff_addr = linkedit_load_addr + symtab_load_command.stroff - linkedit_file_offset;
+                        DataBufferSP nlist_data_sp (ReadMemory (process_sp, symoff_addr, nlist_data_byte_size));
+                        DataBufferSP strtab_data_sp (ReadMemory (process_sp, stroff_addr, strtab_data_byte_size));
+                        nlist_data.SetData (nlist_data_sp, 0, nlist_data_sp->GetByteSize());
+                        strtab_data.SetData (strtab_data_sp, 0, strtab_data_sp->GetByteSize());
+                    }
+                }
+                else
+                {
+                    nlist_data.SetData (m_data, 
+                                        symtab_load_command.symoff, 
+                                        nlist_data_byte_size);
+                    strtab_data.SetData (m_data, 
+                                         symtab_load_command.stroff, 
+                                         strtab_data_byte_size);
+
+                }
 
                 if (nlist_data.GetByteSize() == 0)
                 {
@@ -812,7 +935,6 @@
                     return 0;
                 }
 
-                DataExtractor strtab_data (m_data, symtab_load_command.stroff, symtab_load_command.strsize);
 
                 if (strtab_data.GetByteSize() == 0)
                 {
@@ -821,10 +943,10 @@
                     return 0;
                 }
 
-                static ConstString g_segment_name_TEXT ("__TEXT");
-                static ConstString g_segment_name_DATA ("__DATA");
-                static ConstString g_segment_name_OBJC ("__OBJC");
-                static ConstString g_section_name_eh_frame ("__eh_frame");
+                const ConstString &g_segment_name_TEXT = GetSegmentNameTEXT();
+                const ConstString &g_segment_name_DATA = GetSegmentNameDATA();
+                const ConstString &g_segment_name_OBJC = GetSegmentNameOBJC();
+                const ConstString &g_section_name_eh_frame = GetSectionNameEHFrame();
                 SectionSP text_section_sp(section_list->FindSectionByName(g_segment_name_TEXT));
                 SectionSP data_section_sp(section_list->FindSectionByName(g_segment_name_DATA));
                 SectionSP objc_section_sp(section_list->FindSectionByName(g_segment_name_OBJC));
@@ -1823,6 +1945,24 @@
 
 }
 
+lldb_private::Address
+ObjectFileMachO::GetHeaderAddress ()
+{
+    lldb_private::Address header_addr;
+    SectionList *section_list = GetSectionList();
+    if (section_list)
+    {
+        SectionSP text_segment_sp (section_list->FindSectionByName (GetSegmentNameTEXT()));
+        if (text_segment_sp)
+        {
+            header_addr.SetSection (text_segment_sp.get());
+            header_addr.SetOffset (0);
+        }
+    }
+    return header_addr;
+}
+
+
 ObjectFile::Type
 ObjectFileMachO::CalculateType()
 {
diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
index f4f8ce9..98c33ca 100644
--- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
+++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
@@ -40,13 +40,19 @@
     static const char *
     GetPluginDescriptionStatic();
 
-    static ObjectFile *
+    static lldb_private::ObjectFile *
     CreateInstance (lldb_private::Module* module,
                     lldb::DataBufferSP& dataSP,
                     const lldb_private::FileSpec* file,
                     lldb::addr_t offset,
                     lldb::addr_t length);
 
+    static lldb_private::ObjectFile *
+    CreateMemoryInstance (lldb_private::Module* module, 
+                          lldb::DataBufferSP& data_sp, 
+                          const lldb::ProcessSP &process_sp, 
+                          lldb::addr_t header_addr);
+
     static bool
     MagicBytesMatch (lldb::DataBufferSP& dataSP, 
                      lldb::addr_t offset, 
@@ -61,6 +67,11 @@
                      lldb::addr_t offset,
                      lldb::addr_t length);
 
+    ObjectFileMachO (lldb_private::Module* module,
+                     lldb::DataBufferSP& dataSP,
+                     const lldb::ProcessSP &process_sp,
+                     lldb::addr_t header_addr);
+
     virtual
     ~ObjectFileMachO();
 
@@ -111,7 +122,10 @@
 
     virtual lldb_private::Address
     GetEntryPointAddress ();
-
+    
+    virtual lldb_private::Address
+    GetHeaderAddress ();
+    
     virtual ObjectFile::Type
     CalculateType();
     
@@ -123,6 +137,11 @@
     llvm::MachO::mach_header m_header;
     mutable std::auto_ptr<lldb_private::SectionList> m_sections_ap;
     mutable std::auto_ptr<lldb_private::Symtab> m_symtab_ap;
+    static const lldb_private::ConstString &GetSegmentNameTEXT();
+    static const lldb_private::ConstString &GetSegmentNameDATA();
+    static const lldb_private::ConstString &GetSegmentNameOBJC();
+    static const lldb_private::ConstString &GetSegmentNameLINKEDIT();
+    static const lldb_private::ConstString &GetSectionNameEHFrame();
 
     llvm::MachO::dysymtab_command m_dysymtab;
     std::vector<llvm::MachO::segment_command_64> m_mach_segments;
diff --git a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index 91b087b..7d8dc04 100644
--- a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -120,7 +120,8 @@
 {
     PluginManager::RegisterPlugin (GetPluginNameStatic(),
                                    GetPluginDescriptionStatic(),
-                                   CreateInstance);
+                                   CreateInstance,
+                                   CreateMemoryInstance);
 }
 
 void
@@ -155,6 +156,15 @@
     return NULL;
 }
 
+ObjectFile *
+ObjectFilePECOFF::CreateMemoryInstance (lldb_private::Module* module, 
+                                        lldb::DataBufferSP& data_sp, 
+                                        const lldb::ProcessSP &process_sp, 
+                                        lldb::addr_t header_addr)
+{
+    return NULL;
+}
+
 bool
 ObjectFilePECOFF::MagicBytesMatch (DataBufferSP& dataSP)
 {
diff --git a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
index 5bfe2d6..a0fb7e2 100644
--- a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
+++ b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
@@ -42,6 +42,11 @@
                     lldb::addr_t offset,
                     lldb::addr_t length);
     
+    static lldb_private::ObjectFile *
+    CreateMemoryInstance (lldb_private::Module* module, 
+                          lldb::DataBufferSP& data_sp, 
+                          const lldb::ProcessSP &process_sp, 
+                          lldb::addr_t header_addr);
     static bool
     MagicBytesMatch (lldb::DataBufferSP& dataSP);