xref: /freebsd/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- DWARFUnit.h ----------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
10 #define LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
11 
12 #include "llvm/ADT/DenseSet.h"
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/ADT/iterator_range.h"
17 #include "llvm/BinaryFormat/Dwarf.h"
18 #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
19 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
20 #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
21 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
22 #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
23 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
24 #include "llvm/Support/Compiler.h"
25 #include "llvm/Support/DataExtractor.h"
26 #include <cassert>
27 #include <cstddef>
28 #include <cstdint>
29 #include <map>
30 #include <memory>
31 #include <set>
32 #include <utility>
33 #include <vector>
34 
35 namespace llvm {
36 
37 class DWARFAbbreviationDeclarationSet;
38 class DWARFContext;
39 class DWARFDebugAbbrev;
40 class DWARFUnit;
41 class DWARFDebugRangeList;
42 class DWARFLocationTable;
43 class DWARFObject;
44 class raw_ostream;
45 struct DIDumpOptions;
46 struct DWARFSection;
47 namespace dwarf_linker {
48 namespace parallel {
49 class CompileUnit;
50 }
51 } // namespace dwarf_linker
52 
53 /// Base class describing the header of any kind of "unit."  Some information
54 /// is specific to certain unit types.  We separate this class out so we can
55 /// parse the header before deciding what specific kind of unit to construct.
56 class DWARFUnitHeader {
57   // Offset within section.
58   uint64_t Offset = 0;
59   // Version, address size, and DWARF format.
60   dwarf::FormParams FormParams;
61   uint64_t Length = 0;
62   uint64_t AbbrOffset = 0;
63 
64   // For DWO units only.
65   const DWARFUnitIndex::Entry *IndexEntry = nullptr;
66 
67   // For type units only.
68   uint64_t TypeHash = 0;
69   uint64_t TypeOffset = 0;
70 
71   // For v5 split or skeleton compile units only.
72   std::optional<uint64_t> DWOId;
73 
74   // Unit type as parsed, or derived from the section kind.
75   uint8_t UnitType = 0;
76 
77   // Size as parsed. uint8_t for compactness.
78   uint8_t Size = 0;
79 
80 public:
81   /// Parse a unit header from \p debug_info starting at \p offset_ptr.
82   /// Note that \p SectionKind is used as a hint to guess the unit type
83   /// for DWARF formats prior to DWARFv5. In DWARFv5 the unit type is
84   /// explicitly defined in the header and the hint is ignored.
85   LLVM_ABI Error extract(DWARFContext &Context,
86                          const DWARFDataExtractor &debug_info,
87                          uint64_t *offset_ptr, DWARFSectionKind SectionKind);
88   // For units in DWARF Package File, remember the index entry and update
89   // the abbreviation offset read by extract().
90   LLVM_ABI Error applyIndexEntry(const DWARFUnitIndex::Entry *Entry);
getOffset()91   uint64_t getOffset() const { return Offset; }
getFormParams()92   const dwarf::FormParams &getFormParams() const { return FormParams; }
getVersion()93   uint16_t getVersion() const { return FormParams.Version; }
getFormat()94   dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
getAddressByteSize()95   uint8_t getAddressByteSize() const { return FormParams.AddrSize; }
getRefAddrByteSize()96   uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); }
getDwarfOffsetByteSize()97   uint8_t getDwarfOffsetByteSize() const {
98     return FormParams.getDwarfOffsetByteSize();
99   }
getLength()100   uint64_t getLength() const { return Length; }
getAbbrOffset()101   uint64_t getAbbrOffset() const { return AbbrOffset; }
getDWOId()102   std::optional<uint64_t> getDWOId() const { return DWOId; }
setDWOId(uint64_t Id)103   void setDWOId(uint64_t Id) {
104     assert((!DWOId || *DWOId == Id) && "setting DWOId to a different value");
105     DWOId = Id;
106   }
getIndexEntry()107   const DWARFUnitIndex::Entry *getIndexEntry() const { return IndexEntry; }
getTypeHash()108   uint64_t getTypeHash() const { return TypeHash; }
getTypeOffset()109   uint64_t getTypeOffset() const { return TypeOffset; }
getUnitType()110   uint8_t getUnitType() const { return UnitType; }
isTypeUnit()111   bool isTypeUnit() const {
112     return UnitType == dwarf::DW_UT_type || UnitType == dwarf::DW_UT_split_type;
113   }
getSize()114   uint8_t getSize() const { return Size; }
getUnitLengthFieldByteSize()115   uint8_t getUnitLengthFieldByteSize() const {
116     return dwarf::getUnitLengthFieldByteSize(FormParams.Format);
117   }
getNextUnitOffset()118   uint64_t getNextUnitOffset() const {
119     return Offset + Length + getUnitLengthFieldByteSize();
120   }
121 };
122 
123 LLVM_ABI const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
124                                                  DWARFSectionKind Kind);
125 
126 bool isCompileUnit(const std::unique_ptr<DWARFUnit> &U);
127 
128 /// Describe a collection of units. Intended to hold all units either from
129 /// .debug_info and .debug_types, or from .debug_info.dwo and .debug_types.dwo.
130 class DWARFUnitVector final : public SmallVector<std::unique_ptr<DWARFUnit>, 1> {
131   std::function<std::unique_ptr<DWARFUnit>(uint64_t, DWARFSectionKind,
132                                            const DWARFSection *,
133                                            const DWARFUnitIndex::Entry *)>
134       Parser;
135   int NumInfoUnits = -1;
136 
137 public:
138   using UnitVector = SmallVectorImpl<std::unique_ptr<DWARFUnit>>;
139   using iterator = typename UnitVector::iterator;
140   using iterator_range = llvm::iterator_range<typename UnitVector::iterator>;
141 
142   using compile_unit_range =
143       decltype(make_filter_range(std::declval<iterator_range>(), isCompileUnit));
144 
145   LLVM_ABI DWARFUnit *getUnitForOffset(uint64_t Offset) const;
146   LLVM_ABI DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E);
147 
148   /// Read units from a .debug_info or .debug_types section.  Calls made
149   /// before finishedInfoUnits() are assumed to be for .debug_info sections,
150   /// calls after finishedInfoUnits() are for .debug_types sections.  Caller
151   /// must not mix calls to addUnitsForSection and addUnitsForDWOSection.
152   LLVM_ABI void addUnitsForSection(DWARFContext &C, const DWARFSection &Section,
153                                    DWARFSectionKind SectionKind);
154   /// Read units from a .debug_info.dwo or .debug_types.dwo section.  Calls
155   /// made before finishedInfoUnits() are assumed to be for .debug_info.dwo
156   /// sections, calls after finishedInfoUnits() are for .debug_types.dwo
157   /// sections.  Caller must not mix calls to addUnitsForSection and
158   /// addUnitsForDWOSection.
159   LLVM_ABI void addUnitsForDWOSection(DWARFContext &C,
160                                       const DWARFSection &DWOSection,
161                                       DWARFSectionKind SectionKind,
162                                       bool Lazy = false);
163 
164   /// Add an existing DWARFUnit to this UnitVector. This is used by the DWARF
165   /// verifier to process unit separately.
166   LLVM_ABI DWARFUnit *addUnit(std::unique_ptr<DWARFUnit> Unit);
167 
168   /// Returns number of all units held by this instance.
getNumUnits()169   unsigned getNumUnits() const { return size(); }
170   /// Returns number of units from all .debug_info[.dwo] sections.
getNumInfoUnits()171   unsigned getNumInfoUnits() const {
172     return NumInfoUnits == -1 ? size() : NumInfoUnits;
173   }
174   /// Returns number of units from all .debug_types[.dwo] sections.
getNumTypesUnits()175   unsigned getNumTypesUnits() const { return size() - NumInfoUnits; }
176   /// Indicate that parsing .debug_info[.dwo] is done, and remaining units
177   /// will be from .debug_types[.dwo].
finishedInfoUnits()178   void finishedInfoUnits() { NumInfoUnits = size(); }
179 
180 private:
181   void addUnitsImpl(DWARFContext &Context, const DWARFObject &Obj,
182                     const DWARFSection &Section, const DWARFDebugAbbrev *DA,
183                     const DWARFSection *RS, const DWARFSection *LocSection,
184                     StringRef SS, const DWARFSection &SOS,
185                     const DWARFSection *AOS, const DWARFSection &LS, bool LE,
186                     bool IsDWO, bool Lazy, DWARFSectionKind SectionKind);
187 };
188 
189 /// Represents base address of the CU.
190 /// Represents a unit's contribution to the string offsets table.
191 struct StrOffsetsContributionDescriptor {
192   uint64_t Base = 0;
193   /// The contribution size not including the header.
194   uint64_t Size = 0;
195   /// Format and version.
196   dwarf::FormParams FormParams = {0, 0, dwarf::DwarfFormat::DWARF32};
197 
StrOffsetsContributionDescriptorStrOffsetsContributionDescriptor198   StrOffsetsContributionDescriptor(uint64_t Base, uint64_t Size,
199                                    uint8_t Version, dwarf::DwarfFormat Format)
200       : Base(Base), Size(Size), FormParams({Version, 0, Format}) {}
201   StrOffsetsContributionDescriptor() = default;
202 
getVersionStrOffsetsContributionDescriptor203   uint8_t getVersion() const { return FormParams.Version; }
getFormatStrOffsetsContributionDescriptor204   dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
getDwarfOffsetByteSizeStrOffsetsContributionDescriptor205   uint8_t getDwarfOffsetByteSize() const {
206     return FormParams.getDwarfOffsetByteSize();
207   }
208   /// Determine whether a contribution to the string offsets table is
209   /// consistent with the relevant section size and that its length is
210   /// a multiple of the size of one of its entries.
211   LLVM_ABI Expected<StrOffsetsContributionDescriptor>
212   validateContributionSize(DWARFDataExtractor &DA);
213 };
214 
215 class LLVM_ABI DWARFUnit {
216   DWARFContext &Context;
217   /// Section containing this DWARFUnit.
218   const DWARFSection &InfoSection;
219 
220   DWARFUnitHeader Header;
221   const DWARFDebugAbbrev *Abbrev;
222   const DWARFSection *RangeSection;
223   uint64_t RangeSectionBase;
224   uint64_t LocSectionBase;
225 
226   /// Location table of this unit.
227   std::unique_ptr<DWARFLocationTable> LocTable;
228 
229   const DWARFSection &LineSection;
230   StringRef StringSection;
231   const DWARFSection &StringOffsetSection;
232   const DWARFSection *AddrOffsetSection;
233   DWARFUnit *SU;
234   std::optional<uint64_t> AddrOffsetSectionBase;
235   bool IsLittleEndian;
236   bool IsDWO;
237   const DWARFUnitVector &UnitVector;
238 
239   /// Start, length, and DWARF format of the unit's contribution to the string
240   /// offsets table (DWARF v5).
241   std::optional<StrOffsetsContributionDescriptor>
242       StringOffsetsTableContribution;
243 
244   mutable const DWARFAbbreviationDeclarationSet *Abbrevs;
245   std::optional<object::SectionedAddress> BaseAddr;
246   /// The compile unit debug information entry items.
247   std::vector<DWARFDebugInfoEntry> DieArray;
248 
249   /// Map from range's start address to end address and corresponding DIE.
250   /// IntervalMap does not support range removal, as a result, we use the
251   /// std::map::upper_bound for address range lookup.
252   std::map<uint64_t, std::pair<uint64_t, DWARFDie>> AddrDieMap;
253 
254   /// Map from the location (interpreted DW_AT_location) of a DW_TAG_variable,
255   /// to the end address and the corresponding DIE.
256   std::map<uint64_t, std::pair<uint64_t, DWARFDie>> VariableDieMap;
257   DenseSet<uint64_t> RootsParsedForVariables;
258 
259   using die_iterator_range =
260       iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>;
261 
262   std::shared_ptr<DWARFUnit> DWO;
263 
264 protected:
265   friend dwarf_linker::parallel::CompileUnit;
266 
267   /// Return the index of a \p Die entry inside the unit's DIE vector.
268   ///
269   /// It is illegal to call this method with a DIE that hasn't be
270   /// created by this unit. In other word, it's illegal to call this
271   /// method on a DIE that isn't accessible by following
272   /// children/sibling links starting from this unit's getUnitDIE().
getDIEIndex(const DWARFDebugInfoEntry * Die)273   uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const {
274     auto First = DieArray.data();
275     assert(Die >= First && Die < First + DieArray.size());
276     return Die - First;
277   }
278 
279   /// Return DWARFDebugInfoEntry for the specified index \p Index.
getDebugInfoEntry(unsigned Index)280   const DWARFDebugInfoEntry *getDebugInfoEntry(unsigned Index) const {
281     assert(Index < DieArray.size());
282     return &DieArray[Index];
283   }
284 
285   const DWARFDebugInfoEntry *
286   getParentEntry(const DWARFDebugInfoEntry *Die) const;
287   const DWARFDebugInfoEntry *
288   getSiblingEntry(const DWARFDebugInfoEntry *Die) const;
289   const DWARFDebugInfoEntry *
290   getPreviousSiblingEntry(const DWARFDebugInfoEntry *Die) const;
291   const DWARFDebugInfoEntry *
292   getFirstChildEntry(const DWARFDebugInfoEntry *Die) const;
293   const DWARFDebugInfoEntry *
294   getLastChildEntry(const DWARFDebugInfoEntry *Die) const;
295 
getHeader()296   const DWARFUnitHeader &getHeader() const { return Header; }
297 
298   /// Find the unit's contribution to the string offsets table and determine its
299   /// length and form. The given offset is expected to be derived from the unit
300   /// DIE's DW_AT_str_offsets_base attribute.
301   Expected<std::optional<StrOffsetsContributionDescriptor>>
302   determineStringOffsetsTableContribution(DWARFDataExtractor &DA);
303 
304   /// Find the unit's contribution to the string offsets table and determine its
305   /// length and form. The given offset is expected to be 0 in a dwo file or,
306   /// in a dwp file, the start of the unit's contribution to the string offsets
307   /// table section (as determined by the index table).
308   Expected<std::optional<StrOffsetsContributionDescriptor>>
309   determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA);
310 
311 public:
312   DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
313             const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA,
314             const DWARFSection *RS, const DWARFSection *LocSection,
315             StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS,
316             const DWARFSection &LS, bool LE, bool IsDWO,
317             const DWARFUnitVector &UnitVector);
318 
319   virtual ~DWARFUnit();
320 
isLittleEndian()321   bool isLittleEndian() const { return IsLittleEndian; }
isDWOUnit()322   bool isDWOUnit() const { return IsDWO; }
getContext()323   DWARFContext& getContext() const { return Context; }
getInfoSection()324   const DWARFSection &getInfoSection() const { return InfoSection; }
getOffset()325   uint64_t getOffset() const { return Header.getOffset(); }
getFormParams()326   const dwarf::FormParams &getFormParams() const {
327     return Header.getFormParams();
328   }
getVersion()329   uint16_t getVersion() const { return Header.getVersion(); }
getAddressByteSize()330   uint8_t getAddressByteSize() const { return Header.getAddressByteSize(); }
getRefAddrByteSize()331   uint8_t getRefAddrByteSize() const { return Header.getRefAddrByteSize(); }
getDwarfOffsetByteSize()332   uint8_t getDwarfOffsetByteSize() const {
333     return Header.getDwarfOffsetByteSize();
334   }
335   /// Size in bytes of the parsed unit header.
getHeaderSize()336   uint32_t getHeaderSize() const { return Header.getSize(); }
getLength()337   uint64_t getLength() const { return Header.getLength(); }
getFormat()338   dwarf::DwarfFormat getFormat() const { return Header.getFormat(); }
getUnitType()339   uint8_t getUnitType() const { return Header.getUnitType(); }
isTypeUnit()340   bool isTypeUnit() const { return Header.isTypeUnit(); }
getAbbrOffset()341   uint64_t getAbbrOffset() const { return Header.getAbbrOffset(); }
getNextUnitOffset()342   uint64_t getNextUnitOffset() const { return Header.getNextUnitOffset(); }
getLineSection()343   const DWARFSection &getLineSection() const { return LineSection; }
getStringSection()344   StringRef getStringSection() const { return StringSection; }
getStringOffsetSection()345   const DWARFSection &getStringOffsetSection() const {
346     return StringOffsetSection;
347   }
348 
setSkeletonUnit(DWARFUnit * SU)349   void setSkeletonUnit(DWARFUnit *SU) { this->SU = SU; }
350   // Returns itself if not using Split DWARF, or if the unit is a skeleton unit
351   // - otherwise returns the split full unit's corresponding skeleton, if
352   // available.
getLinkedUnit()353   DWARFUnit *getLinkedUnit() { return IsDWO ? SU : this; }
354 
setAddrOffsetSection(const DWARFSection * AOS,uint64_t Base)355   void setAddrOffsetSection(const DWARFSection *AOS, uint64_t Base) {
356     AddrOffsetSection = AOS;
357     AddrOffsetSectionBase = Base;
358   }
359 
getAddrOffsetSectionBase()360   std::optional<uint64_t> getAddrOffsetSectionBase() const {
361     return AddrOffsetSectionBase;
362   }
363 
364   /// Returns offset to the indexed address value inside .debug_addr section.
getIndexedAddressOffset(uint64_t Index)365   std::optional<uint64_t> getIndexedAddressOffset(uint64_t Index) {
366     if (std::optional<uint64_t> AddrOffsetSectionBase =
367             getAddrOffsetSectionBase())
368       return *AddrOffsetSectionBase + Index * getAddressByteSize();
369 
370     return std::nullopt;
371   }
372 
373   /// Recursively update address to Die map.
374   void updateAddressDieMap(DWARFDie Die);
375 
376   /// Recursively update address to variable Die map.
377   void updateVariableDieMap(DWARFDie Die);
378 
setRangesSection(const DWARFSection * RS,uint64_t Base)379   void setRangesSection(const DWARFSection *RS, uint64_t Base) {
380     RangeSection = RS;
381     RangeSectionBase = Base;
382   }
383 
getLocSectionBase()384   uint64_t getLocSectionBase() const {
385     return LocSectionBase;
386   }
387 
388   std::optional<object::SectionedAddress>
389   getAddrOffsetSectionItem(uint32_t Index) const;
390   Expected<uint64_t> getStringOffsetSectionItem(uint32_t Index) const;
391 
392   DWARFDataExtractor getDebugInfoExtractor() const;
393 
getStringExtractor()394   DataExtractor getStringExtractor() const {
395     return DataExtractor(StringSection, false, 0);
396   }
397 
getLocationTable()398   const DWARFLocationTable &getLocationTable() { return *LocTable; }
399 
400   /// Extract the range list referenced by this compile unit from the
401   /// .debug_ranges section. If the extraction is unsuccessful, an error
402   /// is returned. Successful extraction requires that the compile unit
403   /// has already been extracted.
404   Error extractRangeList(uint64_t RangeListOffset,
405                          DWARFDebugRangeList &RangeList) const;
406   void clear();
407 
408   const std::optional<StrOffsetsContributionDescriptor> &
getStringOffsetsTableContribution()409   getStringOffsetsTableContribution() {
410     extractDIEsIfNeeded(true /*CUDIeOnly*/);
411     return StringOffsetsTableContribution;
412   }
413 
getDwarfStringOffsetsByteSize()414   uint8_t getDwarfStringOffsetsByteSize() const {
415     assert(StringOffsetsTableContribution);
416     return StringOffsetsTableContribution->getDwarfOffsetByteSize();
417   }
418 
getStringOffsetsBase()419   uint64_t getStringOffsetsBase() const {
420     assert(StringOffsetsTableContribution);
421     return StringOffsetsTableContribution->Base;
422   }
423 
getAbbreviationsOffset()424   uint64_t getAbbreviationsOffset() const { return Header.getAbbrOffset(); }
425 
426   const DWARFAbbreviationDeclarationSet *getAbbreviations() const;
427 
isMatchingUnitTypeAndTag(uint8_t UnitType,dwarf::Tag Tag)428   static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag) {
429     switch (UnitType) {
430     case dwarf::DW_UT_compile:
431       return Tag == dwarf::DW_TAG_compile_unit;
432     case dwarf::DW_UT_type:
433       return Tag == dwarf::DW_TAG_type_unit;
434     case dwarf::DW_UT_partial:
435       return Tag == dwarf::DW_TAG_partial_unit;
436     case dwarf::DW_UT_skeleton:
437       return Tag == dwarf::DW_TAG_skeleton_unit;
438     case dwarf::DW_UT_split_compile:
439     case dwarf::DW_UT_split_type:
440       return dwarf::isUnitType(Tag);
441     }
442     return false;
443   }
444 
445   std::optional<object::SectionedAddress> getBaseAddress();
446 
447   DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
448     extractDIEsIfNeeded(ExtractUnitDIEOnly);
449     if (DieArray.empty())
450       return DWARFDie();
451     return DWARFDie(this, &DieArray[0]);
452   }
453 
454   DWARFDie getNonSkeletonUnitDIE(bool ExtractUnitDIEOnly = true,
455                                  StringRef DWOAlternativeLocation = {}) {
456     parseDWO(DWOAlternativeLocation);
457     return DWO ? DWO->getUnitDIE(ExtractUnitDIEOnly)
458                : getUnitDIE(ExtractUnitDIEOnly);
459   }
460 
461   const char *getCompilationDir();
getDWOId()462   std::optional<uint64_t> getDWOId() {
463     extractDIEsIfNeeded(/*CUDieOnly*/ true);
464     return getHeader().getDWOId();
465   }
setDWOId(uint64_t NewID)466   void setDWOId(uint64_t NewID) { Header.setDWOId(NewID); }
467 
468   /// Return a vector of address ranges resulting from a (possibly encoded)
469   /// range list starting at a given offset in the appropriate ranges section.
470   Expected<DWARFAddressRangesVector> findRnglistFromOffset(uint64_t Offset);
471 
472   /// Return a vector of address ranges retrieved from an encoded range
473   /// list whose offset is found via a table lookup given an index (DWARF v5
474   /// and later).
475   Expected<DWARFAddressRangesVector> findRnglistFromIndex(uint32_t Index);
476 
477   /// Return a rangelist's offset based on an index. The index designates
478   /// an entry in the rangelist table's offset array and is supplied by
479   /// DW_FORM_rnglistx.
480   std::optional<uint64_t> getRnglistOffset(uint32_t Index);
481 
482   std::optional<uint64_t> getLoclistOffset(uint32_t Index);
483 
484   Expected<DWARFAddressRangesVector> collectAddressRanges();
485 
486   Expected<DWARFLocationExpressionsVector>
487   findLoclistFromOffset(uint64_t Offset);
488 
489   /// Returns subprogram DIE with address range encompassing the provided
490   /// address. The pointer is alive as long as parsed compile unit DIEs are not
491   /// cleared.
492   DWARFDie getSubroutineForAddress(uint64_t Address);
493 
494   /// Returns variable DIE for the address provided. The pointer is alive as
495   /// long as parsed compile unit DIEs are not cleared.
496   DWARFDie getVariableForAddress(uint64_t Address);
497 
498   /// getInlinedChainForAddress - fetches inlined chain for a given address.
499   /// Returns empty chain if there is no subprogram containing address. The
500   /// chain is valid as long as parsed compile unit DIEs are not cleared.
501   void getInlinedChainForAddress(uint64_t Address,
502                                  SmallVectorImpl<DWARFDie> &InlinedChain);
503 
504   /// Return the DWARFUnitVector containing this unit.
getUnitVector()505   const DWARFUnitVector &getUnitVector() const { return UnitVector; }
506 
507   /// Returns the number of DIEs in the unit. Parses the unit
508   /// if necessary.
getNumDIEs()509   unsigned getNumDIEs() {
510     extractDIEsIfNeeded(false);
511     return DieArray.size();
512   }
513 
514   /// Return the index of a DIE inside the unit's DIE vector.
515   ///
516   /// It is illegal to call this method with a DIE that hasn't be
517   /// created by this unit. In other word, it's illegal to call this
518   /// method on a DIE that isn't accessible by following
519   /// children/sibling links starting from this unit's getUnitDIE().
getDIEIndex(const DWARFDie & D)520   uint32_t getDIEIndex(const DWARFDie &D) const {
521     return getDIEIndex(D.getDebugInfoEntry());
522   }
523 
524   /// Return the DIE object at the given index \p Index.
getDIEAtIndex(unsigned Index)525   DWARFDie getDIEAtIndex(unsigned Index) {
526     return DWARFDie(this, getDebugInfoEntry(Index));
527   }
528 
529   DWARFDie getParent(const DWARFDebugInfoEntry *Die);
530   DWARFDie getSibling(const DWARFDebugInfoEntry *Die);
531   DWARFDie getPreviousSibling(const DWARFDebugInfoEntry *Die);
532   DWARFDie getFirstChild(const DWARFDebugInfoEntry *Die);
533   DWARFDie getLastChild(const DWARFDebugInfoEntry *Die);
534 
535   /// Return the DIE object for a given offset \p Offset inside the
536   /// unit's DIE vector.
getDIEForOffset(uint64_t Offset)537   DWARFDie getDIEForOffset(uint64_t Offset) {
538     if (std::optional<uint32_t> DieIdx = getDIEIndexForOffset(Offset))
539       return DWARFDie(this, &DieArray[*DieIdx]);
540 
541     return DWARFDie();
542   }
543 
544   /// Return the DIE index for a given offset \p Offset inside the
545   /// unit's DIE vector.
getDIEIndexForOffset(uint64_t Offset)546   std::optional<uint32_t> getDIEIndexForOffset(uint64_t Offset) {
547     extractDIEsIfNeeded(false);
548     auto It =
549         llvm::partition_point(DieArray, [=](const DWARFDebugInfoEntry &DIE) {
550           return DIE.getOffset() < Offset;
551         });
552     if (It != DieArray.end() && It->getOffset() == Offset)
553       return It - DieArray.begin();
554     return std::nullopt;
555   }
556 
getLineTableOffset()557   uint32_t getLineTableOffset() const {
558     if (auto IndexEntry = Header.getIndexEntry())
559       if (const auto *Contrib = IndexEntry->getContribution(DW_SECT_LINE))
560         return Contrib->getOffset32();
561     return 0;
562   }
563 
dies()564   die_iterator_range dies() {
565     extractDIEsIfNeeded(false);
566     return die_iterator_range(DieArray.begin(), DieArray.end());
567   }
568 
569   virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0;
570 
571   Error tryExtractDIEsIfNeeded(bool CUDieOnly);
572 
573 private:
574   /// Size in bytes of the .debug_info data associated with this compile unit.
getDebugInfoSize()575   size_t getDebugInfoSize() const {
576     return Header.getLength() + Header.getUnitLengthFieldByteSize() -
577            getHeaderSize();
578   }
579 
580   /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it
581   /// hasn't already been done
582   void extractDIEsIfNeeded(bool CUDieOnly);
583 
584   /// extractDIEsToVector - Appends all parsed DIEs to a vector.
585   void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs,
586                            std::vector<DWARFDebugInfoEntry> &DIEs) const;
587 
588   /// clearDIEs - Clear parsed DIEs to keep memory usage low.
589   void clearDIEs(bool KeepCUDie);
590 
591   /// parseDWO - Parses .dwo file for current compile unit. Returns true if
592   /// it was actually constructed.
593   /// The \p AlternativeLocation specifies an alternative location to get
594   /// the DWARF context for the DWO object; this is the case when it has
595   /// been moved from its original location.
596   bool parseDWO(StringRef AlternativeLocation = {});
597 };
598 
isCompileUnit(const std::unique_ptr<DWARFUnit> & U)599 inline bool isCompileUnit(const std::unique_ptr<DWARFUnit> &U) {
600   return !U->isTypeUnit();
601 }
602 
603 } // end namespace llvm
604 
605 #endif // LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
606