[llvm] r302044 - Create DWARFVerifier.cpp and .h and move all DWARF verification code over into it.

Greg Clayton via llvm-commits llvm-commits at lists.llvm.org
Wed May 3 09:02:29 PDT 2017


Author: gclayton
Date: Wed May  3 11:02:29 2017
New Revision: 302044

URL: http://llvm.org/viewvc/llvm-project?rev=302044&view=rev
Log:
Create DWARFVerifier.cpp and .h and move all DWARF verification code over into it.

Adrian requested we create a DWARFVerifier.cpp file to contain all of the DWARF verification stuff. This change simply moves the functionality over into DWARFVerifier.h and DWARFVerifier.cpp, renames the DWARFVerifier methods to start with lower case, and switches DWARFContext.cpp over to using the new functionality.

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

Added:
    llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
    llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp
Modified:
    llvm/trunk/lib/DebugInfo/DWARF/CMakeLists.txt
    llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp

Added: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h?rev=302044&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h (added)
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h Wed May  3 11:02:29 2017
@@ -0,0 +1,49 @@
+//===- DWARFVerifier.h ----------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
+#define LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
+
+#include <cstdint>
+
+namespace llvm {
+class raw_ostream;
+class DWARFContext;
+class DWARFUnit;
+
+/// A class that verifies DWARF debug information given a DWARF Context.
+class DWARFVerifier {
+  raw_ostream &OS;
+  DWARFContext &DCtx;
+  uint32_t NumDebugInfoErrors;
+  uint32_t NumDebugLineErrors;
+
+public:
+  DWARFVerifier(raw_ostream &S, DWARFContext &D)
+      : OS(S), DCtx(D), NumDebugInfoErrors(0), NumDebugLineErrors(0) {}
+  /// Verify the information in the .debug_info section.
+  ///
+  /// Any errors are reported to the stream that was this object was
+  /// constructed with.
+  ///
+  /// @return True if the .debug_info verifies successfully, false otherwise.
+  bool handleDebugInfo();
+
+  /// Verify the information in the .debug_line section.
+  ///
+  /// Any errors are reported to the stream that was this object was
+  /// constructed with.
+  ///
+  /// @return True if the .debug_line verifies successfully, false otherwise.
+  bool handleDebugLine();
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H

Modified: llvm/trunk/lib/DebugInfo/DWARF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/CMakeLists.txt?rev=302044&r1=302043&r2=302044&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/CMakeLists.txt (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/CMakeLists.txt Wed May  3 11:02:29 2017
@@ -19,6 +19,7 @@ add_llvm_library(LLVMDebugInfoDWARF
   DWARFTypeUnit.cpp
   DWARFUnitIndex.cpp
   DWARFUnit.cpp
+  DWARFVerifier.cpp
   SyntaxHighlighting.cpp
 
   ADDITIONAL_HEADER_DIRS

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp?rev=302044&r1=302043&r2=302044&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp Wed May  3 11:02:29 2017
@@ -7,17 +7,17 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringSwitch.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
@@ -29,6 +29,7 @@
 #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
 #include "llvm/DebugInfo/DWARF/DWARFSection.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
+#include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
 #include "llvm/Object/Decompressor.h"
 #include "llvm/Object/MachO.h"
 #include "llvm/Object/ObjectFile.h"
@@ -537,13 +538,13 @@ public:
 
 bool DWARFContext::verify(raw_ostream &OS, DIDumpType DumpType) {
   bool Success = true;
-  Verifier verifier(OS, *this);
+  DWARFVerifier verifier(OS, *this);
   if (DumpType == DIDT_All || DumpType == DIDT_Info) {
-    if (!verifier.HandleDebugInfo())
+    if (!verifier.handleDebugInfo())
       Success = false;
   }
   if (DumpType == DIDT_All || DumpType == DIDT_Line) {
-    if (!verifier.HandleDebugLine())
+    if (!verifier.handleDebugLine())
       Success = false;
   }
   return Success;

Added: llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp?rev=302044&view=auto
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp (added)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp Wed May  3 11:02:29 2017
@@ -0,0 +1,252 @@
+//===- DWARFVerifier.cpp --------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARF/DWARFSection.h"
+#include "llvm/Support/raw_ostream.h"
+#include <map>
+#include <set>
+#include <vector>
+
+using namespace llvm;
+using namespace dwarf;
+using namespace object;
+
+bool DWARFVerifier::handleDebugInfo() {
+
+  NumDebugInfoErrors = 0;
+  // A map that tracks all references (converted absolute references) so we
+  // can verify each reference points to a valid DIE and not an offset that
+  // lies between to valid DIEs.
+  std::map<uint64_t, std::set<uint32_t>> ReferenceToDIEOffsets;
+
+  OS << "Verifying .debug_info...\n";
+  for (const auto &CU : DCtx.compile_units()) {
+    unsigned NumDies = CU->getNumDIEs();
+    for (unsigned I = 0; I < NumDies; ++I) {
+      auto Die = CU->getDIEAtIndex(I);
+      const auto Tag = Die.getTag();
+      if (Tag == DW_TAG_null)
+        continue;
+      for (auto AttrValue : Die.attributes()) {
+        const auto Attr = AttrValue.Attr;
+        const auto Form = AttrValue.Value.getForm();
+        switch (Attr) {
+        case DW_AT_ranges:
+          // Make sure the offset in the DW_AT_ranges attribute is valid.
+          if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
+            if (*SectionOffset >= DCtx.getRangeSection().Data.size()) {
+              ++NumDebugInfoErrors;
+              OS << "error: DW_AT_ranges offset is beyond .debug_ranges "
+                    "bounds:\n";
+              Die.dump(OS, 0);
+              OS << "\n";
+            }
+          } else {
+            ++NumDebugInfoErrors;
+            OS << "error: DIE has invalid DW_AT_ranges encoding:\n";
+            Die.dump(OS, 0);
+            OS << "\n";
+          }
+          break;
+        case DW_AT_stmt_list:
+          // Make sure the offset in the DW_AT_stmt_list attribute is valid.
+          if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
+            if (*SectionOffset >= DCtx.getLineSection().Data.size()) {
+              ++NumDebugInfoErrors;
+              OS << "error: DW_AT_stmt_list offset is beyond .debug_line "
+                    "bounds: "
+                 << format("0x%08" PRIx32, *SectionOffset) << "\n";
+              CU->getUnitDIE().dump(OS, 0);
+              OS << "\n";
+            }
+          } else {
+            ++NumDebugInfoErrors;
+            OS << "error: DIE has invalid DW_AT_stmt_list encoding:\n";
+            Die.dump(OS, 0);
+            OS << "\n";
+          }
+          break;
+
+        default:
+          break;
+        }
+        switch (Form) {
+        case DW_FORM_ref1:
+        case DW_FORM_ref2:
+        case DW_FORM_ref4:
+        case DW_FORM_ref8:
+        case DW_FORM_ref_udata: {
+          // Verify all CU relative references are valid CU offsets.
+          Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
+          assert(RefVal);
+          if (RefVal) {
+            auto DieCU = Die.getDwarfUnit();
+            auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
+            auto CUOffset = AttrValue.Value.getRawUValue();
+            if (CUOffset >= CUSize) {
+              ++NumDebugInfoErrors;
+              OS << "error: " << FormEncodingString(Form) << " CU offset "
+                 << format("0x%08" PRIx32, CUOffset)
+                 << " is invalid (must be less than CU size of "
+                 << format("0x%08" PRIx32, CUSize) << "):\n";
+              Die.dump(OS, 0);
+              OS << "\n";
+            } else {
+              // Valid reference, but we will verify it points to an actual
+              // DIE later.
+              ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
+            }
+          }
+          break;
+        }
+        case DW_FORM_ref_addr: {
+          // Verify all absolute DIE references have valid offsets in the
+          // .debug_info section.
+          Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
+          assert(RefVal);
+          if (RefVal) {
+            if (*RefVal >= DCtx.getInfoSection().Data.size()) {
+              ++NumDebugInfoErrors;
+              OS << "error: DW_FORM_ref_addr offset beyond .debug_info "
+                    "bounds:\n";
+              Die.dump(OS, 0);
+              OS << "\n";
+            } else {
+              // Valid reference, but we will verify it points to an actual
+              // DIE later.
+              ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
+            }
+          }
+          break;
+        }
+        case DW_FORM_strp: {
+          auto SecOffset = AttrValue.Value.getAsSectionOffset();
+          assert(SecOffset); // DW_FORM_strp is a section offset.
+          if (SecOffset && *SecOffset >= DCtx.getStringSection().size()) {
+            ++NumDebugInfoErrors;
+            OS << "error: DW_FORM_strp offset beyond .debug_str bounds:\n";
+            Die.dump(OS, 0);
+            OS << "\n";
+          }
+          break;
+        }
+        default:
+          break;
+        }
+      }
+    }
+  }
+
+  // Take all references and make sure they point to an actual DIE by
+  // getting the DIE by offset and emitting an error
+  OS << "Verifying .debug_info references...\n";
+  for (auto Pair : ReferenceToDIEOffsets) {
+    auto Die = DCtx.getDIEForOffset(Pair.first);
+    if (Die)
+      continue;
+    ++NumDebugInfoErrors;
+    OS << "error: invalid DIE reference " << format("0x%08" PRIx64, Pair.first)
+       << ". Offset is in between DIEs:\n";
+    for (auto Offset : Pair.second) {
+      auto ReferencingDie = DCtx.getDIEForOffset(Offset);
+      ReferencingDie.dump(OS, 0);
+      OS << "\n";
+    }
+    OS << "\n";
+  }
+  return NumDebugInfoErrors == 0;
+}
+
+bool DWARFVerifier::handleDebugLine() {
+  std::map<uint64_t, DWARFDie> StmtListToDie;
+  NumDebugLineErrors = 0;
+  OS << "Verifying .debug_line...\n";
+  for (const auto &CU : DCtx.compile_units()) {
+    auto CUDie = CU->getUnitDIE();
+    // Get the attribute value as a section offset. No need to produce an
+    // error here if the encoding isn't correct because we validate this in
+    // the .debug_info verifier.
+    auto StmtSectionOffset = toSectionOffset(CUDie.find(DW_AT_stmt_list));
+    if (!StmtSectionOffset)
+      continue;
+    const uint32_t LineTableOffset = *StmtSectionOffset;
+    if (LineTableOffset >= DCtx.getLineSection().Data.size()) {
+      // Make sure we don't get a valid line table back if the offset
+      // is wrong.
+      assert(DCtx.getLineTableForUnit(CU.get()) == nullptr);
+      // Skip this line table as it isn't valid. No need to create an error
+      // here because we validate this in the .debug_info verifier.
+      continue;
+    }
+
+    auto Iter = StmtListToDie.find(LineTableOffset);
+    if (Iter != StmtListToDie.end()) {
+      ++NumDebugLineErrors;
+      OS << "error: two compile unit DIEs, "
+         << format("0x%08" PRIx32, Iter->second.getOffset()) << " and "
+         << format("0x%08" PRIx32, CUDie.getOffset())
+         << ", have the same DW_AT_stmt_list section offset:\n";
+      Iter->second.dump(OS, 0);
+      CUDie.dump(OS, 0);
+      OS << '\n';
+      // Already verified this line table before, no need to do it again.
+      continue;
+    }
+    StmtListToDie[LineTableOffset] = CUDie;
+
+    auto LineTable = DCtx.getLineTableForUnit(CU.get());
+    if (!LineTable) {
+      ++NumDebugLineErrors;
+      OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
+         << "] was not able to be parsed for CU:\n";
+      CUDie.dump(OS, 0);
+      OS << '\n';
+      continue;
+    }
+    uint32_t MaxFileIndex = LineTable->Prologue.FileNames.size();
+    uint64_t PrevAddress = 0;
+    uint32_t RowIndex = 0;
+    for (const auto &Row : LineTable->Rows) {
+      if (Row.Address < PrevAddress) {
+        ++NumDebugLineErrors;
+        OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
+           << "] row[" << RowIndex
+           << "] decreases in address from previous row:\n";
+
+        DWARFDebugLine::Row::dumpTableHeader(OS);
+        if (RowIndex > 0)
+          LineTable->Rows[RowIndex - 1].dump(OS);
+        Row.dump(OS);
+        OS << '\n';
+      }
+
+      if (Row.File > MaxFileIndex) {
+        ++NumDebugLineErrors;
+        OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
+           << "][" << RowIndex << "] has invalid file index " << Row.File
+           << " (valid values are [1," << MaxFileIndex << "]):\n";
+        DWARFDebugLine::Row::dumpTableHeader(OS);
+        Row.dump(OS);
+        OS << '\n';
+      }
+      if (Row.EndSequence)
+        PrevAddress = 0;
+      else
+        PrevAddress = Row.Address;
+      ++RowIndex;
+    }
+  }
+  return NumDebugLineErrors == 0;
+}




More information about the llvm-commits mailing list