summaryrefslogtreecommitdiffstats
path: root/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp')
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp119
1 files changed, 110 insertions, 9 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index c3d8ff2cbc2..e24ef90dd52 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -79,8 +79,10 @@ bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index,
bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index,
uint64_t &Result) const {
- unsigned ItemSize = getDwarfOffsetByteSize();
- uint32_t Offset = StringOffsetSectionBase + Index * ItemSize;
+ if (!StringOffsetsTableContribution)
+ return false;
+ unsigned ItemSize = getDwarfStringOffsetsByteSize();
+ uint32_t Offset = getStringOffsetsBase() + Index * ItemSize;
if (StringOffsetSection.Data.size() < Offset + ItemSize)
return false;
DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection,
@@ -251,15 +253,28 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0);
}
- // In general, we derive the offset of the unit's contibution to the
- // debug_str_offsets{.dwo} section from the unit DIE's
- // DW_AT_str_offsets_base attribute. In dwp files we add to it the offset
- // we get from the index table.
- StringOffsetSectionBase =
- toSectionOffset(UnitDie.find(DW_AT_str_offsets_base), 0);
+ // In general, in DWARF v5 and beyond we derive the start of the unit's
+ // contribution to the string offsets table from the unit DIE's
+ // DW_AT_str_offsets_base attribute. Split DWARF units do not use this
+ // attribute, so we assume that there is a contribution to the string
+ // offsets table starting at offset 0 of the debug_str_offsets.dwo section.
+ // In both cases we need to determine the format of the contribution,
+ // which may differ from the unit's format.
+ uint64_t StringOffsetsContributionBase =
+ isDWO ? 0 : toSectionOffset(UnitDie.find(DW_AT_str_offsets_base), 0);
if (IndexEntry)
if (const auto *C = IndexEntry->getOffset(DW_SECT_STR_OFFSETS))
- StringOffsetSectionBase += C->Offset;
+ StringOffsetsContributionBase += C->Offset;
+
+ DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection,
+ isLittleEndian, 0);
+ if (isDWO)
+ StringOffsetsTableContribution =
+ determineStringOffsetsTableContributionDWO(
+ DA, StringOffsetsContributionBase);
+ else if (getVersion() >= 5)
+ StringOffsetsTableContribution = determineStringOffsetsTableContribution(
+ DA, StringOffsetsContributionBase);
// Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for
// skeleton CU DIE, so that DWARF users not aware of it are not broken.
@@ -466,3 +481,89 @@ const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const {
Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset);
return Abbrevs;
}
+
+Optional<StrOffsetsContributionDescriptor>
+StrOffsetsContributionDescriptor::validateContributionSize(
+ DWARFDataExtractor &DA) {
+ uint8_t EntrySize = getDwarfOffsetByteSize();
+ // In order to ensure that we don't read a partial record at the end of
+ // the section we validate for a multiple of the entry size.
+ uint64_t ValidationSize = alignTo(Size, EntrySize);
+ // Guard against overflow.
+ if (ValidationSize >= Size)
+ if (DA.isValidOffsetForDataOfSize((uint32_t)Base, ValidationSize))
+ return *this;
+ return Optional<StrOffsetsContributionDescriptor>();
+}
+
+// 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>
+parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) {
+ if (!DA.isValidOffsetForDataOfSize(Offset, 16))
+ return Optional<StrOffsetsContributionDescriptor>();
+
+ if (DA.getU32(&Offset) != 0xffffffff)
+ return Optional<StrOffsetsContributionDescriptor>();
+
+ uint64_t Size = DA.getU64(&Offset);
+ uint8_t Version = DA.getU16(&Offset);
+ (void)DA.getU16(&Offset); // padding
+ return StrOffsetsContributionDescriptor(Offset, Size, Version, DWARF64);
+ //return Optional<StrOffsetsContributionDescriptor>(Descriptor);
+}
+
+// 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>
+parseDWARF32StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) {
+ if (!DA.isValidOffsetForDataOfSize(Offset, 8))
+ return Optional<StrOffsetsContributionDescriptor>();
+ uint32_t ContributionSize = DA.getU32(&Offset);
+ if (ContributionSize >= 0xfffffff0)
+ return Optional<StrOffsetsContributionDescriptor>();
+ uint8_t Version = DA.getU16(&Offset);
+ (void)DA.getU16(&Offset); // padding
+ return StrOffsetsContributionDescriptor(Offset, ContributionSize, Version, DWARF32);
+ //return Optional<StrOffsetsContributionDescriptor>(Descriptor);
+}
+
+Optional<StrOffsetsContributionDescriptor>
+DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA,
+ uint64_t Offset) {
+ 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>
+DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA,
+ uint64_t Offset) {
+ if (getVersion() >= 5) {
+ // 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;
+ }
+ // 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.
+ uint64_t Size = 0;
+ if (!IndexEntry)
+ Size = StringOffsetSection.Data.size();
+ else if (const auto *C = IndexEntry->getOffset(DW_SECT_STR_OFFSETS))
+ Size = C->Length;
+ // Return a descriptor with the given offset as base, version 4 and
+ // DWARF32 format.
+ //return Optional<StrOffsetsContributionDescriptor>(
+ //StrOffsetsContributionDescriptor(Offset, Size, 4, DWARF32));
+ return StrOffsetsContributionDescriptor(Offset, Size, 4, DWARF32);
+}
OpenPOWER on IntegriCloud