[llvm] r291967 - Add a variant of DWARFDie::find() and DWARFDie::findRecursively() that takes a llvm::ArrayRef<dwarf::Attribute>.

Greg Clayton via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 13 14:32:12 PST 2017


Author: gclayton
Date: Fri Jan 13 16:32:12 2017
New Revision: 291967

URL: http://llvm.org/viewvc/llvm-project?rev=291967&view=rev
Log:
Add a variant of DWARFDie::find() and DWARFDie::findRecursively() that takes a llvm::ArrayRef<dwarf::Attribute>.

This allows us efficiently look for more than one attribute, something that is quite common in DWARF consumption.

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


Modified:
    llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDie.h
    llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp
    llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp
    llvm/trunk/tools/dsymutil/DwarfLinker.cpp
    llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDie.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDie.h?rev=291967&r1=291966&r2=291967&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDie.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDie.h Fri Jan 13 16:32:12 2017
@@ -10,6 +10,7 @@
 #ifndef LLVM_LIB_DEBUGINFO_DWARFDIE_H
 #define LLVM_LIB_DEBUGINFO_DWARFDIE_H
 
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/iterator.h"
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/ADT/Optional.h"
@@ -125,8 +126,20 @@ public:
   /// \returns an optional DWARFFormValue that will have the form value if the
   /// attribute was successfully extracted.
   Optional<DWARFFormValue> find(dwarf::Attribute Attr) const;
-
   
+  /// Extract the first value of any attribute in Attrs from this DIE.
+  ///
+  /// Extract the first attribute that matches from this DIE only. This call
+  /// doesn't look for the attribute value in any DW_AT_specification or
+  /// DW_AT_abstract_origin referenced DIEs. The attributes will be searched
+  /// linearly in the order they are specified within Attrs.
+  ///
+  /// \param Attrs an array of DWARF attribute to look for.
+  /// \returns an optional that has a valid DWARFFormValue for the first
+  /// matching attribute in Attrs, or None if none of the attributes in Attrs
+  /// exist in this DIE.
+  Optional<DWARFFormValue> find(ArrayRef<dwarf::Attribute> Attrs) const;
+
   /// Extract an attribute value from this DIE and recurse into any
   /// DW_AT_specification or DW_AT_abstract_origin referenced DIEs.
   ///
@@ -135,6 +148,18 @@ public:
   /// attribute was successfully extracted.
   Optional<DWARFFormValue> findRecursively(dwarf::Attribute Attr) const;
 
+  /// Extract the first value of any attribute in Attrs from this DIE and
+  /// recurse into any DW_AT_specification or DW_AT_abstract_origin referenced
+  /// DIEs.
+  ///
+  /// \param Attrs an array of DWARF attribute to look for.
+  /// \returns an optional that has a valid DWARFFormValue for the first
+  /// matching attribute in Attrs, or None if none of the attributes in Attrs
+  /// exist in this DIE or in any DW_AT_specification or DW_AT_abstract_origin
+  /// DIEs.
+  Optional<DWARFFormValue>
+  findRecursively(ArrayRef<dwarf::Attribute> Attrs) const;
+
   /// Extract the specified attribute from this DIE as the referenced DIE.
   ///
   /// Regardless of the reference type, return the correct DWARFDie instance if

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp?rev=291967&r1=291966&r2=291967&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp Fri Jan 13 16:32:12 2017
@@ -158,6 +158,35 @@ DWARFDie::findRecursively(dwarf::Attribu
   return None;
 }
 
+Optional<DWARFFormValue>
+DWARFDie::find(ArrayRef<dwarf::Attribute> Attrs) const {
+  if (!isValid())
+    return None;
+  auto AbbrevDecl = getAbbreviationDeclarationPtr();
+  if (AbbrevDecl) {
+    for (auto Attr : Attrs) {
+      if (auto Value = AbbrevDecl->getAttributeValue(getOffset(), Attr, *U))
+        return Value;
+    }
+  }
+  return None;
+}
+
+Optional<DWARFFormValue>
+DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const {
+  if (!isValid())
+    return None;
+  if (auto Value = find(Attrs))
+    return Value;
+  if (auto Die = getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
+    if (auto Value = Die.find(Attrs))
+      return Value;
+  if (auto Die = getAttributeValueAsReferencedDie(DW_AT_specification))
+    if (auto Value = Die.find(Attrs))
+      return Value;
+  return None;
+}
+
 DWARFDie
 DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const {
   auto SpecRef = toReference(find(Attr));
@@ -171,10 +200,7 @@ DWARFDie::getAttributeValueAsReferencedD
 
 Optional<uint64_t>
 DWARFDie::getRangesBaseAttribute() const {
-  auto Result = toSectionOffset(find(DW_AT_rnglists_base));
-  if (Result)
-    return Result;
-  return toSectionOffset(find(DW_AT_GNU_ranges_base));
+  return toSectionOffset(find({DW_AT_rnglists_base, DW_AT_GNU_ranges_base}));
 }
 
 Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const {
@@ -256,11 +282,8 @@ DWARFDie::getName(DINameKind Kind) const
     return nullptr;
   // Try to get mangled name only if it was asked for.
   if (Kind == DINameKind::LinkageName) {
-    if (auto Name = dwarf::toString(findRecursively(DW_AT_MIPS_linkage_name),
-                                    nullptr))
-      return Name;
-    if (auto Name = dwarf::toString(findRecursively(DW_AT_linkage_name),
-                                    nullptr))
+    if (auto Name = dwarf::toString(findRecursively({DW_AT_MIPS_linkage_name,
+                                    DW_AT_linkage_name}), nullptr))
       return Name;
   }
   if (auto Name = dwarf::toString(findRecursively(DW_AT_name), nullptr))

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp?rev=291967&r1=291966&r2=291967&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp Fri Jan 13 16:32:12 2017
@@ -226,9 +226,7 @@ size_t DWARFUnit::extractDIEsIfNeeded(bo
   // If CU DIE was just parsed, copy several attribute values from it.
   if (!HasCUDie) {
     DWARFDie UnitDie = getUnitDIE();
-    auto BaseAddr = toAddress(UnitDie.find(DW_AT_low_pc));
-    if (!BaseAddr)
-      BaseAddr = toAddress(UnitDie.find(DW_AT_entry_pc));
+    auto BaseAddr = toAddress(UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc}));
     if (BaseAddr)
       setBaseAddress(*BaseAddr);
     AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base), 0);

Modified: llvm/trunk/tools/dsymutil/DwarfLinker.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfLinker.cpp?rev=291967&r1=291966&r2=291967&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/DwarfLinker.cpp (original)
+++ llvm/trunk/tools/dsymutil/DwarfLinker.cpp Fri Jan 13 16:32:12 2017
@@ -3184,10 +3184,8 @@ void DwarfLinker::DIECloner::copyAbbrev(
 
 static uint64_t getDwoId(const DWARFDie &CUDie,
                          const DWARFUnit &Unit) {
-  auto DwoId = dwarf::toUnsigned(CUDie.find(dwarf::DW_AT_dwo_id));
-  if (DwoId)
-    return *DwoId;
-  DwoId = dwarf::toUnsigned(CUDie.find(dwarf::DW_AT_GNU_dwo_id));
+  auto DwoId = dwarf::toUnsigned(CUDie.find({dwarf::DW_AT_dwo_id,
+                                             dwarf::DW_AT_GNU_dwo_id}));
   if (DwoId)
     return *DwoId;
   return 0;
@@ -3196,9 +3194,9 @@ static uint64_t getDwoId(const DWARFDie
 bool DwarfLinker::registerModuleReference(
     const DWARFDie &CUDie, const DWARFUnit &Unit,
     DebugMap &ModuleMap, unsigned Indent) {
-  std::string PCMfile = dwarf::toString(CUDie.find(dwarf::DW_AT_dwo_name), "");
-  if (PCMfile.empty())
-    PCMfile = dwarf::toString(CUDie.find(dwarf::DW_AT_GNU_dwo_name), "");
+  std::string PCMfile =
+      dwarf::toString(CUDie.find({dwarf::DW_AT_dwo_name,
+                                  dwarf::DW_AT_GNU_dwo_name}), "");
   if (PCMfile.empty())
     return false;
 

Modified: llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp?rev=291967&r1=291966&r2=291967&view=diff
==============================================================================
--- llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp (original)
+++ llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp Fri Jan 13 16:32:12 2017
@@ -1476,4 +1476,71 @@ TEST(DWARFDebugInfo, TestDwarfToFunction
   // Test
 }
 
+TEST(DWARFDebugInfo, TestFindAttrs) {
+  // Test the DWARFDie::find() and DWARFDie::findRecursively() that take an
+  // ArrayRef<dwarf::Attribute> value to make sure they work correctly.
+  uint16_t Version = 4;
+  
+  const uint8_t AddrSize = sizeof(void *);
+  initLLVMIfNeeded();
+  Triple Triple = getHostTripleForAddrSize(AddrSize);
+  auto ExpectedDG = dwarfgen::Generator::create(Triple, Version);
+  if (HandleExpectedError(ExpectedDG))
+    return;
+  dwarfgen::Generator *DG = ExpectedDG.get().get();
+  dwarfgen::CompileUnit &CU = DG->addCompileUnit();
+  
+  StringRef DieMangled("_Z3fooi");
+  // Scope to allow us to re-use the same DIE names
+  {
+    // Create a compile unit DIE that has an abbreviation that says it has
+    // children, but doesn't have any actual attributes. This helps us test
+    // a DIE that has only one child: a NULL DIE.
+    auto CUDie = CU.getUnitDIE();
+    auto FuncSpecDie = CUDie.addChild(DW_TAG_subprogram);
+    auto FuncDie = CUDie.addChild(DW_TAG_subprogram);
+    FuncSpecDie.addAttribute(DW_AT_MIPS_linkage_name, DW_FORM_strp, DieMangled);
+    FuncDie.addAttribute(DW_AT_specification, DW_FORM_ref4, FuncSpecDie);
+  }
+  
+  MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
+  auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
+  EXPECT_TRUE((bool)Obj);
+  DWARFContextInMemory DwarfContext(*Obj.get());
+  
+  // Verify the number of compile units is correct.
+  uint32_t NumCUs = DwarfContext.getNumCompileUnits();
+  EXPECT_EQ(NumCUs, 1u);
+  DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0);
+  
+  // Get the compile unit DIE is valid.
+  auto CUDie = U->getUnitDIE(false);
+  EXPECT_TRUE(CUDie.isValid());
+  
+  auto FuncSpecDie = CUDie.getFirstChild();
+  auto FuncDie = FuncSpecDie.getSibling();
+
+  // Make sure that passing in an empty attribute list behave correctly.
+  EXPECT_FALSE(FuncDie.find(ArrayRef<dwarf::Attribute>()).hasValue());
+
+  // Make sure that passing in a list of attribute that are not contained
+  // in the DIE returns nothing.
+  EXPECT_FALSE(FuncDie.find({DW_AT_low_pc, DW_AT_entry_pc}).hasValue());
+
+  ArrayRef<dwarf::Attribute>
+      Attrs = { DW_AT_linkage_name, DW_AT_MIPS_linkage_name };
+  
+  // Make sure we can't extract the linkage name attributes when using
+  // DWARFDie::find() since it won't check the DW_AT_specification DIE.
+  EXPECT_FALSE(FuncDie.find(Attrs).hasValue());
+  
+  // Make sure we can extract the name from the specification die when using
+  // DWARFDie::findRecursively() since it should recurse through the
+  // DW_AT_specification DIE.
+  auto NameOpt = FuncDie.findRecursively(Attrs);
+  EXPECT_TRUE(NameOpt.hasValue());
+  EXPECT_EQ(DieMangled, toString(NameOpt, ""));
+  
+}
+
 } // end anonymous namespace




More information about the llvm-commits mailing list