summaryrefslogtreecommitdiff
path: root/lib/DebugInfo
diff options
context:
space:
mode:
authorGeorge Rimar <grimar@accesssoftek.com>2017-10-27 10:42:04 +0000
committerGeorge Rimar <grimar@accesssoftek.com>2017-10-27 10:42:04 +0000
commit603d7b305534c6a358836deff41d6beeb7f1a65d (patch)
treee9b991090bb788f83ebb71c7ead3259d0f82c607 /lib/DebugInfo
parentaa108d865d3062361edbe9c662af43accd8456d8 (diff)
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@316756 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/DebugInfo')
-rw-r--r--lib/DebugInfo/DWARF/DWARFExpression.cpp10
-rw-r--r--lib/DebugInfo/DWARF/DWARFVerifier.cpp64
2 files changed, 45 insertions, 29 deletions
diff --git a/lib/DebugInfo/DWARF/DWARFExpression.cpp b/lib/DebugInfo/DWARF/DWARFExpression.cpp
index 3417fee14c0..16058e461f4 100644
--- a/lib/DebugInfo/DWARF/DWARFExpression.cpp
+++ b/lib/DebugInfo/DWARF/DWARFExpression.cpp
@@ -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(DataExtractor Data, uint16_t Version,
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(raw_ostream &OS,
const MCRegisterInfo *RegInfo,
bool isEH) {
if (Error) {
- OS << "decoding error.";
+ OS << "<decoding error>";
return false;
}
diff --git a/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index b10697c9a31..f27c849456b 100644
--- a/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -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(const DWARFDie &Die,
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;