[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