ObjectFileELF::GetModuleSpecifications on Linux should work now.
Which means "platform process list" should work and list the architecture.
We are now parsing the elf build-id if it exists, which should allow us to load stripped symbols (looking at that next).

llvm-svn: 182610
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h b/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h
index 11ab1dc..aa2c16b 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h
+++ b/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h
@@ -107,7 +107,7 @@
     GetRelocationJumpSlotType() const;
 
     //--------------------------------------------------------------------------
-    /// Parse an ELFSectionHeader entry starting at position \p offset and
+    /// Parse an ELFHeader entry starting at position \p offset and
     /// update the data extractor with the address size and byte order
     /// attributes as defined by the header.
     ///
@@ -120,7 +120,7 @@
     ///    advanced by the number of bytes read.
     ///
     /// @return
-    ///    True if the ELFSectionHeader was successfully read and false
+    ///    True if the ELFHeader was successfully read and false
     ///    otherwise.
     bool
     Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset);
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 31f1f28..d665e58 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -243,11 +243,8 @@
                                         lldb::offset_t length,
                                         lldb_private::ModuleSpecList &specs)
 {
-// FIXME: mikesart@valvesoftware.com
-// Implementing this function has broken several tests. Specifically this one:
-// Python dotest.py --executable <path-to-lldb> -p TestCallStdStringFunction.py
     const size_t initial_count = specs.GetSize();
-#if 0    
+
     if (ObjectFileELF::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize()))
     {
         DataExtractor data;
@@ -264,15 +261,20 @@
                                                        LLDB_INVALID_CPUTYPE);
                 if (spec.GetArchitecture().IsValid())
                 {
-                    // ObjectFileMachO adds the UUID here also, but that isn't in the elf header
-                    // so we'd have to read the entire file in and calculate the md5sum.
-                    // That'd be bad for this routine...
+                    // We could parse the ABI tag information (in .note, .notes, or .note.ABI-tag) to get the
+                    // machine information. However, we'd have to read a good bit of the rest of the file,
+                    // and this info isn't guaranteed to exist or be correct. More details here:
+                    //  http://refspecs.linuxfoundation.org/LSB_1.2.0/gLSB/noteabitag.html
+                    // Instead of passing potentially incorrect information down the pipeline, grab
+                    // the host information and use it.
+                    spec.GetArchitecture().GetTriple().setOSName (Host::GetOSString().GetCString());
+                    spec.GetArchitecture().GetTriple().setVendorName(Host::GetVendorString().GetCString());
                     specs.Append(spec);
                 }
             }
         }
     }
-#endif
+
     return specs.GetSize() - initial_count;
 }
 
@@ -360,7 +362,12 @@
 bool
 ObjectFileELF::GetUUID(lldb_private::UUID* uuid)
 {
-    // FIXME: Return MD5 sum here.  See comment in ObjectFile.h.
+    if (m_uuid.IsValid())
+    {
+        *uuid = m_uuid;
+        return true;
+    }
+    // FIXME: Return MD5 sum here. See comment in ObjectFile.h.
     return false;
 }
 
@@ -661,6 +668,51 @@
     return NULL;
 }
 
+static bool
+ParseNoteGNUBuildID(DataExtractor& data, lldb_private::UUID& uuid)
+{
+    // Try to parse the note section (ie .note.gnu.build-id|.notes|.note|...) and get the build id.
+    // BuildID documentation: https://fedoraproject.org/wiki/Releases/FeatureBuildId
+    struct
+    {
+        uint32_t name_len;  // Length of note name
+        uint32_t desc_len;  // Length of note descriptor
+        uint32_t type;      // Type of note (1 is ABI_TAG, 3 is BUILD_ID)
+    } notehdr;
+    lldb::offset_t offset = 0;
+    static const uint32_t g_gnu_build_id = 3; // NT_GNU_BUILD_ID from elf.h
+
+    while (true)
+    {
+        if (data.GetU32 (&offset, &notehdr, 3) == NULL)
+            return false;
+
+        notehdr.name_len = llvm::RoundUpToAlignment (notehdr.name_len, 4);
+        notehdr.desc_len = llvm::RoundUpToAlignment (notehdr.desc_len, 4);
+
+        lldb::offset_t offset_next_note = offset + notehdr.name_len + notehdr.desc_len;
+
+        // 16 bytes is UUID|MD5, 20 bytes is SHA1
+        if ((notehdr.type == g_gnu_build_id) && (notehdr.name_len == 4) &&
+            (notehdr.desc_len == 16 || notehdr.desc_len == 20))
+        {
+            char name[4];
+            if (data.GetU8 (&offset, name, 4) == NULL)
+                return false;
+            if (!strcmp(name, "GNU"))
+            {
+                uint8_t uuidbuf[20]; 
+                if (data.GetU8 (&offset, &uuidbuf, notehdr.desc_len) == NULL)
+                    return false;
+                uuid.SetBytes (uuidbuf, notehdr.desc_len);
+                return true;
+            }
+        }
+        offset = offset_next_note;
+    }
+    return false;
+}
+ 
 SectionList *
 ObjectFileELF::GetSectionList()
 {
@@ -727,7 +779,17 @@
             else if (name == g_sect_name_dwarf_debug_ranges)    sect_type = eSectionTypeDWARFDebugRanges;
             else if (name == g_sect_name_dwarf_debug_str)       sect_type = eSectionTypeDWARFDebugStr;
             else if (name == g_sect_name_eh_frame)              sect_type = eSectionTypeEHFrame;
-            
+            else if (header.sh_type == SHT_NOTE)
+            {
+                if (!m_uuid.IsValid())
+                {
+                    DataExtractor data;
+                    if (vm_size && (GetData (header.sh_offset, vm_size, data) == vm_size))
+                    {
+                        ParseNoteGNUBuildID (data, m_uuid);
+                    }
+                }
+            }
             
             SectionSP section_sp(new Section(
                 GetModule(),        // Module to which this section belongs.
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 6efd981..f1fea3c 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -16,6 +16,7 @@
 #include "lldb/lldb-private.h"
 #include "lldb/Host/FileSpec.h"
 #include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Core/UUID.h"
 
 #include "ELFHeader.h"
 
@@ -154,6 +155,9 @@
     /// ELF file header.
     elf::ELFHeader m_header;
 
+    /// ELF build ID
+    lldb_private::UUID m_uuid;
+
     /// Collection of program headers.
     ProgramHeaderColl m_program_headers;