Index: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h @@ -239,6 +239,7 @@ public: class NameIndex; + class NameIterator; class ValueIterator; /// Dwarf 5 Name Index header. @@ -351,9 +352,34 @@ public: /// A single entry in the Name Table (Dwarf 5 sect. 6.1.1.4.6) of the Name /// Index. - struct NameTableEntry { - uint32_t StringOffset; ///< Offset of the name of the described entities. - uint32_t EntryOffset; ///< Offset of the first Entry in the list. + class NameTableEntry { + DataExtractor StrData; + + uint32_t Index; + uint32_t StringOffset; + uint32_t EntryOffset; + + public: + NameTableEntry(const DataExtractor &StrData, uint32_t Index, + uint32_t StringOffset, uint32_t EntryOffset) + : StrData(StrData), Index(Index), StringOffset(StringOffset), + EntryOffset(EntryOffset) {} + + /// Return the index of this name in the parent Name Index. + uint32_t getIndex() const { return Index; } + + /// Returns the offset of the name of the described entities. + uint32_t getStringOffset() const { return StringOffset; } + + /// Return the string referenced by this name table entry or nullptr if the + /// string offset is not valid. + const char *getString() const { + uint32_t Off = StringOffset; + return StrData.getCStr(&Off); + } + + /// Returns the offset of the first Entry in the list. + uint32_t getEntryOffset() const { return EntryOffset; } }; /// Represents a single accelerator table within the Dwarf 5 .debug_names @@ -378,7 +404,7 @@ void dumpForeignTUs(ScopedPrinter &W) const; void dumpAbbreviations(ScopedPrinter &W) const; bool dumpEntry(ScopedPrinter &W, uint32_t *Offset) const; - void dumpName(ScopedPrinter &W, uint32_t Index, + void dumpName(ScopedPrinter &W, const NameTableEntry &NTE, Optional Hash) const; void dumpBucket(ScopedPrinter &W, uint32_t Bucket) const; @@ -432,6 +458,9 @@ /// Look up all entries in this Name Index matching \c Key. iterator_range equal_range(StringRef Key) const; + NameIterator begin() const { return NameIterator(this, 1); } + NameIterator end() const { return NameIterator(this, getNameCount() + 1); } + llvm::Error extract(); uint32_t getUnitOffset() const { return Base; } uint32_t getNextUnitOffset() const { return Base + 4 + Hdr.UnitLength; } @@ -497,6 +526,52 @@ } }; + class NameIterator { + + /// The Name Index we are iterating through. + const NameIndex *CurrentIndex; + + /// The current name in the Name Index. + uint32_t CurrentName; + + void next() { + assert(CurrentName <= CurrentIndex->getNameCount()); + ++CurrentName; + } + + public: + using iterator_category = std::input_iterator_tag; + using value_type = NameTableEntry; + using difference_type = uint32_t; + using pointer = NameTableEntry *; + using reference = NameTableEntry; // We return entries by value. + + /// Creates an iterator whose initial position is name CurrentName in + /// CurrentIndex. + NameIterator(const NameIndex *CurrentIndex, uint32_t CurrentName) + : CurrentIndex(CurrentIndex), CurrentName(CurrentName) {} + + NameTableEntry operator*() const { + return CurrentIndex->getNameTableEntry(CurrentName); + } + NameIterator &operator++() { + next(); + return *this; + } + NameIterator operator++(int) { + NameIterator I = *this; + next(); + return I; + } + + friend bool operator==(const NameIterator &A, const NameIterator &B) { + return A.CurrentIndex == B.CurrentIndex && A.CurrentName == B.CurrentName; + } + friend bool operator!=(const NameIterator &A, const NameIterator &B) { + return !(A == B); + } + }; + private: SmallVector NameIndices; DenseMap CUToNameIndex; Index: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h @@ -242,7 +242,7 @@ const DWARFDebugNames::Abbrev &Abbr, DWARFDebugNames::AttributeEncoding AttrEnc); unsigned verifyNameIndexEntries(const DWARFDebugNames::NameIndex &NI, - uint32_t Name, const DataExtractor &StrData); + const DWARFDebugNames::NameTableEntry &NTE); unsigned verifyNameIndexCompleteness(const DWARFDie &Die, const DWARFDebugNames::NameIndex &NI); Index: llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp @@ -635,7 +635,7 @@ uint32_t StringOffset = AS.getRelocatedValue(4, &StringOffsetOffset); uint32_t EntryOffset = AS.getU32(&EntryOffsetOffset); EntryOffset += EntriesBase; - return {StringOffset, EntryOffset}; + return {Section.StringSection, Index, StringOffset, EntryOffset}; } uint32_t @@ -670,19 +670,18 @@ return true; } -void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W, uint32_t Index, +void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W, + const NameTableEntry &NTE, Optional Hash) const { - const DataExtractor &SS = Section.StringSection; - NameTableEntry NTE = getNameTableEntry(Index); - - DictScope NameScope(W, ("Name " + Twine(Index)).str()); + DictScope NameScope(W, ("Name " + Twine(NTE.getIndex())).str()); if (Hash) W.printHex("Hash", *Hash); - W.startLine() << format("String: 0x%08x", NTE.StringOffset); - W.getOStream() << " \"" << SS.getCStr(&NTE.StringOffset) << "\"\n"; + W.startLine() << format("String: 0x%08x", NTE.getStringOffset()); + W.getOStream() << " \"" << NTE.getString() << "\"\n"; - while (dumpEntry(W, &NTE.EntryOffset)) + uint32_t EntryOffset = NTE.getEntryOffset(); + while (dumpEntry(W, &EntryOffset)) /*empty*/; } @@ -736,7 +735,7 @@ if (Hash % Hdr.BucketCount != Bucket) break; - dumpName(W, Index, Hash); + dumpName(W, getNameTableEntry(Index), Hash); } } @@ -755,8 +754,8 @@ } W.startLine() << "Hash table not present\n"; - for (uint32_t Index = 1; Index <= Hdr.NameCount; ++Index) - dumpName(W, Index, None); + for (NameTableEntry NTE : *this) + dumpName(W, NTE, None); } llvm::Error DWARFDebugNames::extract() { @@ -787,10 +786,9 @@ const Header &Hdr = CurrentIndex->Hdr; if (Hdr.BucketCount == 0) { // No Hash Table, We need to search through all names in the Name Index. - for (uint32_t Index = 1; Index <= Hdr.NameCount; ++Index) { - NameTableEntry NTE = CurrentIndex->getNameTableEntry(Index); - if (CurrentIndex->Section.StringSection.getCStr(&NTE.StringOffset) == Key) - return NTE.EntryOffset; + for (NameTableEntry NTE : *CurrentIndex) { + if (NTE.getString() == Key) + return NTE.getEntryOffset(); } return None; } @@ -810,8 +808,8 @@ return None; // End of bucket NameTableEntry NTE = CurrentIndex->getNameTableEntry(Index); - if (CurrentIndex->Section.StringSection.getCStr(&NTE.StringOffset) == Key) - return NTE.EntryOffset; + if (NTE.getString() == Key) + return NTE.getEntryOffset(); } return None; } Index: llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -920,8 +920,7 @@ if (Hash % NI.getBucketCount() != B.Bucket) break; - auto NTE = NI.getNameTableEntry(Idx); - const char *Str = StrData.getCStr(&NTE.StringOffset); + const char *Str = NI.getNameTableEntry(Idx).getString(); if (caseFoldingDjbHash(Str) != Hash) { error() << formatv("Name Index @ {0:x}: String ({1}) at index {2} " "hashes to {3:x}, but " @@ -1057,30 +1056,29 @@ return Result; } -unsigned -DWARFVerifier::verifyNameIndexEntries(const DWARFDebugNames::NameIndex &NI, - uint32_t Name, - const DataExtractor &StrData) { +unsigned DWARFVerifier::verifyNameIndexEntries( + const DWARFDebugNames::NameIndex &NI, + const DWARFDebugNames::NameTableEntry &NTE) { // Verifying type unit indexes not supported. if (NI.getLocalTUCount() + NI.getForeignTUCount() > 0) return 0; - DWARFDebugNames::NameTableEntry NTE = NI.getNameTableEntry(Name); - const char *CStr = StrData.getCStr(&NTE.StringOffset); + const char *CStr = NTE.getString(); if (!CStr) { error() << formatv( "Name Index @ {0:x}: Unable to get string associated with name {1}.\n", - NI.getUnitOffset(), Name); + NI.getUnitOffset(), NTE.getIndex()); return 1; } StringRef Str(CStr); unsigned NumErrors = 0; unsigned NumEntries = 0; - uint32_t EntryID = NTE.EntryOffset; - Expected EntryOr = NI.getEntry(&NTE.EntryOffset); - for (; EntryOr; ++NumEntries, EntryID = NTE.EntryOffset, - EntryOr = NI.getEntry(&NTE.EntryOffset)) { + uint32_t EntryID = NTE.getEntryOffset(); + uint32_t NextEntryID = EntryID; + Expected EntryOr = NI.getEntry(&NextEntryID); + for (; EntryOr; ++NumEntries, EntryID = NextEntryID, + EntryOr = NI.getEntry(&NextEntryID)) { uint32_t CUIndex = *EntryOr->getCUIndex(); if (CUIndex > NI.getCUCount()) { error() << formatv("Name Index @ {0:x}: Entry @ {1:x} contains an " @@ -1129,13 +1127,14 @@ return; error() << formatv("Name Index @ {0:x}: Name {1} ({2}) is " "not associated with any entries.\n", - NI.getUnitOffset(), Name, Str); + NI.getUnitOffset(), NTE.getIndex(), Str); ++NumErrors; }, [&](const ErrorInfoBase &Info) { - error() << formatv( - "Name Index @ {0:x}: Name {1} ({2}): {3}\n", - NI.getUnitOffset(), Name, Str, Info.message()); + error() + << formatv("Name Index @ {0:x}: Name {1} ({2}): {3}\n", + NI.getUnitOffset(), NTE.getIndex(), Str, + Info.message()); ++NumErrors; }); return NumErrors; @@ -1302,8 +1301,8 @@ if (NumErrors > 0) return NumErrors; for (const auto &NI : AccelTable) - for (uint64_t Name = 1; Name <= NI.getNameCount(); ++Name) - NumErrors += verifyNameIndexEntries(NI, Name, StrData); + for (DWARFDebugNames::NameTableEntry NTE : NI) + NumErrors += verifyNameIndexEntries(NI, NTE); if (NumErrors > 0) return NumErrors;