[llvm] r326003 - Implement equal_range for the DWARF v5 accelerator table

Pavel Labath via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 23 16:35:21 PST 2018


Author: labath
Date: Fri Feb 23 16:35:21 2018
New Revision: 326003

URL: http://llvm.org/viewvc/llvm-project?rev=326003&view=rev
Log:
Implement equal_range for the DWARF v5 accelerator table

Summary:
This patch implements the name lookup functionality of the .debug_names
accelerator table and hooks it up to "llvm-dwarfdump -find". To make the
interface of the two kinds of accelerator tables more consistent, I've
created an abstract "DWARFAcceleratorTable::Entry" class, which provides
a consistent interface to access the common functionality of the table
entries (such as getting the die offset, die tag, etc.). I've also
modified the apple table to vend entries conforming to this interface.

Reviewers: JDevlieghere, aprantl, probinson, dblaikie

Subscribers: vleschuk, clayborg, echristo, llvm-commits

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

Added:
    llvm/trunk/test/tools/llvm-dwarfdump/X86/debug-names-find.s
Modified:
    llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
    llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
    llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.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=326003&r1=326002&r2=326003&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h Fri Feb 23 16:35:21 2018
@@ -35,6 +35,43 @@ protected:
   DataExtractor StringSection;
 
 public:
+  /// An abstract class representing a single entry in the accelerator tables.
+  class Entry {
+  protected:
+    SmallVector<DWARFFormValue, 3> Values;
+
+    Entry() = default;
+
+    // Make these protected so only (final) subclasses can be copied around.
+    Entry(const Entry &) = default;
+    Entry(Entry &&) = default;
+    Entry &operator=(const Entry &) = default;
+    Entry &operator=(Entry &&) = default;
+    ~Entry() = default;
+
+
+  public:
+    /// Returns the Offset of the Compilation Unit associated with this
+    /// Accelerator Entry or None if the Compilation Unit offset is not recorded
+    /// in this Accelerator Entry.
+    virtual Optional<uint64_t> getCUOffset() const = 0;
+
+    /// Returns the Offset of the Debug Info Entry associated with this
+    /// Accelerator Entry or None if the DIE offset is not recorded in this
+    /// Accelerator Entry.
+    virtual Optional<uint64_t> getDIEOffset() const = 0;
+
+    /// Returns the Tag of the Debug Info Entry associated with this
+    /// Accelerator Entry or None if the Tag is not recorded in this
+    /// Accelerator Entry.
+    virtual Optional<dwarf::Tag> getTag() const = 0;
+
+    /// Returns the raw values of fields in the Accelerator Entry. In general,
+    /// these can only be interpreted with the help of the metadata in the
+    /// owning Accelerator Table.
+    ArrayRef<DWARFFormValue> getValues() const { return Values; }
+  };
+
   DWARFAcceleratorTable(const DWARFDataExtractor &AccelSection,
                         DataExtractor StringSection)
       : AccelSection(AccelSection), StringSection(StringSection) {}
@@ -79,13 +116,32 @@ class AppleAcceleratorTable : public DWA
                 uint32_t *DataOffset) const;
 
 public:
-  /// An iterator for the entries associated with one key. Each entry can have
-  /// multiple DWARFFormValues.
-  class ValueIterator : public std::iterator<std::input_iterator_tag,
-                                            ArrayRef<DWARFFormValue>> {
-    const AppleAcceleratorTable *AccelTable = nullptr;
-    SmallVector<DWARFFormValue, 3> AtomForms; ///< The decoded data entry.
+  /// Apple-specific implementation of an Accelerator Entry.
+  class Entry final : public DWARFAcceleratorTable::Entry {
+    const HeaderData *HdrData = nullptr;
+
+    Entry(const HeaderData &Data);
+    Entry() = default;
+
+    void extract(const AppleAcceleratorTable &AccelTable, uint32_t *Offset);
 
+  public:
+    Entry(const Entry &RHS) : HdrData(RHS.HdrData) { Values = RHS.Values; }
+    Optional<uint64_t> getCUOffset() const override;
+    Optional<uint64_t> getDIEOffset() const override;
+    Optional<dwarf::Tag> getTag() const override;
+
+    /// Returns the value of the Atom in this Accelerator Entry, if the Entry
+    /// contains such Atom.
+    Optional<DWARFFormValue> lookup(HeaderData::AtomType Atom) const;
+
+    friend class AppleAcceleratorTable;
+    friend class ValueIterator;
+  };
+
+  class ValueIterator : public std::iterator<std::input_iterator_tag, Entry> {
+    const AppleAcceleratorTable *AccelTable = nullptr;
+    Entry Current;           ///< The current entry.
     unsigned DataOffset = 0; ///< Offset into the section.
     unsigned Data = 0; ///< Current data entry.
     unsigned NumData = 0; ///< Number of data entries.
@@ -98,9 +154,7 @@ public:
     /// End marker.
     ValueIterator() = default;
 
-    const ArrayRef<DWARFFormValue> operator*() const {
-      return AtomForms;
-    }
+    const Entry &operator*() const { return Current; }
     ValueIterator &operator++() { Next(); return *this; }
     ValueIterator operator++(int) {
       ValueIterator I = *this;
@@ -124,6 +178,9 @@ public:
   uint32_t getNumHashes();
   uint32_t getSizeHdr();
   uint32_t getHeaderDataLength();
+
+  /// Return the Atom description, which can be used to interpret the raw values
+  /// of the Accelerator Entries in this table.
   ArrayRef<std::pair<HeaderData::AtomType, HeaderData::Form>> getAtomsDesc();
   bool validateForms();
 
@@ -179,6 +236,9 @@ class DWARFDebugNames : public DWARFAcce
   };
 
 public:
+  class NameIndex;
+  class ValueIterator;
+
   /// Dwarf 5 Name Index header.
   struct Header : public HeaderPOD {
     SmallString<8> AugmentationString;
@@ -214,16 +274,41 @@ public:
     void dump(ScopedPrinter &W) const;
   };
 
-  /// A single entry in the Name Index.
-  struct Entry {
-    const Abbrev &Abbr;
-
-    /// Values of the index attributes described by Abbr.
-    std::vector<DWARFFormValue> Values;
+  /// DWARF v5-specific implementation of an Accelerator Entry.
+  class Entry final : public DWARFAcceleratorTable::Entry {
+    const NameIndex *NameIdx;
+    const Abbrev *Abbr;
+
+    Entry(const NameIndex &NameIdx, const Abbrev &Abbr);
+
+    /// Returns the Index into the Compilation Unit list of the owning Name
+    /// Index or None if this Accelerator Entry does not have an associated
+    /// Compilation Unit. It is up to the user to verify that the returned Index
+    /// is valid in the owning NameIndex (or use getCUOffset(), which will
+    /// handle that check itself).
+    Optional<uint64_t> getCUIndex() const;
 
-    Entry(const Abbrev &Abbr);
+  public:
+    Optional<uint64_t> getCUOffset() const override;
+    Optional<uint64_t> getDIEOffset() const override;
+    Optional<dwarf::Tag> getTag() const override { return tag(); }
+
+    /// .debug_names-specific getter, which always succeeds (DWARF v5 index
+    /// entries always have a tag).
+    dwarf::Tag tag() const { return Abbr->Tag; }
+
+    /// Return the Abbreviation that can be used to interpret the raw values of
+    /// this Accelerator Entry.
+    const Abbrev &getAbbrev() const { return *Abbr; }
+
+    /// Returns the value of the Index Attribute in this Accelerator Entry, if
+    /// the Entry contains such Attribute.
+    Optional<DWARFFormValue> lookup(dwarf::Index Index) const;
 
     void dump(ScopedPrinter &W) const;
+
+    friend class NameIndex;
+    friend class ValueIterator;
   };
 
 private:
@@ -280,15 +365,6 @@ public:
     uint32_t EntryOffsetsBase;
     uint32_t EntriesBase;
 
-    /// Reads offset of compilation unit CU. CU is 0-based.
-    uint32_t getCUOffset(uint32_t CU) const;
-
-    /// Reads offset of local type unit TU, TU is 0-based.
-    uint32_t getLocalTUOffset(uint32_t TU) const;
-
-    /// Reads signature of foreign type unit TU. TU is 0-based.
-    uint64_t getForeignTUOffset(uint32_t TU) const;
-
     /// Reads an entry in the Bucket Array for the given Bucket. The returned
     /// value is a (1-based) index into the Names, StringOffsets and
     /// EntryOffsets arrays. The input Bucket index is 0-based.
@@ -326,13 +402,76 @@ public:
     NameIndex(const DWARFDebugNames &Section, uint32_t Base)
         : Section(Section), Base(Base) {}
 
+    /// Reads offset of compilation unit CU. CU is 0-based.
+    uint32_t getCUOffset(uint32_t CU) const;
+    uint32_t getCUCount() const { return Hdr.CompUnitCount; }
+
+    /// Reads offset of local type unit TU, TU is 0-based.
+    uint32_t getLocalTUOffset(uint32_t TU) const;
+    uint32_t getLocalTUCount() const { return Hdr.LocalTypeUnitCount; }
+
+    /// Reads signature of foreign type unit TU. TU is 0-based.
+    uint64_t getForeignTUSignature(uint32_t TU) const;
+    uint32_t getForeignTUCount() const { return Hdr.ForeignTypeUnitCount; }
+
     llvm::Error extract();
     uint32_t getNextUnitOffset() const { return Base + 4 + Hdr.UnitLength; }
     void dump(ScopedPrinter &W) const;
+
+    friend class DWARFDebugNames;
+  };
+
+  class ValueIterator : public std::iterator<std::input_iterator_tag, Entry> {
+
+    /// The Name Index we are currently iterating through. The implementation
+    /// relies on the fact that this can also be used as an iterator into the
+    /// "NameIndices" vector in the Accelerator section.
+    const NameIndex *CurrentIndex = nullptr;
+
+    Optional<Entry> CurrentEntry;
+    unsigned DataOffset = 0; ///< Offset into the section.
+    std::string Key;         ///< The Key we are searching for.
+    Optional<uint32_t> Hash; ///< Hash of Key, if it has been computed.
+
+    bool getEntryAtCurrentOffset();
+    Optional<uint32_t> findEntryOffsetInCurrentIndex();
+    bool findInCurrentIndex();
+    void searchFromStartOfCurrentIndex();
+    void next();
+
+    /// Set the iterator to the "end" state.
+    void setEnd() { *this = ValueIterator(); }
+
+  public:
+    /// Create a "begin" iterator for looping over all entries in the
+    /// accelerator table matching Key. The iterator will run through all Name
+    /// Indexes in the section in sequence.
+    ValueIterator(const DWARFDebugNames &AccelTable, StringRef Key);
+
+    /// End marker.
+    ValueIterator() = default;
+
+    const Entry &operator*() const { return *CurrentEntry; }
+    ValueIterator &operator++() {
+      next();
+      return *this;
+    }
+    ValueIterator operator++(int) {
+      ValueIterator I = *this;
+      next();
+      return I;
+    }
+
+    friend bool operator==(const ValueIterator &A, const ValueIterator &B) {
+      return A.CurrentIndex == B.CurrentIndex && A.DataOffset == B.DataOffset;
+    }
+    friend bool operator!=(const ValueIterator &A, const ValueIterator &B) {
+      return !(A == B);
+    }
   };
 
 private:
-  std::vector<NameIndex> NameIndices;
+  llvm::SmallVector<NameIndex, 0> NameIndices;
 
 public:
   DWARFDebugNames(const DWARFDataExtractor &AccelSection,
@@ -341,6 +480,9 @@ public:
 
   llvm::Error extract() override;
   void dump(raw_ostream &OS) const override;
+
+  /// Look up all entries in the accelerator table matching \c Key.
+  iterator_range<ValueIterator> equal_range(StringRef Key) const;
 };
 
 } // end namespace llvm

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp?rev=326003&r1=326002&r2=326003&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp Fri Feb 23 16:35:21 2018
@@ -248,15 +248,61 @@ LLVM_DUMP_METHOD void AppleAcceleratorTa
   }
 }
 
+AppleAcceleratorTable::Entry::Entry(
+    const AppleAcceleratorTable::HeaderData &HdrData)
+    : HdrData(&HdrData) {
+  Values.reserve(HdrData.Atoms.size());
+  for (const auto &Atom : HdrData.Atoms)
+    Values.push_back(DWARFFormValue(Atom.second));
+}
+
+void AppleAcceleratorTable::Entry::extract(
+    const AppleAcceleratorTable &AccelTable, uint32_t *Offset) {
+
+  DWARFFormParams FormParams = {AccelTable.Hdr.Version, 0,
+                                dwarf::DwarfFormat::DWARF32};
+  for (auto &Atom : Values)
+    Atom.extractValue(AccelTable.AccelSection, Offset, FormParams);
+}
+
+Optional<DWARFFormValue>
+AppleAcceleratorTable::Entry::lookup(HeaderData::AtomType Atom) const {
+  assert(HdrData && "Dereferencing end iterator?");
+  assert(HdrData->Atoms.size() == Values.size());
+  for (const auto &Tuple : zip_first(HdrData->Atoms, Values)) {
+    if (std::get<0>(Tuple).first == Atom)
+      return std::get<1>(Tuple);
+  }
+  return None;
+}
+
+Optional<uint64_t> AppleAcceleratorTable::Entry::getDIEOffset() const {
+  if (Optional<DWARFFormValue> Off = lookup(dwarf::DW_ATOM_die_offset))
+    return Off->getAsSectionOffset();
+  return None;
+}
+
+Optional<uint64_t> AppleAcceleratorTable::Entry::getCUOffset() const {
+  if (Optional<DWARFFormValue> Off = lookup(dwarf::DW_ATOM_cu_offset))
+    return Off->getAsSectionOffset();
+  return None;
+}
+
+Optional<dwarf::Tag> AppleAcceleratorTable::Entry::getTag() const {
+  Optional<DWARFFormValue> Tag = lookup(dwarf::DW_ATOM_die_tag);
+  if (!Tag)
+    return None;
+  if (Optional<uint64_t> Value = Tag->getAsUnsignedConstant())
+    return dwarf::Tag(*Value);
+  return None;
+}
+
 AppleAcceleratorTable::ValueIterator::ValueIterator(
     const AppleAcceleratorTable &AccelTable, unsigned Offset)
-    : AccelTable(&AccelTable), DataOffset(Offset) {
+    : AccelTable(&AccelTable), Current(AccelTable.HdrData), DataOffset(Offset) {
   if (!AccelTable.AccelSection.isValidOffsetForDataOfSize(DataOffset, 4))
     return;
 
-  for (const auto &Atom : AccelTable.HdrData.Atoms)
-    AtomForms.push_back(DWARFFormValue(Atom.second));
-
   // Read the first entry.
   NumData = AccelTable.AccelSection.getU32(&DataOffset);
   Next();
@@ -270,10 +316,7 @@ void AppleAcceleratorTable::ValueIterato
     NumData = 0;
     return;
   }
-  DWARFFormParams FormParams = {AccelTable->Hdr.Version, 0,
-                                dwarf::DwarfFormat::DWARF32};
-  for (auto &Atom : AtomForms)
-    Atom.extractValue(AccelSection, &DataOffset, FormParams);
+  Current.extract(*AccelTable, &DataOffset);
   ++Data;
 }
 
@@ -475,8 +518,8 @@ Error DWARFDebugNames::NameIndex::extrac
     }
   }
 }
-
-DWARFDebugNames::Entry::Entry(const Abbrev &Abbr) : Abbr(Abbr) {
+DWARFDebugNames::Entry::Entry(const NameIndex &NameIdx, const Abbrev &Abbr)
+    : NameIdx(&NameIdx), Abbr(&Abbr) {
   // This merely creates form values. It is up to the caller
   // (NameIndex::getEntry) to populate them.
   Values.reserve(Abbr.Attributes.size());
@@ -484,14 +527,43 @@ DWARFDebugNames::Entry::Entry(const Abbr
     Values.emplace_back(Attr.Form);
 }
 
+Optional<DWARFFormValue>
+DWARFDebugNames::Entry::lookup(dwarf::Index Index) const {
+  assert(Abbr->Attributes.size() == Values.size());
+  for (const auto &Tuple : zip_first(Abbr->Attributes, Values)) {
+    if (std::get<0>(Tuple).Index == Index)
+      return std::get<1>(Tuple);
+  }
+  return None;
+}
+
+Optional<uint64_t> DWARFDebugNames::Entry::getDIEOffset() const {
+  if (Optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_die_offset))
+    return Off->getAsSectionOffset();
+  return None;
+}
+
+Optional<uint64_t> DWARFDebugNames::Entry::getCUIndex() const {
+  if (Optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_compile_unit))
+    return Off->getAsUnsignedConstant();
+  return None;
+}
+
+Optional<uint64_t> DWARFDebugNames::Entry::getCUOffset() const {
+  Optional<uint64_t> Index = getCUIndex();
+  if (!Index || *Index >= NameIdx->getCUCount())
+    return None;
+  return NameIdx->getCUOffset(*Index);
+}
+
 void DWARFDebugNames::Entry::dump(ScopedPrinter &W) const {
-  W.printHex("Abbrev", Abbr.Code);
-  W.startLine() << "Tag: " << formatTag(Abbr.Tag) << "\n";
+  W.printHex("Abbrev", Abbr->Code);
+  W.startLine() << "Tag: " << formatTag(Abbr->Tag) << "\n";
 
-  assert(Abbr.Attributes.size() == Values.size());
-  for (uint32_t I = 0, E = Values.size(); I < E; ++I) {
-    W.startLine() << formatIndex(Abbr.Attributes[I].Index) << ": ";
-    Values[I].dump(W.getOStream());
+  assert(Abbr->Attributes.size() == Values.size());
+  for (const auto &Tuple : zip_first(Abbr->Attributes, Values)) {
+    W.startLine() << formatIndex(std::get<0>(Tuple).Index) << ": ";
+    std::get<1>(Tuple).dump(W.getOStream());
     W.getOStream() << '\n';
   }
 }
@@ -513,7 +585,7 @@ uint32_t DWARFDebugNames::NameIndex::get
   return Section.AccelSection.getRelocatedValue(4, &Offset);
 }
 
-uint64_t DWARFDebugNames::NameIndex::getForeignTUOffset(uint32_t TU) const {
+uint64_t DWARFDebugNames::NameIndex::getForeignTUSignature(uint32_t TU) const {
   assert(TU < Hdr.ForeignTypeUnitCount);
   uint32_t Offset = CUsBase + (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) * 4;
   return Section.AccelSection.getU64(&Offset);
@@ -535,7 +607,7 @@ DWARFDebugNames::NameIndex::getEntry(uin
     return make_error<StringError>("Invalid abbreviation",
                                    inconvertibleErrorCode());
 
-  Entry E(*AbbrevIt);
+  Entry E(*this, *AbbrevIt);
 
   DWARFFormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};
   for (auto &Value : E.Values) {
@@ -629,7 +701,7 @@ void DWARFDebugNames::NameIndex::dumpFor
   ListScope TUScope(W, "Foreign Type Unit signatures");
   for (uint32_t TU = 0; TU < Hdr.ForeignTypeUnitCount; ++TU) {
     W.startLine() << format("ForeignTU[%u]: 0x%016" PRIx64 "\n", TU,
-                            getForeignTUOffset(TU));
+                            getForeignTUSignature(TU));
   }
 }
 
@@ -697,3 +769,89 @@ LLVM_DUMP_METHOD void DWARFDebugNames::d
   for (const NameIndex &NI : NameIndices)
     NI.dump(W);
 }
+
+Optional<uint32_t>
+DWARFDebugNames::ValueIterator::findEntryOffsetInCurrentIndex() {
+  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;
+    }
+    return None;
+  }
+
+  // The Name Index has a Hash Table, so use that to speed up the search.
+  // Compute the Key Hash, if it has not been done already.
+  if (!Hash)
+    Hash = caseFoldingDjbHash(Key);
+  uint32_t Bucket = *Hash % Hdr.BucketCount;
+  uint32_t Index = CurrentIndex->getBucketArrayEntry(Bucket);
+  if (Index == 0)
+    return None; // Empty bucket
+
+  for (; Index <= Hdr.NameCount; ++Index) {
+    uint32_t Hash = CurrentIndex->getHashArrayEntry(Index);
+    if (Hash % Hdr.BucketCount != Bucket)
+      return None; // End of bucket
+
+    NameTableEntry NTE = CurrentIndex->getNameTableEntry(Index);
+    if (CurrentIndex->Section.StringSection.getCStr(&NTE.StringOffset) == Key)
+      return NTE.EntryOffset;
+  }
+  return None;
+}
+
+bool DWARFDebugNames::ValueIterator::getEntryAtCurrentOffset() {
+  auto EntryOr = CurrentIndex->getEntry(&DataOffset);
+  if (!EntryOr) {
+    consumeError(EntryOr.takeError());
+    return false;
+  }
+  CurrentEntry = std::move(*EntryOr);
+  return true;
+}
+
+bool DWARFDebugNames::ValueIterator::findInCurrentIndex() {
+  Optional<uint32_t> Offset = findEntryOffsetInCurrentIndex();
+  if (!Offset)
+    return false;
+  DataOffset = *Offset;
+  return getEntryAtCurrentOffset();
+}
+
+void DWARFDebugNames::ValueIterator::searchFromStartOfCurrentIndex() {
+  for (const NameIndex *End = CurrentIndex->Section.NameIndices.end();
+       CurrentIndex != End; ++CurrentIndex) {
+    if (findInCurrentIndex())
+      return;
+  }
+  setEnd();
+}
+
+void DWARFDebugNames::ValueIterator::next() {
+  assert(CurrentIndex && "Incrementing an end() iterator?");
+
+  // First try the next entry in the current Index.
+  if (getEntryAtCurrentOffset())
+    return;
+
+  // Try the next Name Index.
+  ++CurrentIndex;
+  searchFromStartOfCurrentIndex();
+}
+
+DWARFDebugNames::ValueIterator::ValueIterator(const DWARFDebugNames &AccelTable,
+                                              StringRef Key)
+    : CurrentIndex(AccelTable.NameIndices.begin()), Key(Key) {
+  searchFromStartOfCurrentIndex();
+}
+
+iterator_range<DWARFDebugNames::ValueIterator>
+DWARFDebugNames::equal_range(StringRef Key) const {
+  if (NameIndices.empty())
+    return make_range(ValueIterator(), ValueIterator());
+  return make_range(ValueIterator(*this, Key), ValueIterator());
+}

Added: llvm/trunk/test/tools/llvm-dwarfdump/X86/debug-names-find.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-dwarfdump/X86/debug-names-find.s?rev=326003&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-dwarfdump/X86/debug-names-find.s (added)
+++ llvm/trunk/test/tools/llvm-dwarfdump/X86/debug-names-find.s Fri Feb 23 16:35:21 2018
@@ -0,0 +1,182 @@
+# RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj -o %t
+# RUN: llvm-dwarfdump -find=foo %t | FileCheck --check-prefix=FOO %s
+# RUN: llvm-dwarfdump -find=baz %t | FileCheck --check-prefix=BAZ %s
+# RUN: llvm-dwarfdump -find=missing %t | FileCheck --check-prefix=MISSING %s
+
+# FOO: DW_TAG_subprogram
+# FOO-NEXT: DW_AT_name ("foo")
+# FOO-NEXT: DW_AT_external
+
+# BAZ: DW_TAG_subprogram
+# BAZ-NEXT: DW_AT_name ("baz")
+# BAZ-NEXT: DW_AT_external
+
+# MISSING-NOT: foo
+# MISSING-NOT: bar
+# MISSING-NOT: baz
+# MISSING-NOT: bazz
+
+	.section	.debug_str,"MS", at progbits,1
+.Lstring_foo:
+	.asciz	"foo"
+.Lstring_foo_mangled:
+	.asciz	"_Z3foov"
+.Lstring_bar:
+	.asciz	"bar"
+.Lstring_baz:
+	.asciz	"baz"
+.Lstring_bazz:
+	.asciz	"bazz"
+.Lstring_producer:
+	.asciz	"Hand-written dwarf"
+
+	.section	.debug_abbrev,"", at progbits
+.Lsection_abbrev:
+	.byte	1                       # Abbreviation Code
+	.byte	17                      # DW_TAG_compile_unit
+	.byte	1                       # DW_CHILDREN_yes
+	.byte	37                      # DW_AT_producer
+	.byte	14                      # DW_FORM_strp
+	.byte	19                      # DW_AT_language
+	.byte	5                       # DW_FORM_data2
+	.byte	0                       # EOM(1)
+	.byte	0                       # EOM(2)
+	.byte	2                       # Abbreviation Code
+	.byte	46                      # DW_TAG_subprogram
+	.byte	0                       # DW_CHILDREN_no
+	.byte	3                       # DW_AT_name
+	.byte	14                      # DW_FORM_strp
+	.byte	63                      # DW_AT_external
+	.byte	25                      # DW_FORM_flag_present
+	.byte	0                       # EOM(1)
+	.byte	0                       # EOM(2)
+	.byte	0                       # EOM(3)
+
+	.section	.debug_info,"", at progbits
+.Lcu_begin0:
+	.long	.Lcu_end0-.Lcu_start0   # Length of Unit
+.Lcu_start0:
+	.short	4                       # DWARF version number
+	.long	.Lsection_abbrev        # Offset Into Abbrev. Section
+	.byte	8                       # Address Size (in bytes)
+	.byte	1                       # Abbrev [1] DW_TAG_compile_unit
+	.long	.Lstring_producer       # DW_AT_producer
+	.short	12                      # DW_AT_language
+.Ldie_foo:
+	.byte	2                       # Abbrev [2] DW_TAG_subprogram
+	.long	.Lstring_foo            # DW_AT_name
+                                        # DW_AT_external
+.Ldie_bar:
+	.byte	2                       # Abbrev [2] DW_TAG_subprogram
+	.long	.Lstring_bar            # DW_AT_name
+                                        # DW_AT_external
+	.byte	0                       # End Of Children Mark
+.Lcu_end0:
+
+.Lcu_begin1:
+	.long	.Lcu_end1-.Lcu_start1   # Length of Unit
+.Lcu_start1:
+	.short	4                       # DWARF version number
+	.long	.Lsection_abbrev        # Offset Into Abbrev. Section
+	.byte	8                       # Address Size (in bytes)
+	.byte	1                       # Abbrev [1] DW_TAG_compile_unit
+	.long	.Lstring_producer       # DW_AT_producer
+	.short	12                      # DW_AT_language
+.Ldie_baz:
+	.byte	2                       # Abbrev [2] DW_TAG_subprogram
+	.long	.Lstring_baz            # DW_AT_name
+                                        # DW_AT_external
+.Ldie_bazz:
+	.byte	2                       # Abbrev [2] DW_TAG_subprogram
+	.long	.Lstring_bazz           # DW_AT_name
+                                        # DW_AT_external
+	.byte	0                       # End Of Children Mark
+.Lcu_end1:
+
+	.section	.debug_names,"", at progbits
+	.long	.Lnames_end0-.Lnames_start0 # Header: contribution length
+.Lnames_start0:
+	.short	5                       # Header: version
+	.short	0                       # Header: padding
+	.long	1                       # Header: compilation unit count
+	.long	0                       # Header: local type unit count
+	.long	0                       # Header: foreign type unit count
+	.long	2                       # Header: bucket count
+	.long	3                       # Header: name count
+	.long	.Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+	.long	0                       # Header: augmentation length
+	.long	.Lcu_begin0             # Compilation unit 0
+	.long	1                       # Bucket 0
+	.long	2                       # Bucket 1
+        .long   193487034               # Hash in Bucket 0
+	.long	193491849               # Hash in Bucket 1
+	.long	-1257882357             # Hash in Bucket 1
+	.long	.Lstring_bar            # String in Bucket 1: bar
+	.long	.Lstring_foo            # String in Bucket 1: foo
+	.long	.Lstring_foo_mangled    # String in Bucket 1: _Z3foov
+	.long	.Lnames0-.Lnames_entries0 # Offset in Bucket 1
+	.long	.Lnames1-.Lnames_entries0 # Offset in Bucket 1
+	.long	.Lnames2-.Lnames_entries0 # Offset in Bucket 1
+.Lnames_abbrev_start0:
+	.byte	46                      # Abbrev code
+	.byte	46                      # DW_TAG_subprogram
+	.byte	3                       # DW_IDX_die_offset
+	.byte	6                       # DW_FORM_data4
+	.byte	0                       # End of abbrev
+	.byte	0                       # End of abbrev
+	.byte	0                       # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+	.byte	46                      # Abbrev code
+	.long	.Ldie_bar               # DW_IDX_die_offset
+	.long	0                       # End of list: bar
+.Lnames1:
+	.byte	46                      # Abbrev code
+	.long	.Ldie_foo               # DW_IDX_die_offset
+	.long	0                       # End of list: foo
+.Lnames2:
+	.byte	46                      # Abbrev code
+	.long	.Ldie_foo               # DW_IDX_die_offset
+	.long	0                       # End of list: _Z3foov
+	.p2align	2
+.Lnames_end0:
+
+# Index of compilation unit 1. This one has no hash table.
+	.long	.Lnames_end1-.Lnames_start1 # Header: contribution length
+.Lnames_start1:
+	.short	5                       # Header: version
+	.short	0                       # Header: padding
+	.long	1                       # Header: compilation unit count
+	.long	0                       # Header: local type unit count
+	.long	0                       # Header: foreign type unit count
+	.long	0                       # Header: bucket count
+	.long	2                       # Header: name count
+	.long	.Lnames_abbrev_end1-.Lnames_abbrev_start1 # Header: abbreviation table size
+	.long	0                       # Header: augmentation length
+	.long	.Lcu_begin1             # Compilation unit 0
+	.long	.Lstring_baz            # String in Bucket 1: baz
+	.long	.Lstring_bazz           # String in Bucket 1: bazz
+	.long	.Lnames3-.Lnames_entries1 # Offset in Bucket 1
+	.long	.Lnames4-.Lnames_entries1 # Offset in Bucket 1
+.Lnames_abbrev_start1:
+	.byte	46                      # Abbrev code
+	.byte	46                      # DW_TAG_subprogram
+	.byte	3                       # DW_IDX_die_offset
+	.byte	6                       # DW_FORM_data4
+	.byte	0                       # End of abbrev
+	.byte	0                       # End of abbrev
+	.byte	0                       # End of abbrev list
+.Lnames_abbrev_end1:
+.Lnames_entries1:
+.Lnames3:
+	.byte	46                      # Abbrev code
+	.long	.Ldie_baz               # DW_IDX_die_offset
+	.long	0                       # End of list: baz
+	.p2align	2
+.Lnames4:
+	.byte	46                      # Abbrev code
+	.long	.Ldie_bazz              # DW_IDX_die_offset
+	.long	0                       # End of list: baz
+	.p2align	2
+.Lnames_end1:

Modified: llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp?rev=326003&r1=326002&r2=326003&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp (original)
+++ llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp Fri Feb 23 16:35:21 2018
@@ -336,6 +336,15 @@ static bool lookup(DWARFContext &DICtx,
 bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
                                Twine Filename, raw_ostream &OS);
 
+template <typename AccelTable>
+static Optional<uint64_t> getDIEOffset(const AccelTable &Accel,
+                                       StringRef Name) {
+  for (const auto &Entry : Accel.equal_range(Name))
+    if (Optional<uint64_t> Off = Entry.getDIEOffset())
+      return *Off;
+  return None;
+}
+
 static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx, Twine Filename,
                            raw_ostream &OS) {
   logAllUnhandledErrors(DICtx.loadRegisterInfo(Obj), errs(),
@@ -363,21 +372,14 @@ static bool dumpObjectFile(ObjectFile &O
   if (!Find.empty()) {
     DumpOffsets[DIDT_ID_DebugInfo] = [&]() -> llvm::Optional<uint64_t> {
       for (auto Name : Find) {
-        auto find = [&](const AppleAcceleratorTable &Accel)
-            -> llvm::Optional<uint64_t> {
-          for (auto Entry : Accel.equal_range(Name))
-            for (auto Atom : Entry)
-              if (auto Offset = Atom.getAsSectionOffset())
-                return Offset;
-          return None;
-        };
-        if (auto Offset = find(DICtx.getAppleNames()))
+        if (auto Offset = getDIEOffset(DICtx.getAppleNames(), Name))
+          return DumpOffsets[DIDT_ID_DebugInfo] = *Offset;
+        if (auto Offset = getDIEOffset(DICtx.getAppleTypes(), Name))
           return DumpOffsets[DIDT_ID_DebugInfo] = *Offset;
-        if (auto Offset = find(DICtx.getAppleTypes()))
+        if (auto Offset = getDIEOffset(DICtx.getAppleNamespaces(), Name))
           return DumpOffsets[DIDT_ID_DebugInfo] = *Offset;
-        if (auto Offset = find(DICtx.getAppleNamespaces()))
+        if (auto Offset = getDIEOffset(DICtx.getDebugNames(), Name))
           return DumpOffsets[DIDT_ID_DebugInfo] = *Offset;
-        // TODO: Add .debug_names support
       }
       return None;
     }();




More information about the llvm-commits mailing list