Skip to content

Commit

Permalink
llvm-dwarfdump: Don't try to parse rnglist tables when dumping CUs
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
dwblaikie committed Oct 5, 2020
1 parent e372c1d commit 6d0be74
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 78 deletions.
15 changes: 11 additions & 4 deletions llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h
Expand Up @@ -116,9 +116,15 @@ class DWARFListTableHeader {
if (Index > HeaderData.OffsetEntryCount)
return None;

return getOffsetEntry(Data, getHeaderOffset() + getHeaderSize(Format), Format, Index);
}

static Optional<uint64_t> 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;
}
Expand Down Expand Up @@ -272,9 +278,10 @@ DWARFListTableBase<DWARFListType>::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;
Expand Down
1 change: 0 additions & 1 deletion llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
Expand Up @@ -229,7 +229,6 @@ class DWARFUnit {
Optional<StrOffsetsContributionDescriptor> StringOffsetsTableContribution;

/// A table of range lists (DWARF v5 and later).
Optional<DWARFDebugRnglistTable> RngListTable;
Optional<DWARFListTableHeader> LoclistTableHeader;

mutable const DWARFAbbreviationDeclarationSet *Abbrevs;
Expand Down
72 changes: 19 additions & 53 deletions llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
Expand Up @@ -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<DWARFDebugRnglistTable>(
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.
Expand Down Expand Up @@ -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<DWARFDebugRnglistTable>(
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);
Expand All @@ -638,30 +609,24 @@ 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<DWARFAddressRangesVector>
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<DWARFAddressRangesVector> DWARFUnit::collectAddressRanges() {
Expand Down Expand Up @@ -1007,11 +972,12 @@ DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) {
}

Optional<uint64_t> DWARFUnit::getRnglistOffset(uint32_t Index) {
if (!RngListTable)
return None;
DataExtractor RangesData(RangeSection->Data, isLittleEndian,
getAddressByteSize());
if (Optional<uint64_t> Off = RngListTable->getOffsetEntry(RangesData, Index))
DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection,
isLittleEndian, 0);
if (Optional<uint64_t> Off = llvm::DWARFListTableHeader::getOffsetEntry(
RangesData, RangeSectionBase, getFormat(), Index))
return *Off + RangeSectionBase;
return None;
}
7 changes: 3 additions & 4 deletions 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

Expand Down Expand Up @@ -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:
Expand Down
6 changes: 2 additions & 4 deletions 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.
Expand Down Expand Up @@ -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
19 changes: 7 additions & 12 deletions 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)
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 6d0be74

Please sign in to comment.