1 //===- DWARFAcceleratorTable.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_DWARFACCELERATORTABLE_H 10 #define LLVM_DEBUGINFO_DWARF_DWARFACCELERATORTABLE_H 11 12 #include "llvm/ADT/DenseSet.h" 13 #include "llvm/ADT/SmallString.h" 14 #include "llvm/ADT/SmallVector.h" 15 #include "llvm/BinaryFormat/Dwarf.h" 16 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" 17 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 18 #include <cstdint> 19 #include <utility> 20 21 namespace llvm { 22 23 class raw_ostream; 24 class ScopedPrinter; 25 26 /// The accelerator tables are designed to allow efficient random access 27 /// (using a symbol name as a key) into debug info by providing an index of the 28 /// debug info DIEs. This class implements the common functionality of Apple and 29 /// DWARF 5 accelerator tables. 30 /// TODO: Generalize the rest of the AppleAcceleratorTable interface and move it 31 /// to this class. 32 class DWARFAcceleratorTable { 33 protected: 34 DWARFDataExtractor AccelSection; 35 DataExtractor StringSection; 36 37 public: 38 /// An abstract class representing a single entry in the accelerator tables. 39 class Entry { 40 protected: 41 SmallVector<DWARFFormValue, 3> Values; 42 43 Entry() = default; 44 45 // Make these protected so only (final) subclasses can be copied around. 46 Entry(const Entry &) = default; 47 Entry(Entry &&) = default; 48 Entry &operator=(const Entry &) = default; 49 Entry &operator=(Entry &&) = default; 50 ~Entry() = default; 51 52 53 public: 54 /// Returns the Offset of the Compilation Unit associated with this 55 /// Accelerator Entry or std::nullopt if the Compilation Unit offset is not 56 /// recorded in this Accelerator Entry. 57 virtual std::optional<uint64_t> getCUOffset() const = 0; 58 59 /// Returns the Tag of the Debug Info Entry associated with this 60 /// Accelerator Entry or std::nullopt if the Tag is not recorded in this 61 /// Accelerator Entry. 62 virtual std::optional<dwarf::Tag> getTag() const = 0; 63 64 /// Returns the raw values of fields in the Accelerator Entry. In general, 65 /// these can only be interpreted with the help of the metadata in the 66 /// owning Accelerator Table. 67 ArrayRef<DWARFFormValue> getValues() const { return Values; } 68 }; 69 70 DWARFAcceleratorTable(const DWARFDataExtractor &AccelSection, 71 DataExtractor StringSection) 72 : AccelSection(AccelSection), StringSection(StringSection) {} 73 virtual ~DWARFAcceleratorTable(); 74 75 virtual Error extract() = 0; 76 virtual void dump(raw_ostream &OS) const = 0; 77 78 DWARFAcceleratorTable(const DWARFAcceleratorTable &) = delete; 79 void operator=(const DWARFAcceleratorTable &) = delete; 80 }; 81 82 /// This implements the Apple accelerator table format, a precursor of the 83 /// DWARF 5 accelerator table format. 84 class AppleAcceleratorTable : public DWARFAcceleratorTable { 85 struct Header { 86 uint32_t Magic; 87 uint16_t Version; 88 uint16_t HashFunction; 89 uint32_t BucketCount; 90 uint32_t HashCount; 91 uint32_t HeaderDataLength; 92 93 void dump(ScopedPrinter &W) const; 94 }; 95 96 struct HeaderData { 97 using AtomType = uint16_t; 98 using Form = dwarf::Form; 99 100 uint64_t DIEOffsetBase; 101 SmallVector<std::pair<AtomType, Form>, 3> Atoms; 102 103 std::optional<uint64_t> 104 extractOffset(std::optional<DWARFFormValue> Value) const; 105 }; 106 107 Header Hdr; 108 HeaderData HdrData; 109 dwarf::FormParams FormParams; 110 uint32_t HashDataEntryLength; 111 bool IsValid = false; 112 113 /// Returns true if we should continue scanning for entries or false if we've 114 /// reached the last (sentinel) entry of encountered a parsing error. 115 bool dumpName(ScopedPrinter &W, SmallVectorImpl<DWARFFormValue> &AtomForms, 116 uint64_t *DataOffset) const; 117 118 /// Reads an uint32_t from the accelerator table at Offset, which is 119 /// incremented by the number of bytes read. 120 std::optional<uint32_t> readU32FromAccel(uint64_t &Offset, 121 bool UseRelocation = false) const; 122 123 /// Reads a StringRef from the string table at Offset. 124 std::optional<StringRef> 125 readStringFromStrSection(uint64_t StringSectionOffset) const; 126 127 /// Return the offset into the section where the Buckets begin. 128 uint64_t getBucketBase() const { return sizeof(Hdr) + Hdr.HeaderDataLength; } 129 130 /// Return the offset into the section where the I-th bucket is. 131 uint64_t getIthBucketBase(uint32_t I) const { 132 return getBucketBase() + I * 4; 133 } 134 135 /// Return the offset into the section where the hash list begins. 136 uint64_t getHashBase() const { return getBucketBase() + getNumBuckets() * 4; } 137 138 /// Return the offset into the section where the I-th hash is. 139 uint64_t getIthHashBase(uint32_t I) const { return getHashBase() + I * 4; } 140 141 /// Return the offset into the section where the offset list begins. 142 uint64_t getOffsetBase() const { return getHashBase() + getNumHashes() * 4; } 143 144 /// Return the offset into the section where the table entries begin. 145 uint64_t getEntriesBase() const { 146 return getOffsetBase() + getNumHashes() * 4; 147 } 148 149 /// Return the offset into the section where the I-th offset is. 150 uint64_t getIthOffsetBase(uint32_t I) const { 151 return getOffsetBase() + I * 4; 152 } 153 154 /// Returns the index of the bucket where a hypothetical Hash would be. 155 uint32_t hashToBucketIdx(uint32_t Hash) const { 156 return Hash % getNumBuckets(); 157 } 158 159 /// Returns true iff a hypothetical Hash would be assigned to the BucketIdx-th 160 /// bucket. 161 bool wouldHashBeInBucket(uint32_t Hash, uint32_t BucketIdx) const { 162 return hashToBucketIdx(Hash) == BucketIdx; 163 } 164 165 /// Reads the contents of the I-th bucket, that is, the index in the hash list 166 /// where the hashes corresponding to this bucket begin. 167 std::optional<uint32_t> readIthBucket(uint32_t I) const { 168 uint64_t Offset = getIthBucketBase(I); 169 return readU32FromAccel(Offset); 170 } 171 172 /// Reads the I-th hash in the hash list. 173 std::optional<uint32_t> readIthHash(uint32_t I) const { 174 uint64_t Offset = getIthHashBase(I); 175 return readU32FromAccel(Offset); 176 } 177 178 /// Reads the I-th offset in the offset list. 179 std::optional<uint32_t> readIthOffset(uint32_t I) const { 180 uint64_t Offset = getIthOffsetBase(I); 181 return readU32FromAccel(Offset); 182 } 183 184 /// Reads a string offset from the accelerator table at Offset, which is 185 /// incremented by the number of bytes read. 186 std::optional<uint32_t> readStringOffsetAt(uint64_t &Offset) const { 187 return readU32FromAccel(Offset, /*UseRelocation*/ true); 188 } 189 190 /// Scans through all Hashes in the BucketIdx-th bucket, attempting to find 191 /// HashToFind. If it is found, its index in the list of hashes is returned. 192 std::optional<uint32_t> idxOfHashInBucket(uint32_t HashToFind, 193 uint32_t BucketIdx) const; 194 195 public: 196 /// Apple-specific implementation of an Accelerator Entry. 197 class Entry final : public DWARFAcceleratorTable::Entry { 198 const AppleAcceleratorTable &Table; 199 200 Entry(const AppleAcceleratorTable &Table); 201 void extract(uint64_t *Offset); 202 203 public: 204 std::optional<uint64_t> getCUOffset() const override; 205 206 /// Returns the Section Offset of the Debug Info Entry associated with this 207 /// Accelerator Entry or std::nullopt if the DIE offset is not recorded in 208 /// this Accelerator Entry. The returned offset is relative to the start of 209 /// the Section containing the DIE. 210 std::optional<uint64_t> getDIESectionOffset() const; 211 212 std::optional<dwarf::Tag> getTag() const override; 213 214 /// Returns the value of the Atom in this Accelerator Entry, if the Entry 215 /// contains such Atom. 216 std::optional<DWARFFormValue> lookup(HeaderData::AtomType Atom) const; 217 218 friend class AppleAcceleratorTable; 219 friend class ValueIterator; 220 }; 221 222 /// An iterator for Entries all having the same string as key. 223 class SameNameIterator 224 : public iterator_facade_base<SameNameIterator, std::forward_iterator_tag, 225 Entry> { 226 Entry Current; 227 uint64_t Offset = 0; 228 229 public: 230 /// Construct a new iterator for the entries at \p DataOffset. 231 SameNameIterator(const AppleAcceleratorTable &AccelTable, 232 uint64_t DataOffset); 233 234 const Entry &operator*() { 235 uint64_t OffsetCopy = Offset; 236 Current.extract(&OffsetCopy); 237 return Current; 238 } 239 SameNameIterator &operator++() { 240 Offset += Current.Table.getHashDataEntryLength(); 241 return *this; 242 } 243 friend bool operator==(const SameNameIterator &A, 244 const SameNameIterator &B) { 245 return A.Offset == B.Offset; 246 } 247 }; 248 249 struct EntryWithName { 250 EntryWithName(const AppleAcceleratorTable &Table) 251 : BaseEntry(Table), StrOffset(0) {} 252 253 std::optional<StringRef> readName() const { 254 return BaseEntry.Table.readStringFromStrSection(StrOffset); 255 } 256 257 Entry BaseEntry; 258 uint32_t StrOffset; 259 }; 260 261 /// An iterator for all entries in the table. 262 class Iterator 263 : public iterator_facade_base<Iterator, std::forward_iterator_tag, 264 EntryWithName> { 265 constexpr static auto EndMarker = std::numeric_limits<uint64_t>::max(); 266 267 EntryWithName Current; 268 uint64_t Offset = EndMarker; 269 uint32_t NumEntriesToCome = 0; 270 271 void setToEnd() { Offset = EndMarker; } 272 bool isEnd() const { return Offset == EndMarker; } 273 const AppleAcceleratorTable &getTable() const { 274 return Current.BaseEntry.Table; 275 } 276 277 /// Reads the next Entry in the table, populating `Current`. 278 /// If not possible (e.g. end of the section), becomes the end iterator. 279 void prepareNextEntryOrEnd(); 280 281 /// Reads the next string pointer and the entry count for that string, 282 /// populating `NumEntriesToCome`. 283 /// If not possible (e.g. end of the section), becomes the end iterator. 284 /// Assumes `Offset` points to a string reference. 285 void prepareNextStringOrEnd(); 286 287 public: 288 Iterator(const AppleAcceleratorTable &Table, bool SetEnd = false); 289 290 Iterator &operator++() { 291 prepareNextEntryOrEnd(); 292 return *this; 293 } 294 bool operator==(const Iterator &It) const { return Offset == It.Offset; } 295 const EntryWithName &operator*() const { 296 assert(!isEnd() && "dereferencing end iterator"); 297 return Current; 298 } 299 }; 300 301 AppleAcceleratorTable(const DWARFDataExtractor &AccelSection, 302 DataExtractor StringSection) 303 : DWARFAcceleratorTable(AccelSection, StringSection) {} 304 305 Error extract() override; 306 uint32_t getNumBuckets() const; 307 uint32_t getNumHashes() const; 308 uint32_t getSizeHdr() const; 309 uint32_t getHeaderDataLength() const; 310 311 /// Returns the size of one HashData entry. 312 uint32_t getHashDataEntryLength() const { return HashDataEntryLength; } 313 314 /// Return the Atom description, which can be used to interpret the raw values 315 /// of the Accelerator Entries in this table. 316 ArrayRef<std::pair<HeaderData::AtomType, HeaderData::Form>> getAtomsDesc(); 317 318 /// Returns true iff `AtomTy` is one of the atoms available in Entries of this 319 /// table. 320 bool containsAtomType(HeaderData::AtomType AtomTy) const { 321 return is_contained(make_first_range(HdrData.Atoms), AtomTy); 322 } 323 324 bool validateForms(); 325 326 /// Return information related to the DWARF DIE we're looking for when 327 /// performing a lookup by name. 328 /// 329 /// \param HashDataOffset an offset into the hash data table 330 /// \returns <DieOffset, DieTag> 331 /// DieOffset is the offset into the .debug_info section for the DIE 332 /// related to the input hash data offset. 333 /// DieTag is the tag of the DIE 334 std::pair<uint64_t, dwarf::Tag> readAtoms(uint64_t *HashDataOffset); 335 void dump(raw_ostream &OS) const override; 336 337 /// Look up all entries in the accelerator table matching \c Key. 338 iterator_range<SameNameIterator> equal_range(StringRef Key) const; 339 340 /// Lookup all entries in the accelerator table. 341 auto entries() const { 342 return make_range(Iterator(*this), Iterator(*this, /*SetEnd*/ true)); 343 } 344 }; 345 346 /// .debug_names section consists of one or more units. Each unit starts with a 347 /// header, which is followed by a list of compilation units, local and foreign 348 /// type units. 349 /// 350 /// These may be followed by an (optional) hash lookup table, which consists of 351 /// an array of buckets and hashes similar to the apple tables above. The only 352 /// difference is that the hashes array is 1-based, and consequently an empty 353 /// bucket is denoted by 0 and not UINT32_MAX. 354 /// 355 /// Next is the name table, which consists of an array of names and array of 356 /// entry offsets. This is different from the apple tables, which store names 357 /// next to the actual entries. 358 /// 359 /// The structure of the entries is described by an abbreviations table, which 360 /// comes after the name table. Unlike the apple tables, which have a uniform 361 /// entry structure described in the header, each .debug_names entry may have 362 /// different index attributes (DW_IDX_???) attached to it. 363 /// 364 /// The last segment consists of a list of entries, which is a 0-terminated list 365 /// referenced by the name table and interpreted with the help of the 366 /// abbreviation table. 367 class DWARFDebugNames : public DWARFAcceleratorTable { 368 public: 369 class NameIndex; 370 class NameIterator; 371 class ValueIterator; 372 373 /// DWARF v5 Name Index header. 374 struct Header { 375 uint64_t UnitLength; 376 dwarf::DwarfFormat Format; 377 uint16_t Version; 378 uint32_t CompUnitCount; 379 uint32_t LocalTypeUnitCount; 380 uint32_t ForeignTypeUnitCount; 381 uint32_t BucketCount; 382 uint32_t NameCount; 383 uint32_t AbbrevTableSize; 384 uint32_t AugmentationStringSize; 385 SmallString<8> AugmentationString; 386 387 Error extract(const DWARFDataExtractor &AS, uint64_t *Offset); 388 void dump(ScopedPrinter &W) const; 389 }; 390 391 /// Index attribute and its encoding. 392 struct AttributeEncoding { 393 dwarf::Index Index; 394 dwarf::Form Form; 395 396 constexpr AttributeEncoding(dwarf::Index Index, dwarf::Form Form) 397 : Index(Index), Form(Form) {} 398 399 friend bool operator==(const AttributeEncoding &LHS, 400 const AttributeEncoding &RHS) { 401 return LHS.Index == RHS.Index && LHS.Form == RHS.Form; 402 } 403 }; 404 405 /// Abbreviation describing the encoding of Name Index entries. 406 struct Abbrev { 407 uint32_t Code; ///< Abbreviation code 408 dwarf::Tag Tag; ///< Dwarf Tag of the described entity. 409 std::vector<AttributeEncoding> Attributes; ///< List of index attributes. 410 411 Abbrev(uint32_t Code, dwarf::Tag Tag, 412 std::vector<AttributeEncoding> Attributes) 413 : Code(Code), Tag(Tag), Attributes(std::move(Attributes)) {} 414 415 void dump(ScopedPrinter &W) const; 416 }; 417 418 /// DWARF v5-specific implementation of an Accelerator Entry. 419 class Entry final : public DWARFAcceleratorTable::Entry { 420 const NameIndex *NameIdx; 421 const Abbrev *Abbr; 422 423 Entry(const NameIndex &NameIdx, const Abbrev &Abbr); 424 425 public: 426 std::optional<uint64_t> getCUOffset() const override; 427 std::optional<dwarf::Tag> getTag() const override { return tag(); } 428 429 /// Returns the Index into the Compilation Unit list of the owning Name 430 /// Index or std::nullopt if this Accelerator Entry does not have an 431 /// associated Compilation Unit. It is up to the user to verify that the 432 /// returned Index is valid in the owning NameIndex (or use getCUOffset(), 433 /// which will handle that check itself). Note that entries in NameIndexes 434 /// which index just a single Compilation Unit are implicitly associated 435 /// with that unit, so this function will return 0 even without an explicit 436 /// DW_IDX_compile_unit attribute. 437 std::optional<uint64_t> getCUIndex() const; 438 439 /// .debug_names-specific getter, which always succeeds (DWARF v5 index 440 /// entries always have a tag). 441 dwarf::Tag tag() const { return Abbr->Tag; } 442 443 /// Returns the Offset of the DIE within the containing CU or TU. 444 std::optional<uint64_t> getDIEUnitOffset() const; 445 446 /// Return the Abbreviation that can be used to interpret the raw values of 447 /// this Accelerator Entry. 448 const Abbrev &getAbbrev() const { return *Abbr; } 449 450 /// Returns the value of the Index Attribute in this Accelerator Entry, if 451 /// the Entry contains such Attribute. 452 std::optional<DWARFFormValue> lookup(dwarf::Index Index) const; 453 454 void dump(ScopedPrinter &W) const; 455 456 friend class NameIndex; 457 friend class ValueIterator; 458 }; 459 460 /// Error returned by NameIndex::getEntry to report it has reached the end of 461 /// the entry list. 462 class SentinelError : public ErrorInfo<SentinelError> { 463 public: 464 static char ID; 465 466 void log(raw_ostream &OS) const override { OS << "Sentinel"; } 467 std::error_code convertToErrorCode() const override; 468 }; 469 470 private: 471 /// DenseMapInfo for struct Abbrev. 472 struct AbbrevMapInfo { 473 static Abbrev getEmptyKey(); 474 static Abbrev getTombstoneKey(); 475 static unsigned getHashValue(uint32_t Code) { 476 return DenseMapInfo<uint32_t>::getHashValue(Code); 477 } 478 static unsigned getHashValue(const Abbrev &Abbr) { 479 return getHashValue(Abbr.Code); 480 } 481 static bool isEqual(uint32_t LHS, const Abbrev &RHS) { 482 return LHS == RHS.Code; 483 } 484 static bool isEqual(const Abbrev &LHS, const Abbrev &RHS) { 485 return LHS.Code == RHS.Code; 486 } 487 }; 488 489 public: 490 /// A single entry in the Name Table (DWARF v5 sect. 6.1.1.4.6) of the Name 491 /// Index. 492 class NameTableEntry { 493 DataExtractor StrData; 494 495 uint32_t Index; 496 uint64_t StringOffset; 497 uint64_t EntryOffset; 498 499 public: 500 NameTableEntry(const DataExtractor &StrData, uint32_t Index, 501 uint64_t StringOffset, uint64_t EntryOffset) 502 : StrData(StrData), Index(Index), StringOffset(StringOffset), 503 EntryOffset(EntryOffset) {} 504 505 /// Return the index of this name in the parent Name Index. 506 uint32_t getIndex() const { return Index; } 507 508 /// Returns the offset of the name of the described entities. 509 uint64_t getStringOffset() const { return StringOffset; } 510 511 /// Return the string referenced by this name table entry or nullptr if the 512 /// string offset is not valid. 513 const char *getString() const { 514 uint64_t Off = StringOffset; 515 return StrData.getCStr(&Off); 516 } 517 518 /// Returns the offset of the first Entry in the list. 519 uint64_t getEntryOffset() const { return EntryOffset; } 520 }; 521 522 /// Represents a single accelerator table within the DWARF v5 .debug_names 523 /// section. 524 class NameIndex { 525 DenseSet<Abbrev, AbbrevMapInfo> Abbrevs; 526 struct Header Hdr; 527 const DWARFDebugNames &Section; 528 529 // Base of the whole unit and of various important tables, as offsets from 530 // the start of the section. 531 uint64_t Base; 532 uint64_t CUsBase; 533 uint64_t BucketsBase; 534 uint64_t HashesBase; 535 uint64_t StringOffsetsBase; 536 uint64_t EntryOffsetsBase; 537 uint64_t EntriesBase; 538 539 void dumpCUs(ScopedPrinter &W) const; 540 void dumpLocalTUs(ScopedPrinter &W) const; 541 void dumpForeignTUs(ScopedPrinter &W) const; 542 void dumpAbbreviations(ScopedPrinter &W) const; 543 bool dumpEntry(ScopedPrinter &W, uint64_t *Offset) const; 544 void dumpName(ScopedPrinter &W, const NameTableEntry &NTE, 545 std::optional<uint32_t> Hash) const; 546 void dumpBucket(ScopedPrinter &W, uint32_t Bucket) const; 547 548 Expected<AttributeEncoding> extractAttributeEncoding(uint64_t *Offset); 549 550 Expected<std::vector<AttributeEncoding>> 551 extractAttributeEncodings(uint64_t *Offset); 552 553 Expected<Abbrev> extractAbbrev(uint64_t *Offset); 554 555 public: 556 NameIndex(const DWARFDebugNames &Section, uint64_t Base) 557 : Section(Section), Base(Base) {} 558 559 /// Reads offset of compilation unit CU. CU is 0-based. 560 uint64_t getCUOffset(uint32_t CU) const; 561 uint32_t getCUCount() const { return Hdr.CompUnitCount; } 562 563 /// Reads offset of local type unit TU, TU is 0-based. 564 uint64_t getLocalTUOffset(uint32_t TU) const; 565 uint32_t getLocalTUCount() const { return Hdr.LocalTypeUnitCount; } 566 567 /// Reads signature of foreign type unit TU. TU is 0-based. 568 uint64_t getForeignTUSignature(uint32_t TU) const; 569 uint32_t getForeignTUCount() const { return Hdr.ForeignTypeUnitCount; } 570 571 /// Reads an entry in the Bucket Array for the given Bucket. The returned 572 /// value is a (1-based) index into the Names, StringOffsets and 573 /// EntryOffsets arrays. The input Bucket index is 0-based. 574 uint32_t getBucketArrayEntry(uint32_t Bucket) const; 575 uint32_t getBucketCount() const { return Hdr.BucketCount; } 576 577 /// Reads an entry in the Hash Array for the given Index. The input Index 578 /// is 1-based. 579 uint32_t getHashArrayEntry(uint32_t Index) const; 580 581 /// Reads an entry in the Name Table for the given Index. The Name Table 582 /// consists of two arrays -- String Offsets and Entry Offsets. The returned 583 /// offsets are relative to the starts of respective sections. Input Index 584 /// is 1-based. 585 NameTableEntry getNameTableEntry(uint32_t Index) const; 586 587 uint32_t getNameCount() const { return Hdr.NameCount; } 588 589 const DenseSet<Abbrev, AbbrevMapInfo> &getAbbrevs() const { 590 return Abbrevs; 591 } 592 593 Expected<Entry> getEntry(uint64_t *Offset) const; 594 595 /// Look up all entries in this Name Index matching \c Key. 596 iterator_range<ValueIterator> equal_range(StringRef Key) const; 597 598 NameIterator begin() const { return NameIterator(this, 1); } 599 NameIterator end() const { return NameIterator(this, getNameCount() + 1); } 600 601 Error extract(); 602 uint64_t getUnitOffset() const { return Base; } 603 uint64_t getNextUnitOffset() const { 604 return Base + dwarf::getUnitLengthFieldByteSize(Hdr.Format) + 605 Hdr.UnitLength; 606 } 607 void dump(ScopedPrinter &W) const; 608 609 friend class DWARFDebugNames; 610 }; 611 612 class ValueIterator { 613 public: 614 using iterator_category = std::input_iterator_tag; 615 using value_type = Entry; 616 using difference_type = std::ptrdiff_t; 617 using pointer = value_type *; 618 using reference = value_type &; 619 620 private: 621 /// The Name Index we are currently iterating through. The implementation 622 /// relies on the fact that this can also be used as an iterator into the 623 /// "NameIndices" vector in the Accelerator section. 624 const NameIndex *CurrentIndex = nullptr; 625 626 /// Whether this is a local iterator (searches in CurrentIndex only) or not 627 /// (searches all name indices). 628 bool IsLocal; 629 630 std::optional<Entry> CurrentEntry; 631 uint64_t DataOffset = 0; ///< Offset into the section. 632 std::string Key; ///< The Key we are searching for. 633 std::optional<uint32_t> Hash; ///< Hash of Key, if it has been computed. 634 635 bool getEntryAtCurrentOffset(); 636 std::optional<uint64_t> findEntryOffsetInCurrentIndex(); 637 bool findInCurrentIndex(); 638 void searchFromStartOfCurrentIndex(); 639 void next(); 640 641 /// Set the iterator to the "end" state. 642 void setEnd() { *this = ValueIterator(); } 643 644 public: 645 /// Create a "begin" iterator for looping over all entries in the 646 /// accelerator table matching Key. The iterator will run through all Name 647 /// Indexes in the section in sequence. 648 ValueIterator(const DWARFDebugNames &AccelTable, StringRef Key); 649 650 /// Create a "begin" iterator for looping over all entries in a specific 651 /// Name Index. Other indices in the section will not be visited. 652 ValueIterator(const NameIndex &NI, StringRef Key); 653 654 /// End marker. 655 ValueIterator() = default; 656 657 const Entry &operator*() const { return *CurrentEntry; } 658 ValueIterator &operator++() { 659 next(); 660 return *this; 661 } 662 ValueIterator operator++(int) { 663 ValueIterator I = *this; 664 next(); 665 return I; 666 } 667 668 friend bool operator==(const ValueIterator &A, const ValueIterator &B) { 669 return A.CurrentIndex == B.CurrentIndex && A.DataOffset == B.DataOffset; 670 } 671 friend bool operator!=(const ValueIterator &A, const ValueIterator &B) { 672 return !(A == B); 673 } 674 }; 675 676 class NameIterator { 677 678 /// The Name Index we are iterating through. 679 const NameIndex *CurrentIndex; 680 681 /// The current name in the Name Index. 682 uint32_t CurrentName; 683 684 void next() { 685 assert(CurrentName <= CurrentIndex->getNameCount()); 686 ++CurrentName; 687 } 688 689 public: 690 using iterator_category = std::input_iterator_tag; 691 using value_type = NameTableEntry; 692 using difference_type = uint32_t; 693 using pointer = NameTableEntry *; 694 using reference = NameTableEntry; // We return entries by value. 695 696 /// Creates an iterator whose initial position is name CurrentName in 697 /// CurrentIndex. 698 NameIterator(const NameIndex *CurrentIndex, uint32_t CurrentName) 699 : CurrentIndex(CurrentIndex), CurrentName(CurrentName) {} 700 701 NameTableEntry operator*() const { 702 return CurrentIndex->getNameTableEntry(CurrentName); 703 } 704 NameIterator &operator++() { 705 next(); 706 return *this; 707 } 708 NameIterator operator++(int) { 709 NameIterator I = *this; 710 next(); 711 return I; 712 } 713 714 friend bool operator==(const NameIterator &A, const NameIterator &B) { 715 return A.CurrentIndex == B.CurrentIndex && A.CurrentName == B.CurrentName; 716 } 717 friend bool operator!=(const NameIterator &A, const NameIterator &B) { 718 return !(A == B); 719 } 720 }; 721 722 private: 723 SmallVector<NameIndex, 0> NameIndices; 724 DenseMap<uint64_t, const NameIndex *> CUToNameIndex; 725 726 public: 727 DWARFDebugNames(const DWARFDataExtractor &AccelSection, 728 DataExtractor StringSection) 729 : DWARFAcceleratorTable(AccelSection, StringSection) {} 730 731 Error extract() override; 732 void dump(raw_ostream &OS) const override; 733 734 /// Look up all entries in the accelerator table matching \c Key. 735 iterator_range<ValueIterator> equal_range(StringRef Key) const; 736 737 using const_iterator = SmallVector<NameIndex, 0>::const_iterator; 738 const_iterator begin() const { return NameIndices.begin(); } 739 const_iterator end() const { return NameIndices.end(); } 740 741 /// Return the Name Index covering the compile unit at CUOffset, or nullptr if 742 /// there is no Name Index covering that unit. 743 const NameIndex *getCUNameIndex(uint64_t CUOffset); 744 }; 745 746 } // end namespace llvm 747 748 #endif // LLVM_DEBUGINFO_DWARF_DWARFACCELERATORTABLE_H 749