void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { const auto *U = getUnitDIE(); if (U == nullptr) return; // First, check if unit DIE describes address ranges for the whole unit. const auto &CUDIERanges = U->getAddressRanges(this); if (!CUDIERanges.empty()) { CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end()); return; } // This function is usually called if there in no .debug_aranges section // in order to produce a compile unit level set of address ranges that // is accurate. If the DIEs weren't parsed, then we don't want all dies for // all compile units to stay loaded when they weren't needed. So we can end // 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); // Collect address ranges from DIEs in .dwo if necessary. bool DWOCreated = parseDWO(); if (DWO.get()) DWO->getUnit()->collectAddressRanges(CURanges); if (DWOCreated) DWO.reset(); // Keep memory down by clearing DIEs if this generate function // caused them to be parsed. if (ClearDIEs) clearDIEs(true); }
void DWARFDie::collectChildrenAddressRanges(DWARFAddressRangesVector& Ranges) const { if (isNULL()) return; if (isSubprogramDIE()) { const auto &DIERanges = getAddressRanges(); Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end()); } for (auto Child: children()) Child.collectChildrenAddressRanges(Ranges); }
void DWARFDebugInfoEntryMinimal::collectChildrenAddressRanges( const DWARFUnit *U, DWARFAddressRangesVector& Ranges) const { if (isNULL()) return; if (isSubprogramDIE()) { const auto &DIERanges = getAddressRanges(U); Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end()); } const DWARFDebugInfoEntryMinimal *Child = getFirstChild(); while (Child) { Child->collectChildrenAddressRanges(U, Ranges); Child = Child->getSibling(); } }
void DWARFDie::collectChildrenAddressRanges( DWARFAddressRangesVector &Ranges) const { if (isNULL()) return; if (isSubprogramDIE()) { if (auto DIERangesOrError = getAddressRanges()) Ranges.insert(Ranges.end(), DIERangesOrError.get().begin(), DIERangesOrError.get().end()); else llvm::consumeError(DIERangesOrError.takeError()); } for (auto Child : children()) Child.collectChildrenAddressRanges(Ranges); }
void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { DWARFDie UnitDie = getUnitDIE(); if (!UnitDie) return; // First, check if unit DIE describes address ranges for the whole unit. auto CUDIERangesOrError = UnitDie.getAddressRanges(); if (CUDIERangesOrError) { if (!CUDIERangesOrError.get().empty()) { CURanges.insert(CURanges.end(), CUDIERangesOrError.get().begin(), CUDIERangesOrError.get().end()); return; } } else WithColor::error() << "decoding address ranges: " << toString(CUDIERangesOrError.takeError()) << '\n'; // This function is usually called if there in no .debug_aranges section // in order to produce a compile unit level set of address ranges that // is accurate. If the DIEs weren't parsed, then we don't want all dies for // all compile units to stay loaded when they weren't needed. So we can end // up parsing the DWARF and then throwing them all away to keep memory usage // down. const bool ClearDIEs = extractDIEsIfNeeded(false) > 1; getUnitDIE().collectChildrenAddressRanges(CURanges); // Collect address ranges from DIEs in .dwo if necessary. bool DWOCreated = parseDWO(); if (DWO) DWO->collectAddressRanges(CURanges); if (DWOCreated) DWO.reset(); // Keep memory down by clearing DIEs if this generate function // caused them to be parsed. if (ClearDIEs) clearDIEs(true); }