[DWARF] Added check that verifies that no abbreviation declaration has more than one attribute with the same name.

SUMMARY

This patch adds a verification check on the abbreviation declarations in the .debug_abbrev section.
The check makes sure that no abbreviation declaration has more than one attributes with the same name.

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

llvm-svn: 308579
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index 88efcd8..1b45ca9 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -418,6 +418,7 @@
 bool DWARFContext::verify(raw_ostream &OS, DIDumpType DumpType) {
   bool Success = true;
   DWARFVerifier verifier(OS, *this);
+  Success &= verifier.handleDebugAbbrev();
   if (DumpType == DIDT_All || DumpType == DIDT_Info) {
     if (!verifier.handleDebugInfo())
       Success = false;
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index 50fc45a..d683642 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -102,6 +102,37 @@
   return NumUnitErrors == 0;
 }
 
+bool DWARFVerifier::handleDebugAbbrev() {
+  OS << "Verifying .debug_abbrev...\n";
+
+  const DWARFObject &DObj = DCtx.getDWARFObj();
+  if (DObj.getAbbrevSection().empty()) {
+    OS << "Warning: .debug_abbrev is empty.\n";
+    return true;
+  }
+
+  unsigned NumErrors = 0;
+  const DWARFDebugAbbrev *Abbrev = DCtx.getDebugAbbrev();
+  if (Abbrev) {
+    const DWARFAbbreviationDeclarationSet *AbbrDecls =
+        Abbrev->getAbbreviationDeclarationSet(0);
+    for (auto AbbrDecl : *AbbrDecls) {
+      SmallDenseSet<uint16_t> AttributeSet;
+      for (auto Attribute : AbbrDecl.attributes()) {
+        auto Result = AttributeSet.insert(Attribute.Attr);
+        if (!Result.second) {
+          OS << format("Error: Abbreviation declaration with code %d ",
+                       AbbrDecl.getCode());
+          OS << "contains multiple " << AttributeString(Attribute.Attr)
+             << " attributes.\n";
+          ++NumErrors;
+        }
+      }
+    }
+  }
+  return NumErrors == 0;
+}
+
 bool DWARFVerifier::handleDebugInfo() {
   OS << "Verifying .debug_info Unit Header Chain...\n";