summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWolfgang Pieb <Wolfgang.Pieb@sony.com>2018-06-20 22:56:37 +0000
committerWolfgang Pieb <Wolfgang.Pieb@sony.com>2018-06-20 22:56:37 +0000
commit5a4174c5401ebc6f6d2576b751b45e374e3c9d37 (patch)
tree877398c8d06cd78966c7723ef5f236228a5c821c
parenta5a4f60b04467710d4603dea6ebf4f7a36e32cc7 (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
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDie.h2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFUnit.h15
-rw-r--r--lib/DebugInfo/DWARF/DWARFContext.cpp7
-rw-r--r--lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp23
-rw-r--r--lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp10
-rw-r--r--lib/DebugInfo/DWARF/DWARFDie.cpp28
-rw-r--r--lib/DebugInfo/DWARF/DWARFUnit.cpp82
-rw-r--r--lib/DebugInfo/DWARF/DWARFVerifier.cpp9
-rw-r--r--test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s39
-rw-r--r--test/DebugInfo/X86/dwarfdump-rnglists.s19
-rw-r--r--tools/dsymutil/DwarfLinker.cpp6
-rw-r--r--tools/llvm-dwarfdump/Statistics.cpp18
14 files changed, 194 insertions, 68 deletions
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
index 38b7f225e77..ce7436d9faa 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
@@ -71,7 +71,7 @@ public:
void clear();
void dump(raw_ostream &OS) const;
- bool extract(const DWARFDataExtractor &data, uint32_t *offset_ptr);
+ Error extract(const DWARFDataExtractor &data, uint32_t *offset_ptr);
const std::vector<RangeListEntry> &getEntries() { return Entries; }
/// getAbsoluteRanges - Returns absolute address ranges defined by this range
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h b/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h
index 49bea290e43..5dd1cca3ce4 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h
@@ -97,7 +97,7 @@ public:
Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr);
/// Look up a rangelist based on a given offset. Extract it and enter it into
/// the ranges map if necessary.
- Optional<DWARFDebugRnglist> findRangeList(DWARFDataExtractor Data,
+ Expected<DWARFDebugRnglist> findRangeList(DWARFDataExtractor Data,
uint32_t Offset);
uint32_t getHeaderOffset() const { return HeaderOffset; }
uint8_t getAddrSize() const { return HeaderData.AddrSize; }
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDie.h b/include/llvm/DebugInfo/DWARF/DWARFDie.h
index 39a3dd32c0f..3bc13c07f6d 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDie.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDie.h
@@ -207,7 +207,7 @@ public:
///
/// \returns a address range vector that might be empty if no address range
/// information is available.
- DWARFAddressRangesVector getAddressRanges() const;
+ Expected<DWARFAddressRangesVector> getAddressRanges() const;
/// Get all address ranges for any DW_TAG_subprogram DIEs in this DIE or any
/// of its children.
diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h
index fa98b728492..7c1a0d8c636 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h
@@ -371,11 +371,12 @@ public:
return DataExtractor(StringSection, false, 0);
}
- /// extractRangeList - extracts the range list referenced by this compile
- /// unit from .debug_ranges section. Returns true on success.
- /// Requires that compile unit is already extracted.
- bool extractRangeList(uint32_t RangeListOffset,
- DWARFDebugRangeList &RangeList) const;
+ /// Extract the range list referenced by this compile unit from the
+ /// .debug_ranges section. If the extraction is unsuccessful, an error
+ /// is returned. Successful extraction requires that the compile unit
+ /// has already been extracted.
+ Error extractRangeList(uint32_t RangeListOffset,
+ DWARFDebugRangeList &RangeList) const;
void clear();
const Optional<StrOffsetsContributionDescriptor> &
@@ -450,12 +451,12 @@ public:
/// Return a vector of address ranges resulting from a (possibly encoded)
/// range list starting at a given offset in the appropriate ranges section.
- DWARFAddressRangesVector findRnglistFromOffset(uint32_t Offset);
+ Expected<DWARFAddressRangesVector> findRnglistFromOffset(uint32_t Offset);
/// Return a vector of address ranges retrieved from an encoded range
/// list whose offset is found via a table lookup given an index (DWARF v5
/// and later).
- DWARFAddressRangesVector findRnglistFromIndex(uint32_t Index);
+ Expected<DWARFAddressRangesVector> findRnglistFromIndex(uint32_t Index);
/// Return a rangelist's offset based on an index. The index designates
/// an entry in the rangelist table's offset array and is supplied by
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);
diff --git a/test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s b/test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s
index b4234596175..25ea30d737c 100644
--- a/test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s
+++ b/test/DebugInfo/X86/dwarfdump-ranges-baseaddr.s
@@ -1,5 +1,6 @@
# RUN: llvm-mc -triple x86_64-pc-linux -filetype=obj %s -o %t
-# RUN: llvm-dwarfdump -v %t | FileCheck %s
+# RUN: llvm-dwarfdump -v %t 2>%t.err | FileCheck %s
+# RUN: FileCheck %s <%t.err -check-prefix=ERR
# CHECK: .debug_info contents:
# CHECK: 0x0000000b: DW_TAG_compile_unit [1]
@@ -68,6 +69,38 @@ foo:
.quad .Lfunc_begin0 # DW_AT_low_pc
.long .Ldebug_ranges0 # DW_AT_ranges
+# A CU with an invalid DW_AT_ranges attribute
+.Lcu_begin1:
+.long 38 # Length of Unit
+.short 4 # DWARF version number
+.long .debug_abbrev # Offset Into Abbrev. Section
+.byte 8 # Address Size (in bytes)
+.byte 1 # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
+.long 0 # DW_AT_producer
+.short 4 # DW_AT_language
+.long 0 # DW_AT_name
+.long 0 # DW_AT_stmt_list
+.long 0 # DW_AT_comp_dir
+.quad .Lfunc_begin0 # DW_AT_low_pc
+.long 0x4000 # DW_AT_ranges
+
+# ERR: error: decoding address ranges: invalid range list offset 0x4000
+
+# A CU where the DW_AT_ranges attribute points to an invalid range list.
+.Lcu_begin2:
+.long 38 # Length of Unit
+.short 4 # DWARF version number
+.long .debug_abbrev # Offset Into Abbrev. Section
+.byte 8 # Address Size (in bytes)
+.byte 1 # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
+.long 0 # DW_AT_producer
+.short 4 # DW_AT_language
+.long 0 # DW_AT_name
+.long 0 # DW_AT_stmt_list
+.long 0 # DW_AT_comp_dir
+.quad .Lfunc_begin0 # DW_AT_low_pc
+.long .Ldebug_ranges1 # DW_AT_ranges
+
.section .debug_ranges,"",@progbits
.Ldebug_ranges0:
.quad .Lfunc_begin0-.Lfunc_begin0
@@ -80,3 +113,7 @@ foo:
.quad .Ltmp5-.text.foo1
.quad 0
.quad 0
+.Ldebug_ranges1:
+ .quad 0
+
+# ERR: error: decoding address ranges: invalid range list entry at offset 0x50
diff --git a/test/DebugInfo/X86/dwarfdump-rnglists.s b/test/DebugInfo/X86/dwarfdump-rnglists.s
index 3916e102f3f..3b07c0351ae 100644
--- a/test/DebugInfo/X86/dwarfdump-rnglists.s
+++ b/test/DebugInfo/X86/dwarfdump-rnglists.s
@@ -1,6 +1,8 @@
# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o %t.o
# RUN: llvm-dwarfdump -v -debug-info %t.o 2> %t.err | FileCheck %s
# RUN: FileCheck %s --input-file %t.err --check-prefix=ERR
+# RUN: llvm-dwarfdump -lookup 10 %t.o 2> %t2.err
+# RUN: FileCheck %s --input-file %t2.err --check-prefix=ERR
# Test object to verify dwarfdump handles v5 range lists.
# We use very simplified compile unit dies.
@@ -42,7 +44,6 @@
.byte 0x00 # EOM(3)
.section .debug_info,"",@progbits
-# DWARF v5 CU header.
.long CU1_5_end-CU1_5_version # Length of Unit
CU1_5_version:
.short 5 # DWARF version number
@@ -57,7 +58,6 @@ CU1_5_version:
.byte 0 # NULL
CU1_5_end:
-# DWARF v5 CU header
.long CU2_5_end-CU2_5_version # Length of Unit
CU2_5_version:
.short 5 # DWARF version number
@@ -83,6 +83,19 @@ CU3_5_version:
.long 0 # DW_AT_ranges
.byte 0 # NULL
CU3_5_end:
+# A CU DIE with an incorrect DW_AT_ranges attribute
+ .long CU4_5_end-CU4_5_version # Length of Unit
+CU4_5_version:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 4 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+# The compile-unit DIE, which has DW_AT_rnglists_base and DW_AT_ranges.
+ .byte 1 # Abbreviation code
+ .long Rnglist_Table0_base # DW_AT_rnglists_base
+ .long 4000 # DW_AT_ranges
+ .byte 0 # NULL
+CU4_5_end:
.section .debug_info.dwo,"",@progbits
@@ -190,3 +203,5 @@ Range1_end:
# CHECK-NEXT: [0x0000002a, 0x00000034))
#ERR: error: parsing a range list table: Did not detect a valid range list table with base = 0x8
+#ERR: error: decoding address ranges: missing or invalid range list table
+#ERR: error: decoding address ranges: invalid range list offset 0xfa0
diff --git a/tools/dsymutil/DwarfLinker.cpp b/tools/dsymutil/DwarfLinker.cpp
index e6f8bdae2e6..9be224d4524 100644
--- a/tools/dsymutil/DwarfLinker.cpp
+++ b/tools/dsymutil/DwarfLinker.cpp
@@ -3503,7 +3503,11 @@ void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit,
for (const auto &RangeAttribute : Unit.getRangesAttributes()) {
uint32_t Offset = RangeAttribute.get();
RangeAttribute.set(Streamer->getRangesSectionSize());
- RangeList.extract(RangeExtractor, &Offset);
+ if (Error E = RangeList.extract(RangeExtractor, &Offset)) {
+ llvm::consumeError(std::move(E));
+ reportWarning("invalid range list ignored.", DMO);
+ RangeList.clear();
+ }
const auto &Entries = RangeList.getEntries();
if (!Entries.empty()) {
const DWARFDebugRangeList::RangeListEntry &First = Entries.front();
diff --git a/tools/llvm-dwarfdump/Statistics.cpp b/tools/llvm-dwarfdump/Statistics.cpp
index 5a274e1935d..5af853d4ef2 100644
--- a/tools/llvm-dwarfdump/Statistics.cpp
+++ b/tools/llvm-dwarfdump/Statistics.cpp
@@ -34,8 +34,14 @@ struct GlobalStats {
/// Extract the low pc from a Die.
static uint64_t getLowPC(DWARFDie Die) {
- if (Die.getAddressRanges().size())
- return Die.getAddressRanges()[0].LowPC;
+ auto RangesOrError = Die.getAddressRanges();
+ DWARFAddressRangesVector Ranges;
+ if (RangesOrError)
+ Ranges = RangesOrError.get();
+ else
+ llvm::consumeError(RangesOrError.takeError());
+ if (Ranges.size())
+ return Ranges[0].LowPC;
return dwarf::toAddress(Die.find(dwarf::DW_AT_low_pc), 0);
}
@@ -137,7 +143,13 @@ static void collectStatsRecursive(DWARFDie Die, std::string Prefix,
}
// PC Ranges.
- auto Ranges = Die.getAddressRanges();
+ auto RangesOrError = Die.getAddressRanges();
+ if (!RangesOrError) {
+ llvm::consumeError(RangesOrError.takeError());
+ return;
+ }
+
+ auto Ranges = RangesOrError.get();
uint64_t BytesInThisScope = 0;
for (auto Range : Ranges)
BytesInThisScope += Range.HighPC - Range.LowPC;