diff options
Diffstat (limited to 'llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp')
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp | 82 |
1 files changed, 48 insertions, 34 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp index 1fd6c1d7d282..3a83317a73a3 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -26,24 +26,26 @@ using namespace llvm; using namespace dwarf; using namespace object; -DWARFVerifier::DieRangeInfo::address_range_iterator +Optional<DWARFAddressRange> DWARFVerifier::DieRangeInfo::insert(const DWARFAddressRange &R) { auto Begin = Ranges.begin(); auto End = Ranges.end(); auto Pos = std::lower_bound(Begin, End, R); if (Pos != End) { - if (Pos->intersects(R)) - return std::move(Pos); - if (Pos != Begin) { - auto Iter = Pos - 1; - if (Iter->intersects(R)) - return std::move(Iter); - } + DWARFAddressRange Range(*Pos); + if (Pos->merge(R)) + return Range; + } + if (Pos != Begin) { + auto Iter = Pos - 1; + DWARFAddressRange Range(*Iter); + if (Iter->merge(R)) + return Range; } Ranges.insert(Pos, R); - return Ranges.end(); + return None; } DWARFVerifier::DieRangeInfo::die_range_info_iterator @@ -112,11 +114,9 @@ bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData, bool ValidAbbrevOffset = true; uint64_t OffsetStart = *Offset; - Length = DebugInfoData.getU32(Offset); - if (Length == dwarf::DW_LENGTH_DWARF64) { - Length = DebugInfoData.getU64(Offset); - isUnitDWARF64 = true; - } + DwarfFormat Format; + std::tie(Length, Format) = DebugInfoData.getInitialLength(Offset); + isUnitDWARF64 = Format == DWARF64; Version = DebugInfoData.getU16(Offset); if (Version >= 5) { @@ -135,7 +135,7 @@ bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData, ValidLength = DebugInfoData.isValidOffset(OffsetStart + Length + 3); ValidVersion = DWARFContext::isSupportedVersion(Version); - ValidAddrSize = AddrSize == 4 || AddrSize == 8; + ValidAddrSize = DWARFContext::isAddressSizeSupported(AddrSize); if (!ValidLength || !ValidVersion || !ValidAddrSize || !ValidAbbrevOffset || !ValidType) { Success = false; @@ -307,7 +307,7 @@ unsigned DWARFVerifier::verifyUnitSection(const DWARFSection &S, Unit = TypeUnitVector.addUnit(std::make_unique<DWARFTypeUnit>( DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangesSection(), &DObj.getLocSection(), DObj.getStrSection(), - DObj.getStrOffsetsSection(), &DObj.getAppleObjCSection(), + DObj.getStrOffsetsSection(), &DObj.getAddrSection(), DObj.getLineSection(), DCtx.isLittleEndian(), false, TypeUnitVector)); break; @@ -321,7 +321,7 @@ unsigned DWARFVerifier::verifyUnitSection(const DWARFSection &S, Unit = CompileUnitVector.addUnit(std::make_unique<DWARFCompileUnit>( DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangesSection(), &DObj.getLocSection(), DObj.getStrSection(), - DObj.getStrOffsetsSection(), &DObj.getAppleObjCSection(), + DObj.getStrOffsetsSection(), &DObj.getAddrSection(), DObj.getLineSection(), DCtx.isLittleEndian(), false, CompileUnitVector)); break; @@ -354,7 +354,7 @@ bool DWARFVerifier::handleDebugInfo() { OS << "Verifying .debug_types Unit Header Chain...\n"; DObj.forEachTypesSections([&](const DWARFSection &S) { - NumErrors += verifyUnitSection(S, DW_SECT_TYPES); + NumErrors += verifyUnitSection(S, DW_SECT_EXT_TYPES); }); return NumErrors == 0; } @@ -399,22 +399,30 @@ unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die, // processing an object file. if (!IsObjectFile || IsMachOObject || Die.getTag() != DW_TAG_compile_unit) { + bool DumpDieAfterError = false; for (auto Range : Ranges) { if (!Range.valid()) { ++NumErrors; error() << "Invalid address range " << Range << "\n"; + DumpDieAfterError = true; continue; } - // Verify that ranges don't intersect. - const auto IntersectingRange = RI.insert(Range); - if (IntersectingRange != RI.Ranges.end()) { + // Verify that ranges don't intersect and also build up the DieRangeInfo + // address ranges. Don't break out of the loop below early, or we will + // think this DIE doesn't have all of the address ranges it is supposed + // to have. Compile units often have DW_AT_ranges that can contain one or + // more dead stripped address ranges which tend to all be at the same + // address: 0 or -1. + if (auto PrevRange = RI.insert(Range)) { ++NumErrors; - error() << "DIE has overlapping address ranges: " << Range << " and " - << *IntersectingRange << "\n"; - break; + error() << "DIE has overlapping ranges in DW_AT_ranges attribute: " + << *PrevRange << " and " << Range << '\n'; + DumpDieAfterError = true; } } + if (DumpDieAfterError) + dump(Die, 2) << '\n'; } // Verify that children don't intersect. @@ -459,8 +467,15 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die, 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.getRangesSection().Data.size()) - ReportError("DW_AT_ranges offset is beyond .debug_ranges bounds:"); + unsigned DwarfVersion = Die.getDwarfUnit()->getVersion(); + const DWARFSection &RangeSection = DwarfVersion < 5 + ? DObj.getRangesSection() + : DObj.getRnglistsSection(); + if (*SectionOffset >= RangeSection.Data.size()) + ReportError( + "DW_AT_ranges offset is beyond " + + StringRef(DwarfVersion < 5 ? ".debug_ranges" : ".debug_rnglists") + + " bounds: " + llvm::formatv("{0:x8}", *SectionOffset)); break; } ReportError("DIE has invalid DW_AT_ranges encoding:"); @@ -481,8 +496,8 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die, DWARFUnit *U = Die.getDwarfUnit(); for (const auto &Entry : *Loc) { DataExtractor Data(toStringRef(Entry.Expr), DCtx.isLittleEndian(), 0); - DWARFExpression Expression(Data, U->getVersion(), - U->getAddressByteSize()); + DWARFExpression Expression(Data, U->getAddressByteSize(), + U->getFormParams().Format); bool Error = any_of(Expression, [](DWARFExpression::Operation &Op) { return Op.isError(); }); @@ -758,7 +773,7 @@ void DWARFVerifier::verifyDebugLineRows() { << "] row[" << RowIndex << "] decreases in address from previous row:\n"; - DWARFDebugLine::Row::dumpTableHeader(OS); + DWARFDebugLine::Row::dumpTableHeader(OS, 0); if (RowIndex > 0) LineTable->Rows[RowIndex - 1].dump(OS); Row.dump(OS); @@ -776,7 +791,7 @@ void DWARFVerifier::verifyDebugLineRows() { << " (valid values are [" << (isDWARF5 ? "0," : "1,") << LineTable->Prologue.FileNames.size() << (isDWARF5 ? ")" : "]") << "):\n"; - DWARFDebugLine::Row::dumpTableHeader(OS); + DWARFDebugLine::Row::dumpTableHeader(OS, 0); Row.dump(OS); OS << '\n'; } @@ -1290,7 +1305,8 @@ static bool isVariableIndexable(const DWARFDie &Die, DWARFContext &DCtx) { for (const auto &Entry : *Loc) { DataExtractor Data(toStringRef(Entry.Expr), DCtx.isLittleEndian(), U->getAddressByteSize()); - DWARFExpression Expression(Data, U->getVersion(), U->getAddressByteSize()); + DWARFExpression Expression(Data, U->getAddressByteSize(), + U->getFormParams().Format); bool IsInteresting = any_of(Expression, [](DWARFExpression::Operation &Op) { return !Op.isError() && (Op.getCode() == DW_OP_addr || Op.getCode() == DW_OP_form_tls_address || @@ -1330,9 +1346,7 @@ unsigned DWARFVerifier::verifyNameIndexCompleteness( // "The name index must contain an entry for each debugging information entry // that defines a named subprogram, label, variable, type, or namespace, // subject to ..." - // Instead whitelisting all TAGs representing a "type" or a "subprogram", to - // make sure we catch any missing items, we instead blacklist all TAGs that we - // know shouldn't be indexed. + // Explicitly exclude all TAGs that we know shouldn't be indexed. switch (Die.getTag()) { // Compile units and modules have names but shouldn't be indexed. case DW_TAG_compile_unit: |