diff options
author | Pavel Labath <labath@google.com> | 2018-03-08 15:34:42 +0000 |
---|---|---|
committer | Pavel Labath <labath@google.com> | 2018-03-08 15:34:42 +0000 |
commit | b136c3934e1ec2d5c955ceedaa9c178fd6f80bf5 (patch) | |
tree | 9c453668d194983f4a3063355b23bbdd1b7611f3 /llvm/lib/DebugInfo | |
parent | 7bbac07f22b82aa8b580624996e11489c4083a8c (diff) | |
download | bcm5719-llvm-b136c3934e1ec2d5c955ceedaa9c178fd6f80bf5.tar.gz bcm5719-llvm-b136c3934e1ec2d5c955ceedaa9c178fd6f80bf5.zip |
DWARFVerifier: Basic verification of .debug_names
Summary:
This patch adds basic .debug_names verification capabilities to the
DWARF verifier. Right now, it checks that the headers and abbreviation
tables of the individual name indexes can be parsed correctly, it
verifies the buckets table and the cross-checks the CU lists for
consistency. I intend to add further checks in follow-up patches.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: vleschuk, echristo, clayborg, llvm-commits
Differential Revision: https://reviews.llvm.org/D44211
llvm-svn: 327011
Diffstat (limited to 'llvm/lib/DebugInfo')
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp index bfc06752363..171ff637e1f 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -778,6 +778,90 @@ unsigned DWARFVerifier::verifyAppleAccelTable(const DWARFSection *AccelSection, return NumErrors; } +unsigned +DWARFVerifier::verifyDebugNamesCULists(const DWARFDebugNames &AccelTable) { + // A map from CU offset to the (first) Name Index offset which claims to index + // this CU. + DenseMap<uint32_t, uint32_t> CUMap; + const uint32_t NotIndexed = std::numeric_limits<uint32_t>::max(); + + CUMap.reserve(DCtx.getNumCompileUnits()); + for (const auto &CU : DCtx.compile_units()) + CUMap[CU->getOffset()] = NotIndexed; + + unsigned NumErrors = 0; + for (const DWARFDebugNames::NameIndex &NI : AccelTable) { + if (NI.getCUCount() == 0) { + error() << formatv("Name Index @ {0:x} does not index any CU\n", + NI.getUnitOffset()); + ++NumErrors; + continue; + } + for (uint32_t CU = 0, End = NI.getCUCount(); CU < End; ++CU) { + uint32_t Offset = NI.getCUOffset(CU); + auto Iter = CUMap.find(Offset); + + if (Iter == CUMap.end()) { + error() << formatv( + "Name Index @ {0:x} references a non-existing CU @ {1:x}\n", + NI.getUnitOffset(), Offset); + ++NumErrors; + continue; + } + + if (Iter->second != NotIndexed) { + error() << formatv("Name Index @ {0:x} references a CU @ {1:x}, but " + "this CU is already indexed by Name Index @ {2:x}\n", + NI.getUnitOffset(), Offset, Iter->second); + continue; + } + Iter->second = NI.getUnitOffset(); + } + } + + for (const auto &KV : CUMap) { + if (KV.second == NotIndexed) + warn() << formatv("CU @ {0:x} not covered by any Name Index\n", KV.first); + } + + return NumErrors; +} + +unsigned DWARFVerifier::verifyDebugNames(const DWARFSection &AccelSection, + const DataExtractor &StrData) { + unsigned NumErrors = 0; + DWARFDataExtractor AccelSectionData(DCtx.getDWARFObj(), AccelSection, + DCtx.isLittleEndian(), 0); + DWARFDebugNames AccelTable(AccelSectionData, StrData); + + OS << "Verifying .debug_names...\n"; + + // This verifies that we can read individual name indices and their + // abbreviation tables. + if (Error E = AccelTable.extract()) { + error() << toString(std::move(E)) << '\n'; + return 1; + } + + NumErrors += verifyDebugNamesCULists(AccelTable); + + for (const DWARFDebugNames::NameIndex &NI : AccelTable) { + for (uint32_t Bucket = 0, End = NI.getBucketCount(); Bucket < End; + ++Bucket) { + uint32_t Index = NI.getBucketArrayEntry(Bucket); + if (Index > NI.getNameCount()) { + error() << formatv("Bucket {0} of Name Index @ {1:x} contains invalid " + "value {2}. Valid range is [0, {3}].\n", + Bucket, NI.getUnitOffset(), Index, + NI.getNameCount()); + ++NumErrors; + } + } + } + + return NumErrors; +} + bool DWARFVerifier::handleAccelTables() { const DWARFObject &D = DCtx.getDWARFObj(); DataExtractor StrData(D.getStringSection(), DCtx.isLittleEndian(), 0); @@ -794,6 +878,9 @@ bool DWARFVerifier::handleAccelTables() { if (!D.getAppleObjCSection().Data.empty()) NumErrors += verifyAppleAccelTable(&D.getAppleObjCSection(), &StrData, ".apple_objc"); + + if (!D.getDebugNamesSection().Data.empty()) + NumErrors += verifyDebugNames(D.getDebugNamesSection(), StrData); return NumErrors == 0; } |