Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //===- DWARFAcceleratorTable.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_DWARFACCELERATORTABLE_H
0010 #define LLVM_DEBUGINFO_DWARF_DWARFACCELERATORTABLE_H
0011 
0012 #include "llvm/ADT/DenseSet.h"
0013 #include "llvm/ADT/SmallString.h"
0014 #include "llvm/ADT/SmallVector.h"
0015 #include "llvm/BinaryFormat/Dwarf.h"
0016 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
0017 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
0018 #include <cstdint>
0019 #include <utility>
0020 
0021 namespace llvm {
0022 
0023 class raw_ostream;
0024 class ScopedPrinter;
0025 
0026 /// The accelerator tables are designed to allow efficient random access
0027 /// (using a symbol name as a key) into debug info by providing an index of the
0028 /// debug info DIEs. This class implements the common functionality of Apple and
0029 /// DWARF 5 accelerator tables.
0030 /// TODO: Generalize the rest of the AppleAcceleratorTable interface and move it
0031 /// to this class.
0032 class DWARFAcceleratorTable {
0033 protected:
0034   DWARFDataExtractor AccelSection;
0035   DataExtractor StringSection;
0036 
0037 public:
0038   /// An abstract class representing a single entry in the accelerator tables.
0039   class Entry {
0040   protected:
0041     SmallVector<DWARFFormValue, 3> Values;
0042 
0043     Entry() = default;
0044 
0045     // Make these protected so only (final) subclasses can be copied around.
0046     Entry(const Entry &) = default;
0047     Entry(Entry &&) = default;
0048     Entry &operator=(const Entry &) = default;
0049     Entry &operator=(Entry &&) = default;
0050     ~Entry() = default;
0051 
0052 
0053   public:
0054     /// Returns the Offset of the Compilation Unit associated with this
0055     /// Accelerator Entry or std::nullopt if the Compilation Unit offset is not
0056     /// recorded in this Accelerator Entry.
0057     virtual std::optional<uint64_t> getCUOffset() const = 0;
0058 
0059     /// Returns the Offset of the Type Unit associated with this
0060     /// Accelerator Entry or std::nullopt if the Type Unit offset is not
0061     /// recorded in this Accelerator Entry.
0062     virtual std::optional<uint64_t> getLocalTUOffset() const {
0063       // Default return for accelerator tables that don't support type units.
0064       return std::nullopt;
0065     }
0066 
0067     /// Returns the type signature of the Type Unit associated with this
0068     /// Accelerator Entry or std::nullopt if the Type Unit offset is not
0069     /// recorded in this Accelerator Entry.
0070     virtual std::optional<uint64_t> getForeignTUTypeSignature() const {
0071       // Default return for accelerator tables that don't support type units.
0072       return std::nullopt;
0073     }
0074 
0075     /// Returns the Tag of the Debug Info Entry associated with this
0076     /// Accelerator Entry or std::nullopt if the Tag is not recorded in this
0077     /// Accelerator Entry.
0078     virtual std::optional<dwarf::Tag> getTag() const = 0;
0079 
0080     /// Returns the raw values of fields in the Accelerator Entry. In general,
0081     /// these can only be interpreted with the help of the metadata in the
0082     /// owning Accelerator Table.
0083     ArrayRef<DWARFFormValue> getValues() const { return Values; }
0084   };
0085 
0086   DWARFAcceleratorTable(const DWARFDataExtractor &AccelSection,
0087                         DataExtractor StringSection)
0088       : AccelSection(AccelSection), StringSection(StringSection) {}
0089   virtual ~DWARFAcceleratorTable();
0090 
0091   virtual Error extract() = 0;
0092   virtual void dump(raw_ostream &OS) const = 0;
0093 
0094   DWARFAcceleratorTable(const DWARFAcceleratorTable &) = delete;
0095   void operator=(const DWARFAcceleratorTable &) = delete;
0096 };
0097 
0098 /// This implements the Apple accelerator table format, a precursor of the
0099 /// DWARF 5 accelerator table format.
0100 class AppleAcceleratorTable : public DWARFAcceleratorTable {
0101   struct Header {
0102     uint32_t Magic;
0103     uint16_t Version;
0104     uint16_t HashFunction;
0105     uint32_t BucketCount;
0106     uint32_t HashCount;
0107     uint32_t HeaderDataLength;
0108 
0109     void dump(ScopedPrinter &W) const;
0110   };
0111 
0112   struct HeaderData {
0113     using AtomType = uint16_t;
0114     using Form = dwarf::Form;
0115 
0116     uint64_t DIEOffsetBase;
0117     SmallVector<std::pair<AtomType, Form>, 3> Atoms;
0118 
0119     std::optional<uint64_t>
0120     extractOffset(std::optional<DWARFFormValue> Value) const;
0121   };
0122 
0123   Header Hdr;
0124   HeaderData HdrData;
0125   dwarf::FormParams FormParams;
0126   uint32_t HashDataEntryLength;
0127   bool IsValid = false;
0128 
0129   /// Returns true if we should continue scanning for entries or false if we've
0130   /// reached the last (sentinel) entry of encountered a parsing error.
0131   bool dumpName(ScopedPrinter &W, SmallVectorImpl<DWARFFormValue> &AtomForms,
0132                 uint64_t *DataOffset) const;
0133 
0134   /// Reads an uint32_t from the accelerator table at Offset, which is
0135   /// incremented by the number of bytes read.
0136   std::optional<uint32_t> readU32FromAccel(uint64_t &Offset,
0137                                            bool UseRelocation = false) const;
0138 
0139   /// Reads a StringRef from the string table at Offset.
0140   std::optional<StringRef>
0141   readStringFromStrSection(uint64_t StringSectionOffset) const;
0142 
0143   /// Return the offset into the section where the Buckets begin.
0144   uint64_t getBucketBase() const { return sizeof(Hdr) + Hdr.HeaderDataLength; }
0145 
0146   /// Return the offset into the section where the I-th bucket is.
0147   uint64_t getIthBucketBase(uint32_t I) const {
0148     return getBucketBase() + I * 4;
0149   }
0150 
0151   /// Return the offset into the section where the hash list begins.
0152   uint64_t getHashBase() const { return getBucketBase() + getNumBuckets() * 4; }
0153 
0154   /// Return the offset into the section where the I-th hash is.
0155   uint64_t getIthHashBase(uint32_t I) const { return getHashBase() + I * 4; }
0156 
0157   /// Return the offset into the section where the offset list begins.
0158   uint64_t getOffsetBase() const { return getHashBase() + getNumHashes() * 4; }
0159 
0160   /// Return the offset into the section where the table entries begin.
0161   uint64_t getEntriesBase() const {
0162     return getOffsetBase() + getNumHashes() * 4;
0163   }
0164 
0165   /// Return the offset into the section where the I-th offset is.
0166   uint64_t getIthOffsetBase(uint32_t I) const {
0167     return getOffsetBase() + I * 4;
0168   }
0169 
0170   /// Returns the index of the bucket where a hypothetical Hash would be.
0171   uint32_t hashToBucketIdx(uint32_t Hash) const {
0172     return Hash % getNumBuckets();
0173   }
0174 
0175   /// Returns true iff a hypothetical Hash would be assigned to the BucketIdx-th
0176   /// bucket.
0177   bool wouldHashBeInBucket(uint32_t Hash, uint32_t BucketIdx) const {
0178     return hashToBucketIdx(Hash) == BucketIdx;
0179   }
0180 
0181   /// Reads the contents of the I-th bucket, that is, the index in the hash list
0182   /// where the hashes corresponding to this bucket begin.
0183   std::optional<uint32_t> readIthBucket(uint32_t I) const {
0184     uint64_t Offset = getIthBucketBase(I);
0185     return readU32FromAccel(Offset);
0186   }
0187 
0188   /// Reads the I-th hash in the hash list.
0189   std::optional<uint32_t> readIthHash(uint32_t I) const {
0190     uint64_t Offset = getIthHashBase(I);
0191     return readU32FromAccel(Offset);
0192   }
0193 
0194   /// Reads the I-th offset in the offset list.
0195   std::optional<uint32_t> readIthOffset(uint32_t I) const {
0196     uint64_t Offset = getIthOffsetBase(I);
0197     return readU32FromAccel(Offset);
0198   }
0199 
0200   /// Reads a string offset from the accelerator table at Offset, which is
0201   /// incremented by the number of bytes read.
0202   std::optional<uint32_t> readStringOffsetAt(uint64_t &Offset) const {
0203     return readU32FromAccel(Offset, /*UseRelocation*/ true);
0204   }
0205 
0206   /// Scans through all Hashes in the BucketIdx-th bucket, attempting to find
0207   /// HashToFind. If it is found, its index in the list of hashes is returned.
0208   std::optional<uint32_t> idxOfHashInBucket(uint32_t HashToFind,
0209                                             uint32_t BucketIdx) const;
0210 
0211 public:
0212   /// Apple-specific implementation of an Accelerator Entry.
0213   class Entry final : public DWARFAcceleratorTable::Entry {
0214     const AppleAcceleratorTable &Table;
0215 
0216     Entry(const AppleAcceleratorTable &Table);
0217     void extract(uint64_t *Offset);
0218 
0219   public:
0220     std::optional<uint64_t> getCUOffset() const override;
0221 
0222     /// Returns the Section Offset of the Debug Info Entry associated with this
0223     /// Accelerator Entry or std::nullopt if the DIE offset is not recorded in
0224     /// this Accelerator Entry. The returned offset is relative to the start of
0225     /// the Section containing the DIE.
0226     std::optional<uint64_t> getDIESectionOffset() const;
0227 
0228     std::optional<dwarf::Tag> getTag() const override;
0229 
0230     /// Returns the value of the Atom in this Accelerator Entry, if the Entry
0231     /// contains such Atom.
0232     std::optional<DWARFFormValue> lookup(HeaderData::AtomType Atom) const;
0233 
0234     friend class AppleAcceleratorTable;
0235     friend class ValueIterator;
0236   };
0237 
0238   /// An iterator for Entries all having the same string as key.
0239   class SameNameIterator
0240       : public iterator_facade_base<SameNameIterator, std::forward_iterator_tag,
0241                                     Entry> {
0242     Entry Current;
0243     uint64_t Offset = 0;
0244 
0245   public:
0246     /// Construct a new iterator for the entries at \p DataOffset.
0247     SameNameIterator(const AppleAcceleratorTable &AccelTable,
0248                      uint64_t DataOffset);
0249 
0250     const Entry &operator*() {
0251       uint64_t OffsetCopy = Offset;
0252       Current.extract(&OffsetCopy);
0253       return Current;
0254     }
0255     SameNameIterator &operator++() {
0256       Offset += Current.Table.getHashDataEntryLength();
0257       return *this;
0258     }
0259     friend bool operator==(const SameNameIterator &A,
0260                            const SameNameIterator &B) {
0261       return A.Offset == B.Offset;
0262     }
0263   };
0264 
0265   struct EntryWithName {
0266     EntryWithName(const AppleAcceleratorTable &Table)
0267         : BaseEntry(Table), StrOffset(0) {}
0268 
0269     std::optional<StringRef> readName() const {
0270       return BaseEntry.Table.readStringFromStrSection(StrOffset);
0271     }
0272 
0273     Entry BaseEntry;
0274     uint32_t StrOffset;
0275   };
0276 
0277   /// An iterator for all entries in the table.
0278   class Iterator
0279       : public iterator_facade_base<Iterator, std::forward_iterator_tag,
0280                                     EntryWithName> {
0281     constexpr static auto EndMarker = std::numeric_limits<uint64_t>::max();
0282 
0283     EntryWithName Current;
0284     uint64_t Offset = EndMarker;
0285     uint32_t NumEntriesToCome = 0;
0286 
0287     void setToEnd() { Offset = EndMarker; }
0288     bool isEnd() const { return Offset == EndMarker; }
0289     const AppleAcceleratorTable &getTable() const {
0290       return Current.BaseEntry.Table;
0291     }
0292 
0293     /// Reads the next Entry in the table, populating `Current`.
0294     /// If not possible (e.g. end of the section), becomes the end iterator.
0295     void prepareNextEntryOrEnd();
0296 
0297     /// Reads the next string pointer and the entry count for that string,
0298     /// populating `NumEntriesToCome`.
0299     /// If not possible (e.g. end of the section), becomes the end iterator.
0300     /// Assumes `Offset` points to a string reference.
0301     void prepareNextStringOrEnd();
0302 
0303   public:
0304     Iterator(const AppleAcceleratorTable &Table, bool SetEnd = false);
0305 
0306     Iterator &operator++() {
0307       prepareNextEntryOrEnd();
0308       return *this;
0309     }
0310     bool operator==(const Iterator &It) const { return Offset == It.Offset; }
0311     const EntryWithName &operator*() const {
0312       assert(!isEnd() && "dereferencing end iterator");
0313       return Current;
0314     }
0315   };
0316 
0317   AppleAcceleratorTable(const DWARFDataExtractor &AccelSection,
0318                         DataExtractor StringSection)
0319       : DWARFAcceleratorTable(AccelSection, StringSection) {}
0320 
0321   Error extract() override;
0322   uint32_t getNumBuckets() const;
0323   uint32_t getNumHashes() const;
0324   uint32_t getSizeHdr() const;
0325   uint32_t getHeaderDataLength() const;
0326 
0327   /// Returns the size of one HashData entry.
0328   uint32_t getHashDataEntryLength() const { return HashDataEntryLength; }
0329 
0330   /// Return the Atom description, which can be used to interpret the raw values
0331   /// of the Accelerator Entries in this table.
0332   ArrayRef<std::pair<HeaderData::AtomType, HeaderData::Form>> getAtomsDesc();
0333 
0334   /// Returns true iff `AtomTy` is one of the atoms available in Entries of this
0335   /// table.
0336   bool containsAtomType(HeaderData::AtomType AtomTy) const {
0337     return is_contained(make_first_range(HdrData.Atoms), AtomTy);
0338   }
0339 
0340   bool validateForms();
0341 
0342   /// Return information related to the DWARF DIE we're looking for when
0343   /// performing a lookup by name.
0344   ///
0345   /// \param HashDataOffset an offset into the hash data table
0346   /// \returns <DieOffset, DieTag>
0347   /// DieOffset is the offset into the .debug_info section for the DIE
0348   /// related to the input hash data offset.
0349   /// DieTag is the tag of the DIE
0350   std::pair<uint64_t, dwarf::Tag> readAtoms(uint64_t *HashDataOffset);
0351   void dump(raw_ostream &OS) const override;
0352 
0353   /// Look up all entries in the accelerator table matching \c Key.
0354   iterator_range<SameNameIterator> equal_range(StringRef Key) const;
0355 
0356   /// Lookup all entries in the accelerator table.
0357   auto entries() const {
0358     return make_range(Iterator(*this), Iterator(*this, /*SetEnd*/ true));
0359   }
0360 };
0361 
0362 /// .debug_names section consists of one or more units. Each unit starts with a
0363 /// header, which is followed by a list of compilation units, local and foreign
0364 /// type units.
0365 ///
0366 /// These may be followed by an (optional) hash lookup table, which consists of
0367 /// an array of buckets and hashes similar to the apple tables above. The only
0368 /// difference is that the hashes array is 1-based, and consequently an empty
0369 /// bucket is denoted by 0 and not UINT32_MAX.
0370 ///
0371 /// Next is the name table, which consists of an array of names and array of
0372 /// entry offsets. This is different from the apple tables, which store names
0373 /// next to the actual entries.
0374 ///
0375 /// The structure of the entries is described by an abbreviations table, which
0376 /// comes after the name table. Unlike the apple tables, which have a uniform
0377 /// entry structure described in the header, each .debug_names entry may have
0378 /// different index attributes (DW_IDX_???) attached to it.
0379 ///
0380 /// The last segment consists of a list of entries, which is a 0-terminated list
0381 /// referenced by the name table and interpreted with the help of the
0382 /// abbreviation table.
0383 class DWARFDebugNames : public DWARFAcceleratorTable {
0384 public:
0385   class NameIndex;
0386   class NameIterator;
0387   class ValueIterator;
0388 
0389   /// DWARF v5 Name Index header.
0390   struct Header {
0391     uint64_t UnitLength;
0392     dwarf::DwarfFormat Format;
0393     uint16_t Version;
0394     uint32_t CompUnitCount;
0395     uint32_t LocalTypeUnitCount;
0396     uint32_t ForeignTypeUnitCount;
0397     uint32_t BucketCount;
0398     uint32_t NameCount;
0399     uint32_t AbbrevTableSize;
0400     uint32_t AugmentationStringSize;
0401     SmallString<8> AugmentationString;
0402 
0403     Error extract(const DWARFDataExtractor &AS, uint64_t *Offset);
0404     void dump(ScopedPrinter &W) const;
0405   };
0406 
0407   /// Index attribute and its encoding.
0408   struct AttributeEncoding {
0409     dwarf::Index Index;
0410     dwarf::Form Form;
0411 
0412     constexpr AttributeEncoding(dwarf::Index Index, dwarf::Form Form)
0413         : Index(Index), Form(Form) {}
0414 
0415     friend bool operator==(const AttributeEncoding &LHS,
0416                            const AttributeEncoding &RHS) {
0417       return LHS.Index == RHS.Index && LHS.Form == RHS.Form;
0418     }
0419   };
0420 
0421   /// Abbreviation describing the encoding of Name Index entries.
0422   struct Abbrev {
0423     uint64_t AbbrevOffset; /// < Abbreviation offset in the .debug_names section
0424     uint32_t Code;         ///< Abbreviation code
0425     dwarf::Tag Tag; ///< Dwarf Tag of the described entity.
0426     std::vector<AttributeEncoding> Attributes; ///< List of index attributes.
0427 
0428     Abbrev(uint32_t Code, dwarf::Tag Tag, uint64_t AbbrevOffset,
0429            std::vector<AttributeEncoding> Attributes)
0430         : AbbrevOffset(AbbrevOffset), Code(Code), Tag(Tag),
0431           Attributes(std::move(Attributes)) {}
0432 
0433     void dump(ScopedPrinter &W) const;
0434   };
0435 
0436   /// DWARF v5-specific implementation of an Accelerator Entry.
0437   class Entry final : public DWARFAcceleratorTable::Entry {
0438     const NameIndex *NameIdx;
0439     const Abbrev *Abbr;
0440 
0441     Entry(const NameIndex &NameIdx, const Abbrev &Abbr);
0442 
0443   public:
0444     const NameIndex *getNameIndex() const { return NameIdx; }
0445     std::optional<uint64_t> getCUOffset() const override;
0446     std::optional<uint64_t> getLocalTUOffset() const override;
0447     std::optional<uint64_t> getForeignTUTypeSignature() const override;
0448     std::optional<dwarf::Tag> getTag() const override { return tag(); }
0449 
0450     // Special function that will return the related CU offset needed type
0451     // units. This gets used to find the .dwo file that originated the entries
0452     // for a given type unit.
0453     std::optional<uint64_t> getRelatedCUOffset() const;
0454 
0455     /// Returns the Index into the Compilation Unit list of the owning Name
0456     /// Index or std::nullopt if this Accelerator Entry does not have an
0457     /// associated Compilation Unit. It is up to the user to verify that the
0458     /// returned Index is valid in the owning NameIndex (or use getCUOffset(),
0459     /// which will handle that check itself). Note that entries in NameIndexes
0460     /// which index just a single Compilation Unit are implicitly associated
0461     /// with that unit, so this function will return 0 even without an explicit
0462     /// DW_IDX_compile_unit attribute, unless there is a DW_IDX_type_unit
0463     /// attribute.
0464     std::optional<uint64_t> getCUIndex() const;
0465 
0466     /// Similar functionality to getCUIndex() but without the DW_IDX_type_unit
0467     /// restriction. This allows us to get the associated a compilation unit
0468     /// index for an entry that is a type unit.
0469     std::optional<uint64_t> getRelatedCUIndex() const;
0470 
0471     /// Returns the index of the Type Unit of the owning
0472     /// Name
0473     /// Index or std::nullopt if this Accelerator Entry does not have an
0474     /// associated Type Unit. It is up to the user to verify that the
0475     /// returned Index is a valid index in the owning NameIndex (or use
0476     /// getLocalTUOffset(), which will handle that check itself).
0477     std::optional<uint64_t> getTUIndex() const;
0478 
0479     /// .debug_names-specific getter, which always succeeds (DWARF v5 index
0480     /// entries always have a tag).
0481     dwarf::Tag tag() const { return Abbr->Tag; }
0482 
0483     /// Returns the Offset of the DIE within the containing CU or TU.
0484     std::optional<uint64_t> getDIEUnitOffset() const;
0485 
0486     /// Returns true if this Entry has information about its parent DIE (i.e. if
0487     /// it has an IDX_parent attribute)
0488     bool hasParentInformation() const;
0489 
0490     /// Returns the Entry corresponding to the parent of the DIE represented by
0491     /// `this` Entry. If the parent is not in the table, nullopt is returned.
0492     /// Precondition: hasParentInformation() == true.
0493     /// An error is returned for ill-formed tables.
0494     Expected<std::optional<DWARFDebugNames::Entry>> getParentDIEEntry() const;
0495 
0496     /// Return the Abbreviation that can be used to interpret the raw values of
0497     /// this Accelerator Entry.
0498     const Abbrev &getAbbrev() const { return *Abbr; }
0499 
0500     /// Returns the value of the Index Attribute in this Accelerator Entry, if
0501     /// the Entry contains such Attribute.
0502     std::optional<DWARFFormValue> lookup(dwarf::Index Index) const;
0503 
0504     void dump(ScopedPrinter &W) const;
0505     void dumpParentIdx(ScopedPrinter &W, const DWARFFormValue &FormValue) const;
0506 
0507     friend class NameIndex;
0508     friend class ValueIterator;
0509   };
0510 
0511   /// Error returned by NameIndex::getEntry to report it has reached the end of
0512   /// the entry list.
0513   class SentinelError : public ErrorInfo<SentinelError> {
0514   public:
0515     static char ID;
0516 
0517     void log(raw_ostream &OS) const override { OS << "Sentinel"; }
0518     std::error_code convertToErrorCode() const override;
0519   };
0520 
0521 private:
0522   /// DenseMapInfo for struct Abbrev.
0523   struct AbbrevMapInfo {
0524     static Abbrev getEmptyKey();
0525     static Abbrev getTombstoneKey();
0526     static unsigned getHashValue(uint32_t Code) {
0527       return DenseMapInfo<uint32_t>::getHashValue(Code);
0528     }
0529     static unsigned getHashValue(const Abbrev &Abbr) {
0530       return getHashValue(Abbr.Code);
0531     }
0532     static bool isEqual(uint32_t LHS, const Abbrev &RHS) {
0533       return LHS == RHS.Code;
0534     }
0535     static bool isEqual(const Abbrev &LHS, const Abbrev &RHS) {
0536       return LHS.Code == RHS.Code;
0537     }
0538   };
0539 
0540 public:
0541   /// A single entry in the Name Table (DWARF v5 sect. 6.1.1.4.6) of the Name
0542   /// Index.
0543   class NameTableEntry {
0544     DataExtractor StrData;
0545 
0546     uint32_t Index;
0547     uint64_t StringOffset;
0548     uint64_t EntryOffset;
0549 
0550   public:
0551     NameTableEntry(const DataExtractor &StrData, uint32_t Index,
0552                    uint64_t StringOffset, uint64_t EntryOffset)
0553         : StrData(StrData), Index(Index), StringOffset(StringOffset),
0554           EntryOffset(EntryOffset) {}
0555 
0556     /// Return the index of this name in the parent Name Index.
0557     uint32_t getIndex() const { return Index; }
0558 
0559     /// Returns the offset of the name of the described entities.
0560     uint64_t getStringOffset() const { return StringOffset; }
0561 
0562     /// Return the string referenced by this name table entry or nullptr if the
0563     /// string offset is not valid.
0564     const char *getString() const {
0565       uint64_t Off = StringOffset;
0566       return StrData.getCStr(&Off);
0567     }
0568 
0569     /// Compares the name of this entry against Target, returning true if they
0570     /// are equal. This is more efficient in hot code paths that do not need the
0571     /// length of the name.
0572     bool sameNameAs(StringRef Target) const {
0573       // Note: this is not the name, but the rest of debug_str starting from
0574       // name. This handles corrupt data (non-null terminated) without
0575       // overrunning the buffer.
0576       StringRef Data = StrData.getData().substr(StringOffset);
0577       size_t TargetSize = Target.size();
0578       return Data.size() > TargetSize && !Data[TargetSize] &&
0579              strncmp(Data.data(), Target.data(), TargetSize) == 0;
0580     }
0581 
0582     /// Returns the offset of the first Entry in the list.
0583     uint64_t getEntryOffset() const { return EntryOffset; }
0584   };
0585 
0586   /// Offsets for the start of various important tables from the start of the
0587   /// section.
0588   struct DWARFDebugNamesOffsets {
0589     uint64_t CUsBase;
0590     uint64_t BucketsBase;
0591     uint64_t HashesBase;
0592     uint64_t StringOffsetsBase;
0593     uint64_t EntryOffsetsBase;
0594     uint64_t EntriesBase;
0595   };
0596 
0597   /// Represents a single accelerator table within the DWARF v5 .debug_names
0598   /// section.
0599   class NameIndex {
0600     DenseSet<Abbrev, AbbrevMapInfo> Abbrevs;
0601     struct Header Hdr;
0602     const DWARFDebugNames &Section;
0603 
0604     // Base of the whole unit and of various important tables, as offsets from
0605     // the start of the section.
0606     uint64_t Base;
0607     DWARFDebugNamesOffsets Offsets;
0608 
0609     void dumpCUs(ScopedPrinter &W) const;
0610     void dumpLocalTUs(ScopedPrinter &W) const;
0611     void dumpForeignTUs(ScopedPrinter &W) const;
0612     void dumpAbbreviations(ScopedPrinter &W) const;
0613     bool dumpEntry(ScopedPrinter &W, uint64_t *Offset) const;
0614     void dumpName(ScopedPrinter &W, const NameTableEntry &NTE,
0615                   std::optional<uint32_t> Hash) const;
0616     void dumpBucket(ScopedPrinter &W, uint32_t Bucket) const;
0617 
0618     Expected<AttributeEncoding> extractAttributeEncoding(uint64_t *Offset);
0619 
0620     Expected<std::vector<AttributeEncoding>>
0621     extractAttributeEncodings(uint64_t *Offset);
0622 
0623     Expected<Abbrev> extractAbbrev(uint64_t *Offset);
0624 
0625   public:
0626     NameIndex(const DWARFDebugNames &Section, uint64_t Base)
0627         : Section(Section), Base(Base) {}
0628 
0629     /// Returns Hdr field
0630     Header getHeader() const { return Hdr; }
0631 
0632     /// Returns Offsets field
0633     DWARFDebugNamesOffsets getOffsets() const { return Offsets; }
0634 
0635     /// Reads offset of compilation unit CU. CU is 0-based.
0636     uint64_t getCUOffset(uint32_t CU) const;
0637     uint32_t getCUCount() const { return Hdr.CompUnitCount; }
0638 
0639     /// Reads offset of local type unit TU, TU is 0-based.
0640     uint64_t getLocalTUOffset(uint32_t TU) const;
0641     uint32_t getLocalTUCount() const { return Hdr.LocalTypeUnitCount; }
0642 
0643     /// Reads signature of foreign type unit TU. TU is 0-based.
0644     uint64_t getForeignTUSignature(uint32_t TU) const;
0645     uint32_t getForeignTUCount() const { return Hdr.ForeignTypeUnitCount; }
0646 
0647     /// Reads an entry in the Bucket Array for the given Bucket. The returned
0648     /// value is a (1-based) index into the Names, StringOffsets and
0649     /// EntryOffsets arrays. The input Bucket index is 0-based.
0650     uint32_t getBucketArrayEntry(uint32_t Bucket) const;
0651     uint32_t getBucketCount() const { return Hdr.BucketCount; }
0652 
0653     /// Reads an entry in the Hash Array for the given Index. The input Index
0654     /// is 1-based.
0655     uint32_t getHashArrayEntry(uint32_t Index) const;
0656 
0657     /// Reads an entry in the Name Table for the given Index. The Name Table
0658     /// consists of two arrays -- String Offsets and Entry Offsets. The returned
0659     /// offsets are relative to the starts of respective sections. Input Index
0660     /// is 1-based.
0661     NameTableEntry getNameTableEntry(uint32_t Index) const;
0662 
0663     uint32_t getNameCount() const { return Hdr.NameCount; }
0664 
0665     const DenseSet<Abbrev, AbbrevMapInfo> &getAbbrevs() const {
0666       return Abbrevs;
0667     }
0668 
0669     Expected<Entry> getEntry(uint64_t *Offset) const;
0670 
0671     /// Returns the Entry at the relative `Offset` from the start of the Entry
0672     /// pool.
0673     Expected<Entry> getEntryAtRelativeOffset(uint64_t Offset) const {
0674       auto OffsetFromSection = Offset + this->Offsets.EntriesBase;
0675       return getEntry(&OffsetFromSection);
0676     }
0677 
0678     /// Look up all entries in this Name Index matching \c Key.
0679     iterator_range<ValueIterator> equal_range(StringRef Key) const;
0680 
0681     NameIterator begin() const { return NameIterator(this, 1); }
0682     NameIterator end() const { return NameIterator(this, getNameCount() + 1); }
0683 
0684     Error extract();
0685     uint64_t getUnitOffset() const { return Base; }
0686     uint64_t getNextUnitOffset() const {
0687       return Base + dwarf::getUnitLengthFieldByteSize(Hdr.Format) +
0688              Hdr.UnitLength;
0689     }
0690     void dump(ScopedPrinter &W) const;
0691 
0692     friend class DWARFDebugNames;
0693   };
0694 
0695   class ValueIterator {
0696   public:
0697     using iterator_category = std::input_iterator_tag;
0698     using value_type = Entry;
0699     using difference_type = std::ptrdiff_t;
0700     using pointer = value_type *;
0701     using reference = value_type &;
0702 
0703   private:
0704     /// The Name Index we are currently iterating through. The implementation
0705     /// relies on the fact that this can also be used as an iterator into the
0706     /// "NameIndices" vector in the Accelerator section.
0707     const NameIndex *CurrentIndex = nullptr;
0708 
0709     /// Whether this is a local iterator (searches in CurrentIndex only) or not
0710     /// (searches all name indices).
0711     bool IsLocal;
0712 
0713     std::optional<Entry> CurrentEntry;
0714     uint64_t DataOffset = 0; ///< Offset into the section.
0715     std::string Key;         ///< The Key we are searching for.
0716     std::optional<uint32_t> Hash; ///< Hash of Key, if it has been computed.
0717 
0718     bool getEntryAtCurrentOffset();
0719     std::optional<uint64_t> findEntryOffsetInCurrentIndex();
0720     bool findInCurrentIndex();
0721     void searchFromStartOfCurrentIndex();
0722     void next();
0723 
0724     /// Set the iterator to the "end" state.
0725     void setEnd() { *this = ValueIterator(); }
0726 
0727   public:
0728     /// Create a "begin" iterator for looping over all entries in the
0729     /// accelerator table matching Key. The iterator will run through all Name
0730     /// Indexes in the section in sequence.
0731     ValueIterator(const DWARFDebugNames &AccelTable, StringRef Key);
0732 
0733     /// Create a "begin" iterator for looping over all entries in a specific
0734     /// Name Index. Other indices in the section will not be visited.
0735     ValueIterator(const NameIndex &NI, StringRef Key);
0736 
0737     /// End marker.
0738     ValueIterator() = default;
0739 
0740     const Entry &operator*() const { return *CurrentEntry; }
0741     ValueIterator &operator++() {
0742       next();
0743       return *this;
0744     }
0745     ValueIterator operator++(int) {
0746       ValueIterator I = *this;
0747       next();
0748       return I;
0749     }
0750 
0751     friend bool operator==(const ValueIterator &A, const ValueIterator &B) {
0752       return A.CurrentIndex == B.CurrentIndex && A.DataOffset == B.DataOffset;
0753     }
0754     friend bool operator!=(const ValueIterator &A, const ValueIterator &B) {
0755       return !(A == B);
0756     }
0757   };
0758 
0759   class NameIterator {
0760 
0761     /// The Name Index we are iterating through.
0762     const NameIndex *CurrentIndex;
0763 
0764     /// The current name in the Name Index.
0765     uint32_t CurrentName;
0766 
0767     void next() {
0768       assert(CurrentName <= CurrentIndex->getNameCount());
0769       ++CurrentName;
0770     }
0771 
0772   public:
0773     using iterator_category = std::input_iterator_tag;
0774     using value_type = NameTableEntry;
0775     using difference_type = uint32_t;
0776     using pointer = NameTableEntry *;
0777     using reference = NameTableEntry; // We return entries by value.
0778 
0779     /// Creates an iterator whose initial position is name CurrentName in
0780     /// CurrentIndex.
0781     NameIterator(const NameIndex *CurrentIndex, uint32_t CurrentName)
0782         : CurrentIndex(CurrentIndex), CurrentName(CurrentName) {}
0783 
0784     NameTableEntry operator*() const {
0785       return CurrentIndex->getNameTableEntry(CurrentName);
0786     }
0787     NameIterator &operator++() {
0788       next();
0789       return *this;
0790     }
0791     NameIterator operator++(int) {
0792       NameIterator I = *this;
0793       next();
0794       return I;
0795     }
0796 
0797     friend bool operator==(const NameIterator &A, const NameIterator &B) {
0798       return A.CurrentIndex == B.CurrentIndex && A.CurrentName == B.CurrentName;
0799     }
0800     friend bool operator!=(const NameIterator &A, const NameIterator &B) {
0801       return !(A == B);
0802     }
0803   };
0804 
0805 private:
0806   SmallVector<NameIndex, 0> NameIndices;
0807   DenseMap<uint64_t, const NameIndex *> UnitOffsetToNameIndex;
0808 
0809 public:
0810   DWARFDebugNames(const DWARFDataExtractor &AccelSection,
0811                   DataExtractor StringSection)
0812       : DWARFAcceleratorTable(AccelSection, StringSection) {}
0813 
0814   Error extract() override;
0815   void dump(raw_ostream &OS) const override;
0816 
0817   /// Look up all entries in the accelerator table matching \c Key.
0818   iterator_range<ValueIterator> equal_range(StringRef Key) const;
0819 
0820   using const_iterator = SmallVector<NameIndex, 0>::const_iterator;
0821   const_iterator begin() const { return NameIndices.begin(); }
0822   const_iterator end() const { return NameIndices.end(); }
0823 
0824   /// Return the Name Index covering the compile unit or local type unit at
0825   /// UnitOffset, or nullptr if there is no Name Index covering that unit.
0826   const NameIndex *getCUOrTUNameIndex(uint64_t UnitOffset);
0827 };
0828 
0829 /// Calculates the starting offsets for various sections within the
0830 /// .debug_names section.
0831 namespace dwarf {
0832 DWARFDebugNames::DWARFDebugNamesOffsets
0833 findDebugNamesOffsets(uint64_t EndOfHeaderOffset,
0834                       const DWARFDebugNames::Header &Hdr);
0835 }
0836 
0837 /// If `Name` is the name of a templated function that includes template
0838 /// parameters, returns a substring of `Name` containing no template
0839 /// parameters.
0840 /// E.g.: StripTemplateParameters("foo<int>") = "foo".
0841 std::optional<StringRef> StripTemplateParameters(StringRef Name);
0842 
0843 struct ObjCSelectorNames {
0844   /// For "-[A(Category) method:]", this would be "method:"
0845   StringRef Selector;
0846   /// For "-[A(Category) method:]", this would be "A(category)"
0847   StringRef ClassName;
0848   /// For "-[A(Category) method:]", this would be "A"
0849   std::optional<StringRef> ClassNameNoCategory;
0850   /// For "-[A(Category) method:]", this would be "A method:"
0851   std::optional<std::string> MethodNameNoCategory;
0852 };
0853 
0854 /// If `Name` is the AT_name of a DIE which refers to an Objective-C selector,
0855 /// returns an instance of ObjCSelectorNames. The Selector and ClassName fields
0856 /// are guaranteed to be non-empty in the result.
0857 std::optional<ObjCSelectorNames> getObjCNamesIfSelector(StringRef Name);
0858 
0859 } // end namespace llvm
0860 
0861 #endif // LLVM_DEBUGINFO_DWARF_DWARFACCELERATORTABLE_H