diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -252,13 +252,36 @@ std::shared_ptr DWO; - uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) { +protected: + /// Return the index of a \p Die entry inside the unit's DIE vector. + /// + /// It is illegal to call this method with a DIE that hasn't be + /// created by this unit. In other word, it's illegal to call this + /// method on a DIE that isn't accessible by following + /// children/sibling links starting from this unit's getUnitDIE(). + uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const { auto First = DieArray.data(); assert(Die >= First && Die < First + DieArray.size()); return Die - First; } -protected: + /// Return DWARFDebugInfoEntry for the specified index \p Index. + const DWARFDebugInfoEntry *getDebugInfoEntry(unsigned Index) const { + assert(Index < DieArray.size()); + return &DieArray[Index]; + } + + const DWARFDebugInfoEntry * + getParentEntry(const DWARFDebugInfoEntry *Die) const; + const DWARFDebugInfoEntry * + getSiblingEntry(const DWARFDebugInfoEntry *Die) const; + const DWARFDebugInfoEntry * + getPreviousSiblingEntry(const DWARFDebugInfoEntry *Die) const; + const DWARFDebugInfoEntry * + getFirstChildEntry(const DWARFDebugInfoEntry *Die) const; + const DWARFDebugInfoEntry * + getLastChildEntry(const DWARFDebugInfoEntry *Die) const; + const DWARFUnitHeader &getHeader() const { return Header; } /// Find the unit's contribution to the string offsets table and determine its @@ -472,14 +495,13 @@ /// created by this unit. In other word, it's illegal to call this /// method on a DIE that isn't accessible by following /// children/sibling links starting from this unit's getUnitDIE(). - uint32_t getDIEIndex(const DWARFDie &D) { + uint32_t getDIEIndex(const DWARFDie &D) const { return getDIEIndex(D.getDebugInfoEntry()); } - /// Return the DIE object at the given index. + /// Return the DIE object at the given index \p Index. DWARFDie getDIEAtIndex(unsigned Index) { - assert(Index < DieArray.size()); - return DWARFDie(this, &DieArray[Index]); + return DWARFDie(this, getDebugInfoEntry(Index)); } DWARFDie getParent(const DWARFDebugInfoEntry *Die); @@ -488,19 +510,26 @@ DWARFDie getFirstChild(const DWARFDebugInfoEntry *Die); DWARFDie getLastChild(const DWARFDebugInfoEntry *Die); - /// Return the DIE object for a given offset inside the + /// Return the DIE object for a given offset \p Offset inside the /// unit's DIE vector. - /// - /// The unit needs to have its DIEs extracted for this method to work. DWARFDie getDIEForOffset(uint64_t Offset) { + if (Optional DieIdx = getDIEIndexForOffset(Offset)) + return DWARFDie(this, &DieArray[*DieIdx]); + + return DWARFDie(); + } + + /// Return the DIE index for a given offset \p Offset inside the + /// unit's DIE vector. + Optional getDIEIndexForOffset(uint64_t Offset) { extractDIEsIfNeeded(false); auto It = llvm::partition_point(DieArray, [=](const DWARFDebugInfoEntry &DIE) { return DIE.getOffset() < Offset; }); if (It != DieArray.end() && It->getOffset() == Offset) - return DWARFDie(this, &*It); - return DWARFDie(); + return It - DieArray.begin(); + return None; } uint32_t getLineTableOffset() const { diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -877,39 +877,66 @@ } 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 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 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 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 +945,7 @@ 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 +956,56 @@ "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 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 +1020,13 @@ 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(this)->getUnitDIE()) && + "Bad unit die"); + return &DieArray.back(); } - return DWARFDie(); + return nullptr; } const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const {