[ARM] Create objdump subtarget from build attrs

Enable an ELFObjectFile to read the its arm build attributes to
produce a target triple with a specific ARM architecture.
llvm-objdump now uses this functionality to automatically produce
a more accurate target.

Differential Revision: https://reviews.llvm.org/D28769

llvm-svn: 292366
diff --git a/llvm/lib/Support/ARMAttributeParser.cpp b/llvm/lib/Support/ARMAttributeParser.cpp
index 792510e..63e800a 100644
--- a/llvm/lib/Support/ARMAttributeParser.cpp
+++ b/llvm/lib/Support/ARMAttributeParser.cpp
@@ -89,32 +89,43 @@
 
 void ARMAttributeParser::IntegerAttribute(AttrType Tag, const uint8_t *Data,
                                           uint32_t &Offset) {
-  SW.printNumber(ARMBuildAttrs::AttrTypeAsString(Tag),
-                 ParseInteger(Data, Offset));
+
+  uint64_t Value = ParseInteger(Data, Offset);
+  Attributes.insert(std::make_pair(Tag, Value));
+
+  if (SW)
+    SW->printNumber(ARMBuildAttrs::AttrTypeAsString(Tag), Value);
 }
 
 void ARMAttributeParser::StringAttribute(AttrType Tag, const uint8_t *Data,
                                          uint32_t &Offset) {
   StringRef TagName = ARMBuildAttrs::AttrTypeAsString(Tag, /*TagPrefix*/false);
+  StringRef ValueDesc = ParseString(Data, Offset);
 
-  DictScope AS(SW, "Attribute");
-  SW.printNumber("Tag", Tag);
-  if (!TagName.empty())
-    SW.printString("TagName", TagName);
-  SW.printString("Value", ParseString(Data, Offset));
+  if (SW) {
+    DictScope AS(*SW, "Attribute");
+    SW->printNumber("Tag", Tag);
+    if (!TagName.empty())
+      SW->printString("TagName", TagName);
+    SW->printString("Value", ValueDesc);
+  }
 }
 
 void ARMAttributeParser::PrintAttribute(unsigned Tag, unsigned Value,
                                         StringRef ValueDesc) {
-  StringRef TagName = ARMBuildAttrs::AttrTypeAsString(Tag, /*TagPrefix*/false);
+  Attributes.insert(std::make_pair(Tag, Value));
 
-  DictScope AS(SW, "Attribute");
-  SW.printNumber("Tag", Tag);
-  SW.printNumber("Value", Value);
-  if (!TagName.empty())
-    SW.printString("TagName", TagName);
-  if (!ValueDesc.empty())
-    SW.printString("Description", ValueDesc);
+  if (SW) {
+    StringRef TagName = ARMBuildAttrs::AttrTypeAsString(Tag,
+                                                        /*TagPrefix*/false);
+    DictScope AS(*SW, "Attribute");
+    SW->printNumber("Tag", Tag);
+    SW->printNumber("Value", Value);
+    if (!TagName.empty())
+      SW->printString("TagName", TagName);
+    if (!ValueDesc.empty())
+      SW->printString("Description", ValueDesc);
+  }
 }
 
 void ARMAttributeParser::CPU_arch(AttrType Tag, const uint8_t *Data,
@@ -449,20 +460,22 @@
   uint64_t Integer = ParseInteger(Data, Offset);
   StringRef String = ParseString(Data, Offset);
 
-  DictScope AS(SW, "Attribute");
-  SW.printNumber("Tag", Tag);
-  SW.startLine() << "Value: " << Integer << ", " << String << '\n';
-  SW.printString("TagName", AttrTypeAsString(Tag, /*TagPrefix*/false));
-  switch (Integer) {
-  case 0:
-    SW.printString("Description", StringRef("No Specific Requirements"));
-    break;
-  case 1:
-    SW.printString("Description", StringRef("AEABI Conformant"));
-    break;
-  default:
-    SW.printString("Description", StringRef("AEABI Non-Conformant"));
-    break;
+  if (SW) {
+    DictScope AS(*SW, "Attribute");
+    SW->printNumber("Tag", Tag);
+    SW->startLine() << "Value: " << Integer << ", " << String << '\n';
+    SW->printString("TagName", AttrTypeAsString(Tag, /*TagPrefix*/false));
+    switch (Integer) {
+    case 0:
+      SW->printString("Description", StringRef("No Specific Requirements"));
+      break;
+    case 1:
+      SW->printString("Description", StringRef("AEABI Conformant"));
+      break;
+    default:
+      SW->printString("Description", StringRef("AEABI Non-Conformant"));
+      break;
+    }
   }
 }
 
@@ -604,27 +617,33 @@
 void ARMAttributeParser::ParseSubsection(const uint8_t *Data, uint32_t Length) {
   uint32_t Offset = sizeof(uint32_t); /* SectionLength */
 
-  SW.printNumber("SectionLength", Length);
-
   const char *VendorName = reinterpret_cast<const char*>(Data + Offset);
   size_t VendorNameLength = std::strlen(VendorName);
-  SW.printString("Vendor", StringRef(VendorName, VendorNameLength));
   Offset = Offset + VendorNameLength + 1;
 
-  if (StringRef(VendorName, VendorNameLength).lower() != "aeabi")
+  if (SW) {
+    SW->printNumber("SectionLength", Length);
+    SW->printString("Vendor", StringRef(VendorName, VendorNameLength));
+  }
+
+  if (StringRef(VendorName, VendorNameLength).lower() != "aeabi") {
     return;
+  }
 
   while (Offset < Length) {
     /// Tag_File | Tag_Section | Tag_Symbol   uleb128:byte-size
     uint8_t Tag = Data[Offset];
-    SW.printEnum("Tag", Tag, makeArrayRef(TagNames));
     Offset = Offset + sizeof(Tag);
 
     uint32_t Size =
       *reinterpret_cast<const support::ulittle32_t*>(Data + Offset);
-    SW.printNumber("Size", Size);
     Offset = Offset + sizeof(Size);
 
+    if (SW) {
+      SW->printEnum("Tag", Tag, makeArrayRef(TagNames));
+      SW->printNumber("Size", Size);
+    }
+
     if (Size > Length) {
       errs() << "subsection length greater than section length\n";
       return;
@@ -651,31 +670,38 @@
       return;
     }
 
-    DictScope ASS(SW, ScopeName);
-
-    if (!Indicies.empty())
-      SW.printList(IndexName, Indicies);
-
-    ParseAttributeList(Data, Offset, Length);
+    if (SW) {
+      DictScope ASS(*SW, ScopeName);
+      if (!Indicies.empty())
+        SW->printList(IndexName, Indicies);
+      ParseAttributeList(Data, Offset, Length);
+    } else {
+      ParseAttributeList(Data, Offset, Length);
+    }
   }
 }
 
-void ARMAttributeParser::Parse(ArrayRef<uint8_t> Section) {
+void ARMAttributeParser::Parse(ArrayRef<uint8_t> Section, bool isLittle) {
   size_t Offset = 1;
   unsigned SectionNumber = 0;
 
   while (Offset < Section.size()) {
-    uint32_t SectionLength =
-      *reinterpret_cast<const support::ulittle32_t*>(Section.data() + Offset);
+    uint32_t SectionLength = isLittle ?
+      support::endian::read32le(Section.data() + Offset) :
+      support::endian::read32be(Section.data() + Offset);
 
-    SW.startLine() << "Section " << ++SectionNumber << " {\n";
-    SW.indent();
+    if (SW) {
+      SW->startLine() << "Section " << ++SectionNumber << " {\n";
+      SW->indent();
+    }
 
     ParseSubsection(Section.data() + Offset, SectionLength);
     Offset = Offset + SectionLength;
 
-    SW.unindent();
-    SW.startLine() << "}\n";
+    if (SW) {
+      SW->unindent();
+      SW->startLine() << "}\n";
+    }
   }
 }
 }