aboutsummaryrefslogtreecommitdiff
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.cpp82
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: