diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-04-14 21:41:27 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-06-22 18:20:56 +0000 |
commit | bdd1243df58e60e85101c09001d9812a789b6bc4 (patch) | |
tree | a1ce621c7301dd47ba2ddc3b8eaa63b441389481 /contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | |
parent | 781624ca2d054430052c828ba8d2c2eaf2d733e7 (diff) | |
parent | e3b557809604d036af6e00c60f012c2025b59a5e (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 208 |
1 files changed, 136 insertions, 72 deletions
diff --git a/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index 74667fcb92bc..c199e0118a6f 100644 --- a/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -134,11 +134,11 @@ void DWARFUnitVector::addUnitsImpl( } DWARFUnit *DWARFUnitVector::addUnit(std::unique_ptr<DWARFUnit> Unit) { - auto I = std::upper_bound(begin(), end(), Unit, - [](const std::unique_ptr<DWARFUnit> &LHS, - const std::unique_ptr<DWARFUnit> &RHS) { - return LHS->getOffset() < RHS->getOffset(); - }); + auto I = llvm::upper_bound(*this, Unit, + [](const std::unique_ptr<DWARFUnit> &LHS, + const std::unique_ptr<DWARFUnit> &RHS) { + return LHS->getOffset() < RHS->getOffset(); + }); return this->insert(I, std::move(Unit))->get(); } @@ -160,11 +160,11 @@ DWARFUnitVector::getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) { if (!CUOff) return nullptr; - auto Offset = CUOff->Offset; + uint64_t Offset = CUOff->getOffset(); auto end = begin() + getNumInfoUnits(); auto *CU = - std::upper_bound(begin(), end, CUOff->Offset, + std::upper_bound(begin(), end, CUOff->getOffset(), [](uint64_t LHS, const std::unique_ptr<DWARFUnit> &RHS) { return LHS < RHS->getNextUnitOffset(); }); @@ -192,7 +192,7 @@ DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, bool IsDWO, const DWARFUnitVector &UnitVector) : Context(DC), InfoSection(Section), Header(Header), Abbrev(DA), RangeSection(RS), LineSection(LS), StringSection(SS), - StringOffsetSection(SOS), AddrOffsetSection(AOS), isLittleEndian(LE), + StringOffsetSection(SOS), AddrOffsetSection(AOS), IsLittleEndian(LE), IsDWO(IsDWO), UnitVector(UnitVector) { clear(); } @@ -200,11 +200,11 @@ DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, DWARFUnit::~DWARFUnit() = default; DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const { - return DWARFDataExtractor(Context.getDWARFObj(), InfoSection, isLittleEndian, + return DWARFDataExtractor(Context.getDWARFObj(), InfoSection, IsLittleEndian, getAddressByteSize()); } -Optional<object::SectionedAddress> +std::optional<object::SectionedAddress> DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const { if (!AddrOffsetSectionBase) { auto R = Context.info_section_units(); @@ -215,14 +215,14 @@ DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const { if (IsDWO && hasSingleElement(R)) return (*R.begin())->getAddrOffsetSectionItem(Index); - return None; + return std::nullopt; } uint64_t Offset = *AddrOffsetSectionBase + Index * getAddressByteSize(); if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize()) - return None; + return std::nullopt; DWARFDataExtractor DA(Context.getDWARFObj(), *AddrOffsetSection, - isLittleEndian, getAddressByteSize()); + IsLittleEndian, getAddressByteSize()); uint64_t Section; uint64_t Address = DA.getRelocatedAddress(&Offset, &Section); return {{Address, Section}}; @@ -240,7 +240,7 @@ Expected<uint64_t> DWARFUnit::getStringOffsetSectionItem(uint32_t Index) const { ", which is too large", inconvertibleErrorCode()); DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, - isLittleEndian, 0); + IsLittleEndian, 0); return DA.getRelocatedValue(ItemSize, &Offset); } @@ -353,12 +353,12 @@ bool DWARFUnitHeader::applyIndexEntry(const DWARFUnitIndex::Entry *Entry) { return false; auto *UnitContrib = IndexEntry->getContribution(); if (!UnitContrib || - UnitContrib->Length != (getLength() + getUnitLengthFieldByteSize())) + UnitContrib->getLength() != (getLength() + getUnitLengthFieldByteSize())) return false; auto *AbbrEntry = IndexEntry->getContribution(DW_SECT_ABBREV); if (!AbbrEntry) return false; - AbbrOffset = AbbrEntry->Offset; + AbbrOffset = AbbrEntry->getOffset(); return true; } @@ -367,7 +367,7 @@ Error DWARFUnit::extractRangeList(uint64_t RangeListOffset, // Require that compile unit is extracted. assert(!DieArray.empty()); DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, - isLittleEndian, getAddressByteSize()); + IsLittleEndian, getAddressByteSize()); uint64_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; return RangeList.extract(RangesData, &ActualRangeListOffset); } @@ -377,7 +377,7 @@ void DWARFUnit::clear() { BaseAddr.reset(); RangeSectionBase = 0; LocSectionBase = 0; - AddrOffsetSectionBase = None; + AddrOffsetSectionBase = std::nullopt; SU = nullptr; clearDIEs(false); AddrDieMap.clear(); @@ -499,10 +499,11 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) { return Error::success(); DWARFDie UnitDie(this, &DieArray[0]); - if (Optional<uint64_t> DWOId = toUnsigned(UnitDie.find(DW_AT_GNU_dwo_id))) + if (std::optional<uint64_t> DWOId = + toUnsigned(UnitDie.find(DW_AT_GNU_dwo_id))) Header.setDWOId(*DWOId); if (!IsDWO) { - assert(AddrOffsetSectionBase == None); + assert(AddrOffsetSectionBase == std::nullopt); assert(RangeSectionBase == 0); assert(LocSectionBase == 0); AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_addr_base)); @@ -521,7 +522,7 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) { // In both cases we need to determine the format of the contribution, // which may differ from the unit's format. DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, - isLittleEndian, 0); + IsLittleEndian, 0); if (IsDWO || getVersion() >= 5) { auto StringOffsetOrError = IsDWO ? determineStringOffsetsTableContributionDWO(DA) @@ -543,7 +544,7 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) { uint64_t ContributionBaseOffset = 0; if (auto *IndexEntry = Header.getIndexEntry()) if (auto *Contrib = IndexEntry->getContribution(DW_SECT_RNGLISTS)) - ContributionBaseOffset = Contrib->Offset; + ContributionBaseOffset = Contrib->getOffset(); setRangesSection( &Context.getDWARFObj().getRnglistsDWOSection(), ContributionBaseOffset + @@ -564,9 +565,9 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) { if (auto *IndexEntry = Header.getIndexEntry()) if (const auto *C = IndexEntry->getContribution( Header.getVersion() >= 5 ? DW_SECT_LOCLISTS : DW_SECT_EXT_LOC)) - Data = Data.substr(C->Offset, C->Length); + Data = Data.substr(C->getOffset(), C->getLength()); - DWARFDataExtractor DWARFData(Data, isLittleEndian, getAddressByteSize()); + DWARFDataExtractor DWARFData(Data, IsLittleEndian, getAddressByteSize()); LocTable = std::make_unique<DWARFDebugLoclists>(DWARFData, Header.getVersion()); LocSectionBase = DWARFListTableHeader::getHeaderSize(Header.getFormat()); @@ -574,12 +575,12 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) { LocTable = std::make_unique<DWARFDebugLoclists>( DWARFDataExtractor(Context.getDWARFObj(), Context.getDWARFObj().getLoclistsSection(), - isLittleEndian, getAddressByteSize()), + IsLittleEndian, getAddressByteSize()), getVersion()); } else { LocTable = std::make_unique<DWARFDebugLoc>(DWARFDataExtractor( Context.getDWARFObj(), Context.getDWARFObj().getLocSection(), - isLittleEndian, getAddressByteSize())); + IsLittleEndian, getAddressByteSize())); } // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for @@ -587,10 +588,10 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) { return Error::success(); } -bool DWARFUnit::parseDWO() { +bool DWARFUnit::parseDWO(StringRef DWOAlternativeLocation) { if (IsDWO) return false; - if (DWO.get()) + if (DWO) return false; DWARFDie UnitDie = getUnitDIE(); if (!UnitDie) @@ -611,8 +612,17 @@ bool DWARFUnit::parseDWO() { if (!DWOId) return false; auto DWOContext = Context.getDWOContext(AbsolutePath); - if (!DWOContext) - return false; + if (!DWOContext) { + // Use the alternative location to get the DWARF context for the DWO object. + if (DWOAlternativeLocation.empty()) + return false; + // If the alternative context does not correspond to the original DWO object + // (different hashes), the below 'getDWOCompileUnitForHash' call will catch + // the issue, with a returned null context. + DWOContext = Context.getDWOContext(DWOAlternativeLocation); + if (!DWOContext) + return false; + } DWARFCompileUnit *DWOCU = DWOContext->getDWOCompileUnitForHash(*DWOId); if (!DWOCU) @@ -650,7 +660,7 @@ DWARFUnit::findRnglistFromOffset(uint64_t Offset) { return RangeList.getAbsoluteRanges(getBaseAddress()); } DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, - isLittleEndian, Header.getAddressByteSize()); + IsLittleEndian, Header.getAddressByteSize()); DWARFDebugRnglistTable RnglistTable; auto RangeListOrError = RnglistTable.findList(RangesData, Offset); if (RangeListOrError) @@ -819,7 +829,7 @@ void DWARFUnit::updateVariableDieMap(DWARFDie Die) { // exact address. uint64_t GVSize = 1; if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type)) - if (Optional<uint64_t> Size = Die.getTypeSize(getAddressByteSize())) + if (std::optional<uint64_t> Size = Die.getTypeSize(getAddressByteSize())) GVSize = *Size; if (Address != UINT64_MAX) @@ -877,39 +887,66 @@ const DWARFUnitIndex &llvm::getDWARFUnitIndex(DWARFContext &Context, } DWARFDie DWARFUnit::getParent(const DWARFDebugInfoEntry *Die) { + if (const DWARFDebugInfoEntry *Entry = getParentEntry(Die)) + return DWARFDie(this, Entry); + + return DWARFDie(); +} + +const DWARFDebugInfoEntry * +DWARFUnit::getParentEntry(const DWARFDebugInfoEntry *Die) const { if (!Die) - return DWARFDie(); + return nullptr; + assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size()); - if (Optional<uint32_t> ParentIdx = Die->getParentIdx()) { + if (std::optional<uint32_t> ParentIdx = Die->getParentIdx()) { assert(*ParentIdx < DieArray.size() && "ParentIdx is out of DieArray boundaries"); - return DWARFDie(this, &DieArray[*ParentIdx]); + return getDebugInfoEntry(*ParentIdx); } - return DWARFDie(); + return nullptr; } DWARFDie DWARFUnit::getSibling(const DWARFDebugInfoEntry *Die) { + if (const DWARFDebugInfoEntry *Sibling = getSiblingEntry(Die)) + return DWARFDie(this, Sibling); + + return DWARFDie(); +} + +const DWARFDebugInfoEntry * +DWARFUnit::getSiblingEntry(const DWARFDebugInfoEntry *Die) const { if (!Die) - return DWARFDie(); + return nullptr; + assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size()); - if (Optional<uint32_t> SiblingIdx = Die->getSiblingIdx()) { + if (std::optional<uint32_t> SiblingIdx = Die->getSiblingIdx()) { assert(*SiblingIdx < DieArray.size() && "SiblingIdx is out of DieArray boundaries"); - return DWARFDie(this, &DieArray[*SiblingIdx]); + return &DieArray[*SiblingIdx]; } - return DWARFDie(); + return nullptr; } DWARFDie DWARFUnit::getPreviousSibling(const DWARFDebugInfoEntry *Die) { + if (const DWARFDebugInfoEntry *Sibling = getPreviousSiblingEntry(Die)) + return DWARFDie(this, Sibling); + + return DWARFDie(); +} + +const DWARFDebugInfoEntry * +DWARFUnit::getPreviousSiblingEntry(const DWARFDebugInfoEntry *Die) const { if (!Die) - return DWARFDie(); + return nullptr; + assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size()); - Optional<uint32_t> ParentIdx = Die->getParentIdx(); + std::optional<uint32_t> ParentIdx = Die->getParentIdx(); if (!ParentIdx) // Die is a root die, there is no previous sibling. - return DWARFDie(); + return nullptr; assert(*ParentIdx < DieArray.size() && "ParentIdx is out of DieArray boundaries"); @@ -918,7 +955,7 @@ DWARFDie DWARFUnit::getPreviousSibling(const DWARFDebugInfoEntry *Die) { uint32_t PrevDieIdx = getDIEIndex(Die) - 1; if (PrevDieIdx == *ParentIdx) // Immediately previous node is parent, there is no previous sibling. - return DWARFDie(); + return nullptr; while (DieArray[PrevDieIdx].getParentIdx() != *ParentIdx) { PrevDieIdx = *DieArray[PrevDieIdx].getParentIdx(); @@ -929,32 +966,56 @@ DWARFDie DWARFUnit::getPreviousSibling(const DWARFDebugInfoEntry *Die) { "PrevDieIdx is not a child of parent of Die"); } - return DWARFDie(this, &DieArray[PrevDieIdx]); + return &DieArray[PrevDieIdx]; } DWARFDie DWARFUnit::getFirstChild(const DWARFDebugInfoEntry *Die) { + if (const DWARFDebugInfoEntry *Child = getFirstChildEntry(Die)) + return DWARFDie(this, Child); + + return DWARFDie(); +} + +const DWARFDebugInfoEntry * +DWARFUnit::getFirstChildEntry(const DWARFDebugInfoEntry *Die) const { + if (!Die) + return nullptr; + assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size()); + if (!Die->hasChildren()) - return DWARFDie(); + return nullptr; // TODO: Instead of checking here for invalid die we might reject // invalid dies at parsing stage(DWARFUnit::extractDIEsToVector). // We do not want access out of bounds when parsing corrupted debug data. size_t I = getDIEIndex(Die) + 1; if (I >= DieArray.size()) - return DWARFDie(); - return DWARFDie(this, &DieArray[I]); + return nullptr; + return &DieArray[I]; } DWARFDie DWARFUnit::getLastChild(const DWARFDebugInfoEntry *Die) { + if (const DWARFDebugInfoEntry *Child = getLastChildEntry(Die)) + return DWARFDie(this, Child); + + return DWARFDie(); +} + +const DWARFDebugInfoEntry * +DWARFUnit::getLastChildEntry(const DWARFDebugInfoEntry *Die) const { + if (!Die) + return nullptr; + assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size()); + if (!Die->hasChildren()) - return DWARFDie(); + return nullptr; - if (Optional<uint32_t> SiblingIdx = Die->getSiblingIdx()) { + if (std::optional<uint32_t> SiblingIdx = Die->getSiblingIdx()) { assert(*SiblingIdx < DieArray.size() && "SiblingIdx is out of DieArray boundaries"); assert(DieArray[*SiblingIdx - 1].getTag() == dwarf::DW_TAG_null && "Bad end of children marker"); - return DWARFDie(this, &DieArray[*SiblingIdx - 1]); + return &DieArray[*SiblingIdx - 1]; } // If SiblingIdx is set for non-root dies we could be sure that DWARF is @@ -969,11 +1030,13 @@ DWARFDie DWARFUnit::getLastChild(const DWARFDebugInfoEntry *Die) { if (getDIEIndex(Die) == 0 && DieArray.size() > 1 && DieArray.back().getTag() == dwarf::DW_TAG_null) { // For the unit die we might take last item from DieArray. - assert(getDIEIndex(Die) == getDIEIndex(getUnitDIE()) && "Bad unit die"); - return DWARFDie(this, &DieArray.back()); + assert(getDIEIndex(Die) == + getDIEIndex(const_cast<DWARFUnit *>(this)->getUnitDIE()) && + "Bad unit die"); + return &DieArray.back(); } - return DWARFDie(); + return nullptr; } const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const { @@ -982,12 +1045,13 @@ const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const { return Abbrevs; } -llvm::Optional<object::SectionedAddress> DWARFUnit::getBaseAddress() { +std::optional<object::SectionedAddress> DWARFUnit::getBaseAddress() { if (BaseAddr) return BaseAddr; DWARFDie UnitDie = getUnitDIE(); - Optional<DWARFFormValue> PC = UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc}); + std::optional<DWARFFormValue> PC = + UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc}); BaseAddr = toSectionedAddress(PC); return BaseAddr; } @@ -1071,12 +1135,12 @@ parseDWARFStringOffsetsTableHeader(DWARFDataExtractor &DA, return Desc.validateContributionSize(DA); } -Expected<Optional<StrOffsetsContributionDescriptor>> +Expected<std::optional<StrOffsetsContributionDescriptor>> DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA) { assert(!IsDWO); auto OptOffset = toSectionOffset(getUnitDIE().find(DW_AT_str_offsets_base)); if (!OptOffset) - return None; + return std::nullopt; auto DescOrError = parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), *OptOffset); if (!DescOrError) @@ -1084,18 +1148,18 @@ DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA) { return *DescOrError; } -Expected<Optional<StrOffsetsContributionDescriptor>> -DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) { +Expected<std::optional<StrOffsetsContributionDescriptor>> +DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA) { assert(IsDWO); uint64_t Offset = 0; auto IndexEntry = Header.getIndexEntry(); const auto *C = IndexEntry ? IndexEntry->getContribution(DW_SECT_STR_OFFSETS) : nullptr; if (C) - Offset = C->Offset; + Offset = C->getOffset(); if (getVersion() >= 5) { if (DA.getData().data() == nullptr) - return None; + return std::nullopt; Offset += Header.getFormat() == dwarf::DwarfFormat::DWARF32 ? 8 : 16; // Look for a valid contribution at the given offset. auto DescOrError = parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), Offset); @@ -1108,33 +1172,33 @@ DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) { // the length of the string offsets section. StrOffsetsContributionDescriptor Desc; if (C) - Desc = StrOffsetsContributionDescriptor(C->Offset, C->Length, 4, + Desc = StrOffsetsContributionDescriptor(C->getOffset(), C->getLength(), 4, Header.getFormat()); else if (!IndexEntry && !StringOffsetSection.Data.empty()) Desc = StrOffsetsContributionDescriptor(0, StringOffsetSection.Data.size(), 4, Header.getFormat()); else - return None; + return std::nullopt; auto DescOrError = Desc.validateContributionSize(DA); if (!DescOrError) return DescOrError.takeError(); return *DescOrError; } -Optional<uint64_t> DWARFUnit::getRnglistOffset(uint32_t Index) { - DataExtractor RangesData(RangeSection->Data, isLittleEndian, +std::optional<uint64_t> DWARFUnit::getRnglistOffset(uint32_t Index) { + DataExtractor RangesData(RangeSection->Data, IsLittleEndian, getAddressByteSize()); DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, - isLittleEndian, 0); - if (Optional<uint64_t> Off = llvm::DWARFListTableHeader::getOffsetEntry( + IsLittleEndian, 0); + if (std::optional<uint64_t> Off = llvm::DWARFListTableHeader::getOffsetEntry( RangesData, RangeSectionBase, getFormat(), Index)) return *Off + RangeSectionBase; - return None; + return std::nullopt; } -Optional<uint64_t> DWARFUnit::getLoclistOffset(uint32_t Index) { - if (Optional<uint64_t> Off = llvm::DWARFListTableHeader::getOffsetEntry( +std::optional<uint64_t> DWARFUnit::getLoclistOffset(uint32_t Index) { + if (std::optional<uint64_t> Off = llvm::DWARFListTableHeader::getOffsetEntry( LocTable->getData(), LocSectionBase, getFormat(), Index)) return *Off + LocSectionBase; - return None; + return std::nullopt; } |