<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/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp
index 3e05d21..12622b5 100644
--- a/source/Commands/CommandObjectTarget.cpp
+++ b/source/Commands/CommandObjectTarget.cpp
@@ -2760,7 +2760,7 @@
                         Module *module = module_address.GetModulePtr();
                         if (module)
                         {
-                            PrintModule (strm, module);
+                            PrintModule (target, module, UINT32_MAX, 0, strm);
                             result.SetStatus (eReturnStatusSuccessFinishResult);
                         }
                         else
@@ -2808,8 +2808,8 @@
                         module = module_sp.get();
                     }
                     
-                    strm.Printf("[%3u] ", image_idx);
-                    PrintModule (strm, module);
+                    int indent = strm.Printf("[%3u] ", image_idx);
+                    PrintModule (target, module, image_idx, indent, strm);
 
                 }
                 result.SetStatus (eReturnStatusSuccessFinishResult);
@@ -2829,108 +2829,160 @@
 protected:
 
     void
-    PrintModule (Stream &strm, Module *module)
+    PrintModule (Target *target, Module *module, uint32_t idx, int indent, Stream &strm)
     {
 
         bool dump_object_name = false;
         if (m_options.m_format_array.empty())
         {
-            DumpFullpath(strm, &module->GetFileSpec(), 0);
-            dump_object_name = true;
+            m_options.m_format_array.push_back(std::make_pair('u', 0));
+            m_options.m_format_array.push_back(std::make_pair('h', 0));
+            m_options.m_format_array.push_back(std::make_pair('f', 0));
+            m_options.m_format_array.push_back(std::make_pair('S', 0));
         }
-        else
+        const size_t num_entries = m_options.m_format_array.size();
+        bool print_space = false;
+        for (size_t i=0; i<num_entries; ++i)
         {
-            const size_t num_entries = m_options.m_format_array.size();
-            for (size_t i=0; i<num_entries; ++i)
+            if (print_space)
+                strm.PutChar(' ');
+            print_space = true;
+            const char format_char = m_options.m_format_array[i].first;
+            uint32_t width = m_options.m_format_array[i].second;
+            switch (format_char)
             {
-                if (i > 0)
-                    strm.PutChar(' ');
-                char format_char = m_options.m_format_array[i].first;
-                uint32_t width = m_options.m_format_array[i].second;
-                switch (format_char)
-                {
-                    case 'A':
-                        DumpModuleArchitecture (strm, module, false, width);
-                        break;
-                        
-                    case 't':
-                        DumpModuleArchitecture (strm, module, true, width);
-                        break;
-                        
-                    case 'f':
-                        DumpFullpath (strm, &module->GetFileSpec(), width);
-                        dump_object_name = true;
-                        break;
-                        
-                    case 'd':
-                        DumpDirectory (strm, &module->GetFileSpec(), width);
-                        break;
-                        
-                    case 'b':
-                        DumpBasename (strm, &module->GetFileSpec(), width);
-                        dump_object_name = true;
-                        break;
-                        
-                    case 'r':
-                        {
-                            uint32_t ref_count = 0;
-                            ModuleSP module_sp (module->shared_from_this());
-                            if (module_sp)
-                            {
-                                // Take one away to make sure we don't count our local "module_sp"
-                                ref_count = module_sp.use_count() - 1;
-                            }
-                            if (width)
-                                strm.Printf("{%*u}", width, ref_count);
-                            else
-                                strm.Printf("{%u}", ref_count);
-                        }
-                        break;
+                case 'A':
+                    DumpModuleArchitecture (strm, module, false, width);
+                    break;
+                    
+                case 't':
+                    DumpModuleArchitecture (strm, module, true, width);
+                    break;
+                    
+                case 'f':
+                    DumpFullpath (strm, &module->GetFileSpec(), width);
+                    dump_object_name = true;
+                    break;
+                    
+                case 'd':
+                    DumpDirectory (strm, &module->GetFileSpec(), width);
+                    break;
+                    
+                case 'b':
+                    DumpBasename (strm, &module->GetFileSpec(), width);
+                    dump_object_name = true;
+                    break;
+                
+                case 'h':
+                case 'o':
+                    // Image header address
+                    {
+                        uint32_t addr_nibble_width = target ? (target->GetArchitecture().GetAddressByteSize() * 2) : 16;
 
-                    case 's':
-                    case 'S':
+                        ObjectFile *objfile = module->GetObjectFile ();
+                        if (objfile)
                         {
-                            SymbolVendor *symbol_vendor = module->GetSymbolVendor();
-                            if (symbol_vendor)
+                            Address header_addr(objfile->GetHeaderAddress());
+                            if (header_addr.IsValid())
                             {
-                                SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
-                                if (symbol_file)
+                                if (target && !target->GetSectionLoadList().IsEmpty())
                                 {
-                                    if (format_char == 'S')
-                                        DumpBasename(strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
+                                    lldb::addr_t header_load_addr = header_addr.GetLoadAddress (target);
+                                    if (header_load_addr == LLDB_INVALID_ADDRESS)
+                                    {
+                                        header_addr.Dump (&strm, target, Address::DumpStyleModuleWithFileAddress, Address::DumpStyleFileAddress);
+                                    }
                                     else
-                                        DumpFullpath (strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
-                                    dump_object_name = true;
+                                    {
+                                        if (format_char == 'o')
+                                        {
+                                            // Show the offset of slide for the image
+                                            strm.Printf ("0x%*.*llx", addr_nibble_width, addr_nibble_width, header_load_addr - header_addr.GetFileAddress());
+                                        }
+                                        else
+                                        {
+                                            // Show the load address of the image
+                                            strm.Printf ("0x%*.*llx", addr_nibble_width, addr_nibble_width, header_load_addr);
+                                        }
+                                    }
                                     break;
                                 }
+                                // The address was valid, but the image isn't loaded, output the address in an appropriate format
+                                header_addr.Dump (&strm, target, Address::DumpStyleFileAddress);
+                                break;
                             }
-                            strm.Printf("%.*s", width, "<NONE>");
                         }
-                        break;
-                        
-                    case 'm':
-                        module->GetModificationTime().Dump(&strm, width);
-                        break;
+                        strm.Printf ("%*s", addr_nibble_width + 2, "");
+                    }
+                    break;
+                case 'r':
+                    {
+                        uint32_t ref_count = 0;
+                        ModuleSP module_sp (module->shared_from_this());
+                        if (module_sp)
+                        {
+                            // Take one away to make sure we don't count our local "module_sp"
+                            ref_count = module_sp.use_count() - 1;
+                        }
+                        if (width)
+                            strm.Printf("{%*u}", width, ref_count);
+                        else
+                            strm.Printf("{%u}", ref_count);
+                    }
+                    break;
 
-                    case 'p':
-                        strm.Printf("%p", module);
-                        break;
+                case 's':
+                case 'S':
+                    {
+                        SymbolVendor *symbol_vendor = module->GetSymbolVendor();
+                        if (symbol_vendor)
+                        {
+                            SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
+                            if (symbol_file)
+                            {
+                                if (format_char == 'S')
+                                {
+                                    FileSpec &symfile_spec = symbol_file->GetObjectFile()->GetFileSpec();
+                                    // Dump symbol file only if different from module file
+                                    if (!symfile_spec || symfile_spec == module->GetFileSpec())
+                                    {
+                                        print_space = false;
+                                        break;
+                                    }
+                                    // Add a newline and indent past the index
+                                    strm.Printf ("\n%*s", indent, "");
+                                }
+                                DumpFullpath (strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
+                                dump_object_name = true;
+                                break;
+                            }
+                        }
+                        strm.Printf("%.*s", width, "<NONE>");
+                    }
+                    break;
+                    
+                case 'm':
+                    module->GetModificationTime().Dump(&strm, width);
+                    break;
 
-                    case 'u':
-                        DumpModuleUUID(strm, module);
-                        break;
-                        
-                    default:
-                        break;
-                }
-                
+                case 'p':
+                    strm.Printf("%p", module);
+                    break;
+
+                case 'u':
+                    DumpModuleUUID(strm, module);
+                    break;
+                    
+                default:
+                    break;
             }
-            if (dump_object_name)
-            {
-                const char *object_name = module->GetObjectName().GetCString();
-                if (object_name)
-                    strm.Printf ("(%s)", object_name);
-            }
+            
+        }
+        if (dump_object_name)
+        {
+            const char *object_name = module->GetObjectName().GetCString();
+            if (object_name)
+                strm.Printf ("(%s)", object_name);
         }
         strm.EOL();
     }
@@ -2944,12 +2996,14 @@
     { LLDB_OPT_SET_1, false, "address",    'a', required_argument, NULL, 0, eArgTypeAddress, "Display the image at this address."},
     { LLDB_OPT_SET_1, false, "arch",       'A', optional_argument, NULL, 0, eArgTypeWidth,   "Display the architecture when listing images."},
     { LLDB_OPT_SET_1, false, "triple",     't', optional_argument, NULL, 0, eArgTypeWidth,   "Display the triple when listing images."},
+    { LLDB_OPT_SET_1, false, "header",     'h', no_argument,       NULL, 0, eArgTypeNone,    "Display the image header address as a load address if debugging, a file address otherwise."},
+    { LLDB_OPT_SET_1, false, "offset",     'o', no_argument,       NULL, 0, eArgTypeNone,    "Display the image header address offset from the header file address (the slide amount)."},
     { LLDB_OPT_SET_1, false, "uuid",       'u', no_argument,       NULL, 0, eArgTypeNone,    "Display the UUID when listing images."},
     { LLDB_OPT_SET_1, false, "fullpath",   'f', optional_argument, NULL, 0, eArgTypeWidth,   "Display the fullpath to the image object file."},
     { LLDB_OPT_SET_1, false, "directory",  'd', optional_argument, NULL, 0, eArgTypeWidth,   "Display the directory with optional width for the image object file."},
     { LLDB_OPT_SET_1, false, "basename",   'b', optional_argument, NULL, 0, eArgTypeWidth,   "Display the basename with optional width for the image object file."},
     { LLDB_OPT_SET_1, false, "symfile",    's', optional_argument, NULL, 0, eArgTypeWidth,   "Display the fullpath to the image symbol file with optional width."},
-    { LLDB_OPT_SET_1, false, "symfile-basename", 'S', optional_argument, NULL, 0, eArgTypeWidth,   "Display the basename to the image symbol file with optional width."},
+    { LLDB_OPT_SET_1, false, "symfile-unique", 'S', optional_argument, NULL, 0, eArgTypeWidth,   "Display the symbol file with optional width only if it is different from the executable object file."},
     { LLDB_OPT_SET_1, false, "mod-time",   'm', optional_argument, NULL, 0, eArgTypeWidth,   "Display the modification time with optional width of the module."},
     { LLDB_OPT_SET_1, false, "ref-count",  'r', optional_argument, NULL, 0, eArgTypeWidth,   "Display the reference count if the module is still in the shared module cache."},
     { LLDB_OPT_SET_1, false, "pointer",    'p', optional_argument, NULL, 0, eArgTypeNone,    "Display the module pointer."},