diff options
Diffstat (limited to 'llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp')
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 110 |
1 files changed, 75 insertions, 35 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index 8493950a29b2..f17dacfce665 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -192,17 +192,18 @@ DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const { Optional<object::SectionedAddress> DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const { - if (IsDWO) { + if (!AddrOffsetSectionBase) { auto R = Context.info_section_units(); // Surprising if a DWO file has more than one skeleton unit in it - this // probably shouldn't be valid, but if a use case is found, here's where to // support it (probably have to linearly search for the matching skeleton CU // here) - if (hasSingleElement(R)) + if (IsDWO && hasSingleElement(R)) return (*R.begin())->getAddrOffsetSectionItem(Index); - } - if (!AddrOffsetSectionBase) + return None; + } + uint64_t Offset = *AddrOffsetSectionBase + Index * getAddressByteSize(); if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize()) return None; @@ -258,26 +259,73 @@ bool DWARFUnitHeader::extract(DWARFContext &Context, } else if (UnitType == DW_UT_split_compile || UnitType == DW_UT_skeleton) DWOId = debug_info.getU64(offset_ptr, &Err); - if (errorToBool(std::move(Err))) + if (Err) { + Context.getWarningHandler()(joinErrors( + createStringError( + errc::invalid_argument, + "DWARF unit at 0x%8.8" PRIx64 " cannot be parsed:", Offset), + std::move(Err))); return false; + } // Header fields all parsed, capture the size of this unit header. assert(*offset_ptr - Offset <= 255 && "unexpected header size"); Size = uint8_t(*offset_ptr - Offset); + uint64_t NextCUOffset = Offset + getUnitLengthFieldByteSize() + getLength(); + + if (!debug_info.isValidOffset(getNextUnitOffset() - 1)) { + Context.getWarningHandler()( + createStringError(errc::invalid_argument, + "DWARF unit from offset 0x%8.8" PRIx64 " incl. " + "to offset 0x%8.8" PRIx64 " excl. " + "extends past section size 0x%8.8zx", + Offset, NextCUOffset, debug_info.size())); + return false; + } + + if (!DWARFContext::isSupportedVersion(getVersion())) { + Context.getWarningHandler()(createStringError( + errc::invalid_argument, + "DWARF unit at offset 0x%8.8" PRIx64 " " + "has unsupported version %" PRIu16 ", supported are 2-%u", + Offset, getVersion(), DWARFContext::getMaxSupportedVersion())); + return false; + } // Type offset is unit-relative; should be after the header and before // the end of the current unit. - bool TypeOffsetOK = - !isTypeUnit() - ? true - : TypeOffset >= Size && - TypeOffset < getLength() + getUnitLengthFieldByteSize(); - bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); - bool VersionOK = DWARFContext::isSupportedVersion(getVersion()); - bool AddrSizeOK = DWARFContext::isAddressSizeSupported(getAddressByteSize()); + if (isTypeUnit() && TypeOffset < Size) { + Context.getWarningHandler()( + createStringError(errc::invalid_argument, + "DWARF type unit at offset " + "0x%8.8" PRIx64 " " + "has its relocated type_offset 0x%8.8" PRIx64 " " + "pointing inside the header", + Offset, Offset + TypeOffset)); + return false; + } + if (isTypeUnit() && + TypeOffset >= getUnitLengthFieldByteSize() + getLength()) { + Context.getWarningHandler()(createStringError( + errc::invalid_argument, + "DWARF type unit from offset 0x%8.8" PRIx64 " incl. " + "to offset 0x%8.8" PRIx64 " excl. has its " + "relocated type_offset 0x%8.8" PRIx64 " pointing past the unit end", + Offset, NextCUOffset, Offset + TypeOffset)); + return false; + } - if (!LengthOK || !VersionOK || !AddrSizeOK || !TypeOffsetOK) + if (!DWARFContext::isAddressSizeSupported(getAddressByteSize())) { + SmallVector<std::string, 3> Sizes; + for (auto Size : DWARFContext::getSupportedAddressSizes()) + Sizes.push_back(std::to_string(Size)); + Context.getWarningHandler()(createStringError( + errc::invalid_argument, + "DWARF unit at offset 0x%8.8" PRIx64 " " + "has unsupported address size %" PRIu8 ", supported are %s", + Offset, getAddressByteSize(), llvm::join(Sizes, ", ").c_str())); return false; + } // Keep track of the highest DWARF version we encounter across all units. Context.setMaxVersionIfGreater(getVersion()); @@ -340,6 +388,7 @@ void DWARFUnit::clear() { RangeSectionBase = 0; LocSectionBase = 0; AddrOffsetSectionBase = None; + SU = nullptr; clearDIEs(false); DWO.reset(); } @@ -360,6 +409,8 @@ void DWARFUnit::extractDIEsToVector( uint64_t NextCUOffset = getNextUnitOffset(); DWARFDebugInfoEntry DIE; DWARFDataExtractor DebugInfoData = getDebugInfoExtractor(); + // The end offset has been already checked by DWARFUnitHeader::extract. + assert(DebugInfoData.isValidOffset(NextCUOffset - 1)); uint32_t Depth = 0; bool IsCUDie = true; @@ -384,6 +435,8 @@ void DWARFUnit::extractDIEsToVector( // Normal DIE if (AbbrDecl->hasChildren()) ++Depth; + else if (Depth == 0) + break; // This unit has a single DIE with no children. } else { // NULL DIE. if (Depth > 0) @@ -392,17 +445,6 @@ void DWARFUnit::extractDIEsToVector( break; // We are done with this compile unit! } } - - // Give a little bit of info if we encounter corrupt DWARF (our offset - // should always terminate at or before the start of the next compilation - // unit header). - if (DIEOffset > NextCUOffset) - Context.getWarningHandler()( - createStringError(errc::invalid_argument, - "DWARF compile unit extends beyond its " - "bounds cu 0x%8.8" PRIx64 " " - "at 0x%8.8" PRIx64 "\n", - getOffset(), DIEOffset)); } void DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { @@ -545,13 +587,11 @@ bool DWARFUnit::parseDWO() { if (!DWOCU) return false; DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU); + DWO->setSkeletonUnit(this); // Share .debug_addr and .debug_ranges section with compile unit in .dwo if (AddrOffsetSectionBase) DWO->setAddrOffsetSection(AddrOffsetSection, *AddrOffsetSectionBase); - if (getVersion() >= 5) { - DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), - DWARFListTableHeader::getHeaderSize(getFormat())); - } else { + if (getVersion() == 4) { auto DWORangesBase = UnitDie.getRangesBaseAttribute(); DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); } @@ -688,15 +728,15 @@ DWARFUnit::getInlinedChainForAddress(uint64_t Address, DWARFDie SubroutineDIE = (DWO ? *DWO : *this).getSubroutineForAddress(Address); - if (!SubroutineDIE) - return; - - while (!SubroutineDIE.isSubprogramDIE()) { + while (SubroutineDIE) { + if (SubroutineDIE.isSubprogramDIE()) { + InlinedChain.push_back(SubroutineDIE); + return; + } if (SubroutineDIE.getTag() == DW_TAG_inlined_subroutine) InlinedChain.push_back(SubroutineDIE); SubroutineDIE = SubroutineDIE.getParent(); } - InlinedChain.push_back(SubroutineDIE); } const DWARFUnitIndex &llvm::getDWARFUnitIndex(DWARFContext &Context, @@ -793,7 +833,7 @@ DWARFDie DWARFUnit::getLastChild(const DWARFDebugInfoEntry *Die) { const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const { if (!Abbrevs) - Abbrevs = Abbrev->getAbbreviationDeclarationSet(Header.getAbbrOffset()); + Abbrevs = Abbrev->getAbbreviationDeclarationSet(getAbbreviationsOffset()); return Abbrevs; } |
