Skip to content

Commit

Permalink
[dwarfdump] Verify compatibility of attribute TAGs.
Browse files Browse the repository at this point in the history
Verify that DW_AT_specification and DW_AT_abstract_origin reference a
DIE with a compatible tag.

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

llvm-svn: 342712
  • Loading branch information
JDevlieghere committed Sep 21, 2018
1 parent b6eb21c commit 7ef2c20
Show file tree
Hide file tree
Showing 4 changed files with 424 additions and 7 deletions.
4 changes: 4 additions & 0 deletions llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
Expand Up @@ -134,6 +134,10 @@ class DWARFUnitVector final : public SmallVector<std::unique_ptr<DWARFUnit>, 1>
void addUnitsForDWOSection(DWARFContext &C, const DWARFSection &DWOSection,
DWARFSectionKind SectionKind, bool Lazy = false);

/// Add an existing DWARFUnit to this UnitVector. This is used by the DWARF
/// verifier to process unit separately.
DWARFUnit *addUnit(std::unique_ptr<DWARFUnit> Unit);

/// Returns number of all units held by this instance.
unsigned getNumUnits() const { return size(); }
/// Returns number of units from all .debug_info[.dwo] sections.
Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
Expand Up @@ -112,6 +112,15 @@ void DWARFUnitVector::addUnitsImpl(
}
}

DWARFUnit *DWARFUnitVector::addUnit(std::unique_ptr<DWARFUnit> Unit) {
auto I = std::upper_bound(begin(), end(), Unit,
[](const std::unique_ptr<DWARFUnit> &LHS,
const std::unique_ptr<DWARFUnit> &RHS) {
return LHS->getOffset() < RHS->getOffset();
});
return this->insert(I, std::move(Unit))->get();
}

DWARFUnit *DWARFUnitVector::getUnitForOffset(uint32_t Offset) const {
auto end = begin() + getNumInfoUnits();
auto *CU =
Expand Down
32 changes: 25 additions & 7 deletions llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
Expand Up @@ -261,7 +261,8 @@ unsigned DWARFVerifier::verifyUnitSection(const DWARFSection &S,
bool isUnitDWARF64 = false;
bool isHeaderChainValid = true;
bool hasDIE = DebugInfoData.isValidOffset(Offset);
DWARFUnitVector UnitVector{};
DWARFUnitVector TypeUnitVector;
DWARFUnitVector CompileUnitVector;
while (hasDIE) {
OffsetStart = Offset;
if (!verifyUnitHeader(DebugInfoData, &Offset, UnitIdx, UnitType,
Expand All @@ -272,15 +273,15 @@ unsigned DWARFVerifier::verifyUnitSection(const DWARFSection &S,
} else {
DWARFUnitHeader Header;
Header.extract(DCtx, DebugInfoData, &OffsetStart, SectionKind);
std::unique_ptr<DWARFUnit> Unit;
DWARFUnit *Unit;
switch (UnitType) {
case dwarf::DW_UT_type:
case dwarf::DW_UT_split_type: {
Unit.reset(new DWARFTypeUnit(
Unit = TypeUnitVector.addUnit(llvm::make_unique<DWARFTypeUnit>(
DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangeSection(),
DObj.getStringSection(), DObj.getStringOffsetSection(),
&DObj.getAppleObjCSection(), DObj.getLineSection(),
DCtx.isLittleEndian(), false, UnitVector));
DCtx.isLittleEndian(), false, TypeUnitVector));
break;
}
case dwarf::DW_UT_skeleton:
Expand All @@ -289,11 +290,11 @@ unsigned DWARFVerifier::verifyUnitSection(const DWARFSection &S,
case dwarf::DW_UT_partial:
// UnitType = 0 means that we are verifying a compile unit in DWARF v4.
case 0: {
Unit.reset(new DWARFCompileUnit(
Unit = CompileUnitVector.addUnit(llvm::make_unique<DWARFCompileUnit>(
DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangeSection(),
DObj.getStringSection(), DObj.getStringOffsetSection(),
&DObj.getAppleObjCSection(), DObj.getLineSection(),
DCtx.isLittleEndian(), false, UnitVector));
DCtx.isLittleEndian(), false, CompileUnitVector));
break;
}
default: { llvm_unreachable("Invalid UnitType."); }
Expand Down Expand Up @@ -444,7 +445,24 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
}
break;
}

case DW_AT_specification:
case DW_AT_abstract_origin: {
if (auto ReferencedDie = Die.getAttributeValueAsReferencedDie(Attr)) {
auto DieTag = Die.getTag();
auto RefTag = ReferencedDie.getTag();
if (DieTag == RefTag)
break;
if (DieTag == DW_TAG_inlined_subroutine && RefTag == DW_TAG_subprogram)
break;
if (DieTag == DW_TAG_variable && RefTag == DW_TAG_member)
break;
ReportError("DIE with tag " + TagString(DieTag) + " has " +
AttributeString(Attr) +
" that points to DIE with "
"incompatible tag " +
TagString(RefTag));
}
}
default:
break;
}
Expand Down

0 comments on commit 7ef2c20

Please sign in to comment.