Index: lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp +++ lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp @@ -114,14 +114,27 @@ return createError("unsupported rnglists encoding DW_RLE_startx_length " "at offset 0x%" PRIx32, *OffsetPtr - 1); - case dwarf::DW_RLE_offset_pair: - return createError("unsupported rnglists encoding DW_RLE_offset_pair at " - "offset 0x%" PRIx32, - *OffsetPtr - 1); - case dwarf::DW_RLE_base_address: - return createError("unsupported rnglists encoding DW_RLE_base_address at " - "offset 0x%" PRIx32, - *OffsetPtr - 1); + case dwarf::DW_RLE_offset_pair: { + uint32_t PreviousOffset = *OffsetPtr - 1; + uint64_t StartingOffset = Data.getULEB128(OffsetPtr); + uint64_t EndingOffset = Data.getULEB128(OffsetPtr); + if (End < *OffsetPtr) + return createError("read past end of table when reading " + "DW_RLE_offset_pair encoding at offset 0x%" PRIx32, + PreviousOffset); + CurrentRanges.push_back( + RangeListEntry{EntryOffset, Encoding, StartingOffset, EndingOffset}); + break; + } + case dwarf::DW_RLE_base_address: { + if ((End - *OffsetPtr) < HeaderData.AddrSize) + return createError("insufficient space remaining in table for " + "DW_RLE_base_address encoding at offset 0x%" PRIx32, + *OffsetPtr - 1); + uint64_t Base = Data.getAddress(OffsetPtr); + CurrentRanges.push_back(RangeListEntry{EntryOffset, Encoding, Base, 0}); + break; + } case dwarf::DW_RLE_start_end: { if ((End - *OffsetPtr) < unsigned(HeaderData.AddrSize * 2)) return createError("insufficient space remaining in table for " @@ -173,7 +186,18 @@ static void dumpRangeEntry(raw_ostream &OS, DWARFDebugRnglists::RangeListEntry Entry, uint8_t AddrSize, uint8_t MaxEncodingStringLength, - DIDumpOptions DumpOpts) { + uint64_t &CurrentBase, DIDumpOptions DumpOpts) { + auto PrintRawEntry = [](raw_ostream &OS, + DWARFDebugRnglists::RangeListEntry Entry, + uint8_t AddrSize, DIDumpOptions DumpOpts) { + if (DumpOpts.Verbose) { + DumpOpts.DisplayRawContents = true; + DWARFAddressRange(Entry.Value0, Entry.Value1) + .dump(OS, AddrSize, DumpOpts); + OS << " => "; + } + }; + if (DumpOpts.Verbose) { // Print the section offset in verbose mode. OS << format("0x%8.8" PRIx32 ":", Entry.Offset); @@ -190,19 +214,23 @@ case dwarf::DW_RLE_end_of_list: OS << (DumpOpts.Verbose ? "" : ""); break; + case dwarf::DW_RLE_base_address: + // In non-verbose mode we do not print anything for this entry. + CurrentBase = Entry.Value0; + if (!DumpOpts.Verbose) + return; + OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Entry.Value0); + break; case dwarf::DW_RLE_start_length: - if (DumpOpts.Verbose) { - // Make the address range display its contents in raw form rather than - // as an interval (i.e. without brackets). - DumpOpts.DisplayRawContents = true; - DWARFAddressRange(Entry.Value0, Entry.Value1) - .dump(OS, AddrSize, DumpOpts); - OS << " => "; - } - DumpOpts.DisplayRawContents = false; + PrintRawEntry(OS, Entry, AddrSize, DumpOpts); DWARFAddressRange(Entry.Value0, Entry.Value0 + Entry.Value1) .dump(OS, AddrSize, DumpOpts); break; + case dwarf::DW_RLE_offset_pair: + PrintRawEntry(OS, Entry, AddrSize, DumpOpts); + DWARFAddressRange(Entry.Value0 + CurrentBase, Entry.Value1 + CurrentBase) + .dump(OS, AddrSize, DumpOpts); + break; case dwarf::DW_RLE_start_end: DWARFAddressRange(Entry.Value0, Entry.Value1).dump(OS, AddrSize, DumpOpts); break; @@ -235,10 +263,11 @@ } OS << "Ranges:\n"; + uint64_t CurrentBase = 0; for (const auto &List : Ranges) for (const auto &Entry : List) dumpRangeEntry(OS, Entry, HeaderData.AddrSize, MaxEncodingStringLength, - DumpOpts); + CurrentBase, DumpOpts); } uint32_t DWARFDebugRnglists::length() const { Index: test/tools/llvm-dwarfdump/X86/debug_rnglists.s =================================================================== --- test/tools/llvm-dwarfdump/X86/debug_rnglists.s +++ test/tools/llvm-dwarfdump/X86/debug_rnglists.s @@ -56,14 +56,40 @@ # BOTH-NOT: Offsets: # BOTH: Ranges: # BOTH-NOT: [ + +# 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]*}}: +# VERBOSE-SAME: Range List Header: length = 0x0000000e, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 + +# BOTH-NEXT: Ranges: +# TERSE-NEXT: [0x0000000000000800, 0x0000000000001000) +# TERSE-NEXT: + +# VERBOSE-NEXT: 0x000000b1: [DW_RLE_offset_pair]: 0x0000000000000800, 0x0000000000001000 => +# VERBOSE-SAME: [0x0000000000000800, 0x0000000000001000) +# VERBOSE-NEXT: 0x000000b6: [DW_RLE_end_of_list] + +# TERSE-NEXT: Range List Header: length = 0x00000017, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 + +# VERBOSE-NEXT: 0x{{[0-9a-f]*}}: +# VERBOSE-SAME: Range List Header: length = 0x00000017, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 + +# BOTH-NEXT: Ranges: +# TERSE-NEXT: [0x0000000000001800, 0x0000000000002000) +# TERSE-NEXT: + +# VERBOSE-NEXT: 0x000000c3: [DW_RLE_base_address]: 0x0000000000001000 +# VERBOSE-NEXT: 0x000000cc: [DW_RLE_offset_pair ]: 0x0000000000000800, 0x0000000000001000 => +# VERBOSE-SAME: [0x0000000000001800, 0x0000000000002000) +# VERBOSE-NEXT: 0x000000d1: [DW_RLE_end_of_list ] + # 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-NEXT: error: unsupported rnglists encoding DW_RLE_offset_pair at offset 0xb1 -# ERR-NEXT: error: unsupported rnglists encoding DW_RLE_base_address at offset 0xc # ERR-NOT: error: .section .debug_rnglists,"",@progbits @@ -161,7 +187,7 @@ .byte 0 # DW_RLE_end_of_list # Seventh table (testing DW_RLE_offset_pair) -.long 12 # Table length +.long 14 # Table length .short 5 # Version .byte 8 # Address size .byte 0 # Segment selector size @@ -169,12 +195,13 @@ # First range list .byte 4 # DW_RLE_offset_pair -.byte 3 # Start offset (index in .debug_addr) -.byte 19 # End offset (index in .debug_addr) +.byte 0x80, 0x10 # Start offset +.byte 0x80, 0x20 # End offset (index in .debug_addr) .byte 0 # DW_RLE_end_of_list -# Eigth table (testing DW_RLE_base_address) -.long 18 # Table length +# Eigth table (testing DW_RLE_base_address and its impact +# on DW_RLE_offset_pair) +.long 23 # Table length .short 5 # Version .byte 8 # Address size .byte 0 # Segment selector size @@ -183,4 +210,7 @@ # First range list .byte 5 # DW_RLE_base_address .quad 0x1000 # Base address +.byte 4 # DW_RLE_offset_pair +.byte 0x80, 0x10 # Start offset +.byte 0x80, 0x20 # End offset .byte 0 # DW_RLE_end_of_list