diff options
-rw-r--r-- | llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h | 9 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h | 14 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 22 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp | 80 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 2 | ||||
-rw-r--r-- | llvm/test/tools/llvm-dwarfdump/X86/debug_rnglists.s | 27 |
6 files changed, 123 insertions, 31 deletions
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h index 0615bbf0308..5cc8d789e59 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H #define LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H +#include "llvm/ADT/Optional.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" @@ -23,6 +24,7 @@ namespace llvm { class Error; class raw_ostream; +class DWARFUnit; /// A class representing a single range list entry. struct RangeListEntry : public DWARFListEntryBase { @@ -35,7 +37,9 @@ struct RangeListEntry : public DWARFListEntryBase { Error extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr); void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, - uint64_t &CurrentBase, DIDumpOptions DumpOpts) const; + uint64_t &CurrentBase, DIDumpOptions DumpOpts, + llvm::function_ref<Optional<SectionedAddress>(uint32_t)> + LookupPooledAddress) const; bool isSentinel() const { return EntryKind == dwarf::DW_RLE_end_of_list; } }; @@ -44,7 +48,8 @@ class DWARFDebugRnglist : public DWARFListType<RangeListEntry> { public: /// Build a DWARFAddressRangesVector from a rangelist. DWARFAddressRangesVector - getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr) const; + getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr, + DWARFUnit &U) const; }; class DWARFDebugRnglistTable : public DWARFListTableBase<DWARFDebugRnglist> { diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h index 8cf9e400892..8c15d9d58d4 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h @@ -156,7 +156,10 @@ public: uint32_t getHeaderOffset() const { return Header.getHeaderOffset(); } uint8_t getAddrSize() const { return Header.getAddrSize(); } - void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const; + void dump(raw_ostream &OS, + llvm::function_ref<Optional<SectionedAddress>(uint32_t)> + LookupPooledAddress, + DIDumpOptions DumpOpts = {}) const; /// Return the contents of the offset entry designated by a given index. Optional<uint32_t> getOffsetEntry(uint32_t Index) const { @@ -229,8 +232,11 @@ Error DWARFListType<ListEntryType>::extract(DWARFDataExtractor Data, } template <typename DWARFListType> -void DWARFListTableBase<DWARFListType>::dump(raw_ostream &OS, - DIDumpOptions DumpOpts) const { +void DWARFListTableBase<DWARFListType>::dump( + raw_ostream &OS, + llvm::function_ref<Optional<SectionedAddress>(uint32_t)> + LookupPooledAddress, + DIDumpOptions DumpOpts) const { Header.dump(OS, DumpOpts); OS << HeaderString << "\n"; @@ -249,7 +255,7 @@ void DWARFListTableBase<DWARFListType>::dump(raw_ostream &OS, for (const auto &List : ListMap) for (const auto &Entry : List.second.getEntries()) Entry.dump(OS, getAddrSize(), MaxEncodingStringLength, CurrentBase, - DumpOpts); + DumpOpts, LookupPooledAddress); } template <typename DWARFListType> diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index ddabc7a4652..18ec8476e9d 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -269,9 +269,11 @@ 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) { +static void +dumpRnglistsSection(raw_ostream &OS, DWARFDataExtractor &rnglistData, + llvm::function_ref<Optional<SectionedAddress>(uint32_t)> + LookupPooledAddress, + DIDumpOptions DumpOpts) { uint32_t Offset = 0; while (rnglistData.isValidOffset(Offset)) { llvm::DWARFDebugRnglistTable Rnglists; @@ -285,7 +287,7 @@ static void dumpRnglistsSection(raw_ostream &OS, break; Offset = TableOffset + Length; } else { - Rnglists.dump(OS, DumpOpts); + Rnglists.dump(OS, LookupPooledAddress, DumpOpts); } } } @@ -495,18 +497,26 @@ void DWARFContext::dump( } } + auto LookupPooledAddress = [&](uint32_t Index) -> Optional<SectionedAddress> { + const auto &CUs = compile_units(); + auto I = CUs.begin(); + if (I == CUs.end()) + return None; + return (*I)->getAddrOffsetSectionItem(Index); + }; + if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists, DObj->getRnglistsSection().Data)) { DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(), isLittleEndian(), 0); - dumpRnglistsSection(OS, RnglistData, DumpOpts); + dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts); } if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists, DObj->getRnglistsDWOSection().Data)) { DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(), isLittleEndian(), 0); - dumpRnglistsSection(OS, RnglistData, DumpOpts); + dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts); } if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames, diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp index 72f84159957..cb5fb0d49da 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp @@ -32,21 +32,34 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, Value0 = Value1 = 0; break; // TODO: Support other encodings. - case dwarf::DW_RLE_base_addressx: - return createStringError(errc::not_supported, - "unsupported rnglists encoding DW_RLE_base_addressx " - "at offset 0x%" PRIx32, - *OffsetPtr - 1); + case dwarf::DW_RLE_base_addressx: { + uint32_t PreviousOffset = *OffsetPtr - 1; + Value0 = Data.getULEB128(OffsetPtr); + if (End < *OffsetPtr) + return createStringError( + errc::invalid_argument, + "read past end of table when reading " + "DW_RLE_base_addressx encoding at offset 0x%" PRIx32, + PreviousOffset); + break; + } case dwarf::DW_RLE_startx_endx: return createStringError(errc::not_supported, "unsupported rnglists encoding DW_RLE_startx_endx at " "offset 0x%" PRIx32, *OffsetPtr - 1); - case dwarf::DW_RLE_startx_length: - return createStringError(errc::not_supported, - "unsupported rnglists encoding DW_RLE_startx_length " - "at offset 0x%" PRIx32, - *OffsetPtr - 1); + case dwarf::DW_RLE_startx_length: { + uint32_t PreviousOffset = *OffsetPtr - 1; + Value0 = Data.getULEB128(OffsetPtr); + Value1 = Data.getULEB128(OffsetPtr); + if (End < *OffsetPtr) + return createStringError( + errc::invalid_argument, + "read past end of table when reading " + "DW_RLE_startx_length encoding at offset 0x%" PRIx32, + PreviousOffset); + break; + } case dwarf::DW_RLE_offset_pair: { uint32_t PreviousOffset = *OffsetPtr - 1; Value0 = Data.getULEB128(OffsetPtr); @@ -100,12 +113,19 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, return Error::success(); } -DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( - llvm::Optional<SectionedAddress> BaseAddr) const { +DWARFAddressRangesVector +DWARFDebugRnglist::getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr, + DWARFUnit &U) const { DWARFAddressRangesVector Res; for (const RangeListEntry &RLE : Entries) { if (RLE.EntryKind == dwarf::DW_RLE_end_of_list) break; + if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) { + BaseAddr = U.getAddrOffsetSectionItem(RLE.Value0); + if (!BaseAddr) + BaseAddr = {RLE.Value0, 0}; + continue; + } if (RLE.EntryKind == dwarf::DW_RLE_base_address) { BaseAddr = {RLE.Value0, RLE.SectionIndex}; continue; @@ -133,6 +153,15 @@ DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( E.LowPC = RLE.Value0; E.HighPC = E.LowPC + RLE.Value1; break; + case dwarf::DW_RLE_startx_length: { + auto Start = U.getAddrOffsetSectionItem(RLE.Value0); + if (!Start) + Start = {0, 0}; + E.SectionIndex = Start->SectionIndex; + E.LowPC = Start->Address; + E.HighPC = E.LowPC + RLE.Value1; + break; + } default: // Unsupported encodings should have been reported during extraction, // so we should not run into any here. @@ -143,9 +172,11 @@ 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, 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, uint8_t AddrSize, DIDumpOptions DumpOpts) { if (DumpOpts.Verbose) { @@ -172,6 +203,17 @@ void RangeListEntry::dump(raw_ostream &OS, uint8_t AddrSize, case dwarf::DW_RLE_end_of_list: OS << (DumpOpts.Verbose ? "" : "<End of list>"); break; + // case dwarf::DW_RLE_base_addressx: + case dwarf::DW_RLE_base_addressx: { + if (auto SA = LookupPooledAddress(Value0)) + CurrentBase = SA->Address; + else + CurrentBase = Value0; + if (!DumpOpts.Verbose) + return; + OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); + break; + } case dwarf::DW_RLE_base_address: // In non-verbose mode we do not print anything for this entry. CurrentBase = Value0; @@ -191,6 +233,14 @@ void RangeListEntry::dump(raw_ostream &OS, uint8_t AddrSize, case dwarf::DW_RLE_start_end: DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts); break; + case dwarf::DW_RLE_startx_length: { + PrintRawEntry(OS, *this, AddrSize, DumpOpts); + uint64_t Start = 0; + if (auto SA = LookupPooledAddress(Value0)) + Start = SA->Address; + DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts); + break; + } break; default: llvm_unreachable("Unsupported range list encoding"); } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index 081163ba61f..4cf1f938c3e 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -539,7 +539,7 @@ DWARFUnit::findRnglistFromOffset(uint32_t Offset) { isLittleEndian, RngListTable->getAddrSize()); auto RangeListOrError = RngListTable->findList(RangesData, Offset); if (RangeListOrError) - return RangeListOrError.get().getAbsoluteRanges(getBaseAddress()); + return RangeListOrError.get().getAbsoluteRanges(getBaseAddress(), *this); return RangeListOrError.takeError(); } diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_rnglists.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_rnglists.s index 8f718b699f5..60533ca2721 100644 --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_rnglists.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_rnglists.s @@ -57,6 +57,29 @@ # BOTH: ranges: # BOTH-NOT: [ +# TERSE-NEXT: range list header: length = 0x0000000b, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 + +# VERBOSE-NEXT: 0x{{[0-9a-f]*}}: +# VERBOSE-SAME: range list header: length = 0x0000000b, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 + +# BOTH-NEXT: ranges: +# TERSE-NEXT: <End of list> + +# VERBOSE-NEXT: 0x00000082: [DW_RLE_base_addressx]: 0x0000000000000000 +# VERBOSE-NEXT: 0x00000084: [DW_RLE_end_of_list ] + +# TERSE-NEXT: range list header: length = 0x0000000c, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 + +# VERBOSE-NEXT: 0x{{[0-9a-f]*}}: +# VERBOSE-SAME: range list header: length = 0x0000000c, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 + +# BOTH-NEXT: ranges: +# TERSE-NEXT: [0x0000000000000000, 0x000000000000002a) +# TERSE-NEXT: <End of list> + +# VERBOSE-NEXT: 0x000000a1: [DW_RLE_startx_length]: 0x0000000000000002, 0x000000000000002a => [0x0000000000000000, 0x000000000000002a) +# VERBOSE-NEXT: 0x000000a4: [DW_RLE_end_of_list ] + # TERSE-NEXT: range list header: length = 0x0000000e, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 # VERBOSE-NEXT: 0x{{[0-9a-f]*}}: @@ -87,9 +110,7 @@ # BOTH-NOT: range list header: # ERR-NOT: error: -# ERR: error: unsupported rnglists encoding DW_RLE_base_addressx at offset 0x82 -# ERR-NEXT: error: unsupported rnglists encoding DW_RLE_startx_endx at offset 0x91 -# ERR-NEXT: error: unsupported rnglists encoding DW_RLE_startx_length at offset 0xa1 +# ERR: error: unsupported rnglists encoding DW_RLE_startx_endx at offset 0x91 # ERR-NOT: error: .section .debug_rnglists,"",@progbits |