summaryrefslogtreecommitdiff
path: root/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp')
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp80
1 files changed, 33 insertions, 47 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index 7673a721c4ea..6424c2f59844 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -390,6 +390,9 @@ bool DWARFVerifier::handleDebugInfo() {
OS << "Verifying non-dwo Units...\n";
NumErrors += verifyUnits(DCtx.getNormalUnitsVector());
+
+ OS << "Verifying dwo Units...\n";
+ NumErrors += verifyUnits(DCtx.getDWOUnitsVector());
return NumErrors == 0;
}
@@ -400,10 +403,13 @@ unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die,
if (!Die.isValid())
return NumErrors;
+ DWARFUnit *Unit = Die.getDwarfUnit();
+
auto RangesOrError = Die.getAddressRanges();
if (!RangesOrError) {
// FIXME: Report the error.
- ++NumErrors;
+ if (!Unit->isDWOUnit())
+ ++NumErrors;
llvm::consumeError(RangesOrError.takeError());
return NumErrors;
}
@@ -496,15 +502,18 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
};
const DWARFObject &DObj = DCtx.getDWARFObj();
+ DWARFUnit *U = Die.getDwarfUnit();
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()) {
- unsigned DwarfVersion = Die.getDwarfUnit()->getVersion();
+ unsigned DwarfVersion = U->getVersion();
const DWARFSection &RangeSection = DwarfVersion < 5
? DObj.getRangesSection()
: DObj.getRnglistsSection();
+ if (U->isDWOUnit() && RangeSection.Data.empty())
+ break;
if (*SectionOffset >= RangeSection.Data.size())
ReportError(
"DW_AT_ranges offset is beyond " +
@@ -517,7 +526,7 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
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())
+ if (*SectionOffset >= U->getLineSection().Data.size())
ReportError("DW_AT_stmt_list offset is beyond .debug_line bounds: " +
llvm::formatv("{0:x8}", *SectionOffset));
break;
@@ -525,9 +534,18 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
ReportError("DIE has invalid DW_AT_stmt_list encoding:");
break;
case DW_AT_location: {
+ // FIXME: It might be nice if there's a way to walk location expressions
+ // without trying to resolve the address ranges - it'd be a more efficient
+ // API (since the API is currently unnecessarily resolving addresses for
+ // this use case which only wants to validate the expressions themselves) &
+ // then the expressions could be validated even if the addresses can't be
+ // resolved.
+ // That sort of API would probably look like a callback "for each
+ // expression" with some way to lazily resolve the address ranges when
+ // needed (& then the existing API used here could be built on top of that -
+ // using the callback API to build the data structure and return it).
if (Expected<std::vector<DWARFLocationExpression>> Loc =
Die.getLocations(DW_AT_location)) {
- DWARFUnit *U = Die.getDwarfUnit();
for (const auto &Entry : *Loc) {
DataExtractor Data(toStringRef(Entry.Expr), DCtx.isLittleEndian(), 0);
DWARFExpression Expression(Data, U->getAddressByteSize(),
@@ -539,8 +557,12 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
if (Error || !Expression.verify(U))
ReportError("DIE contains invalid DWARF expression:");
}
- } else
- ReportError(toString(Loc.takeError()));
+ } else if (Error Err = handleErrors(
+ Loc.takeError(), [&](std::unique_ptr<ResolverError> E) {
+ return U->isDWOUnit() ? Error::success()
+ : Error(std::move(E));
+ }))
+ ReportError(toString(std::move(Err)));
break;
}
case DW_AT_specification:
@@ -576,7 +598,8 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
case DW_AT_call_file:
case DW_AT_decl_file: {
if (auto FileIdx = AttrValue.Value.getAsUnsignedConstant()) {
- DWARFUnit *U = Die.getDwarfUnit();
+ if (U->isDWOUnit() && !U->isTypeUnit())
+ break;
const auto *LT = U->getContext().getLineTableForUnit(U);
if (LT) {
if (!LT->hasFileAtIndex(*FileIdx)) {
@@ -616,7 +639,6 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
DWARFAttribute &AttrValue,
ReferenceMap &LocalReferences,
ReferenceMap &CrossUnitReferences) {
- const DWARFObject &DObj = DCtx.getDWARFObj();
auto DieCU = Die.getDwarfUnit();
unsigned NumErrors = 0;
const auto Form = AttrValue.Value.getForm();
@@ -667,51 +689,15 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
}
break;
}
- case DW_FORM_strp: {
- auto SecOffset = AttrValue.Value.getAsSectionOffset();
- assert(SecOffset); // DW_FORM_strp is a section offset.
- if (SecOffset && *SecOffset >= DObj.getStrSection().size()) {
- ++NumErrors;
- error() << "DW_FORM_strp offset beyond .debug_str bounds:\n";
- dump(Die) << '\n';
- }
- break;
- }
+ case DW_FORM_strp:
case DW_FORM_strx:
case DW_FORM_strx1:
case DW_FORM_strx2:
case DW_FORM_strx3:
case DW_FORM_strx4: {
- auto Index = AttrValue.Value.getRawUValue();
- auto DieCU = Die.getDwarfUnit();
- // Check that we have a valid DWARF v5 string offsets table.
- if (!DieCU->getStringOffsetsTableContribution()) {
- ++NumErrors;
- error() << FormEncodingString(Form)
- << " used without a valid string offsets table:\n";
- dump(Die) << '\n';
- break;
- }
- // Check that the index is within the bounds of the section.
- unsigned ItemSize = DieCU->getDwarfStringOffsetsByteSize();
- // Use a 64-bit type to calculate the offset to guard against overflow.
- uint64_t Offset =
- (uint64_t)DieCU->getStringOffsetsBase() + Index * ItemSize;
- if (DObj.getStrOffsetsSection().Data.size() < Offset + ItemSize) {
- ++NumErrors;
- error() << FormEncodingString(Form) << " uses index "
- << format("%" PRIu64, Index) << ", which is too large:\n";
- dump(Die) << '\n';
- break;
- }
- // Check that the string offset is valid.
- uint64_t StringOffset = *DieCU->getStringOffsetSectionItem(Index);
- if (StringOffset >= DObj.getStrSection().size()) {
+ if (Error E = AttrValue.Value.getAsCString().takeError()) {
++NumErrors;
- error() << FormEncodingString(Form) << " uses index "
- << format("%" PRIu64, Index)
- << ", but the referenced string"
- " offset is beyond .debug_str bounds:\n";
+ error() << toString(std::move(E)) << ":\n";
dump(Die) << '\n';
}
break;