DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges( llvm::Optional<SectionedAddress> BaseAddr) const { DWARFAddressRangesVector Res; for (const RangeListEntry &RLE : Entries) { if (RLE.isBaseAddressSelectionEntry(AddressSize)) { BaseAddr = {RLE.EndAddress, RLE.SectionIndex}; continue; } DWARFAddressRange E; E.LowPC = RLE.StartAddress; E.HighPC = RLE.EndAddress; E.SectionIndex = RLE.SectionIndex; // Base address of a range list entry is determined by the closest preceding // base address selection entry in the same range list. It defaults to the // base address of the compilation unit if there is no such entry. if (BaseAddr) { E.LowPC += BaseAddr->Address; E.HighPC += BaseAddr->Address; if (E.SectionIndex == -1ULL) E.SectionIndex = BaseAddr->SectionIndex; } Res.push_back(E); } return Res; }
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); }
unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die, DieRangeInfo &ParentRI) { unsigned NumErrors = 0; if (!Die.isValid()) return NumErrors; DWARFAddressRangesVector Ranges = Die.getAddressRanges(); // Build RI for this DIE and check that ranges within this DIE do not // overlap. DieRangeInfo RI(Die); for (auto Range : Ranges) { if (!Range.valid()) { ++NumErrors; error() << "Invalid address range " << Range << "\n"; continue; } // Verify that ranges don't intersect. const auto IntersectingRange = RI.insert(Range); if (IntersectingRange != RI.Ranges.end()) { ++NumErrors; error() << "DIE has overlapping address ranges: " << Range << " and " << *IntersectingRange << "\n"; break; } } // Verify that children don't intersect. const auto IntersectingChild = ParentRI.insert(RI); if (IntersectingChild != ParentRI.Children.end()) { ++NumErrors; error() << "DIEs have overlapping address ranges:"; Die.dump(OS, 0); IntersectingChild->Die.dump(OS, 0); OS << "\n"; } // Verify that ranges are contained within their parent. bool ShouldBeContained = !Ranges.empty() && !ParentRI.Ranges.empty() && !(Die.getTag() == DW_TAG_subprogram && ParentRI.Die.getTag() == DW_TAG_subprogram); if (ShouldBeContained && !ParentRI.contains(RI)) { ++NumErrors; error() << "DIE address ranges are not " "contained in its parent's ranges:"; Die.dump(OS, 0); ParentRI.Die.dump(OS, 0); OS << "\n"; } // Recursively check children. for (DWARFDie Child : Die) NumErrors += verifyDieRanges(Child, RI); return NumErrors; }
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); }
DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges(uint64_t BaseAddress) const { DWARFAddressRangesVector Res; for (const RangeListEntry &RLE : Entries) { if (RLE.isBaseAddressSelectionEntry(AddressSize)) { BaseAddress = RLE.EndAddress; } else { Res.push_back({BaseAddress + RLE.StartAddress, BaseAddress + RLE.EndAddress, RLE.SectionIndex}); } } return Res; }
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 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(); } }
static void dumpRanges(const DWARFObject &Obj, raw_ostream &OS, const DWARFAddressRangesVector &Ranges, unsigned AddressSize, unsigned Indent, const DIDumpOptions &DumpOpts) { ArrayRef<SectionName> SectionNames; if (DumpOpts.Verbose) SectionNames = Obj.getSectionNames(); for (size_t I = 0; I < Ranges.size(); ++I) { const DWARFAddressRange &R = Ranges[I]; OS << '\n'; OS.indent(Indent); OS << format("[0x%0*" PRIx64 " - 0x%0*" PRIx64 ")", AddressSize * 2, R.LowPC, AddressSize * 2, R.HighPC); if (SectionNames.empty() || R.SectionIndex == -1ULL) continue; StringRef Name = SectionNames[R.SectionIndex].Name; OS << " \"" << Name << '\"'; // Print section index if name is not unique. if (!SectionNames[R.SectionIndex].IsNameUnique) OS << format(" [%" PRIu64 "]", R.SectionIndex); } }
DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( llvm::Optional<BaseAddress> BaseAddr) const { DWARFAddressRangesVector Res; for (const RangeListEntry &RLE : Entries) { if (RLE.EntryKind == dwarf::DW_RLE_end_of_list) break; if (RLE.EntryKind == dwarf::DW_RLE_base_address) { BaseAddr = {RLE.Value0, RLE.SectionIndex}; continue; } DWARFAddressRange E; E.SectionIndex = RLE.SectionIndex; if (BaseAddr && E.SectionIndex == -1ULL) E.SectionIndex = BaseAddr->SectionIndex; switch (RLE.EntryKind) { case dwarf::DW_RLE_offset_pair: E.LowPC = RLE.Value0; E.HighPC = RLE.Value1; if (BaseAddr) { E.LowPC += BaseAddr->Address; E.HighPC += BaseAddr->Address; } break; case dwarf::DW_RLE_start_end: E.LowPC = RLE.Value0; E.HighPC = RLE.Value1; break; case dwarf::DW_RLE_start_length: E.LowPC = RLE.Value0; E.HighPC = E.LowPC + RLE.Value1; break; default: // Unsupported encodings should have been reported during extraction, // so we should not run into any here. llvm_unreachable("Unsupported range list encoding"); } Res.push_back(E); } return Res; }
static void dumpRanges(raw_ostream &OS, const DWARFAddressRangesVector& Ranges, unsigned AddressSize, unsigned Indent) { if (Ranges.empty()) return; for (const auto &Range: Ranges) { OS << '\n'; OS.indent(Indent); OS << format("[0x%0*" PRIx64 " - 0x%0*" PRIx64 ")", AddressSize*2, Range.first, AddressSize*2, Range.second); } }
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); }