From 6d0be74af5555f7bc56ac72cbd98ff270fd1291b Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Sun, 4 Oct 2020 19:06:28 -0700 Subject: [PATCH] llvm-dwarfdump: Don't try to parse rnglist tables when dumping CUs It's not possible to do this in complete generality - a CU using a sec_offset DW_AT_ranges has no way of knowing where its rnglists contribution starts, so should not attempt to parse any full rnglist table/header to do so. And even using FORM_rnglistx there's no need to parse the header - the offset can be computed using the CU's DWARF format (32 or 64) to compute offset entry sizes, and then the list parsed at that offset without ever trying to find a rnglist contribution header immediately prior to the rnglists_base. --- .../llvm/DebugInfo/DWARF/DWARFListTable.h | 15 ++-- llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h | 1 - llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 72 +++++-------------- .../X86/dwarfdump-rnglists-dwarf64.s | 7 +- llvm/test/DebugInfo/X86/dwarfdump-rnglists.s | 6 +- .../test/tools/llvm-dwarfdump/X86/tombstone.s | 19 ++--- 6 files changed, 42 insertions(+), 78 deletions(-) diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h index ee9f7adb96c48..8f58b4e6458e1 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h @@ -116,9 +116,15 @@ class DWARFListTableHeader { if (Index > HeaderData.OffsetEntryCount) return None; + return getOffsetEntry(Data, getHeaderOffset() + getHeaderSize(Format), Format, Index); + } + + static Optional getOffsetEntry(DataExtractor Data, + uint64_t OffsetTableOffset, + dwarf::DwarfFormat Format, + uint32_t Index) { uint8_t OffsetByteSize = Format == dwarf::DWARF64 ? 8 : 4; - uint64_t Offset = - getHeaderOffset() + getHeaderSize(Format) + OffsetByteSize * Index; + uint64_t Offset = OffsetTableOffset + OffsetByteSize * Index; auto R = Data.getUnsigned(&Offset, OffsetByteSize); return R; } @@ -272,9 +278,10 @@ DWARFListTableBase::findList(DWARFDataExtractor Data, uint64_t Offset) { // Extract the list from the section and enter it into the list map. DWARFListType List; - Data = DWARFDataExtractor(Data, getHeaderOffset() + Header.length()); + if (Header.length()) + Data = DWARFDataExtractor(Data, getHeaderOffset() + Header.length()); if (Error E = - List.extract(Data, getHeaderOffset(), &Offset, + List.extract(Data, Header.length() ? getHeaderOffset() : 0, &Offset, Header.getSectionName(), Header.getListTypeString())) return std::move(E); return List; diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h index d0664c271fb57..0b0238f7235e2 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -229,7 +229,6 @@ class DWARFUnit { Optional StringOffsetsTableContribution; /// A table of range lists (DWARF v5 and later). - Optional RngListTable; Optional LoclistTableHeader; mutable const DWARFAbbreviationDeclarationSet *Abbrevs; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index b871e6ebdca56..67066db15b4ab 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -503,27 +503,9 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) { DWARFListTableHeader::getHeaderSize(Header.getFormat())); } 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); - auto TableOrError = parseListTableHeader( - RangesDA, RangeSectionBase, Header.getFormat()); - if (!TableOrError) - return createStringError(errc::invalid_argument, - "parsing a range list table: " + - toString(TableOrError.takeError())); - - RngListTable = TableOrError.get(); - - // 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 = - ContributionBaseOffset + RngListTable->getHeaderSize(); - } + toSectionOffset(UnitDie.find(DW_AT_rnglists_base), + DWARFListTableHeader::getHeaderSize( + Header.getFormat()))); // In a split dwarf unit, there is no DW_AT_loclists_base attribute. // Setting LocSectionBase to point past the table header. @@ -602,19 +584,8 @@ bool DWARFUnit::parseDWO() { if (AddrOffsetSectionBase) DWO->setAddrOffsetSection(AddrOffsetSection, *AddrOffsetSectionBase); if (getVersion() >= 5) { - DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0); - DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, - isLittleEndian, 0); - if (auto TableOrError = parseListTableHeader( - RangesDA, RangeSectionBase, Header.getFormat())) - DWO->RngListTable = TableOrError.get(); - else - Context.getRecoverableErrorHandler()(createStringError( - errc::invalid_argument, "parsing a range list table: %s", - toString(TableOrError.takeError()).c_str())); - - if (DWO->RngListTable) - DWO->RangeSectionBase = DWO->RngListTable->getHeaderSize(); + DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), + DWARFListTableHeader::getHeaderSize(getFormat())); } else { auto DWORangesBase = UnitDie.getRangesBaseAttribute(); DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); @@ -638,17 +609,13 @@ DWARFUnit::findRnglistFromOffset(uint64_t Offset) { return std::move(E); return RangeList.getAbsoluteRanges(getBaseAddress()); } - if (RngListTable) { - DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, - isLittleEndian, RngListTable->getAddrSize()); - auto RangeListOrError = RngListTable->findList(RangesData, Offset); - if (RangeListOrError) - return RangeListOrError.get().getAbsoluteRanges(getBaseAddress(), *this); - return RangeListOrError.takeError(); - } - - return createStringError(errc::invalid_argument, - "missing or invalid range list table"); + DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, + isLittleEndian, Header.getAddressByteSize()); + DWARFDebugRnglistTable RnglistTable; + auto RangeListOrError = RnglistTable.findList(RangesData, Offset); + if (RangeListOrError) + return RangeListOrError.get().getAbsoluteRanges(getBaseAddress(), *this); + return RangeListOrError.takeError(); } Expected @@ -656,12 +623,10 @@ DWARFUnit::findRnglistFromIndex(uint32_t Index) { if (auto Offset = getRnglistOffset(Index)) return findRnglistFromOffset(*Offset); - if (RngListTable) - return createStringError(errc::invalid_argument, - "invalid range list table index %d", Index); - return createStringError(errc::invalid_argument, - "missing or invalid range list table"); + "invalid range list table index %d (possibly " + "missing the entire range list table)", + Index); } Expected DWARFUnit::collectAddressRanges() { @@ -1007,11 +972,12 @@ DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) { } Optional DWARFUnit::getRnglistOffset(uint32_t Index) { - if (!RngListTable) - return None; DataExtractor RangesData(RangeSection->Data, isLittleEndian, getAddressByteSize()); - if (Optional Off = RngListTable->getOffsetEntry(RangesData, Index)) + DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, + isLittleEndian, 0); + if (Optional Off = llvm::DWARFListTableHeader::getOffsetEntry( + RangesData, RangeSectionBase, getFormat(), Index)) return *Off + RangeSectionBase; return None; } diff --git a/llvm/test/DebugInfo/X86/dwarfdump-rnglists-dwarf64.s b/llvm/test/DebugInfo/X86/dwarfdump-rnglists-dwarf64.s index f6c8751083f3a..5c8eaffe001cf 100644 --- a/llvm/test/DebugInfo/X86/dwarfdump-rnglists-dwarf64.s +++ b/llvm/test/DebugInfo/X86/dwarfdump-rnglists-dwarf64.s @@ -1,8 +1,8 @@ # RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o %t.o # RUN: not llvm-dwarfdump -v -debug-info %t.o 2> %t.err | FileCheck %s -# RUN: FileCheck %s --input-file %t.err --check-prefix=ERR +# RUN: FileCheck %s --input-file %t.err --check-prefix=ERR --implicit-check-not=error # RUN: not llvm-dwarfdump -lookup 10 %t.o 2> %t2.err -# RUN: FileCheck %s --input-file %t2.err --check-prefix=ERR +# RUN: FileCheck %s --input-file %t2.err --check-prefix=ERR --implicit-check-not=error # RUN: llvm-dwarfdump -debug-rnglists %t.o | \ # RUN: FileCheck %s --check-prefix=RNGLISTS @@ -209,8 +209,7 @@ Range1_end: # CHECK-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x1) rangelist = 0x00000025 # CHECK-NEXT: [0x0000002a, 0x00000034)) -#ERR: error: parsing a range list table: did not detect a valid list table with base = 0x8 -#ERR: error: decoding address ranges: missing or invalid range list table +#ERR: error: decoding address ranges: invalid range list offset 0x4000500000008 #ERR: error: decoding address ranges: invalid range list offset 0xfa0 # RNGLISTS: .debug_rnglists contents: diff --git a/llvm/test/DebugInfo/X86/dwarfdump-rnglists.s b/llvm/test/DebugInfo/X86/dwarfdump-rnglists.s index 45cf65c985f8c..74de6427df717 100644 --- a/llvm/test/DebugInfo/X86/dwarfdump-rnglists.s +++ b/llvm/test/DebugInfo/X86/dwarfdump-rnglists.s @@ -1,8 +1,8 @@ # RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o %t.o # RUN: not llvm-dwarfdump -v -debug-info %t.o 2> %t.err | FileCheck %s -# RUN: FileCheck %s --input-file %t.err --check-prefix=ERR +# RUN: FileCheck %s --input-file %t.err --check-prefix=ERR --implicit-check-not=error # RUN: not llvm-dwarfdump -lookup 10 %t.o 2> %t2.err -# RUN: FileCheck %s --input-file %t2.err --check-prefix=ERR +# RUN: FileCheck %s --input-file %t2.err --check-prefix=ERR --implicit-check-not=error # Test object to verify dwarfdump handles v5 range lists. # We use very simplified compile unit dies. @@ -203,6 +203,4 @@ Range1_end: # CHECK-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x1) rangelist = 0x00000015 # CHECK-NEXT: [0x0000002a, 0x00000034)) -#ERR: error: parsing a range list table: did not detect a valid list table with base = 0x8 -#ERR: error: decoding address ranges: missing or invalid range list table #ERR: error: decoding address ranges: invalid range list offset 0xfa0 diff --git a/llvm/test/tools/llvm-dwarfdump/X86/tombstone.s b/llvm/test/tools/llvm-dwarfdump/X86/tombstone.s index 3465d08bf261e..7b4ff70e5ff58 100644 --- a/llvm/test/tools/llvm-dwarfdump/X86/tombstone.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/tombstone.s @@ -1,7 +1,5 @@ # RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o %t.o -# RUN: not llvm-dwarfdump -v -debug-info -debug-line -debug-addr -debug-rnglists -debug-ranges %t.o | FileCheck --implicit-check-not=DW_TAG --implicit-check-not=DW_AT %s - -# FIXME: Remove the 'not' once the rnglist are lazily/correctly parsed (see comment below) +# RUN: llvm-dwarfdump -v -debug-info -debug-line -debug-addr -debug-rnglists -debug-ranges %t.o | FileCheck --implicit-check-not=DW_TAG --implicit-check-not=DW_AT %s # Test that llvm - dwarfdump strips addresses relating to dead code(using the # DWARFv6 - proposed tombstone constant & nearest equivalent for debug_ranges) @@ -45,17 +43,14 @@ # CHECK: DW_TAG_compile_unit # CHECK: DW_AT_addr_base -# FIXME: Lazily parse rnglists rather than expecting to be able to parse an -# entire rnglists contribution (since there's no way to know where such a -# contribution starts) - rather than assuming one starts at 0. # CHECK: DW_AT_ranges -# [0x0000000000000042, 0x0000000000000048) -# [0x0000000000000042, 0x0000000000000048) -# [0x0000000000000042, 0x0000000000000048) -# [0x0000000000000042, 0x0000000000000042) -# [0x0000000000000042, 0x0000000000000048) -# [0x0000000000000042, 0x0000000000000048)) +# CHECK-NEXT: [0x0000000000000042, 0x0000000000000048) +# CHECK-NEXT: [0x0000000000000042, 0x0000000000000048) +# CHECK-NEXT: [0x0000000000000042, 0x0000000000000048) +# CHECK-NEXT: [0x0000000000000042, 0x0000000000000042) +# CHECK-NEXT: [0x0000000000000042, 0x0000000000000048) +# CHECK-NEXT: [0x0000000000000042, 0x0000000000000048)) # CHECK: DW_TAG_subprogram # CHECK: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000000) address = 0xffffffffffffffff (dead code)) # CHECK: DW_AT_high_pc [DW_FORM_data4] (0x00000006)