diff options
author | Wolfgang Pieb <Wolfgang.Pieb@sony.com> | 2018-10-31 01:12:58 +0000 |
---|---|---|
committer | Wolfgang Pieb <Wolfgang.Pieb@sony.com> | 2018-10-31 01:12:58 +0000 |
commit | f39a9bbe72376648a5aaed2e882710649de079cd (patch) | |
tree | 94b886742562753c75b5af15a909f6a5bf120084 /llvm/lib | |
parent | 8fddd9818599663cee75b834c19df9bfd41a64f2 (diff) | |
download | bcm5719-llvm-f39a9bbe72376648a5aaed2e882710649de079cd.tar.gz bcm5719-llvm-f39a9bbe72376648a5aaed2e882710649de079cd.zip |
[DWARF] Revert r345546: Refactor range list extraction and dumping
This patch caused some internal tests to break which are being investigated.
llvm-svn: 345687
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 74 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp | 96 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp | 96 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp | 74 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 101 |
7 files changed, 229 insertions, 214 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt index 437c845718d..b4770e561f7 100644 --- a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt +++ b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt @@ -15,6 +15,7 @@ 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 3a0f52753b0..a29c9c2f160 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -25,6 +25,7 @@ #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,31 +268,26 @@ static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData, } } -// 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> +// Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5). static void -dumpListSection(raw_ostream &OS, DWARFContext *C, StringRef SectionName, - uint16_t MaxVersion, DWARFDataExtractor &ListData, - llvm::function_ref<Optional<SectionedAddress>(uint32_t)> - LookupPooledAddress, - DIDumpOptions DumpOpts, bool isDWO = false) { +dumpRnglistsSection(raw_ostream &OS, DWARFDataExtractor &rnglistData, + llvm::function_ref<Optional<SectionedAddress>(uint32_t)> + LookupPooledAddress, + DIDumpOptions DumpOpts) { uint32_t Offset = 0; - while (ListData.isValidOffset(Offset)) { - ListTable Table(C, SectionName, isDWO); - if (Error Err = Table.extract(ListData, MaxVersion, &Offset)) { + while (rnglistData.isValidOffset(Offset)) { + llvm::DWARFDebugRnglistTable Rnglists; + uint32_t TableOffset = Offset; + if (Error Err = Rnglists.extract(rnglistData, &Offset)) { WithColor::error() << toString(std::move(Err)) << '\n'; - // If table extraction set Offset to 0, it indicates that we cannot - // continue to read the section. - if (Offset == 0) + 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) break; - // In DWARF v4 and earlier, dump as much of the lists as we can. - if (MaxVersion < 5) - Table.dump(OS, LookupPooledAddress, DumpOpts); + Offset = TableOffset + Length; } else { - Table.dump(OS, LookupPooledAddress, DumpOpts); + Rnglists.dump(OS, LookupPooledAddress, DumpOpts); } } } @@ -512,6 +508,22 @@ void DWARFContext::dump( dumpAddrSection(OS, AddrData, DumpOpts, getMaxVersion(), getCUAddrSize()); } + if (shouldDump(Explicit, ".debug_ranges", DIDT_ID_DebugRanges, + DObj->getRangeSection().Data)) { + 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); + } + } + auto LookupPooledAddress = [&](uint32_t Index) -> Optional<SectionedAddress> { const auto &CUs = compile_units(); auto I = CUs.begin(); @@ -520,32 +532,18 @@ void DWARFContext::dump( return (*I)->getAddrOffsetSectionItem(Index); }; - if (shouldDump(Explicit, ".debug_ranges", DIDT_ID_DebugRanges, - DObj->getRangeSection().Data)) { - uint8_t savedAddressByteSize = getCUAddrSize(); - DWARFDataExtractor rangesData(*DObj, DObj->getRangeSection(), - isLittleEndian(), savedAddressByteSize); - dumpListSection<DWARFDebugRnglistTable>(OS, this, ".debug_ranges", - /* MaxVersion = */ 4, rangesData, - LookupPooledAddress, DumpOpts); - } - if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists, DObj->getRnglistsSection().Data)) { DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(), - isLittleEndian(), getCUAddrSize()); - dumpListSection<DWARFDebugRnglistTable>(OS, this, ".debug_rnglists", - getMaxVersion(5), RnglistData, - LookupPooledAddress, DumpOpts); + isLittleEndian(), 0); + dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts); } if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists, DObj->getRnglistsDWOSection().Data)) { DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(), - isLittleEndian(), getCUAddrSize()); - dumpListSection<DWARFDebugRnglistTable>(OS, this, ".debug_rnglists.dwo", - getMaxVersion(5), RnglistData, - LookupPooledAddress, DumpOpts); + isLittleEndian(), 0); + dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, 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 new file mode 100644 index 00000000000..dfb913000a4 --- /dev/null +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp @@ -0,0 +1,96 @@ +//===- 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<SectionedAddress> 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 737603bc88c..cb5fb0d49da 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp @@ -13,30 +13,19 @@ #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, - uint16_t Version, StringRef /* SectionName */, - uint32_t *OffsetPtr, bool /* isDWO */) { + uint32_t *OffsetPtr) { Offset = *OffsetPtr; SectionIndex = -1ULL; - - 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); - } + // 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); switch (Encoding) { case dwarf::DW_RLE_end_of_list: @@ -72,23 +61,6 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, break; } 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); @@ -99,7 +71,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 " @@ -107,16 +79,18 @@ 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); - Value1 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); + Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); + Value1 = Data.getRelocatedAddress(OffsetPtr); break; + } case dwarf::DW_RLE_start_length: { uint32_t PreviousOffset = *OffsetPtr - 1; Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); @@ -199,9 +173,8 @@ DWARFDebugRnglist::getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr, } void RangeListEntry::dump( - raw_ostream &OS, DWARFContext *, uint8_t AddrSize, uint64_t &CurrentBase, - unsigned Indent, uint16_t Version, uint8_t MaxEncodingStringLength, - DIDumpOptions DumpOpts, + raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, + uint64_t &CurrentBase, DIDumpOptions DumpOpts, llvm::function_ref<Optional<SectionedAddress>(uint32_t)> LookupPooledAddress) const { auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry, @@ -214,34 +187,21 @@ void RangeListEntry::dump( } }; - // Output indentations before we print the actual entry. We only print - // anything for DW_RLE_base_address when we are in verbose mode. - if (Version < 5 || DumpOpts.Verbose || !isBaseAddressSelectionEntry()) - OS.indent(Indent); - - // Always print the section offset in DWARF v4 and earlier. - if (Version < 5) { - OS << format("%08x", Offset); - DumpOpts.Verbose = false; - } - if (DumpOpts.Verbose) { // Print the section offset in verbose mode. OS << format("0x%8.8" PRIx32 ":", Offset); - 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 << ": "; - } + 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 << ": "; } switch (EntryKind) { case dwarf::DW_RLE_end_of_list: - OS << (DumpOpts.Verbose ? "" : " <End of list>"); + OS << (DumpOpts.Verbose ? "" : "<End of list>"); break; // case dwarf::DW_RLE_base_addressx: case dwarf::DW_RLE_base_addressx: { @@ -257,13 +217,6 @@ void RangeListEntry::dump( case dwarf::DW_RLE_base_address: // In non-verbose mode we do not print anything for this entry. CurrentBase = Value0; - 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(" %*.*" PRIx64, AddrSize * 2, AddrSize * 2, allOnes); - OS << format(" %*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); - break; - } if (!DumpOpts.Verbose) return; OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); @@ -273,11 +226,6 @@ void RangeListEntry::dump( DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts); break; case dwarf::DW_RLE_offset_pair: - if (Version < 5) { - OS << format(" %*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); - OS << format(" %*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value1); - break; - } PrintRawEntry(OS, *this, AddrSize, DumpOpts); DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase) .dump(OS, AddrSize, DumpOpts); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index 874a2ba07fa..31c4cd5e472 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -15,6 +15,7 @@ #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 69a9231f785..462c036d73a 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp @@ -20,43 +20,30 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data, uint32_t *OffsetPtr) { HeaderOffset = *OffsetPtr; // Read and verify the length field. - 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; + if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t))) return createStringError(errc::invalid_argument, - "section is not large enough to contain a " - "%s table length at offset 0x%" PRIx32, - SectionName.data(), HeaderOffset); - } + "section is not large enough to contain a " + "%s table length at offset 0x%" PRIx32, + SectionName.data(), *OffsetPtr); // TODO: Add support for DWARF64. HeaderData.Length = Data.getU32(OffsetPtr); - if (HeaderData.Length == 0xffffffffu) { - *OffsetPtr = 0; + if (HeaderData.Length == 0xffffffffu) 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 (TableLength < sizeof(Header)) { - *OffsetPtr = End; + 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, 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); - } + "%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); HeaderData.Version = Data.getU16(OffsetPtr); HeaderData.AddrSize = Data.getU8(OffsetPtr); @@ -64,36 +51,27 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data, HeaderData.OffsetEntryCount = Data.getU32(OffsetPtr); // Perform basic validation of the remaining header fields. - if (HeaderData.Version != 5) { - *OffsetPtr = End; + if (HeaderData.Version != 5) 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) { - *OffsetPtr = End; + "unrecognised %s table version %" PRIu16 + " in table at offset 0x%" PRIx32, + SectionName.data(), HeaderData.Version, HeaderOffset); + if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8) 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) { - *OffsetPtr = End; + if (HeaderData.SegSize != 0) 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)) { - *OffsetPtr = End; + HeaderData.OffsetEntryCount * sizeof(uint32_t)) 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)); @@ -123,11 +101,9 @@ void DWARFListTableHeader::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { } } -uint32_t DWARFListTableHeader::getTableLength() const { +uint32_t DWARFListTableHeader::length() 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 + (HeaderData.Version > 4) * sizeof(uint32_t); + return HeaderData.Length + sizeof(uint32_t); } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index 88565af1ec0..d475c44c393 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -296,16 +296,13 @@ bool DWARFUnitHeader::extract(DWARFContext &Context, return true; } -// Parse a list table header, including the optional array of offsets +// Parse the rangelist table header, including the optional array of offsets // following it (DWARF v5 and later). -template <typename DWARFListTable> -static Expected<DWARFListTable> -parseListTableHeader(DWARFDataExtractor DA, DWARFContext *C, - StringRef SectionName, uint32_t Offset, bool isDWO) { +static Expected<DWARFDebugRnglistTable> +parseRngListTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { // 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" @@ -313,46 +310,20 @@ parseListTableHeader(DWARFDataExtractor DA, DWARFContext *C, Offset); Offset -= 12U; } + llvm::DWARFDebugRnglistTable Table; if (Error E = Table.extractHeaderAndOffsets(DA, &Offset)) return std::move(E); return Table; } -// 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; +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); } void DWARFUnit::clear() { @@ -466,24 +437,35 @@ 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) { - RangeSectionName = ".debug_rnglists.dwo"; + if (IsDWO) setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0); - } else { - RangeSectionName = ".debug_rnglists"; + else 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. - } + } return DieArray.size(); } @@ -521,9 +503,16 @@ bool DWARFUnit::parseDWO() { DWO->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); if (getVersion() >= 5) { DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0); - DWO->RngListTable = setupListTable<DWARFDebugRnglistTable>( - DWOCU, DWO->RangeSection, ".debug_rnglists.dwo", DWO->RangeSectionBase, - /* isDWO =*/true, isLittleEndian); + 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(); } else { auto DWORangesBase = UnitDie.getRangesBaseAttribute(); DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); @@ -541,6 +530,12 @@ 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()); |