Index: include/llvm/DebugInfo/DWARF/DWARFListTable.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFListTable.h +++ include/llvm/DebugInfo/DWARF/DWARFListTable.h @@ -57,7 +57,7 @@ struct Header { /// The total length of the entries for this table, not including the length /// field itself. - uint32_t Length = 0; + uint64_t Length = 0; /// The DWARF version number. uint16_t Version; /// The size in bytes of an address on the target architecture. For @@ -75,7 +75,7 @@ /// The offset table, which contains offsets to the individual list entries. /// It is used by forms such as DW_FORM_rnglistx. /// FIXME: Generate the table and use the appropriate forms. - std::vector Offsets; + std::vector Offsets; /// The table's format, either DWARF32 or DWARF64. dwarf::DwarfFormat Format; /// The offset at which the header (and hence the table) is located within @@ -97,14 +97,26 @@ } uint64_t getHeaderOffset() const { return HeaderOffset; } uint8_t getAddrSize() const { return HeaderData.AddrSize; } - uint32_t getLength() const { return HeaderData.Length; } + uint64_t getLength() const { return HeaderData.Length; } uint16_t getVersion() const { return HeaderData.Version; } StringRef getSectionName() const { return SectionName; } StringRef getListTypeString() const { return ListTypeString; } dwarf::DwarfFormat getFormat() const { return Format; } + /// Return the size of the table header including the length but not including + /// the offsets. + static uint8_t getHeaderSize(dwarf::DwarfFormat Format) { + switch (Format) { + case dwarf::DwarfFormat::DWARF32: + return 12; + case dwarf::DwarfFormat::DWARF64: + return 20; + } + llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64"); + } + void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const; - Optional getOffsetEntry(uint32_t Index) const { + Optional getOffsetEntry(uint32_t Index) const { if (Index < Offsets.size()) return Offsets[Index]; return None; @@ -116,7 +128,7 @@ /// Returns the length of the table, including the length field, or 0 if the /// length has not been determined (e.g. because the table has not yet been /// parsed, or there was a problem in parsing). - uint32_t length() const; + uint64_t length() const; }; /// A class representing a table of lists as specified in the DWARF v5 @@ -155,6 +167,7 @@ uint64_t getHeaderOffset() const { return Header.getHeaderOffset(); } uint8_t getAddrSize() const { return Header.getAddrSize(); } + dwarf::DwarfFormat getFormat() const { return Header.getFormat(); } void dump(raw_ostream &OS, llvm::function_ref(uint32_t)> @@ -162,23 +175,17 @@ DIDumpOptions DumpOpts = {}) const; /// Return the contents of the offset entry designated by a given index. - Optional getOffsetEntry(uint32_t Index) const { + Optional getOffsetEntry(uint32_t Index) const { return Header.getOffsetEntry(Index); } /// Return the size of the table header including the length but not including /// the offsets. This is dependent on the table format, which is unambiguously /// derived from parsing the table. uint8_t getHeaderSize() const { - switch (Header.getFormat()) { - case dwarf::DwarfFormat::DWARF32: - return 12; - case dwarf::DwarfFormat::DWARF64: - return 20; - } - llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64"); + return DWARFListTableHeader::getHeaderSize(getFormat()); } - uint32_t length() { return Header.length(); } + uint64_t length() { return Header.length(); } }; template Index: include/llvm/DebugInfo/DWARF/DWARFUnit.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -416,7 +416,7 @@ /// 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 /// DW_FORM_rnglistx. - Optional getRnglistOffset(uint32_t Index) { + Optional getRnglistOffset(uint32_t Index) { if (RngListTable) return RngListTable->getOffsetEntry(Index); return None; Index: lib/DebugInfo/DWARF/DWARFListTable.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFListTable.cpp +++ lib/DebugInfo/DWARF/DWARFListTable.cpp @@ -24,25 +24,34 @@ "section is not large enough to contain a " "%s table length at offset 0x%" PRIx64, SectionName.data(), *OffsetPtr); - // TODO: Add support for DWARF64. - HeaderData.Length = Data.getRelocatedValue(4, OffsetPtr); - if (HeaderData.Length == dwarf::DW_LENGTH_DWARF64) - return createStringError(errc::not_supported, - "DWARF64 is not supported in %s at offset 0x%" PRIx64, - SectionName.data(), HeaderOffset); Format = dwarf::DwarfFormat::DWARF32; - if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header)) + uint8_t OffsetByteSize = 4; + HeaderData.Length = Data.getRelocatedValue(4, OffsetPtr); + if (HeaderData.Length == dwarf::DW_LENGTH_DWARF64) { + Format = dwarf::DwarfFormat::DWARF64; + OffsetByteSize = 8; + HeaderData.Length = Data.getU64(OffsetPtr); + } else if (HeaderData.Length >= dwarf::DW_LENGTH_lo_reserved) { + return createStringError(errc::invalid_argument, + "%s table at offset 0x%" PRIx64 + " has unsupported reserved unit length of value 0x%8.8" PRIx64, + SectionName.data(), HeaderOffset, HeaderData.Length); + } + uint64_t FullLength = + HeaderData.Length + dwarf::getUnitLengthFieldByteSize(Format); + assert(FullLength == length()); + if (FullLength < getHeaderSize(Format)) return createStringError(errc::invalid_argument, "%s table at offset 0x%" PRIx64 - " has too small length (0x%" PRIx32 + " has too small length (0x%" PRIx64 ") to contain a complete header", - SectionName.data(), HeaderOffset, length()); - uint64_t End = HeaderOffset + length(); - if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset)) + SectionName.data(), HeaderOffset, FullLength); + uint64_t End = HeaderOffset + FullLength; + if (!Data.isValidOffsetForDataOfSize(HeaderOffset, FullLength)) return createStringError(errc::invalid_argument, "section is not large enough to contain a %s table " - "of length 0x%" PRIx32 " at offset 0x%" PRIx64, - SectionName.data(), length(), HeaderOffset); + "of length 0x%" PRIx64 " at offset 0x%" PRIx64, + SectionName.data(), FullLength, HeaderOffset); HeaderData.Version = Data.getU16(OffsetPtr); HeaderData.AddrSize = Data.getU8(OffsetPtr); @@ -65,15 +74,15 @@ "%s table at offset 0x%" PRIx64 " has unsupported segment selector size %" PRIu8, SectionName.data(), HeaderOffset, HeaderData.SegSize); - if (End < HeaderOffset + sizeof(HeaderData) + - HeaderData.OffsetEntryCount * sizeof(uint32_t)) + if (End < HeaderOffset + getHeaderSize(Format) + + HeaderData.OffsetEntryCount * OffsetByteSize) return createStringError(errc::invalid_argument, "%s table at offset 0x%" PRIx64 " 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.getRelocatedValue(4, OffsetPtr)); + Offsets.push_back(Data.getRelocatedValue(OffsetByteSize, OffsetPtr)); return Error::success(); } @@ -81,7 +90,7 @@ if (DumpOpts.Verbose) OS << format("0x%8.8" PRIx64 ": ", HeaderOffset); OS << format( - "%s list header: length = 0x%8.8" PRIx32 ", version = 0x%4.4" PRIx16 ", " + "%s list header: length = 0x%8.8" PRIx64 ", version = 0x%4.4" PRIx16 ", " "addr_size = 0x%2.2" PRIx8 ", seg_size = 0x%2.2" PRIx8 ", offset_entry_count = " "0x%8.8" PRIx32 "\n", @@ -91,18 +100,17 @@ if (HeaderData.OffsetEntryCount > 0) { OS << "offsets: ["; for (const auto &Off : Offsets) { - OS << format("\n0x%8.8" PRIx32, Off); + OS << format("\n0x%8.8" PRIx64, Off); if (DumpOpts.Verbose) OS << format(" => 0x%8.8" PRIx64, - Off + HeaderOffset + sizeof(HeaderData)); + Off + HeaderOffset + getHeaderSize(Format)); } OS << "\n]\n"; } } -uint32_t DWARFListTableHeader::length() const { +uint64_t DWARFListTableHeader::length() const { if (HeaderData.Length == 0) return 0; - // TODO: DWARF64 support. - return HeaderData.Length + sizeof(uint32_t); + return HeaderData.Length + dwarf::getUnitLengthFieldByteSize(Format); } Index: test/tools/llvm-dwarfdump/X86/Inputs/debug_rnglists_DWARF64.s =================================================================== --- test/tools/llvm-dwarfdump/X86/Inputs/debug_rnglists_DWARF64.s +++ /dev/null @@ -1,2 +0,0 @@ -.section .debug_rnglists,"",@progbits -.long 0xffffffff # Unsupported DWARF64 format Index: test/tools/llvm-dwarfdump/X86/debug_rnglists_dwarf64.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_rnglists_dwarf64.s @@ -0,0 +1,39 @@ +# RUN: llvm-mc %s -filetype obj -triple x86_64-pc-linux -o - | \ +# RUN: llvm-dwarfdump -v --debug-rnglists - | \ +# RUN: FileCheck %s + +# CHECK: .debug_rnglists contents: +# CHECK-NEXT: 0x00000000: range list header: +# CHECK-SAME: length = 0x0000001a, +# CHECK-SAME: version = 0x0005, +# CHECK-SAME: addr_size = 0x08, +# CHECK-SAME: seg_size = 0x00, +# CHECK-SAME: offset_entry_count = 0x00000002 +# CHECK-NEXT: offsets: [ +# CHECK-NEXT: 0x00000010 => 0x00000024 +# CHECK-NEXT: 0x00000011 => 0x00000025 +# CHECK-NEXT: ] +# CHECK-NEXT: ranges: +# CHECK-NEXT: 0x00000024: [DW_RLE_end_of_list] +# CHECK-NEXT: 0x00000025: [DW_RLE_end_of_list] + + .section .debug_rnglists,"",@progbits + .long 0xffffffff # DWARF64 mark + .quad .Lend - .Lversion # Table length +.Lversion: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 2 # Offset entry count + +.Loffsets: + .quad .Ltable0 - .Loffsets + .quad .Ltable1 - .Loffsets + +.Ltable0: + .byte 0 # DW_RLE_end_of_list + +.Ltable1: + .byte 0 # DW_RLE_end_of_list + +.Lend: Index: test/tools/llvm-dwarfdump/X86/debug_rnglists_invalid.s =================================================================== --- test/tools/llvm-dwarfdump/X86/debug_rnglists_invalid.s +++ test/tools/llvm-dwarfdump/X86/debug_rnglists_invalid.s @@ -37,11 +37,6 @@ # CHECK-NEXT: error: section is not large enough to contain a .debug_rnglists table of length 0x1f at offset 0xe5 # CHECK-NOT: error: -# RUN: llvm-mc %S/Inputs/debug_rnglists_DWARF64.s -filetype obj -triple x86_64-pc-linux -o - | \ -# RUN: llvm-dwarfdump --debug-rnglists - 2>&1 | FileCheck %s --check-prefix=DWARF64 - -# DWARF64: DWARF64 is not supported in .debug_rnglists at offset 0x0 - .section .debug_rnglists,"",@progbits # Table 1 (good) Index: test/tools/llvm-dwarfdump/X86/debug_rnglists_reserved_length.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_rnglists_reserved_length.s @@ -0,0 +1,10 @@ +# RUN: llvm-mc %s -filetype obj -triple x86_64-pc-linux -o - | \ +# RUN: llvm-dwarfdump --debug-rnglists - 2>&1 | \ +# RUN: FileCheck %s + +# CHECK-NOT: error: +# CHECK: error: .debug_rnglists table at offset 0x0 has unsupported reserved unit length of value 0xfffffff0 +# CHECK-NOT: error: + +.section .debug_rnglists,"",@progbits +.long 0xfffffff0