summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/DebugInfo/DWARF/CMakeLists.txt1
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFContext.cpp56
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp96
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp97
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFDie.cpp1
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp72
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp99
7 files changed, 201 insertions, 221 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
index b4770e561f7..437c845718d 100644
--- a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
@@ -15,7 +15,6 @@ add_llvm_library(LLVMDebugInfoDWARF
DWARFDebugLoc.cpp
DWARFDebugMacro.cpp
DWARFDebugPubTable.cpp
- DWARFDebugRangeList.cpp
DWARFDebugRnglists.cpp
DWARFDie.cpp
DWARFExpression.cpp
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index a5c31a56fad..be0192cdeda 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -25,7 +25,6 @@
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
@@ -267,24 +266,29 @@ static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData,
}
}
-// Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5).
-static void dumpRnglistsSection(raw_ostream &OS,
- DWARFDataExtractor &rnglistData,
- DIDumpOptions DumpOpts) {
+// Dump a section that contains a sequence of tables of lists, such as range
+// or location list tables. In DWARF v5 we expect to find properly formatted
+// tables with headers. In DWARF v4 and earlier we simply expect a sequence of
+// lists, which we treat, mutatis mutandis, like DWARF v5 tables.
+template <typename ListTable>
+static void dumpListSection(raw_ostream &OS, DWARFContext *C,
+ StringRef SectionName, uint16_t MaxVersion,
+ DWARFDataExtractor &ListData,
+ DIDumpOptions DumpOpts, bool isDWO = false) {
uint32_t Offset = 0;
- while (rnglistData.isValidOffset(Offset)) {
- llvm::DWARFDebugRnglistTable Rnglists;
- uint32_t TableOffset = Offset;
- if (Error Err = Rnglists.extract(rnglistData, &Offset)) {
+ while (ListData.isValidOffset(Offset)) {
+ ListTable Table(C, SectionName, isDWO);
+ if (Error Err = Table.extract(ListData, MaxVersion, &Offset)) {
WithColor::error() << toString(std::move(Err)) << '\n';
- uint64_t Length = Rnglists.length();
- // Keep going after an error, if we can, assuming that the length field
- // could be read. If it couldn't, stop reading the section.
- if (Length == 0)
+ // If table extraction set Offset to 0, it indicates that we cannot
+ // continue to read the section.
+ if (Offset == 0)
break;
- Offset = TableOffset + Length;
+ // In DWARF v4 and earlier, dump as much of the lists as we can.
+ if (MaxVersion < 5)
+ Table.dump(OS, DumpOpts);
} else {
- Rnglists.dump(OS, DumpOpts);
+ Table.dump(OS, DumpOpts);
}
}
}
@@ -484,29 +488,25 @@ void DWARFContext::dump(
uint8_t savedAddressByteSize = getCUAddrSize();
DWARFDataExtractor rangesData(*DObj, DObj->getRangeSection(),
isLittleEndian(), savedAddressByteSize);
- uint32_t offset = 0;
- DWARFDebugRangeList rangeList;
- while (rangesData.isValidOffset(offset)) {
- if (Error E = rangeList.extract(rangesData, &offset)) {
- WithColor::error() << toString(std::move(E)) << '\n';
- break;
- }
- rangeList.dump(OS);
- }
+ dumpListSection<DWARFDebugRnglistTable>(
+ OS, this, ".debug_ranges", /* MaxVersion = */ 4, rangesData, DumpOpts);
}
if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists,
DObj->getRnglistsSection().Data)) {
DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(),
- isLittleEndian(), 0);
- dumpRnglistsSection(OS, RnglistData, DumpOpts);
+ isLittleEndian(), getCUAddrSize());
+ dumpListSection<DWARFDebugRnglistTable>(
+ OS, this, ".debug_rnglists", getMaxVersion(5), RnglistData, DumpOpts);
}
if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists,
DObj->getRnglistsDWOSection().Data)) {
DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(),
- isLittleEndian(), 0);
- dumpRnglistsSection(OS, RnglistData, DumpOpts);
+ isLittleEndian(), getCUAddrSize());
+ dumpListSection<DWARFDebugRnglistTable>(OS, this, ".debug_rnglists.dwo",
+ getMaxVersion(5), RnglistData,
+ DumpOpts);
}
if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames,
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp
deleted file mode 100644
index 84e3c634f54..00000000000
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-//===- DWARFDebugRangesList.cpp -------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cinttypes>
-#include <cstdint>
-
-using namespace llvm;
-
-void DWARFDebugRangeList::clear() {
- Offset = -1U;
- AddressSize = 0;
- Entries.clear();
-}
-
-Error DWARFDebugRangeList::extract(const DWARFDataExtractor &data,
- uint32_t *offset_ptr) {
- clear();
- if (!data.isValidOffset(*offset_ptr))
- return createStringError(errc::invalid_argument,
- "invalid range list offset 0x%" PRIx32, *offset_ptr);
-
- AddressSize = data.getAddressSize();
- if (AddressSize != 4 && AddressSize != 8)
- return createStringError(errc::invalid_argument,
- "invalid address size: %" PRIu8, AddressSize);
- Offset = *offset_ptr;
- while (true) {
- RangeListEntry Entry;
- Entry.SectionIndex = -1ULL;
-
- uint32_t prev_offset = *offset_ptr;
- Entry.StartAddress = data.getRelocatedAddress(offset_ptr);
- Entry.EndAddress =
- data.getRelocatedAddress(offset_ptr, &Entry.SectionIndex);
-
- // Check that both values were extracted correctly.
- if (*offset_ptr != prev_offset + 2 * AddressSize) {
- clear();
- return createStringError(errc::invalid_argument,
- "invalid range list entry at offset 0x%" PRIx32,
- prev_offset);
- }
- if (Entry.isEndOfListEntry())
- break;
- Entries.push_back(Entry);
- }
- return Error::success();
-}
-
-void DWARFDebugRangeList::dump(raw_ostream &OS) const {
- for (const RangeListEntry &RLE : Entries) {
- const char *format_str = (AddressSize == 4
- ? "%08x %08" PRIx64 " %08" PRIx64 "\n"
- : "%08x %016" PRIx64 " %016" PRIx64 "\n");
- OS << format(format_str, Offset, RLE.StartAddress, RLE.EndAddress);
- }
- OS << format("%08x <End of list>\n", Offset);
-}
-
-DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges(
- llvm::Optional<BaseAddress> BaseAddr) const {
- DWARFAddressRangesVector Res;
- for (const RangeListEntry &RLE : Entries) {
- if (RLE.isBaseAddressSelectionEntry(AddressSize)) {
- BaseAddr = {RLE.EndAddress, RLE.SectionIndex};
- continue;
- }
-
- DWARFAddressRange E;
- E.LowPC = RLE.StartAddress;
- E.HighPC = RLE.EndAddress;
- E.SectionIndex = RLE.SectionIndex;
- // Base address of a range list entry is determined by the closest preceding
- // base address selection entry in the same range list. It defaults to the
- // base address of the compilation unit if there is no such entry.
- if (BaseAddr) {
- E.LowPC += BaseAddr->Address;
- E.HighPC += BaseAddr->Address;
- if (E.SectionIndex == -1ULL)
- E.SectionIndex = BaseAddr->SectionIndex;
- }
- Res.push_back(E);
- }
- return Res;
-}
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp
index eeb85edf5b2..0b0133304c3 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp
@@ -13,19 +13,30 @@
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
- uint32_t *OffsetPtr) {
+ uint16_t Version, StringRef /* SectionName */,
+ uint32_t *OffsetPtr, bool /* isDWO */) {
Offset = *OffsetPtr;
SectionIndex = -1ULL;
- // The caller should guarantee that we have at least 1 byte available, so
- // we just assert instead of revalidate.
- assert(*OffsetPtr < End &&
- "not enough space to extract a rangelist encoding");
- uint8_t Encoding = Data.getU8(OffsetPtr);
+
+ assert((Data.getAddressSize() == 4 || Data.getAddressSize() == 8) &&
+ "Unsupported address size");
+
+ // We model a DWARF v4 range list entry like DWARF v5 DW_RLE_offset_pair,
+ // since it is subject to base adjustment.
+ uint8_t Encoding = dwarf::DW_RLE_offset_pair;
+ if (Version > 4) {
+ // The caller should guarantee that we have at least 1 byte available, so
+ // we just assert instead of revalidate.
+ assert(*OffsetPtr < End &&
+ "not enough space to extract a rangelist encoding");
+ Encoding = Data.getU8(OffsetPtr);
+ }
switch (Encoding) {
case dwarf::DW_RLE_end_of_list:
@@ -48,6 +59,23 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
"at offset 0x%" PRIx32,
*OffsetPtr - 1);
case dwarf::DW_RLE_offset_pair: {
+ if (Version < 5) {
+ if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2))
+ return createStringError(
+ errc::illegal_byte_sequence,
+ "invalid range list entry at offset 0x%" PRIx32, *OffsetPtr);
+ Value0 = Data.getRelocatedAddress(OffsetPtr);
+ Value1 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
+ // Adjust the EntryKind for end-of-list and base_address based on the
+ // contents.
+ if (Value0 == maxUIntN(Data.getAddressSize() * 8)) {
+ Encoding = dwarf::DW_RLE_base_address;
+ Value0 = Value1;
+ Value1 = 0;
+ } else if (Value0 == 0 && Value1 == 0)
+ Encoding = dwarf::DW_RLE_end_of_list;
+ break;
+ }
uint32_t PreviousOffset = *OffsetPtr - 1;
Value0 = Data.getULEB128(OffsetPtr);
Value1 = Data.getULEB128(OffsetPtr);
@@ -58,7 +86,7 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
PreviousOffset);
break;
}
- case dwarf::DW_RLE_base_address: {
+ case dwarf::DW_RLE_base_address:
if ((End - *OffsetPtr) < Data.getAddressSize())
return createStringError(errc::invalid_argument,
"insufficient space remaining in table for "
@@ -66,18 +94,16 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
*OffsetPtr - 1);
Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
break;
- }
- case dwarf::DW_RLE_start_end: {
+ case dwarf::DW_RLE_start_end:
if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2))
return createStringError(errc::invalid_argument,
"insufficient space remaining in table for "
"DW_RLE_start_end encoding "
"at offset 0x%" PRIx32,
*OffsetPtr - 1);
- Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
- Value1 = Data.getRelocatedAddress(OffsetPtr);
+ Value0 = Data.getRelocatedAddress(OffsetPtr);
+ Value1 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
break;
- }
case dwarf::DW_RLE_start_length: {
uint32_t PreviousOffset = *OffsetPtr - 1;
Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
@@ -143,9 +169,10 @@ DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
return Res;
}
-void RangeListEntry::dump(raw_ostream &OS, uint8_t AddrSize,
- uint8_t MaxEncodingStringLength,
- uint64_t &CurrentBase, DIDumpOptions DumpOpts) const {
+void RangeListEntry::dump(raw_ostream &OS, DWARFContext *, uint8_t AddrSize,
+ uint64_t &CurrentBase, unsigned Indent,
+ uint16_t Version, uint8_t MaxEncodingStringLength,
+ DIDumpOptions DumpOpts) const {
auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,
uint8_t AddrSize, DIDumpOptions DumpOpts) {
if (DumpOpts.Verbose) {
@@ -156,27 +183,49 @@ void RangeListEntry::dump(raw_ostream &OS, uint8_t AddrSize,
}
};
+ // Output indentations before we print the actual entry. We only print
+ // anything for DW_RLE_base_address when we are in verbose mode.
+ if (DumpOpts.Verbose || !isBaseAddressSelectionEntry())
+ OS.indent(Indent);
+
if (DumpOpts.Verbose) {
// Print the section offset in verbose mode.
OS << format("0x%8.8" PRIx32 ":", Offset);
- auto EncodingString = dwarf::RangeListEncodingString(EntryKind);
- // Unsupported encodings should have been reported during parsing.
- assert(!EncodingString.empty() && "Unknown range entry encoding");
- OS << format(" [%s%*c", EncodingString.data(),
- MaxEncodingStringLength - EncodingString.size() + 1, ']');
- if (EntryKind != dwarf::DW_RLE_end_of_list)
- OS << ": ";
+ if (Version > 4) {
+ auto EncodingString = dwarf::RangeListEncodingString(EntryKind);
+ // Unsupported encodings should have been reported during parsing.
+ assert(!EncodingString.empty() && "Unknown range entry encoding");
+ OS << format(" [%s%*c", EncodingString.data(),
+ MaxEncodingStringLength - EncodingString.size() + 1, ']');
+ if (!isEndOfList())
+ OS << ": ";
+ }
}
switch (EntryKind) {
case dwarf::DW_RLE_end_of_list:
- OS << (DumpOpts.Verbose ? "" : "<End of list>");
+ if (DumpOpts.Verbose) {
+ // For DWARF v4 and earlier, we print the raw entry, i.e. 2 zeros.
+ if (Version < 5) {
+ OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
+ OS << format(", 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value1);
+ }
+ break;
+ }
+ OS << "<End of list>";
break;
case dwarf::DW_RLE_base_address:
- // In non-verbose mode we do not print anything for this entry.
+ // In non-verbose mode, we do not print anything for this entry.
CurrentBase = Value0;
if (!DumpOpts.Verbose)
return;
+ if (Version < 5) {
+ // Dump the entry in pre-DWARF v5 format, i.e. with a -1 as Value0.
+ uint64_t allOnes = maxUIntN(AddrSize * 8);
+ OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, allOnes);
+ OS << format(", 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
+ break;
+ }
OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
break;
case dwarf::DW_RLE_start_length:
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index 35567d0f67a..25457781e8c 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -15,7 +15,6 @@
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp
index 462c036d73a..835f7279e26 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp
@@ -20,30 +20,43 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data,
uint32_t *OffsetPtr) {
HeaderOffset = *OffsetPtr;
// Read and verify the length field.
- if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t)))
+ if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t))) {
+ // By setting *OffsetPtr to 0, we indicate to the caller that
+ // we could not detemine the length of the table.
+ *OffsetPtr = 0;
return createStringError(errc::invalid_argument,
"section is not large enough to contain a "
"%s table length at offset 0x%" PRIx32,
- SectionName.data(), *OffsetPtr);
+ SectionName.data(), HeaderOffset);
+ }
// TODO: Add support for DWARF64.
HeaderData.Length = Data.getU32(OffsetPtr);
- if (HeaderData.Length == 0xffffffffu)
+ if (HeaderData.Length == 0xffffffffu) {
+ *OffsetPtr = 0;
return createStringError(errc::not_supported,
"DWARF64 is not supported in %s at offset 0x%" PRIx32,
SectionName.data(), HeaderOffset);
+ }
+
+ uint32_t TableLength = HeaderData.Length + sizeof(uint32_t);
+ uint32_t End = HeaderOffset + TableLength;
Format = dwarf::DwarfFormat::DWARF32;
- if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header))
- return createStringError(errc::invalid_argument,
- "%s table at offset 0x%" PRIx32
- " has too small length (0x%" PRIx32
- ") to contain a complete header",
- SectionName.data(), HeaderOffset, length());
- uint32_t End = HeaderOffset + length();
- if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset))
- return createStringError(errc::invalid_argument,
- "section is not large enough to contain a %s table "
- "of length 0x%" PRIx32 " at offset 0x%" PRIx32,
- SectionName.data(), length(), HeaderOffset);
+ if (TableLength < sizeof(Header)) {
+ *OffsetPtr = End;
+ return createStringError(
+ errc::invalid_argument,
+ "%s table at offset 0x%" PRIx32 " has too small length (0x%" PRIx32
+ ") to contain a complete header",
+ SectionName.data(), HeaderOffset, TableLength);
+ }
+ if (!Data.isValidOffsetForDataOfSize(HeaderOffset, TableLength)) {
+ *OffsetPtr = 0; // No recovery if the length exceeds the section size.
+ return createStringError(
+ errc::invalid_argument,
+ "section is not large enough to contain a %s table "
+ "of length 0x%" PRIx32 " at offset 0x%" PRIx32,
+ SectionName.data(), TableLength, HeaderOffset);
+ }
HeaderData.Version = Data.getU16(OffsetPtr);
HeaderData.AddrSize = Data.getU8(OffsetPtr);
@@ -51,27 +64,36 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data,
HeaderData.OffsetEntryCount = Data.getU32(OffsetPtr);
// Perform basic validation of the remaining header fields.
- if (HeaderData.Version != 5)
+ if (HeaderData.Version != 5) {
+ *OffsetPtr = End;
return createStringError(errc::invalid_argument,
- "unrecognised %s table version %" PRIu16
- " in table at offset 0x%" PRIx32,
- SectionName.data(), HeaderData.Version, HeaderOffset);
- if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)
+ "unrecognised %s table version %" PRIu16
+ " in table at offset 0x%" PRIx32,
+ SectionName.data(), HeaderData.Version,
+ HeaderOffset);
+ }
+ if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8) {
+ *OffsetPtr = End;
return createStringError(errc::not_supported,
"%s table at offset 0x%" PRIx32
" has unsupported address size %" PRIu8,
SectionName.data(), HeaderOffset, HeaderData.AddrSize);
- if (HeaderData.SegSize != 0)
+ }
+ if (HeaderData.SegSize != 0) {
+ *OffsetPtr = End;
return createStringError(errc::not_supported,
"%s table at offset 0x%" PRIx32
" has unsupported segment selector size %" PRIu8,
SectionName.data(), HeaderOffset, HeaderData.SegSize);
+ }
if (End < HeaderOffset + sizeof(HeaderData) +
- HeaderData.OffsetEntryCount * sizeof(uint32_t))
+ HeaderData.OffsetEntryCount * sizeof(uint32_t)) {
+ *OffsetPtr = End;
return createStringError(errc::invalid_argument,
"%s table at offset 0x%" PRIx32 " has more offset entries (%" PRIu32
") than there is space for",
SectionName.data(), HeaderOffset, HeaderData.OffsetEntryCount);
+ }
Data.setAddressSize(HeaderData.AddrSize);
for (uint32_t I = 0; I < HeaderData.OffsetEntryCount; ++I)
Offsets.push_back(Data.getU32(OffsetPtr));
@@ -101,9 +123,11 @@ void DWARFListTableHeader::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
}
}
-uint32_t DWARFListTableHeader::length() const {
+uint32_t DWARFListTableHeader::getTableLength() const {
if (HeaderData.Length == 0)
return 0;
+ assert(HeaderData.Version > 0 &&
+ "No DWARF version in header when using getTableLength()");
// TODO: DWARF64 support.
- return HeaderData.Length + sizeof(uint32_t);
+ return HeaderData.Length + (HeaderData.Version > 4) * sizeof(uint32_t);
}
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index b2bc2c8fa32..38dfe67f299 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -264,13 +264,16 @@ bool DWARFUnitHeader::extract(DWARFContext &Context,
return true;
}
-// Parse the rangelist table header, including the optional array of offsets
+// Parse a list table header, including the optional array of offsets
// following it (DWARF v5 and later).
-static Expected<DWARFDebugRnglistTable>
-parseRngListTableHeader(DWARFDataExtractor &DA, uint32_t Offset) {
+template <typename DWARFListTable>
+static Expected<DWARFListTable>
+parseListTableHeader(DWARFDataExtractor DA, DWARFContext *C,
+ StringRef SectionName, uint32_t Offset, bool isDWO) {
// TODO: Support DWARF64
// We are expected to be called with Offset 0 or pointing just past the table
// header, which is 12 bytes long for DWARF32.
+ DWARFListTable Table(C, SectionName, isDWO);
if (Offset > 0) {
if (Offset < 12U)
return createStringError(errc::invalid_argument, "Did not detect a valid"
@@ -278,20 +281,46 @@ parseRngListTableHeader(DWARFDataExtractor &DA, uint32_t Offset) {
Offset);
Offset -= 12U;
}
- llvm::DWARFDebugRnglistTable Table;
if (Error E = Table.extractHeaderAndOffsets(DA, &Offset))
return std::move(E);
return Table;
}
-Error DWARFUnit::extractRangeList(uint32_t RangeListOffset,
- DWARFDebugRangeList &RangeList) const {
- // Require that compile unit is extracted.
- assert(!DieArray.empty());
- DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection,
- isLittleEndian, getAddressByteSize());
- uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
- return RangeList.extract(RangesData, &ActualRangeListOffset);
+// Parse a DWARF v5 list table (e.g. either a rangelist table or a location
+// list table). For DWARF units with version 4 or earlier, we instead create
+// the table artifically by giving it a size that equals the section size.
+template <typename DWARFListTable>
+static Optional<DWARFListTable>
+setupListTable(DWARFUnit *U, const DWARFSection *Section, StringRef SectionName,
+ uint32_t &Base, bool isDWO, bool isLittleEndian) {
+ if (!Section->Data.size())
+ return None;
+ DWARFContext &Ctx = U->getContext();
+ DWARFListTable Table(&Ctx, SectionName, isDWO);
+ // Parse the list table header. Individual lists are extracted lazily.
+ DWARFDataExtractor DA(Ctx.getDWARFObj(), *Section, isLittleEndian,
+ U->getAddressByteSize());
+ if (U->getVersion() < 5) {
+ Base = 0;
+ Table.setHeaderData(Section->Data.size(), U->getVersion(),
+ DA.getAddressSize());
+ return Table;
+ }
+ if (auto TableOrError = parseListTableHeader<DWARFListTable>(
+ DA, &Ctx, SectionName, Base, isDWO))
+ Table = TableOrError.get();
+ else {
+ WithColor::error() << "parsing a " << Table.getListTypeString().data()
+ << " list table: " << toString(TableOrError.takeError())
+ << '\n';
+ return None;
+ }
+ // In a split dwarf unit, there are no attributes like DW_AT_rnglists_base or
+ // DW_AT_loclists_base that describe the table base. Adjust Base to point past
+ // the table header which is expected to start at offset 0.
+ if (isDWO)
+ Base = Table.getHeaderSize();
+ return Table;
}
void DWARFUnit::clear() {
@@ -411,31 +440,20 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
// DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to
// describe address ranges.
+ StringRef RangeSectionName = ".debug_ranges";
if (getVersion() >= 5) {
- if (isDWO)
+ if (isDWO) {
+ RangeSectionName = ".debug_rnglists.dwo";
setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0);
- else
+ } else {
+ RangeSectionName = ".debug_rnglists";
setRangesSection(&Context.getDWARFObj().getRnglistsSection(),
toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0));
- if (RangeSection->Data.size()) {
- // Parse the range list table header. Individual range lists are
- // extracted lazily.
- DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection,
- isLittleEndian, 0);
- if (auto TableOrError =
- parseRngListTableHeader(RangesDA, RangeSectionBase))
- RngListTable = TableOrError.get();
- else
- WithColor::error() << "parsing a range list table: "
- << toString(TableOrError.takeError())
- << '\n';
-
- // In a split dwarf unit, there is no DW_AT_rnglists_base attribute.
- // Adjust RangeSectionBase to point past the table header.
- if (isDWO && RngListTable)
- RangeSectionBase = RngListTable->getHeaderSize();
}
}
+ RngListTable = setupListTable<DWARFDebugRnglistTable>(
+ this, RangeSection, RangeSectionName, RangeSectionBase, isDWO,
+ isLittleEndian);
// Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for
// skeleton CU DIE, so that DWARF users not aware of it are not broken.
@@ -477,16 +495,9 @@ bool DWARFUnit::parseDWO() {
DWO->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase);
if (getVersion() >= 5) {
DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0);
- DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection,
- isLittleEndian, 0);
- if (auto TableOrError = parseRngListTableHeader(RangesDA, RangeSectionBase))
- DWO->RngListTable = TableOrError.get();
- else
- WithColor::error() << "parsing a range list table: "
- << toString(TableOrError.takeError())
- << '\n';
- if (DWO->RngListTable)
- DWO->RangeSectionBase = DWO->RngListTable->getHeaderSize();
+ DWO->RngListTable = setupListTable<DWARFDebugRnglistTable>(
+ DWOCU, DWO->RangeSection, ".debug_rnglists.dwo", DWO->RangeSectionBase,
+ /* isDWO =*/true, isLittleEndian);
} else {
auto DWORangesBase = UnitDie.getRangesBaseAttribute();
DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0);
@@ -504,12 +515,6 @@ void DWARFUnit::clearDIEs(bool KeepCUDie) {
Expected<DWARFAddressRangesVector>
DWARFUnit::findRnglistFromOffset(uint32_t Offset) {
- if (getVersion() <= 4) {
- DWARFDebugRangeList RangeList;
- if (Error E = extractRangeList(Offset, RangeList))
- return std::move(E);
- return RangeList.getAbsoluteRanges(getBaseAddress());
- }
if (RngListTable) {
DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection,
isLittleEndian, RngListTable->getAddrSize());
OpenPOWER on IntegriCloud