[Lldb-commits] [lldb] r333878 - AppleDWARFIndex: Get function method-ness directly from debug info

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Mon Jun 4 02:05:27 PDT 2018


Author: labath
Date: Mon Jun  4 02:05:27 2018
New Revision: 333878

URL: http://llvm.org/viewvc/llvm-project?rev=333878&view=rev
Log:
AppleDWARFIndex: Get function method-ness directly from debug info

Summary:
When searching for methods only, we need to do extra work to make sure
the functions we get from the apple tables are indeed methods.
Previously we were resolving the DIE into a SymbolContext and then
checked whether the enclosing CompilerDeclContext is a
class (or struct, or union).

This patch changes that to operate on the debug info directly. This
should be:
- simpler
- faster
- more consistent with the ManualDWARFIndex (which does the same check,
  only at indexing time).

What we lose this ways is for the language plugin to have a say in what
it considers to be a "class", but that's probably more flexibility than
we need (and if we really wanted to do that in the future, we could
implement a more direct way to consult the plugin about this).

This also fixes the find-method-local-struct test, which was failing
because we were not able to construct a CompilerDeclContext for a local
struct correctly.

As a drive-by, I rename the DWARFDIE's IsStructClassOrUnion method to
match the name on the CompilerDeclContext class.

Reviewers: clayborg, JDevlieghere

Subscribers: aprantl, lldb-commits

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

Modified:
    lldb/trunk/lit/SymbolFile/DWARF/find-method-local-struct.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
    lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp

Modified: lldb/trunk/lit/SymbolFile/DWARF/find-method-local-struct.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/DWARF/find-method-local-struct.cpp?rev=333878&r1=333877&r2=333878&view=diff
==============================================================================
--- lldb/trunk/lit/SymbolFile/DWARF/find-method-local-struct.cpp (original)
+++ lldb/trunk/lit/SymbolFile/DWARF/find-method-local-struct.cpp Mon Jun  4 02:05:27 2018
@@ -1,6 +1,3 @@
-// llvm.org/pr37537
-// XFAIL: *
-
 // RUN: clang %s -g -c -o %t --target=x86_64-apple-macosx
 // RUN: lldb-test symbols --name=foo --find=function --function-flags=method %t | \
 // RUN:   FileCheck %s

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp?rev=333878&r1=333877&r2=333878&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp Mon Jun  4 02:05:27 2018
@@ -146,6 +146,14 @@ void AppleDWARFIndex::GetNamespaces(Cons
     m_apple_namespaces_up->FindByName(name.GetStringRef(), offsets);
 }
 
+static bool KeepFunctionDIE(DWARFDIE die, uint32_t name_type_mask) {
+  bool looking_for_methods = name_type_mask & eFunctionNameTypeMethod;
+  bool looking_for_functions = name_type_mask & eFunctionNameTypeBase;
+  if (looking_for_methods && looking_for_functions)
+    return true;
+  return looking_for_methods == die.IsMethod();
+}
+
 void AppleDWARFIndex::GetFunctions(
     ConstString name, DWARFDebugInfo &info,
     llvm::function_ref<bool(const DWARFDIE &die, bool include_inlines,
@@ -228,47 +236,15 @@ void AppleDWARFIndex::GetFunctions(
         if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die))
           continue; // The containing decl contexts don't match
 
+        if (!KeepFunctionDIE(die, name_type_mask))
+          continue;
+
+        if (resolved_dies.find(die.GetDIE()) != resolved_dies.end())
+          continue;
+
         // If we get to here, the die is good, and we should add it:
-        if (resolved_dies.find(die.GetDIE()) == resolved_dies.end() &&
-            resolve_function(die, include_inlines, sc_list)) {
-          bool keep_die = true;
-          if ((name_type_mask &
-               (eFunctionNameTypeBase | eFunctionNameTypeMethod)) !=
-              (eFunctionNameTypeBase | eFunctionNameTypeMethod)) {
-            // We are looking for either basenames or methods, so we need
-            // to trim out the ones we won't want by looking at the type
-            SymbolContext sc;
-            if (sc_list.GetLastContext(sc)) {
-              if (sc.block) {
-                // We have an inlined function
-              } else if (sc.function) {
-                Type *type = sc.function->GetType();
-
-                if (type) {
-                  CompilerDeclContext decl_ctx =
-                      get_decl_context_containing_uid(type->GetID());
-                  if (decl_ctx.IsStructUnionOrClass()) {
-                    if (name_type_mask & eFunctionNameTypeBase) {
-                      sc_list.RemoveContextAtIndex(sc_list.GetSize() - 1);
-                      keep_die = false;
-                    }
-                  } else {
-                    if (name_type_mask & eFunctionNameTypeMethod) {
-                      sc_list.RemoveContextAtIndex(sc_list.GetSize() - 1);
-                      keep_die = false;
-                    }
-                  }
-                } else {
-                  m_module.ReportWarning(
-                      "function at die offset 0x%8.8x had no function type",
-                      die_ref.die_offset);
-                }
-              }
-            }
-          }
-          if (keep_die)
-            resolved_dies.insert(die.GetDIE());
-        }
+        if (resolve_function(die, include_inlines, sc_list))
+          resolved_dies.insert(die.GetDIE());
       } else
         ReportInvalidDIEOffset(die_ref.die_offset, name.GetStringRef());
     }

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp?rev=333878&r1=333877&r2=333878&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp Mon Jun  4 02:05:27 2018
@@ -10,15 +10,29 @@
 #include "DWARFDIE.h"
 
 #include "DWARFASTParser.h"
-#include "DWARFUnit.h"
 #include "DWARFDIECollection.h"
 #include "DWARFDebugInfo.h"
-#include "DWARFDeclContext.h"
-
 #include "DWARFDebugInfoEntry.h"
+#include "DWARFDeclContext.h"
+#include "DWARFUnit.h"
 
 using namespace lldb_private;
 
+void DWARFDIE::ElaboratingDIEIterator::Next() {
+  assert(!m_worklist.empty() && "Incrementing end iterator?");
+
+  // Pop the current item from the list.
+  DWARFDIE die = m_worklist.back();
+  m_worklist.pop_back();
+
+  // And add back any items that elaborate it.
+  for (dw_attr_t attr : {DW_AT_specification, DW_AT_abstract_origin}) {
+    if (DWARFDIE d = die.GetReferencedDIE(attr))
+      if (m_seen.insert(die.GetID()).second)
+        m_worklist.push_back(d);
+  }
+}
+
 DWARFDIE
 DWARFDIE::GetParent() const {
   if (IsValid())
@@ -209,12 +223,19 @@ DWARFDIE::GetParentDeclContextDIE() cons
     return DWARFDIE();
 }
 
-bool DWARFDIE::IsStructClassOrUnion() const {
+bool DWARFDIE::IsStructUnionOrClass() const {
   const dw_tag_t tag = Tag();
   return tag == DW_TAG_class_type || tag == DW_TAG_structure_type ||
          tag == DW_TAG_union_type;
 }
 
+bool DWARFDIE::IsMethod() const {
+  for (DWARFDIE d: elaborating_dies())
+    if (d.GetParent().IsStructUnionOrClass())
+      return true;
+  return false;
+}
+
 DWARFDIE
 DWARFDIE::GetContainingDWOModuleDIE() const {
   if (IsValid()) {

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.h?rev=333878&r1=333877&r2=333878&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDIE.h Mon Jun  4 02:05:27 2018
@@ -11,15 +11,20 @@
 #define SymbolFileDWARF_DWARFDIE_h_
 
 #include "DWARFBaseDIE.h"
+#include "llvm/ADT/SmallSet.h"
 
 class DWARFDIE : public DWARFBaseDIE {
 public:
+  class ElaboratingDIEIterator;
+
   using DWARFBaseDIE::DWARFBaseDIE;
 
   //----------------------------------------------------------------------
   // Tests
   //----------------------------------------------------------------------
-  bool IsStructClassOrUnion() const;
+  bool IsStructUnionOrClass() const;
+
+  bool IsMethod() const;
 
   //----------------------------------------------------------------------
   // Accessors
@@ -29,6 +34,8 @@ public:
   DWARFDIE
   GetContainingDWOModuleDIE() const;
 
+  inline llvm::iterator_range<ElaboratingDIEIterator> elaborating_dies() const;
+
   //----------------------------------------------------------------------
   // Accessing information about a DIE
   //----------------------------------------------------------------------
@@ -112,4 +119,58 @@ public:
   lldb_private::CompilerDeclContext GetContainingDeclContext() const;
 };
 
+/// Iterate through all DIEs elaborating (i.e. reachable by a chain of
+/// DW_AT_specification and DW_AT_abstract_origin attributes) a given DIE. For
+/// convenience, the starting die is included in the sequence as the first
+/// item.
+class DWARFDIE::ElaboratingDIEIterator
+    : public std::iterator<std::input_iterator_tag, DWARFDIE> {
+
+  // The operating invariant is: top of m_worklist contains the "current" item
+  // and the rest of the list are items yet to be visited. An empty worklist
+  // means we've reached the end.
+  // Infinite recursion is prevented by maintaining a list of seen DIEs.
+  // Container sizes are optimized for the case of following DW_AT_specification
+  // and DW_AT_abstract_origin just once.
+  llvm::SmallVector<DWARFDIE, 2> m_worklist;
+  llvm::SmallSet<lldb::user_id_t, 3> m_seen;
+
+  void Next();
+
+public:
+  /// An iterator starting at die d.
+  explicit ElaboratingDIEIterator(DWARFDIE d) : m_worklist(1, d) {}
+
+  /// End marker
+  ElaboratingDIEIterator() {}
+
+  const DWARFDIE &operator*() const { return m_worklist.back(); }
+  ElaboratingDIEIterator &operator++() {
+    Next();
+    return *this;
+  }
+  ElaboratingDIEIterator operator++(int) {
+    ElaboratingDIEIterator I = *this;
+    Next();
+    return I;
+  }
+
+  friend bool operator==(const ElaboratingDIEIterator &a,
+                         const ElaboratingDIEIterator &b) {
+    if (a.m_worklist.empty() || b.m_worklist.empty())
+      return a.m_worklist.empty() == b.m_worklist.empty();
+    return a.m_worklist.back() == b.m_worklist.back();
+  }
+  friend bool operator!=(const ElaboratingDIEIterator &a,
+                         const ElaboratingDIEIterator &b) {
+    return !(a == b);
+  }
+};
+
+llvm::iterator_range<DWARFDIE::ElaboratingDIEIterator>
+DWARFDIE::elaborating_dies() const {
+  return llvm::make_range(ElaboratingDIEIterator(*this),
+                          ElaboratingDIEIterator());
+}
+
 #endif // SymbolFileDWARF_DWARFDIE_h_

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp?rev=333878&r1=333877&r2=333878&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp Mon Jun  4 02:05:27 2018
@@ -288,22 +288,7 @@ void ManualDWARFIndex::IndexUnitImpl(
           }
           // If we have a mangled name, then the DW_AT_name attribute is
           // usually the method name without the class or any parameters
-          const DWARFDebugInfoEntry *parent = die.GetParent();
-          bool is_method = false;
-          if (parent) {
-            DWARFDIE parent_die(&unit, parent);
-            if (parent_die.IsStructClassOrUnion())
-              is_method = true;
-            else {
-              if (specification_die_form.IsValid()) {
-                DWARFDIE specification_die =
-                    unit.GetSymbolFileDWARF()->DebugInfo()->GetDIE(
-                        DIERef(specification_die_form));
-                if (specification_die.GetParent().IsStructClassOrUnion())
-                  is_method = true;
-              }
-            }
-          }
+          bool is_method = DWARFDIE(&unit, &die).IsMethod();
 
           if (is_method)
             set.function_methods.Insert(ConstString(name),




More information about the lldb-commits mailing list