[llvm] r316756 - [llvm-dwarfdump] - Teach verifier to report broken DWARF expressions.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 27 03:42:04 PDT 2017


Author: grimar
Date: Fri Oct 27 03:42:04 2017
New Revision: 316756

URL: http://llvm.org/viewvc/llvm-project?rev=316756&view=rev
Log:
[llvm-dwarfdump] - Teach verifier to report broken DWARF expressions.

Patch improves next things:

* Fixes assert/crash in getOpDesc when giving it a invalid expression op code.
* DWARFExpression::print() called DWARFExpression::Operation::getEndOffset() which
  returned and used uninitialized field EndOffset. Patch fixes that.
* Teaches verifier to verify DW_AT_location and error out on broken expressions.

Differential revision: https://reviews.llvm.org/D39294

Added:
    llvm/trunk/test/tools/llvm-dwarfdump/X86/verify_broken_exprloc.s
Modified:
    llvm/trunk/lib/DebugInfo/DWARF/DWARFExpression.cpp
    llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFExpression.cpp?rev=316756&r1=316755&r2=316756&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFExpression.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFExpression.cpp Fri Oct 27 03:42:04 2017
@@ -104,7 +104,9 @@ static DescVector getDescriptions() {
 static DWARFExpression::Operation::Description getOpDesc(unsigned OpCode) {
   // FIXME: Make this constexpr once all compilers are smart enough to do it.
   static DescVector Descriptions = getDescriptions();
-  assert(OpCode < Descriptions.size());
+  // Handle possible corrupted or unsupported operation.
+  if (OpCode >= Descriptions.size())
+    return {};
   return Descriptions[OpCode];
 }
 
@@ -117,8 +119,10 @@ bool DWARFExpression::Operation::extract
   Opcode = Data.getU8(&Offset);
 
   Desc = getOpDesc(Opcode);
-  if (Desc.Version == Operation::DwarfNA)
+  if (Desc.Version == Operation::DwarfNA) {
+    EndOffset = Offset;
     return false;
+  }
 
   for (unsigned Operand = 0; Operand < 2; ++Operand) {
     unsigned Size = Desc.Op[Operand];
@@ -221,7 +225,7 @@ bool DWARFExpression::Operation::print(r
                                        const MCRegisterInfo *RegInfo,
                                        bool isEH) {
   if (Error) {
-    OS << "decoding error.";
+    OS << "<decoding error>";
     return false;
   }
 

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp?rev=316756&r1=316755&r2=316756&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp Fri Oct 27 03:42:04 2017
@@ -13,9 +13,11 @@
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
 #include "llvm/DebugInfo/DWARF/DWARFSection.h"
 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/raw_ostream.h"
 #include <map>
 #include <set>
@@ -377,45 +379,55 @@ unsigned DWARFVerifier::verifyDieRanges(
 
 unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
                                                  DWARFAttribute &AttrValue) {
-  const DWARFObject &DObj = DCtx.getDWARFObj();
   unsigned NumErrors = 0;
+  auto ReportError = [&](const Twine &TitleMsg) {
+    ++NumErrors;
+    error() << TitleMsg << '\n';
+    Die.dump(OS, 0, DumpOpts);
+    OS << "\n";
+  };
+
+  const DWARFObject &DObj = DCtx.getDWARFObj();
   const auto Attr = AttrValue.Attr;
   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 >= DObj.getRangeSection().Data.size()) {
-        ++NumErrors;
-        error() << "DW_AT_ranges offset is beyond .debug_ranges "
-                   "bounds:\n";
-        Die.dump(OS, 0, DumpOpts);
-        OS << "\n";
-      }
-    } else {
-      ++NumErrors;
-      error() << "DIE has invalid DW_AT_ranges encoding:\n";
-      Die.dump(OS, 0, DumpOpts);
-      OS << "\n";
+      if (*SectionOffset >= DObj.getRangeSection().Data.size())
+        ReportError("DW_AT_ranges offset is beyond .debug_ranges bounds:");
+      break;
     }
+    ReportError("DIE has invalid DW_AT_ranges encoding:");
     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 >= DObj.getLineSection().Data.size()) {
-        ++NumErrors;
-        error() << "DW_AT_stmt_list offset is beyond .debug_line "
-                   "bounds: "
-                << format("0x%08" PRIx64, *SectionOffset) << "\n";
-        Die.dump(OS, 0, DumpOpts);
-        OS << "\n";
-      }
-    } else {
-      ++NumErrors;
-      error() << "DIE has invalid DW_AT_stmt_list encoding:\n";
-      Die.dump(OS, 0, DumpOpts);
-      OS << "\n";
+      if (*SectionOffset >= DObj.getLineSection().Data.size())
+        ReportError("DW_AT_stmt_list offset is beyond .debug_line bounds: " +
+                    llvm::formatv("{0:x16}", *SectionOffset));
+      break;
     }
+    ReportError("DIE has invalid DW_AT_stmt_list encoding:");
     break;
+  case DW_AT_location: {
+    Optional<ArrayRef<uint8_t>> Expr = AttrValue.Value.getAsBlock();
+    if (!Expr) {
+      ReportError("DIE has invalid DW_AT_location encoding:");
+      break;
+    }
+
+    DWARFUnit *U = Die.getDwarfUnit();
+    DataExtractor Data(
+        StringRef(reinterpret_cast<const char *>(Expr->data()), Expr->size()),
+        DCtx.isLittleEndian(), 0);
+    DWARFExpression Expression(Data, U->getVersion(), U->getAddressByteSize());
+    bool Error = llvm::any_of(Expression, [](DWARFExpression::Operation &Op) {
+      return Op.isError();
+    });
+    if (Error)
+      ReportError("DIE contains invalid DWARF expression:");
+    break;
+  }
 
   default:
     break;

Added: llvm/trunk/test/tools/llvm-dwarfdump/X86/verify_broken_exprloc.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-dwarfdump/X86/verify_broken_exprloc.s?rev=316756&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-dwarfdump/X86/verify_broken_exprloc.s (added)
+++ llvm/trunk/test/tools/llvm-dwarfdump/X86/verify_broken_exprloc.s Fri Oct 27 03:42:04 2017
@@ -0,0 +1,52 @@
+# RUN: llvm-mc %s -filetype obj -triple i686-pc-linux -o %t
+
+## Check we don't crash when parsing invalid expression opcode.
+# RUN: llvm-dwarfdump %t | FileCheck %s
+# CHECK:      DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:  DW_AT_location  (<decoding error>)
+
+## Check verifier reports an error.
+# RUN: not llvm-dwarfdump -verify %t 2>&1 | FileCheck %s --check-prefix=VERIFY
+# VERIFY:      DIE contains invalid DWARF expression:
+# VERIFY:      DW_TAG_GNU_call_site_parameter
+# VERIFY-NEXT:   DW_AT_location    (<decoding error>)
+
+.section  .debug_info,"", at progbits
+  .long  0x12
+  .value  0x4
+  .long  0
+  .byte  0x4
+
+  .uleb128 0x1 # DW_TAG_compile_unit [1]
+  .long  0
+  .byte  0x0
+
+  .uleb128 0x2  # DW_TAG_GNU_call_site_parameter [2]
+  .uleb128 0x1  # Expression size.
+  .byte  0xff   # Broken expression.
+
+  .byte  0      # End mark.
+  .byte  0      # End mark.
+
+.section .debug_abbrev,"", at progbits
+  .uleb128 0x1    # ID [1]
+  .uleb128 0x11   # DW_TAG_compile_unit, DW_CHILDREN_yes
+  .byte  0x1
+  .uleb128 0x25   # DW_AT_producer, DW_FORM_strp
+  .uleb128 0xe
+  .uleb128 0x13   # DW_AT_language, DW_FORM_data1
+  .uleb128 0xb
+  .byte  0
+  .byte  0
+
+  .uleb128 0x2    # ID [2]
+  .uleb128 0x410a # DW_TAG_GNU_call_site_parameter, DW_CHILDREN_no
+  .byte  0
+  .uleb128 0x2    # DW_AT_location, DW_FORM_exprloc
+  .uleb128 0x18
+  .byte  0
+  .byte  0
+  .byte  0
+
+.section .debug_str,"MS", at progbits,1
+.string "test"




More information about the llvm-commits mailing list