aboutsummaryrefslogtreecommitdiff
path: root/lib/DebugInfo/DWARF/DWARFUnit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/DebugInfo/DWARF/DWARFUnit.cpp')
-rw-r--r--lib/DebugInfo/DWARF/DWARFUnit.cpp147
1 files changed, 98 insertions, 49 deletions
diff --git a/lib/DebugInfo/DWARF/DWARFUnit.cpp b/lib/DebugInfo/DWARF/DWARFUnit.cpp
index 80234665bdeb..b74acf60c747 100644
--- a/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -1,9 +1,8 @@
//===- DWARFUnit.cpp ------------------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -198,7 +197,7 @@ DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const {
getAddressByteSize());
}
-Optional<SectionedAddress>
+Optional<object::SectionedAddress>
DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const {
if (IsDWO) {
auto R = Context.info_section_units();
@@ -242,17 +241,21 @@ bool DWARFUnitHeader::extract(DWARFContext &Context,
IndexEntry = Entry;
if (!IndexEntry && Index)
IndexEntry = Index->getFromOffset(*offset_ptr);
- Length = debug_info.getU32(offset_ptr);
- // FIXME: Support DWARF64.
- unsigned SizeOfLength = 4;
+ Length = debug_info.getRelocatedValue(4, offset_ptr);
FormParams.Format = DWARF32;
+ unsigned SizeOfLength = 4;
+ if (Length == 0xffffffff) {
+ Length = debug_info.getU64(offset_ptr);
+ FormParams.Format = DWARF64;
+ SizeOfLength = 8;
+ }
FormParams.Version = debug_info.getU16(offset_ptr);
if (FormParams.Version >= 5) {
UnitType = debug_info.getU8(offset_ptr);
FormParams.AddrSize = debug_info.getU8(offset_ptr);
- AbbrOffset = debug_info.getU32(offset_ptr);
+ AbbrOffset = debug_info.getRelocatedValue(FormParams.getDwarfOffsetByteSize(), offset_ptr);
} else {
- AbbrOffset = debug_info.getRelocatedValue(4, offset_ptr);
+ AbbrOffset = debug_info.getRelocatedValue(FormParams.getDwarfOffsetByteSize(), offset_ptr);
FormParams.AddrSize = debug_info.getU8(offset_ptr);
// Fake a unit type based on the section type. This isn't perfect,
// but distinguishing compile and type units is generally enough.
@@ -432,12 +435,17 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
// which may differ from the unit's format.
DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection,
isLittleEndian, 0);
- if (IsDWO)
- StringOffsetsTableContribution =
- determineStringOffsetsTableContributionDWO(DA);
- else if (getVersion() >= 5)
- StringOffsetsTableContribution =
- determineStringOffsetsTableContribution(DA);
+ if (IsDWO || getVersion() >= 5) {
+ auto StringOffsetOrError =
+ IsDWO ? determineStringOffsetsTableContributionDWO(DA)
+ : determineStringOffsetsTableContribution(DA);
+ if (!StringOffsetOrError) {
+ WithColor::error() << "invalid contribution to string offsets table in section .debug_str_offsets[.dwo]: "
+ << toString(StringOffsetOrError.takeError()) << '\n';
+ } else {
+ StringOffsetsTableContribution = *StringOffsetOrError;
+ }
+ }
// DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to
// describe address ranges.
@@ -634,7 +642,7 @@ DWARFUnit::getInlinedChainForAddress(uint64_t Address,
// First, find the subroutine that contains the given address (the leaf
// of inlined chain).
DWARFDie SubroutineDIE =
- (DWO ? DWO.get() : this)->getSubroutineForAddress(Address);
+ (DWO ? *DWO : *this).getSubroutineForAddress(Address);
if (!SubroutineDIE)
return;
@@ -745,7 +753,7 @@ const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const {
return Abbrevs;
}
-llvm::Optional<SectionedAddress> DWARFUnit::getBaseAddress() {
+llvm::Optional<object::SectionedAddress> DWARFUnit::getBaseAddress() {
if (BaseAddr)
return BaseAddr;
@@ -755,7 +763,7 @@ llvm::Optional<SectionedAddress> DWARFUnit::getBaseAddress() {
return BaseAddr;
}
-Optional<StrOffsetsContributionDescriptor>
+Expected<StrOffsetsContributionDescriptor>
StrOffsetsContributionDescriptor::validateContributionSize(
DWARFDataExtractor &DA) {
uint8_t EntrySize = getDwarfOffsetByteSize();
@@ -766,58 +774,94 @@ StrOffsetsContributionDescriptor::validateContributionSize(
if (ValidationSize >= Size)
if (DA.isValidOffsetForDataOfSize((uint32_t)Base, ValidationSize))
return *this;
- return None;
+ return createStringError(errc::invalid_argument, "length exceeds section size");
}
// Look for a DWARF64-formatted contribution to the string offsets table
// starting at a given offset and record it in a descriptor.
-static Optional<StrOffsetsContributionDescriptor>
+static Expected<StrOffsetsContributionDescriptor>
parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) {
if (!DA.isValidOffsetForDataOfSize(Offset, 16))
- return None;
+ return createStringError(errc::invalid_argument, "section offset exceeds section size");
if (DA.getU32(&Offset) != 0xffffffff)
- return None;
+ return createStringError(errc::invalid_argument, "32 bit contribution referenced from a 64 bit unit");
uint64_t Size = DA.getU64(&Offset);
uint8_t Version = DA.getU16(&Offset);
(void)DA.getU16(&Offset); // padding
// The encoded length includes the 2-byte version field and the 2-byte
// padding, so we need to subtract them out when we populate the descriptor.
- return {{Offset, Size - 4, Version, DWARF64}};
+ return StrOffsetsContributionDescriptor(Offset, Size - 4, Version, DWARF64);
}
// Look for a DWARF32-formatted contribution to the string offsets table
// starting at a given offset and record it in a descriptor.
-static Optional<StrOffsetsContributionDescriptor>
+static Expected<StrOffsetsContributionDescriptor>
parseDWARF32StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) {
if (!DA.isValidOffsetForDataOfSize(Offset, 8))
- return None;
+ return createStringError(errc::invalid_argument, "section offset exceeds section size");
+
uint32_t ContributionSize = DA.getU32(&Offset);
if (ContributionSize >= 0xfffffff0)
- return None;
+ return createStringError(errc::invalid_argument, "invalid length");
+
uint8_t Version = DA.getU16(&Offset);
(void)DA.getU16(&Offset); // padding
// The encoded length includes the 2-byte version field and the 2-byte
// padding, so we need to subtract them out when we populate the descriptor.
- return {{Offset, ContributionSize - 4, Version, DWARF32}};
+ return StrOffsetsContributionDescriptor(Offset, ContributionSize - 4, Version,
+ DWARF32);
+}
+
+static Expected<StrOffsetsContributionDescriptor>
+parseDWARFStringOffsetsTableHeader(DWARFDataExtractor &DA,
+ llvm::dwarf::DwarfFormat Format,
+ uint64_t Offset) {
+ StrOffsetsContributionDescriptor Desc;
+ switch (Format) {
+ case dwarf::DwarfFormat::DWARF64: {
+ if (Offset < 16)
+ return createStringError(errc::invalid_argument, "insufficient space for 64 bit header prefix");
+ auto DescOrError = parseDWARF64StringOffsetsTableHeader(DA, (uint32_t)Offset - 16);
+ if (!DescOrError)
+ return DescOrError.takeError();
+ Desc = *DescOrError;
+ break;
+ }
+ case dwarf::DwarfFormat::DWARF32: {
+ if (Offset < 8)
+ return createStringError(errc::invalid_argument, "insufficient space for 32 bit header prefix");
+ auto DescOrError = parseDWARF32StringOffsetsTableHeader(DA, (uint32_t)Offset - 8);
+ if (!DescOrError)
+ return DescOrError.takeError();
+ Desc = *DescOrError;
+ break;
+ }
+ }
+ return Desc.validateContributionSize(DA);
}
-Optional<StrOffsetsContributionDescriptor>
+Expected<Optional<StrOffsetsContributionDescriptor>>
DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA) {
- auto Offset = toSectionOffset(getUnitDIE().find(DW_AT_str_offsets_base), 0);
- Optional<StrOffsetsContributionDescriptor> Descriptor;
- // Attempt to find a DWARF64 contribution 16 bytes before the base.
- if (Offset >= 16)
- Descriptor =
- parseDWARF64StringOffsetsTableHeader(DA, (uint32_t)Offset - 16);
- // Try to find a DWARF32 contribution 8 bytes before the base.
- if (!Descriptor && Offset >= 8)
- Descriptor = parseDWARF32StringOffsetsTableHeader(DA, (uint32_t)Offset - 8);
- return Descriptor ? Descriptor->validateContributionSize(DA) : Descriptor;
-}
-
-Optional<StrOffsetsContributionDescriptor>
+ uint64_t Offset;
+ if (IsDWO) {
+ Offset = 0;
+ if (DA.getData().data() == nullptr)
+ return None;
+ } else {
+ auto OptOffset = toSectionOffset(getUnitDIE().find(DW_AT_str_offsets_base));
+ if (!OptOffset)
+ return None;
+ Offset = *OptOffset;
+ }
+ auto DescOrError = parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), Offset);
+ if (!DescOrError)
+ return DescOrError.takeError();
+ return *DescOrError;
+}
+
+Expected<Optional<StrOffsetsContributionDescriptor>>
DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) {
uint64_t Offset = 0;
auto IndexEntry = Header.getIndexEntry();
@@ -826,19 +870,24 @@ DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) {
if (C)
Offset = C->Offset;
if (getVersion() >= 5) {
+ if (DA.getData().data() == nullptr)
+ return None;
+ Offset += Header.getFormat() == dwarf::DwarfFormat::DWARF32 ? 8 : 16;
// Look for a valid contribution at the given offset.
- auto Descriptor =
- parseDWARF64StringOffsetsTableHeader(DA, (uint32_t)Offset);
- if (!Descriptor)
- Descriptor = parseDWARF32StringOffsetsTableHeader(DA, (uint32_t)Offset);
- return Descriptor ? Descriptor->validateContributionSize(DA) : Descriptor;
+ auto DescOrError = parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), Offset);
+ if (!DescOrError)
+ return DescOrError.takeError();
+ return *DescOrError;
}
// Prior to DWARF v5, we derive the contribution size from the
// index table (in a package file). In a .dwo file it is simply
// the length of the string offsets section.
if (!IndexEntry)
- return {{0, StringOffsetSection.Data.size(), 4, DWARF32}};
+ return {
+ Optional<StrOffsetsContributionDescriptor>(
+ {0, StringOffsetSection.Data.size(), 4, DWARF32})};
if (C)
- return {{C->Offset, C->Length, 4, DWARF32}};
+ return {Optional<StrOffsetsContributionDescriptor>(
+ {C->Offset, C->Length, 4, DWARF32})};
return None;
}