Make a DWARFDIE class that can help avoid using the wrong DWARFUnit when extracting attributes
Many places pass around a DWARFDebugInfoEntryMinimal and a DWARFUnit. It is easy to get things wrong by using the wrong DWARFUnit with a DWARFDebugInfoEntryMinimal. This patch creates a DWARFDie class that contains the DWARFUnit and DWARFDebugInfoEntryMinimal objects so that they can't get out of sync. All attribute extraction has been moved out of DWARFDebugInfoEntryMinimal and into DWARFDie. DWARFDebugInfoEntryMinimal was also renamed to DWARFDebugInfoEntry.
DWARFDie objects are temporary objects that are used by clients and contain 2 pointers that you always need to have anyway. Keeping them grouped will avoid errors and simplify many of the attribute extracting APIs by not having to pass in a DWARFUnit.
Differential Revision: https://reviews.llvm.org/D27634
llvm-svn: 289565
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index caa3694..2424ea4 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -151,27 +151,20 @@
}
const char *DWARFUnit::getCompilationDir() {
- extractDIEsIfNeeded(true);
- if (DieArray.empty())
- return nullptr;
- return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr);
+ return getUnitDIE().getAttributeValueAsString(DW_AT_comp_dir, nullptr);
}
uint64_t DWARFUnit::getDWOId() {
- extractDIEsIfNeeded(true);
- const uint64_t FailValue = -1ULL;
- if (DieArray.empty())
- return FailValue;
- return DieArray[0]
- .getAttributeValueAsUnsignedConstant(this, DW_AT_GNU_dwo_id, FailValue);
+ return getUnitDIE().getAttributeValueAsUnsignedConstant(DW_AT_GNU_dwo_id,
+ -1ULL);
}
void DWARFUnit::setDIERelations() {
if (DieArray.size() <= 1)
return;
- std::vector<DWARFDebugInfoEntryMinimal *> ParentChain;
- DWARFDebugInfoEntryMinimal *SiblingChain = nullptr;
+ std::vector<DWARFDebugInfoEntry *> ParentChain;
+ DWARFDebugInfoEntry *SiblingChain = nullptr;
for (auto &DIE : DieArray) {
if (SiblingChain) {
SiblingChain->setSibling(&DIE);
@@ -197,7 +190,7 @@
void DWARFUnit::extractDIEsToVector(
bool AppendCUDie, bool AppendNonCUDies,
- std::vector<DWARFDebugInfoEntryMinimal> &Dies) const {
+ std::vector<DWARFDebugInfoEntry> &Dies) const {
if (!AppendCUDie && !AppendNonCUDies)
return;
@@ -205,7 +198,7 @@
// next compilation unit header.
uint32_t DIEOffset = Offset + getHeaderSize();
uint32_t NextCUOffset = getNextUnitOffset();
- DWARFDebugInfoEntryMinimal DIE;
+ DWARFDebugInfoEntry DIE;
DataExtractor DebugInfoData = getDebugInfoExtractor();
uint32_t Depth = 0;
bool IsCUDie = true;
@@ -260,15 +253,15 @@
// If CU DIE was just parsed, copy several attribute values from it.
if (!HasCUDie) {
- uint64_t BaseAddr =
- DieArray[0].getAttributeValueAsAddress(this, DW_AT_low_pc, -1ULL);
+ DWARFDie UnitDie = getUnitDIE();
+ uint64_t BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_low_pc, -1ULL);
if (BaseAddr == -1ULL)
- BaseAddr = DieArray[0].getAttributeValueAsAddress(this, DW_AT_entry_pc, 0);
+ BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_entry_pc, 0);
setBaseAddress(BaseAddr);
- AddrOffsetSectionBase = DieArray[0].getAttributeValueAsSectionOffset(
- this, DW_AT_GNU_addr_base, 0);
- RangeSectionBase = DieArray[0].getAttributeValueAsSectionOffset(
- this, DW_AT_rnglists_base, 0);
+ AddrOffsetSectionBase = UnitDie.getAttributeValueAsSectionOffset(
+ DW_AT_GNU_addr_base, 0);
+ RangeSectionBase = UnitDie.getAttributeValueAsSectionOffset(
+ DW_AT_rnglists_base, 0);
// 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.
}
@@ -297,15 +290,15 @@
return false;
if (DWO.get())
return false;
- extractDIEsIfNeeded(true);
- if (DieArray.empty())
+ DWARFDie UnitDie = getUnitDIE();
+ if (!UnitDie)
return false;
const char *DWOFileName =
- DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, nullptr);
+ UnitDie.getAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
if (!DWOFileName)
return false;
const char *CompilationDir =
- DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr);
+ UnitDie.getAttributeValueAsString(DW_AT_comp_dir, nullptr);
SmallString<16> AbsolutePath;
if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) {
sys::path::append(AbsolutePath, CompilationDir);
@@ -320,7 +313,7 @@
}
// Share .debug_addr and .debug_ranges section with compile unit in .dwo
DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase);
- uint32_t DWORangesBase = DieArray[0].getRangesBaseAttribute(this, 0);
+ uint32_t DWORangesBase = UnitDie.getRangesBaseAttribute(0);
DWOCU->setRangesSection(RangeSection, DWORangesBase);
return true;
}
@@ -334,7 +327,7 @@
// contents which will cause just the internal pointers to be swapped
// so that when temporary vector goes out of scope, it will destroy the
// contents.
- std::vector<DWARFDebugInfoEntryMinimal> TmpArray;
+ std::vector<DWARFDebugInfoEntry> TmpArray;
DieArray.swap(TmpArray);
// Save at least the compile unit DIE
if (KeepCUDie)
@@ -343,11 +336,11 @@
}
void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) {
- const auto *U = getUnitDIE();
- if (U == nullptr)
+ DWARFDie UnitDie = getUnitDIE();
+ if (!UnitDie)
return;
// First, check if unit DIE describes address ranges for the whole unit.
- const auto &CUDIERanges = U->getAddressRanges(this);
+ const auto &CUDIERanges = UnitDie.getAddressRanges();
if (!CUDIERanges.empty()) {
CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end());
return;
@@ -360,7 +353,7 @@
// up parsing the DWARF and then throwing them all away to keep memory usage
// down.
const bool ClearDIEs = extractDIEsIfNeeded(false) > 1;
- DieArray[0].collectChildrenAddressRanges(this, CURanges);
+ getUnitDIE().collectChildrenAddressRanges(CURanges);
// Collect address ranges from DIEs in .dwo if necessary.
bool DWOCreated = parseDWO();
@@ -375,36 +368,37 @@
clearDIEs(true);
}
-const DWARFDebugInfoEntryMinimal *
+DWARFDie
DWARFUnit::getSubprogramForAddress(uint64_t Address) {
extractDIEsIfNeeded(false);
- for (const DWARFDebugInfoEntryMinimal &DIE : DieArray) {
+ for (const DWARFDebugInfoEntry &D : DieArray) {
+ DWARFDie DIE(this, &D);
if (DIE.isSubprogramDIE() &&
- DIE.addressRangeContainsAddress(this, Address)) {
- return &DIE;
+ DIE.addressRangeContainsAddress(Address)) {
+ return DIE;
}
}
- return nullptr;
+ return DWARFDie();
}
-DWARFDebugInfoEntryInlinedChain
-DWARFUnit::getInlinedChainForAddress(uint64_t Address) {
+void
+DWARFUnit::getInlinedChainForAddress(uint64_t Address,
+ SmallVectorImpl<DWARFDie> &InlinedChain) {
// First, find a subprogram that contains the given address (the root
// of inlined chain).
- const DWARFUnit *ChainCU = nullptr;
- const DWARFDebugInfoEntryMinimal *SubprogramDIE;
+ DWARFDie SubprogramDIE;
// Try to look for subprogram DIEs in the DWO file.
parseDWO();
- if (DWO) {
- if ((SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address)))
- ChainCU = DWO->getUnit();
- } else if ((SubprogramDIE = getSubprogramForAddress(Address)))
- ChainCU = this;
+ if (DWO)
+ SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address);
+ else
+ SubprogramDIE = getSubprogramForAddress(Address);
// Get inlined chain rooted at this subprogram DIE.
- if (!SubprogramDIE)
- return DWARFDebugInfoEntryInlinedChain();
- return SubprogramDIE->getInlinedChainForAddress(ChainCU, Address);
+ if (SubprogramDIE)
+ SubprogramDIE.getInlinedChainForAddress(Address, InlinedChain);
+ else
+ InlinedChain.clear();
}
const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,