[Debuginfo][DWARF][NFC] Add paired methods working with DWARFDebugInfoEntry.

This review is extracted from D96035.

DWARF Debuginfo classes have two representations for DIEs: DWARFDebugInfoEntry
(short) and DWARFDie(extended). Depending on the task, it might be more convenient
to use DWARFDebugInfoEntry or/and DWARFDie. DWARFUnit class already has methods
working with DWARFDie and DWARFDebugInfoEntry. This patch adds more
methods working with DWARFDebugInfoEntry to have paired functionality.

Reviewed By: aprantl

Differential Revision: https://reviews.llvm.org/D126059
This commit is contained in:
Alexey Lapshin 2022-07-29 13:43:02 +03:00
parent 7d76da539f
commit ece341f598
2 changed files with 111 additions and 29 deletions

View File

@ -252,13 +252,36 @@ class DWARFUnit {
std::shared_ptr<DWARFUnit> 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 @@ public:
/// 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 @@ public:
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<uint32_t> 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<uint32_t> 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 {

View File

@ -877,39 +877,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()) {
assert(*ParentIdx < DieArray.size() &&
"ParentIdx is out of DieArray boundaries");
return DWARFDie(this, &DieArray[*ParentIdx]);
return getDebugInfoEntry(*ParentIdx);
}
return nullptr;
}
DWARFDie DWARFUnit::getSibling(const DWARFDebugInfoEntry *Die) {
if (const DWARFDebugInfoEntry *Sibling = getSiblingEntry(Die))
return DWARFDie(this, Sibling);
return DWARFDie();
}
DWARFDie DWARFUnit::getSibling(const DWARFDebugInfoEntry *Die) {
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()) {
assert(*SiblingIdx < DieArray.size() &&
"SiblingIdx is out of DieArray boundaries");
return DWARFDie(this, &DieArray[*SiblingIdx]);
return &DieArray[*SiblingIdx];
}
return nullptr;
}
DWARFDie DWARFUnit::getPreviousSibling(const DWARFDebugInfoEntry *Die) {
if (const DWARFDebugInfoEntry *Sibling = getPreviousSiblingEntry(Die))
return DWARFDie(this, Sibling);
return DWARFDie();
}
DWARFDie DWARFUnit::getPreviousSibling(const DWARFDebugInfoEntry *Die) {
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();
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 @@ 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 +956,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()) {
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 @@ 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 {