[llvm] r333738 - DWARFAcceleratorTable: Add an iterator-based api for accessing names in the index

Pavel Labath via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 1 03:33:11 PDT 2018


Author: labath
Date: Fri Jun  1 03:33:11 2018
New Revision: 333738

URL: http://llvm.org/viewvc/llvm-project?rev=333738&view=rev
Log:
DWARFAcceleratorTable: Add an iterator-based api for accessing names in the index

Summary:
Back when we were introducing the DWARF v5 name index, there was a
short discussion whether we shouldn't have a nicer api for iterating
over the index. At that time, I did not find it necessary since the
iteration over names was done only from within the index itself (and I
figured the internal implementation can deal with a slightly rough
interface).

However, now I ran into a use for this kind of API in LLDB (for finding
all names matching a regular expression), so it looked like a nice
opportunity to introduce one. To make the API more useful, I've made the
NameTableEntry class a bit smarter: it now stores the string section
reference (so it can return its name) and its position in the name index
(mainly useful for dumping/logging).

I also convert the internal users to use the new API, which also gives
test coverage for the added code.

Reviewers: JDevlieghere, aprantl, dblaikie

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D47590

Modified:
    llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
    llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
    llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
    llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h?rev=333738&r1=333737&r2=333738&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h Fri Jun  1 03:33:11 2018
@@ -239,6 +239,7 @@ class DWARFDebugNames : public DWARFAcce
 
 public:
   class NameIndex;
+  class NameIterator;
   class ValueIterator;
 
   /// Dwarf 5 Name Index header.
@@ -351,9 +352,34 @@ private:
 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 @@ public:
     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<uint32_t> Hash) const;
     void dumpBucket(ScopedPrinter &W, uint32_t Bucket) const;
 
@@ -432,6 +458,9 @@ public:
     /// Look up all entries in this Name Index matching \c Key.
     iterator_range<ValueIterator> 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; }
@@ -496,6 +525,52 @@ public:
       return !(A == B);
     }
   };
+
+  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<NameIndex, 0> NameIndices;

Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h?rev=333738&r1=333737&r2=333738&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h Fri Jun  1 03:33:11 2018
@@ -242,7 +242,7 @@ private:
                                     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);
 

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp?rev=333738&r1=333737&r2=333738&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp Fri Jun  1 03:33:11 2018
@@ -635,7 +635,7 @@ DWARFDebugNames::NameIndex::getNameTable
   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 @@ bool DWARFDebugNames::NameIndex::dumpEnt
   return true;
 }
 
-void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W, uint32_t Index,
+void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W,
+                                          const NameTableEntry &NTE,
                                           Optional<uint32_t> 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 @@ void DWARFDebugNames::NameIndex::dumpBuc
     if (Hash % Hdr.BucketCount != Bucket)
       break;
 
-    dumpName(W, Index, Hash);
+    dumpName(W, getNameTableEntry(Index), Hash);
   }
 }
 
@@ -755,8 +754,8 @@ LLVM_DUMP_METHOD void DWARFDebugNames::N
   }
 
   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 @@ DWARFDebugNames::ValueIterator::findEntr
   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 @@ DWARFDebugNames::ValueIterator::findEntr
       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;
 }

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp?rev=333738&r1=333737&r2=333738&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp Fri Jun  1 03:33:11 2018
@@ -920,8 +920,7 @@ DWARFVerifier::verifyNameIndexBuckets(co
       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 @@ static SmallVector<StringRef, 2> getName
   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<DWARFDebugNames::Entry> 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<DWARFDebugNames::Entry> 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 @@ DWARFVerifier::verifyNameIndexEntries(co
                       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 @@ unsigned DWARFVerifier::verifyDebugNames
   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;




More information about the llvm-commits mailing list