diff options
author | Wolfgang Pieb <Wolfgang.Pieb@sony.com> | 2018-06-20 22:56:37 +0000 |
---|---|---|
committer | Wolfgang Pieb <Wolfgang.Pieb@sony.com> | 2018-06-20 22:56:37 +0000 |
commit | 5a4174c5401ebc6f6d2576b751b45e374e3c9d37 (patch) | |
tree | 877398c8d06cd78966c7723ef5f236228a5c821c /lib/DebugInfo | |
parent | a5a4f60b04467710d4603dea6ebf4f7a36e32cc7 (diff) |
[DWARF] Improved error reporting for range lists.
Errors found processing the DW_AT_ranges attribute are propagated by lower level
routines and reported by their callers.
Reviewer: JDevlieghere
Differential Revision: https://reviews.llvm.org/D48344
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@335188 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/DebugInfo')
-rw-r--r-- | lib/DebugInfo/DWARF/DWARFContext.cpp | 7 | ||||
-rw-r--r-- | lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp | 23 | ||||
-rw-r--r-- | lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp | 10 | ||||
-rw-r--r-- | lib/DebugInfo/DWARF/DWARFDie.cpp | 28 | ||||
-rw-r--r-- | lib/DebugInfo/DWARF/DWARFUnit.cpp | 82 | ||||
-rw-r--r-- | lib/DebugInfo/DWARF/DWARFVerifier.cpp | 9 |
6 files changed, 108 insertions, 51 deletions
diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp index a4053a30536..2ac94d05bc6 100644 --- a/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -470,8 +470,13 @@ void DWARFContext::dump( isLittleEndian(), savedAddressByteSize); uint32_t offset = 0; DWARFDebugRangeList rangeList; - while (rangeList.extract(rangesData, &offset)) + while (rangesData.isValidOffset(offset)) { + if (Error E = rangeList.extract(rangesData, &offset)) { + WithColor::error() << toString(std::move(E)) << '\n'; + break; + } rangeList.dump(OS); + } } if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists, diff --git a/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp b/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp index 87a0fd366af..a565718debd 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp @@ -16,20 +16,30 @@ using namespace llvm; +// FIXME: There are several versions of this. Consolidate them. +template <typename... Ts> +static Error createError(char const *Fmt, const Ts &... Vals) { + std::string Buffer; + raw_string_ostream Stream(Buffer); + Stream << format(Fmt, Vals...); + return make_error<StringError>(Stream.str(), inconvertibleErrorCode()); +} + void DWARFDebugRangeList::clear() { Offset = -1U; AddressSize = 0; Entries.clear(); } -bool DWARFDebugRangeList::extract(const DWARFDataExtractor &data, - uint32_t *offset_ptr) { +Error DWARFDebugRangeList::extract(const DWARFDataExtractor &data, + uint32_t *offset_ptr) { clear(); if (!data.isValidOffset(*offset_ptr)) - return false; + return createError("invalid range list offset 0x%" PRIx32, *offset_ptr); + AddressSize = data.getAddressSize(); if (AddressSize != 4 && AddressSize != 8) - return false; + return createError("invalid address size: %d", AddressSize); Offset = *offset_ptr; while (true) { RangeListEntry Entry; @@ -43,13 +53,14 @@ bool DWARFDebugRangeList::extract(const DWARFDataExtractor &data, // Check that both values were extracted correctly. if (*offset_ptr != prev_offset + 2 * AddressSize) { clear(); - return false; + return createError("invalid range list entry at offset 0x%" PRIx32, + prev_offset); } if (Entry.isEndOfListEntry()) break; Entries.push_back(Entry); } - return true; + return Error::success(); } void DWARFDebugRangeList::dump(raw_ostream &OS) const { diff --git a/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp b/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp index 34359c0ef87..533b0922c1d 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp @@ -208,6 +208,8 @@ DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( Error DWARFDebugRnglist::extract(DWARFDataExtractor Data, uint32_t HeaderOffset, uint32_t End, uint32_t *OffsetPtr) { + if (*OffsetPtr < HeaderOffset || *OffsetPtr >= End) + return createError("invalid range list offset 0x%" PRIx32, *OffsetPtr); Entries.clear(); while (*OffsetPtr < End) { RangeListEntry Entry{0, 0, 0, 0, 0}; @@ -351,7 +353,7 @@ uint32_t DWARFDebugRnglistTable::length() const { return HeaderData.Length + sizeof(uint32_t); } -Optional<DWARFDebugRnglist> +Expected<DWARFDebugRnglist> DWARFDebugRnglistTable::findRangeList(DWARFDataExtractor Data, uint32_t Offset) { auto Entry = Ranges.find(Offset); @@ -362,10 +364,8 @@ DWARFDebugRnglistTable::findRangeList(DWARFDataExtractor Data, DWARFDebugRnglist RngList; uint32_t End = HeaderOffset + length(); uint32_t StartingOffset = Offset; - if (Error E = RngList.extract(Data, HeaderOffset, End, &Offset)) { - llvm::consumeError(std::move(E)); - return None; - } + if (Error E = RngList.extract(Data, HeaderOffset, End, &Offset)) + return std::move(E); Ranges[StartingOffset] = RngList; return RngList; } diff --git a/lib/DebugInfo/DWARF/DWARFDie.cpp b/lib/DebugInfo/DWARF/DWARFDie.cpp index a471d97d75d..0ef65c2b0b6 100644 --- a/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -270,8 +270,12 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, FV.setUValue(*RangeListOffset); FV.dump(OS, DumpOpts); } - dumpRanges(Obj, OS, Die.getAddressRanges(), U->getAddressByteSize(), - sizeof(BaseIndent) + Indent + 4, DumpOpts); + if (auto RangesOrError = Die.getAddressRanges()) + dumpRanges(Obj, OS, RangesOrError.get(), U->getAddressByteSize(), + sizeof(BaseIndent) + Indent + 4, DumpOpts); + else + WithColor::error() << "decoding address ranges: " + << toString(RangesOrError.takeError()) << '\n'; } OS << ")\n"; @@ -385,13 +389,13 @@ bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC, return false; } -DWARFAddressRangesVector DWARFDie::getAddressRanges() const { +Expected<DWARFAddressRangesVector> DWARFDie::getAddressRanges() const { if (isNULL()) return DWARFAddressRangesVector(); // Single range specified by low/high PC. uint64_t LowPC, HighPC, Index; if (getLowAndHighPC(LowPC, HighPC, Index)) - return {{LowPC, HighPC, Index}}; + return DWARFAddressRangesVector{{LowPC, HighPC, Index}}; Optional<DWARFFormValue> Value = find(DW_AT_ranges); if (Value) { @@ -407,8 +411,11 @@ void DWARFDie::collectChildrenAddressRanges( if (isNULL()) return; if (isSubprogramDIE()) { - const auto &DIERanges = getAddressRanges(); - Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end()); + if (auto DIERangesOrError = getAddressRanges()) + Ranges.insert(Ranges.end(), DIERangesOrError.get().begin(), + DIERangesOrError.get().end()); + else + llvm::consumeError(DIERangesOrError.takeError()); } for (auto Child : children()) @@ -416,10 +423,15 @@ void DWARFDie::collectChildrenAddressRanges( } bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const { - for (const auto &R : getAddressRanges()) { + auto RangesOrError = getAddressRanges(); + if (!RangesOrError) { + llvm::consumeError(RangesOrError.takeError()); + return false; + } + + for (const auto &R : RangesOrError.get()) if (R.LowPC <= Address && Address < R.HighPC) return true; - } return false; } diff --git a/lib/DebugInfo/DWARF/DWARFUnit.cpp b/lib/DebugInfo/DWARF/DWARFUnit.cpp index 260c5dc94c4..6b7970d426b 100644 --- a/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -181,8 +181,8 @@ parseRngListTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { return Table; } -bool DWARFUnit::extractRangeList(uint32_t RangeListOffset, - DWARFDebugRangeList &RangeList) const { +Error DWARFUnit::extractRangeList(uint32_t RangeListOffset, + DWARFDebugRangeList &RangeList) const { // Require that compile unit is extracted. assert(!DieArray.empty()); DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, @@ -397,26 +397,39 @@ void DWARFUnit::clearDIEs(bool KeepCUDie) { } } -DWARFAddressRangesVector DWARFUnit::findRnglistFromOffset(uint32_t Offset) { +Expected<DWARFAddressRangesVector> +DWARFUnit::findRnglistFromOffset(uint32_t Offset) { if (getVersion() <= 4) { DWARFDebugRangeList RangeList; - if (extractRangeList(Offset, RangeList)) - return RangeList.getAbsoluteRanges(getBaseAddress()); - return DWARFAddressRangesVector(); + if (Error E = extractRangeList(Offset, RangeList)) + return std::move(E); + return RangeList.getAbsoluteRanges(getBaseAddress()); } if (RngListTable) { DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, isLittleEndian, RngListTable->getAddrSize()); - if (auto RangeList = RngListTable->findRangeList(RangesData, Offset)) - return RangeList->getAbsoluteRanges(getBaseAddress()); + auto RangeListOrError = RngListTable->findRangeList(RangesData, Offset); + if (RangeListOrError) + return RangeListOrError.get().getAbsoluteRanges(getBaseAddress()); + return RangeListOrError.takeError(); } - return DWARFAddressRangesVector(); + + return make_error<StringError>("missing or invalid range list table", + inconvertibleErrorCode()); } -DWARFAddressRangesVector DWARFUnit::findRnglistFromIndex(uint32_t Index) { +Expected<DWARFAddressRangesVector> +DWARFUnit::findRnglistFromIndex(uint32_t Index) { if (auto Offset = getRnglistOffset(Index)) return findRnglistFromOffset(*Offset + RangeSectionBase); - return DWARFAddressRangesVector(); + + std::string Buffer; + raw_string_ostream Stream(Buffer); + if (RngListTable) + Stream << format("invalid range list table index %d", Index); + else + Stream << "missing or invalid range list table"; + return make_error<StringError>(Stream.str(), inconvertibleErrorCode()); } void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { @@ -424,11 +437,16 @@ void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { if (!UnitDie) return; // First, check if unit DIE describes address ranges for the whole unit. - const auto &CUDIERanges = UnitDie.getAddressRanges(); - if (!CUDIERanges.empty()) { - CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end()); - return; - } + auto CUDIERangesOrError = UnitDie.getAddressRanges(); + if (CUDIERangesOrError) { + if (!CUDIERangesOrError.get().empty()) { + CURanges.insert(CURanges.end(), CUDIERangesOrError.get().begin(), + CUDIERangesOrError.get().end()); + return; + } + } else + WithColor::error() << "decoding address ranges: " + << toString(CUDIERangesOrError.takeError()) << '\n'; // This function is usually called if there in no .debug_aranges section // in order to produce a compile unit level set of address ranges that @@ -454,21 +472,25 @@ void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { void DWARFUnit::updateAddressDieMap(DWARFDie Die) { if (Die.isSubroutineDIE()) { - for (const auto &R : Die.getAddressRanges()) { - // Ignore 0-sized ranges. - if (R.LowPC == R.HighPC) - continue; - auto B = AddrDieMap.upper_bound(R.LowPC); - if (B != AddrDieMap.begin() && R.LowPC < (--B)->second.first) { - // The range is a sub-range of existing ranges, we need to split the - // existing range. - if (R.HighPC < B->second.first) - AddrDieMap[R.HighPC] = B->second; - if (R.LowPC > B->first) - AddrDieMap[B->first].first = R.LowPC; + auto DIERangesOrError = Die.getAddressRanges(); + if (DIERangesOrError) { + for (const auto &R : DIERangesOrError.get()) { + // Ignore 0-sized ranges. + if (R.LowPC == R.HighPC) + continue; + auto B = AddrDieMap.upper_bound(R.LowPC); + if (B != AddrDieMap.begin() && R.LowPC < (--B)->second.first) { + // The range is a sub-range of existing ranges, we need to split the + // existing range. + if (R.HighPC < B->second.first) + AddrDieMap[R.HighPC] = B->second; + if (R.LowPC > B->first) + AddrDieMap[B->first].first = R.LowPC; + } + AddrDieMap[R.LowPC] = std::make_pair(R.HighPC, Die); } - AddrDieMap[R.LowPC] = std::make_pair(R.HighPC, Die); - } + } else + llvm::consumeError(DIERangesOrError.takeError()); } // Parent DIEs are added to the AddrDieMap prior to the Children DIEs to // simplify the logic to update AddrDieMap. The child's range will always diff --git a/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/lib/DebugInfo/DWARF/DWARFVerifier.cpp index e456de5b103..bb52f062d28 100644 --- a/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -324,8 +324,15 @@ unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die, if (!Die.isValid()) return NumErrors; - DWARFAddressRangesVector Ranges = Die.getAddressRanges(); + auto RangesOrError = Die.getAddressRanges(); + if (!RangesOrError) { + // FIXME: Report the error. + ++NumErrors; + llvm::consumeError(RangesOrError.takeError()); + return NumErrors; + } + DWARFAddressRangesVector Ranges = RangesOrError.get(); // Build RI for this DIE and check that ranges within this DIE do not // overlap. DieRangeInfo RI(Die); |