Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:42

0001 //===- DWARFUnit.h ----------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
0010 #define LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
0011 
0012 #include "llvm/ADT/DenseSet.h"
0013 #include "llvm/ADT/STLExtras.h"
0014 #include "llvm/ADT/SmallVector.h"
0015 #include "llvm/ADT/StringRef.h"
0016 #include "llvm/ADT/iterator_range.h"
0017 #include "llvm/BinaryFormat/Dwarf.h"
0018 #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
0019 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
0020 #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
0021 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
0022 #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
0023 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
0024 #include "llvm/Support/DataExtractor.h"
0025 #include <cassert>
0026 #include <cstddef>
0027 #include <cstdint>
0028 #include <map>
0029 #include <memory>
0030 #include <set>
0031 #include <utility>
0032 #include <vector>
0033 
0034 namespace llvm {
0035 
0036 class DWARFAbbreviationDeclarationSet;
0037 class DWARFContext;
0038 class DWARFDebugAbbrev;
0039 class DWARFUnit;
0040 class DWARFDebugRangeList;
0041 class DWARFLocationTable;
0042 class DWARFObject;
0043 class raw_ostream;
0044 struct DIDumpOptions;
0045 struct DWARFSection;
0046 namespace dwarf_linker {
0047 namespace parallel {
0048 class CompileUnit;
0049 }
0050 } // namespace dwarf_linker
0051 
0052 /// Base class describing the header of any kind of "unit."  Some information
0053 /// is specific to certain unit types.  We separate this class out so we can
0054 /// parse the header before deciding what specific kind of unit to construct.
0055 class DWARFUnitHeader {
0056   // Offset within section.
0057   uint64_t Offset = 0;
0058   // Version, address size, and DWARF format.
0059   dwarf::FormParams FormParams;
0060   uint64_t Length = 0;
0061   uint64_t AbbrOffset = 0;
0062 
0063   // For DWO units only.
0064   const DWARFUnitIndex::Entry *IndexEntry = nullptr;
0065 
0066   // For type units only.
0067   uint64_t TypeHash = 0;
0068   uint64_t TypeOffset = 0;
0069 
0070   // For v5 split or skeleton compile units only.
0071   std::optional<uint64_t> DWOId;
0072 
0073   // Unit type as parsed, or derived from the section kind.
0074   uint8_t UnitType = 0;
0075 
0076   // Size as parsed. uint8_t for compactness.
0077   uint8_t Size = 0;
0078 
0079 public:
0080   /// Parse a unit header from \p debug_info starting at \p offset_ptr.
0081   /// Note that \p SectionKind is used as a hint to guess the unit type
0082   /// for DWARF formats prior to DWARFv5. In DWARFv5 the unit type is
0083   /// explicitly defined in the header and the hint is ignored.
0084   Error extract(DWARFContext &Context, const DWARFDataExtractor &debug_info,
0085                 uint64_t *offset_ptr, DWARFSectionKind SectionKind);
0086   // For units in DWARF Package File, remember the index entry and update
0087   // the abbreviation offset read by extract().
0088   Error applyIndexEntry(const DWARFUnitIndex::Entry *Entry);
0089   uint64_t getOffset() const { return Offset; }
0090   const dwarf::FormParams &getFormParams() const { return FormParams; }
0091   uint16_t getVersion() const { return FormParams.Version; }
0092   dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
0093   uint8_t getAddressByteSize() const { return FormParams.AddrSize; }
0094   uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); }
0095   uint8_t getDwarfOffsetByteSize() const {
0096     return FormParams.getDwarfOffsetByteSize();
0097   }
0098   uint64_t getLength() const { return Length; }
0099   uint64_t getAbbrOffset() const { return AbbrOffset; }
0100   std::optional<uint64_t> getDWOId() const { return DWOId; }
0101   void setDWOId(uint64_t Id) {
0102     assert((!DWOId || *DWOId == Id) && "setting DWOId to a different value");
0103     DWOId = Id;
0104   }
0105   const DWARFUnitIndex::Entry *getIndexEntry() const { return IndexEntry; }
0106   uint64_t getTypeHash() const { return TypeHash; }
0107   uint64_t getTypeOffset() const { return TypeOffset; }
0108   uint8_t getUnitType() const { return UnitType; }
0109   bool isTypeUnit() const {
0110     return UnitType == dwarf::DW_UT_type || UnitType == dwarf::DW_UT_split_type;
0111   }
0112   uint8_t getSize() const { return Size; }
0113   uint8_t getUnitLengthFieldByteSize() const {
0114     return dwarf::getUnitLengthFieldByteSize(FormParams.Format);
0115   }
0116   uint64_t getNextUnitOffset() const {
0117     return Offset + Length + getUnitLengthFieldByteSize();
0118   }
0119 };
0120 
0121 const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
0122                                         DWARFSectionKind Kind);
0123 
0124 bool isCompileUnit(const std::unique_ptr<DWARFUnit> &U);
0125 
0126 /// Describe a collection of units. Intended to hold all units either from
0127 /// .debug_info and .debug_types, or from .debug_info.dwo and .debug_types.dwo.
0128 class DWARFUnitVector final : public SmallVector<std::unique_ptr<DWARFUnit>, 1> {
0129   std::function<std::unique_ptr<DWARFUnit>(uint64_t, DWARFSectionKind,
0130                                            const DWARFSection *,
0131                                            const DWARFUnitIndex::Entry *)>
0132       Parser;
0133   int NumInfoUnits = -1;
0134 
0135 public:
0136   using UnitVector = SmallVectorImpl<std::unique_ptr<DWARFUnit>>;
0137   using iterator = typename UnitVector::iterator;
0138   using iterator_range = llvm::iterator_range<typename UnitVector::iterator>;
0139 
0140   using compile_unit_range =
0141       decltype(make_filter_range(std::declval<iterator_range>(), isCompileUnit));
0142 
0143   DWARFUnit *getUnitForOffset(uint64_t Offset) const;
0144   DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E);
0145 
0146   /// Read units from a .debug_info or .debug_types section.  Calls made
0147   /// before finishedInfoUnits() are assumed to be for .debug_info sections,
0148   /// calls after finishedInfoUnits() are for .debug_types sections.  Caller
0149   /// must not mix calls to addUnitsForSection and addUnitsForDWOSection.
0150   void addUnitsForSection(DWARFContext &C, const DWARFSection &Section,
0151                           DWARFSectionKind SectionKind);
0152   /// Read units from a .debug_info.dwo or .debug_types.dwo section.  Calls
0153   /// made before finishedInfoUnits() are assumed to be for .debug_info.dwo
0154   /// sections, calls after finishedInfoUnits() are for .debug_types.dwo
0155   /// sections.  Caller must not mix calls to addUnitsForSection and
0156   /// addUnitsForDWOSection.
0157   void addUnitsForDWOSection(DWARFContext &C, const DWARFSection &DWOSection,
0158                              DWARFSectionKind SectionKind, bool Lazy = false);
0159 
0160   /// Add an existing DWARFUnit to this UnitVector. This is used by the DWARF
0161   /// verifier to process unit separately.
0162   DWARFUnit *addUnit(std::unique_ptr<DWARFUnit> Unit);
0163 
0164   /// Returns number of all units held by this instance.
0165   unsigned getNumUnits() const { return size(); }
0166   /// Returns number of units from all .debug_info[.dwo] sections.
0167   unsigned getNumInfoUnits() const {
0168     return NumInfoUnits == -1 ? size() : NumInfoUnits;
0169   }
0170   /// Returns number of units from all .debug_types[.dwo] sections.
0171   unsigned getNumTypesUnits() const { return size() - NumInfoUnits; }
0172   /// Indicate that parsing .debug_info[.dwo] is done, and remaining units
0173   /// will be from .debug_types[.dwo].
0174   void finishedInfoUnits() { NumInfoUnits = size(); }
0175 
0176 private:
0177   void addUnitsImpl(DWARFContext &Context, const DWARFObject &Obj,
0178                     const DWARFSection &Section, const DWARFDebugAbbrev *DA,
0179                     const DWARFSection *RS, const DWARFSection *LocSection,
0180                     StringRef SS, const DWARFSection &SOS,
0181                     const DWARFSection *AOS, const DWARFSection &LS, bool LE,
0182                     bool IsDWO, bool Lazy, DWARFSectionKind SectionKind);
0183 };
0184 
0185 /// Represents base address of the CU.
0186 /// Represents a unit's contribution to the string offsets table.
0187 struct StrOffsetsContributionDescriptor {
0188   uint64_t Base = 0;
0189   /// The contribution size not including the header.
0190   uint64_t Size = 0;
0191   /// Format and version.
0192   dwarf::FormParams FormParams = {0, 0, dwarf::DwarfFormat::DWARF32};
0193 
0194   StrOffsetsContributionDescriptor(uint64_t Base, uint64_t Size,
0195                                    uint8_t Version, dwarf::DwarfFormat Format)
0196       : Base(Base), Size(Size), FormParams({Version, 0, Format}) {}
0197   StrOffsetsContributionDescriptor() = default;
0198 
0199   uint8_t getVersion() const { return FormParams.Version; }
0200   dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
0201   uint8_t getDwarfOffsetByteSize() const {
0202     return FormParams.getDwarfOffsetByteSize();
0203   }
0204   /// Determine whether a contribution to the string offsets table is
0205   /// consistent with the relevant section size and that its length is
0206   /// a multiple of the size of one of its entries.
0207   Expected<StrOffsetsContributionDescriptor>
0208   validateContributionSize(DWARFDataExtractor &DA);
0209 };
0210 
0211 class DWARFUnit {
0212   DWARFContext &Context;
0213   /// Section containing this DWARFUnit.
0214   const DWARFSection &InfoSection;
0215 
0216   DWARFUnitHeader Header;
0217   const DWARFDebugAbbrev *Abbrev;
0218   const DWARFSection *RangeSection;
0219   uint64_t RangeSectionBase;
0220   uint64_t LocSectionBase;
0221 
0222   /// Location table of this unit.
0223   std::unique_ptr<DWARFLocationTable> LocTable;
0224 
0225   const DWARFSection &LineSection;
0226   StringRef StringSection;
0227   const DWARFSection &StringOffsetSection;
0228   const DWARFSection *AddrOffsetSection;
0229   DWARFUnit *SU;
0230   std::optional<uint64_t> AddrOffsetSectionBase;
0231   bool IsLittleEndian;
0232   bool IsDWO;
0233   const DWARFUnitVector &UnitVector;
0234 
0235   /// Start, length, and DWARF format of the unit's contribution to the string
0236   /// offsets table (DWARF v5).
0237   std::optional<StrOffsetsContributionDescriptor>
0238       StringOffsetsTableContribution;
0239 
0240   mutable const DWARFAbbreviationDeclarationSet *Abbrevs;
0241   std::optional<object::SectionedAddress> BaseAddr;
0242   /// The compile unit debug information entry items.
0243   std::vector<DWARFDebugInfoEntry> DieArray;
0244 
0245   /// Map from range's start address to end address and corresponding DIE.
0246   /// IntervalMap does not support range removal, as a result, we use the
0247   /// std::map::upper_bound for address range lookup.
0248   std::map<uint64_t, std::pair<uint64_t, DWARFDie>> AddrDieMap;
0249 
0250   /// Map from the location (interpreted DW_AT_location) of a DW_TAG_variable,
0251   /// to the end address and the corresponding DIE.
0252   std::map<uint64_t, std::pair<uint64_t, DWARFDie>> VariableDieMap;
0253   DenseSet<uint64_t> RootsParsedForVariables;
0254 
0255   using die_iterator_range =
0256       iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>;
0257 
0258   std::shared_ptr<DWARFUnit> DWO;
0259 
0260 protected:
0261   friend dwarf_linker::parallel::CompileUnit;
0262 
0263   /// Return the index of a \p Die entry inside the unit's DIE vector.
0264   ///
0265   /// It is illegal to call this method with a DIE that hasn't be
0266   /// created by this unit. In other word, it's illegal to call this
0267   /// method on a DIE that isn't accessible by following
0268   /// children/sibling links starting from this unit's getUnitDIE().
0269   uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const {
0270     auto First = DieArray.data();
0271     assert(Die >= First && Die < First + DieArray.size());
0272     return Die - First;
0273   }
0274 
0275   /// Return DWARFDebugInfoEntry for the specified index \p Index.
0276   const DWARFDebugInfoEntry *getDebugInfoEntry(unsigned Index) const {
0277     assert(Index < DieArray.size());
0278     return &DieArray[Index];
0279   }
0280 
0281   const DWARFDebugInfoEntry *
0282   getParentEntry(const DWARFDebugInfoEntry *Die) const;
0283   const DWARFDebugInfoEntry *
0284   getSiblingEntry(const DWARFDebugInfoEntry *Die) const;
0285   const DWARFDebugInfoEntry *
0286   getPreviousSiblingEntry(const DWARFDebugInfoEntry *Die) const;
0287   const DWARFDebugInfoEntry *
0288   getFirstChildEntry(const DWARFDebugInfoEntry *Die) const;
0289   const DWARFDebugInfoEntry *
0290   getLastChildEntry(const DWARFDebugInfoEntry *Die) const;
0291 
0292   const DWARFUnitHeader &getHeader() const { return Header; }
0293 
0294   /// Find the unit's contribution to the string offsets table and determine its
0295   /// length and form. The given offset is expected to be derived from the unit
0296   /// DIE's DW_AT_str_offsets_base attribute.
0297   Expected<std::optional<StrOffsetsContributionDescriptor>>
0298   determineStringOffsetsTableContribution(DWARFDataExtractor &DA);
0299 
0300   /// Find the unit's contribution to the string offsets table and determine its
0301   /// length and form. The given offset is expected to be 0 in a dwo file or,
0302   /// in a dwp file, the start of the unit's contribution to the string offsets
0303   /// table section (as determined by the index table).
0304   Expected<std::optional<StrOffsetsContributionDescriptor>>
0305   determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA);
0306 
0307 public:
0308   DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
0309             const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA,
0310             const DWARFSection *RS, const DWARFSection *LocSection,
0311             StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS,
0312             const DWARFSection &LS, bool LE, bool IsDWO,
0313             const DWARFUnitVector &UnitVector);
0314 
0315   virtual ~DWARFUnit();
0316 
0317   bool isLittleEndian() const { return IsLittleEndian; }
0318   bool isDWOUnit() const { return IsDWO; }
0319   DWARFContext& getContext() const { return Context; }
0320   const DWARFSection &getInfoSection() const { return InfoSection; }
0321   uint64_t getOffset() const { return Header.getOffset(); }
0322   const dwarf::FormParams &getFormParams() const {
0323     return Header.getFormParams();
0324   }
0325   uint16_t getVersion() const { return Header.getVersion(); }
0326   uint8_t getAddressByteSize() const { return Header.getAddressByteSize(); }
0327   uint8_t getRefAddrByteSize() const { return Header.getRefAddrByteSize(); }
0328   uint8_t getDwarfOffsetByteSize() const {
0329     return Header.getDwarfOffsetByteSize();
0330   }
0331   /// Size in bytes of the parsed unit header.
0332   uint32_t getHeaderSize() const { return Header.getSize(); }
0333   uint64_t getLength() const { return Header.getLength(); }
0334   dwarf::DwarfFormat getFormat() const { return Header.getFormat(); }
0335   uint8_t getUnitType() const { return Header.getUnitType(); }
0336   bool isTypeUnit() const { return Header.isTypeUnit(); }
0337   uint64_t getAbbrOffset() const { return Header.getAbbrOffset(); }
0338   uint64_t getNextUnitOffset() const { return Header.getNextUnitOffset(); }
0339   const DWARFSection &getLineSection() const { return LineSection; }
0340   StringRef getStringSection() const { return StringSection; }
0341   const DWARFSection &getStringOffsetSection() const {
0342     return StringOffsetSection;
0343   }
0344 
0345   void setSkeletonUnit(DWARFUnit *SU) { this->SU = SU; }
0346   // Returns itself if not using Split DWARF, or if the unit is a skeleton unit
0347   // - otherwise returns the split full unit's corresponding skeleton, if
0348   // available.
0349   DWARFUnit *getLinkedUnit() { return IsDWO ? SU : this; }
0350 
0351   void setAddrOffsetSection(const DWARFSection *AOS, uint64_t Base) {
0352     AddrOffsetSection = AOS;
0353     AddrOffsetSectionBase = Base;
0354   }
0355 
0356   std::optional<uint64_t> getAddrOffsetSectionBase() const {
0357     return AddrOffsetSectionBase;
0358   }
0359 
0360   /// Returns offset to the indexed address value inside .debug_addr section.
0361   std::optional<uint64_t> getIndexedAddressOffset(uint64_t Index) {
0362     if (std::optional<uint64_t> AddrOffsetSectionBase =
0363             getAddrOffsetSectionBase())
0364       return *AddrOffsetSectionBase + Index * getAddressByteSize();
0365 
0366     return std::nullopt;
0367   }
0368 
0369   /// Recursively update address to Die map.
0370   void updateAddressDieMap(DWARFDie Die);
0371 
0372   /// Recursively update address to variable Die map.
0373   void updateVariableDieMap(DWARFDie Die);
0374 
0375   void setRangesSection(const DWARFSection *RS, uint64_t Base) {
0376     RangeSection = RS;
0377     RangeSectionBase = Base;
0378   }
0379 
0380   uint64_t getLocSectionBase() const {
0381     return LocSectionBase;
0382   }
0383 
0384   std::optional<object::SectionedAddress>
0385   getAddrOffsetSectionItem(uint32_t Index) const;
0386   Expected<uint64_t> getStringOffsetSectionItem(uint32_t Index) const;
0387 
0388   DWARFDataExtractor getDebugInfoExtractor() const;
0389 
0390   DataExtractor getStringExtractor() const {
0391     return DataExtractor(StringSection, false, 0);
0392   }
0393 
0394   const DWARFLocationTable &getLocationTable() { return *LocTable; }
0395 
0396   /// Extract the range list referenced by this compile unit from the
0397   /// .debug_ranges section. If the extraction is unsuccessful, an error
0398   /// is returned. Successful extraction requires that the compile unit
0399   /// has already been extracted.
0400   Error extractRangeList(uint64_t RangeListOffset,
0401                          DWARFDebugRangeList &RangeList) const;
0402   void clear();
0403 
0404   const std::optional<StrOffsetsContributionDescriptor> &
0405   getStringOffsetsTableContribution() {
0406     extractDIEsIfNeeded(true /*CUDIeOnly*/);
0407     return StringOffsetsTableContribution;
0408   }
0409 
0410   uint8_t getDwarfStringOffsetsByteSize() const {
0411     assert(StringOffsetsTableContribution);
0412     return StringOffsetsTableContribution->getDwarfOffsetByteSize();
0413   }
0414 
0415   uint64_t getStringOffsetsBase() const {
0416     assert(StringOffsetsTableContribution);
0417     return StringOffsetsTableContribution->Base;
0418   }
0419 
0420   uint64_t getAbbreviationsOffset() const { return Header.getAbbrOffset(); }
0421 
0422   const DWARFAbbreviationDeclarationSet *getAbbreviations() const;
0423 
0424   static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag) {
0425     switch (UnitType) {
0426     case dwarf::DW_UT_compile:
0427       return Tag == dwarf::DW_TAG_compile_unit;
0428     case dwarf::DW_UT_type:
0429       return Tag == dwarf::DW_TAG_type_unit;
0430     case dwarf::DW_UT_partial:
0431       return Tag == dwarf::DW_TAG_partial_unit;
0432     case dwarf::DW_UT_skeleton:
0433       return Tag == dwarf::DW_TAG_skeleton_unit;
0434     case dwarf::DW_UT_split_compile:
0435     case dwarf::DW_UT_split_type:
0436       return dwarf::isUnitType(Tag);
0437     }
0438     return false;
0439   }
0440 
0441   std::optional<object::SectionedAddress> getBaseAddress();
0442 
0443   DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
0444     extractDIEsIfNeeded(ExtractUnitDIEOnly);
0445     if (DieArray.empty())
0446       return DWARFDie();
0447     return DWARFDie(this, &DieArray[0]);
0448   }
0449 
0450   DWARFDie getNonSkeletonUnitDIE(bool ExtractUnitDIEOnly = true,
0451                                  StringRef DWOAlternativeLocation = {}) {
0452     parseDWO(DWOAlternativeLocation);
0453     return DWO ? DWO->getUnitDIE(ExtractUnitDIEOnly)
0454                : getUnitDIE(ExtractUnitDIEOnly);
0455   }
0456 
0457   const char *getCompilationDir();
0458   std::optional<uint64_t> getDWOId() {
0459     extractDIEsIfNeeded(/*CUDieOnly*/ true);
0460     return getHeader().getDWOId();
0461   }
0462   void setDWOId(uint64_t NewID) { Header.setDWOId(NewID); }
0463 
0464   /// Return a vector of address ranges resulting from a (possibly encoded)
0465   /// range list starting at a given offset in the appropriate ranges section.
0466   Expected<DWARFAddressRangesVector> findRnglistFromOffset(uint64_t Offset);
0467 
0468   /// Return a vector of address ranges retrieved from an encoded range
0469   /// list whose offset is found via a table lookup given an index (DWARF v5
0470   /// and later).
0471   Expected<DWARFAddressRangesVector> findRnglistFromIndex(uint32_t Index);
0472 
0473   /// Return a rangelist's offset based on an index. The index designates
0474   /// an entry in the rangelist table's offset array and is supplied by
0475   /// DW_FORM_rnglistx.
0476   std::optional<uint64_t> getRnglistOffset(uint32_t Index);
0477 
0478   std::optional<uint64_t> getLoclistOffset(uint32_t Index);
0479 
0480   Expected<DWARFAddressRangesVector> collectAddressRanges();
0481 
0482   Expected<DWARFLocationExpressionsVector>
0483   findLoclistFromOffset(uint64_t Offset);
0484 
0485   /// Returns subprogram DIE with address range encompassing the provided
0486   /// address. The pointer is alive as long as parsed compile unit DIEs are not
0487   /// cleared.
0488   DWARFDie getSubroutineForAddress(uint64_t Address);
0489 
0490   /// Returns variable DIE for the address provided. The pointer is alive as
0491   /// long as parsed compile unit DIEs are not cleared.
0492   DWARFDie getVariableForAddress(uint64_t Address);
0493 
0494   /// getInlinedChainForAddress - fetches inlined chain for a given address.
0495   /// Returns empty chain if there is no subprogram containing address. The
0496   /// chain is valid as long as parsed compile unit DIEs are not cleared.
0497   void getInlinedChainForAddress(uint64_t Address,
0498                                  SmallVectorImpl<DWARFDie> &InlinedChain);
0499 
0500   /// Return the DWARFUnitVector containing this unit.
0501   const DWARFUnitVector &getUnitVector() const { return UnitVector; }
0502 
0503   /// Returns the number of DIEs in the unit. Parses the unit
0504   /// if necessary.
0505   unsigned getNumDIEs() {
0506     extractDIEsIfNeeded(false);
0507     return DieArray.size();
0508   }
0509 
0510   /// Return the index of a DIE inside the unit's DIE vector.
0511   ///
0512   /// It is illegal to call this method with a DIE that hasn't be
0513   /// created by this unit. In other word, it's illegal to call this
0514   /// method on a DIE that isn't accessible by following
0515   /// children/sibling links starting from this unit's getUnitDIE().
0516   uint32_t getDIEIndex(const DWARFDie &D) const {
0517     return getDIEIndex(D.getDebugInfoEntry());
0518   }
0519 
0520   /// Return the DIE object at the given index \p Index.
0521   DWARFDie getDIEAtIndex(unsigned Index) {
0522     return DWARFDie(this, getDebugInfoEntry(Index));
0523   }
0524 
0525   DWARFDie getParent(const DWARFDebugInfoEntry *Die);
0526   DWARFDie getSibling(const DWARFDebugInfoEntry *Die);
0527   DWARFDie getPreviousSibling(const DWARFDebugInfoEntry *Die);
0528   DWARFDie getFirstChild(const DWARFDebugInfoEntry *Die);
0529   DWARFDie getLastChild(const DWARFDebugInfoEntry *Die);
0530 
0531   /// Return the DIE object for a given offset \p Offset inside the
0532   /// unit's DIE vector.
0533   DWARFDie getDIEForOffset(uint64_t Offset) {
0534     if (std::optional<uint32_t> DieIdx = getDIEIndexForOffset(Offset))
0535       return DWARFDie(this, &DieArray[*DieIdx]);
0536 
0537     return DWARFDie();
0538   }
0539 
0540   /// Return the DIE index for a given offset \p Offset inside the
0541   /// unit's DIE vector.
0542   std::optional<uint32_t> getDIEIndexForOffset(uint64_t Offset) {
0543     extractDIEsIfNeeded(false);
0544     auto It =
0545         llvm::partition_point(DieArray, [=](const DWARFDebugInfoEntry &DIE) {
0546           return DIE.getOffset() < Offset;
0547         });
0548     if (It != DieArray.end() && It->getOffset() == Offset)
0549       return It - DieArray.begin();
0550     return std::nullopt;
0551   }
0552 
0553   uint32_t getLineTableOffset() const {
0554     if (auto IndexEntry = Header.getIndexEntry())
0555       if (const auto *Contrib = IndexEntry->getContribution(DW_SECT_LINE))
0556         return Contrib->getOffset32();
0557     return 0;
0558   }
0559 
0560   die_iterator_range dies() {
0561     extractDIEsIfNeeded(false);
0562     return die_iterator_range(DieArray.begin(), DieArray.end());
0563   }
0564 
0565   virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0;
0566 
0567   Error tryExtractDIEsIfNeeded(bool CUDieOnly);
0568 
0569 private:
0570   /// Size in bytes of the .debug_info data associated with this compile unit.
0571   size_t getDebugInfoSize() const {
0572     return Header.getLength() + Header.getUnitLengthFieldByteSize() -
0573            getHeaderSize();
0574   }
0575 
0576   /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it
0577   /// hasn't already been done
0578   void extractDIEsIfNeeded(bool CUDieOnly);
0579 
0580   /// extractDIEsToVector - Appends all parsed DIEs to a vector.
0581   void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs,
0582                            std::vector<DWARFDebugInfoEntry> &DIEs) const;
0583 
0584   /// clearDIEs - Clear parsed DIEs to keep memory usage low.
0585   void clearDIEs(bool KeepCUDie);
0586 
0587   /// parseDWO - Parses .dwo file for current compile unit. Returns true if
0588   /// it was actually constructed.
0589   /// The \p AlternativeLocation specifies an alternative location to get
0590   /// the DWARF context for the DWO object; this is the case when it has
0591   /// been moved from its original location.
0592   bool parseDWO(StringRef AlternativeLocation = {});
0593 };
0594 
0595 inline bool isCompileUnit(const std::unique_ptr<DWARFUnit> &U) {
0596   return !U->isTypeUnit();
0597 }
0598 
0599 } // end namespace llvm
0600 
0601 #endif // LLVM_DEBUGINFO_DWARF_DWARFUNIT_H