summaryrefslogtreecommitdiffstats
path: root/llvm/lib/DebugInfo
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/DebugInfo')
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp139
1 files changed, 135 insertions, 4 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index 87b7be1eb84..9fd6463ba46 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -24,6 +24,83 @@ using namespace llvm;
using namespace dwarf;
using namespace object;
+DWARFVerifier::DieRangeInfo::address_range_iterator
+DWARFVerifier::DieRangeInfo::insert(const DWARFAddressRange &R) {
+ const auto Begin = Ranges.cbegin();
+ const auto End = Ranges.cend();
+ auto Pos = std::lower_bound(Begin, End, R);
+
+ if (Pos != End) {
+ if (Pos->intersects(R))
+ return Pos;
+ if (Pos != Begin) {
+ auto Iter = Pos - 1;
+ if (Iter->intersects(R))
+ return Iter;
+ }
+ }
+
+ Ranges.insert(Pos, R);
+ return Ranges.cend();
+}
+
+DWARFVerifier::DieRangeInfo::die_range_info_iterator
+DWARFVerifier::DieRangeInfo::insert(const DieRangeInfo &RI) {
+ const auto End = Children.end();
+ auto Iter = Children.begin();
+ while (Iter != End) {
+ if (Iter->intersects(RI))
+ return Iter;
+ ++Iter;
+ }
+ Children.insert(RI);
+ return Children.cend();
+}
+
+bool DWARFVerifier::DieRangeInfo::contains(const DieRangeInfo &RHS) const {
+ // Both list of ranges are sorted so we can make this fast.
+
+ if (Ranges.empty() || RHS.Ranges.empty())
+ return false;
+
+ // Since the ranges are sorted we can advance where we start searching with
+ // this object's ranges as we traverse RHS.Ranges.
+ const auto End = Ranges.cend();
+ auto Iter = findRange(RHS.Ranges.front());
+
+ // Now linearly walk the ranges in this object and see if they contain each
+ // ranges from RHS.Ranges.
+ for (const auto &R : RHS.Ranges) {
+ while (Iter != End) {
+ if (Iter->contains(R))
+ break;
+ ++Iter;
+ }
+ if (Iter == End)
+ return false;
+ }
+ return true;
+}
+
+bool DWARFVerifier::DieRangeInfo::intersects(const DieRangeInfo &RHS) const {
+ if (Ranges.empty() || RHS.Ranges.empty())
+ return false;
+
+ const auto End = Ranges.end();
+ auto Iter = findRange(RHS.Ranges.front());
+ for (const auto &R : RHS.Ranges) {
+ if (R.HighPC <= Iter->LowPC)
+ continue;
+ while (Iter != End) {
+ if (Iter->intersects(R))
+ return true;
+ ++Iter;
+ }
+ }
+
+ return false;
+}
+
bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
uint32_t *Offset, unsigned UnitIndex,
uint8_t &UnitType, bool &isUnitDWARF64) {
@@ -94,12 +171,15 @@ bool DWARFVerifier::verifyUnitContents(DWARFUnit Unit) {
auto Die = Unit.getDIEAtIndex(I);
if (Die.getTag() == DW_TAG_null)
continue;
- NumUnitErrors += verifyDieRanges(Die);
for (auto AttrValue : Die.attributes()) {
NumUnitErrors += verifyDebugInfoAttribute(Die, AttrValue);
NumUnitErrors += verifyDebugInfoForm(Die, AttrValue);
}
}
+
+ DieRangeInfo RI;
+ DWARFDie Die = Unit.getUnitDIE(/* ExtractUnitDIEOnly = */ false);
+ NumUnitErrors += verifyDieRanges(Die, RI);
return NumUnitErrors == 0;
}
@@ -210,16 +290,67 @@ bool DWARFVerifier::handleDebugInfo() {
return (isHeaderChainValid && NumDebugInfoErrors == 0);
}
-unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die) {
+unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die,
+ DieRangeInfo &ParentRI) {
unsigned NumErrors = 0;
- for (auto Range : Die.getAddressRanges()) {
- if (Range.LowPC >= Range.HighPC) {
+
+ if (!Die.isValid())
+ return NumErrors;
+
+ DWARFAddressRangesVector Ranges = Die.getAddressRanges();
+
+ // Build RI for this DIE and check that ranges within this DIE do not
+ // overlap.
+ DieRangeInfo RI(Die);
+ for (auto Range : Ranges) {
+ if (!Range.valid()) {
++NumErrors;
OS << format("error: Invalid address range [0x%08" PRIx64
" - 0x%08" PRIx64 "].\n",
Range.LowPC, Range.HighPC);
+ continue;
+ }
+
+ // Verify that ranges don't intersect.
+ const auto IntersectingRange = RI.insert(Range);
+ if (IntersectingRange != RI.Ranges.cend()) {
+ ++NumErrors;
+ OS << format("error: DIE has overlapping address ranges: [0x%08" PRIx64
+ " - 0x%08" PRIx64 "] and [0x%08" PRIx64 " - 0x%08" PRIx64
+ "].\n",
+ Range.LowPC, Range.HighPC, IntersectingRange->LowPC,
+ IntersectingRange->HighPC);
+ break;
}
}
+
+ // Verify that children don't intersect.
+ const auto IntersectingChild = ParentRI.insert(RI);
+ if (IntersectingChild != ParentRI.Children.cend()) {
+ ++NumErrors;
+ OS << "error: DIEs have overlapping address ranges:";
+ Die.dump(OS, 0);
+ IntersectingChild->Die.dump(OS, 0);
+ OS << "\n";
+ }
+
+ // Verify that ranges are contained within their parent.
+ bool ShouldBeContained = !Ranges.empty() && !ParentRI.Ranges.empty() &&
+ !(Die.getTag() == DW_TAG_subprogram &&
+ ParentRI.Die.getTag() == DW_TAG_subprogram);
+ if (ShouldBeContained && !ParentRI.contains(RI)) {
+ ++NumErrors;
+ OS << "error: DIE address ranges are not "
+ "contained in its parent's ranges:";
+ Die.dump(OS, 0);
+ ParentRI.Die.dump(OS, 0);
+ OS << "\n";
+ }
+
+ // Recursively check children.
+ for (DWARFDie Child : Die)
+ NumErrors += verifyDieRanges(Child, RI);
+
return NumErrors;
}
OpenPOWER on IntegriCloud