[Lldb-commits] [lldb] r333178 - DWARF: Move indexing code from DWARFUnit to ManualDWARFIndex

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Thu May 24 05:12:49 PDT 2018


Author: labath
Date: Thu May 24 05:12:49 2018
New Revision: 333178

URL: http://llvm.org/viewvc/llvm-project?rev=333178&view=rev
Log:
DWARF: Move indexing code from DWARFUnit to ManualDWARFIndex

Summary:
I think this makes sense for several reasons:
- better separation of concerns: DWARFUnit's job should be to provide a
  nice interface to its users to access the unit contents.
  ManualDWARFIndex can then use this interface to build an index and
  provide it to its users.
- closer alignment with llvm parsers: there is no indexing equivalent in
  llvm, and there probably never will be, as the index is very centered
  around how lldb wants to access debug info. If we ever switch to
  llvm's parser, this will allow us swap out DWARFUnit implementations
  and keep indexing as-is.
- closer proximity of the indexing code to AppleDWARFIndex will make it
  easier to keep the two in sync (e.g. right now the two use very
  different algorithms to determine whether a DW_TAG_subroutine
  represents a "method"). This is my primary motivation for making this
  change now, but I am leaving this work to a separate patch.

The only interface change to DWARFUnit I needed to make was to add an
efficient way to iterate over the list of all DIEs. Adding this also
aligns us closer to the llvm parser.

Reviewers: JDevlieghere, clayborg, aprantl

Subscribers: lldb-commits

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

Modified:
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
    lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp?rev=333178&r1=333177&r2=333178&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp Thu May 24 05:12:49 2018
@@ -9,20 +9,18 @@
 
 #include "DWARFUnit.h"
 
-#include "Plugins/Language/ObjC/ObjCLanguage.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Host/StringConvert.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/LineTable.h"
 #include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/StreamString.h"
 #include "lldb/Utility/Timer.h"
 
 #include "DWARFDIECollection.h"
-#include "DWARFDebugAbbrev.h"
 #include "DWARFDebugAranges.h"
 #include "DWARFDebugInfo.h"
 #include "LogChannelDWARF.h"
-#include "NameToDIE.h"
 #include "SymbolFileDWARFDebugMap.h"
 #include "SymbolFileDWARFDwo.h"
 
@@ -627,332 +625,6 @@ SymbolFileDWARFDwo *DWARFUnit::GetDwoSym
 
 dw_offset_t DWARFUnit::GetBaseObjOffset() const { return m_base_obj_offset; }
 
-void DWARFUnit::Index(NameToDIE &func_basenames, NameToDIE &func_fullnames,
-                      NameToDIE &func_methods, NameToDIE &func_selectors,
-                      NameToDIE &objc_class_selectors, NameToDIE &globals,
-                      NameToDIE &types, NameToDIE &namespaces) {
-  assert(!m_dwarf->GetBaseCompileUnit() &&
-         "DWARFUnit associated with .dwo or .dwp "
-         "should not be indexed directly");
-
-  Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
-
-  if (log) {
-    m_dwarf->GetObjectFile()->GetModule()->LogMessage(
-        log, "DWARFUnit::Index() for compile unit at .debug_info[0x%8.8x]",
-        GetOffset());
-  }
-
-  const LanguageType cu_language = GetLanguageType();
-  DWARFFormValue::FixedFormSizes fixed_form_sizes =
-      DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
-                                                      IsDWARF64());
-
-  IndexPrivate(this, cu_language, fixed_form_sizes, GetOffset(), func_basenames,
-               func_fullnames, func_methods, func_selectors,
-               objc_class_selectors, globals, types, namespaces);
-
-  SymbolFileDWARFDwo *dwo_symbol_file = GetDwoSymbolFile();
-  if (dwo_symbol_file) {
-    IndexPrivate(
-        dwo_symbol_file->GetCompileUnit(), cu_language, fixed_form_sizes,
-        GetOffset(), func_basenames, func_fullnames, func_methods,
-        func_selectors, objc_class_selectors, globals, types, namespaces);
-  }
-}
-
-void DWARFUnit::IndexPrivate(
-    DWARFUnit *dwarf_cu, const LanguageType cu_language,
-    const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
-    const dw_offset_t cu_offset, NameToDIE &func_basenames,
-    NameToDIE &func_fullnames, NameToDIE &func_methods,
-    NameToDIE &func_selectors, NameToDIE &objc_class_selectors,
-    NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces) {
-  DWARFDebugInfoEntry::const_iterator pos;
-  DWARFDebugInfoEntry::const_iterator begin = dwarf_cu->m_die_array.begin();
-  DWARFDebugInfoEntry::const_iterator end = dwarf_cu->m_die_array.end();
-  for (pos = begin; pos != end; ++pos) {
-    const DWARFDebugInfoEntry &die = *pos;
-
-    const dw_tag_t tag = die.Tag();
-
-    switch (tag) {
-    case DW_TAG_array_type:
-    case DW_TAG_base_type:
-    case DW_TAG_class_type:
-    case DW_TAG_constant:
-    case DW_TAG_enumeration_type:
-    case DW_TAG_inlined_subroutine:
-    case DW_TAG_namespace:
-    case DW_TAG_string_type:
-    case DW_TAG_structure_type:
-    case DW_TAG_subprogram:
-    case DW_TAG_subroutine_type:
-    case DW_TAG_typedef:
-    case DW_TAG_union_type:
-    case DW_TAG_unspecified_type:
-    case DW_TAG_variable:
-      break;
-
-    default:
-      continue;
-    }
-
-    DWARFAttributes attributes;
-    const char *name = NULL;
-    const char *mangled_cstr = NULL;
-    bool is_declaration = false;
-    // bool is_artificial = false;
-    bool has_address = false;
-    bool has_location_or_const_value = false;
-    bool is_global_or_static_variable = false;
-
-    DWARFFormValue specification_die_form;
-    const size_t num_attributes =
-        die.GetAttributes(dwarf_cu, fixed_form_sizes, attributes);
-    if (num_attributes > 0) {
-      for (uint32_t i = 0; i < num_attributes; ++i) {
-        dw_attr_t attr = attributes.AttributeAtIndex(i);
-        DWARFFormValue form_value;
-        switch (attr) {
-        case DW_AT_name:
-          if (attributes.ExtractFormValueAtIndex(i, form_value))
-            name = form_value.AsCString();
-          break;
-
-        case DW_AT_declaration:
-          if (attributes.ExtractFormValueAtIndex(i, form_value))
-            is_declaration = form_value.Unsigned() != 0;
-          break;
-
-        //                case DW_AT_artificial:
-        //                    if (attributes.ExtractFormValueAtIndex(i,
-        //                    form_value))
-        //                        is_artificial = form_value.Unsigned() != 0;
-        //                    break;
-
-        case DW_AT_MIPS_linkage_name:
-        case DW_AT_linkage_name:
-          if (attributes.ExtractFormValueAtIndex(i, form_value))
-            mangled_cstr = form_value.AsCString();
-          break;
-
-        case DW_AT_low_pc:
-        case DW_AT_high_pc:
-        case DW_AT_ranges:
-          has_address = true;
-          break;
-
-        case DW_AT_entry_pc:
-          has_address = true;
-          break;
-
-        case DW_AT_location:
-        case DW_AT_const_value:
-          has_location_or_const_value = true;
-          if (tag == DW_TAG_variable) {
-            const DWARFDebugInfoEntry *parent_die = die.GetParent();
-            while (parent_die != NULL) {
-              switch (parent_die->Tag()) {
-              case DW_TAG_subprogram:
-              case DW_TAG_lexical_block:
-              case DW_TAG_inlined_subroutine:
-                // Even if this is a function level static, we don't add it. We
-                // could theoretically add these if we wanted to by
-                // introspecting into the DW_AT_location and seeing if the
-                // location describes a hard coded address, but we don't want
-                // the performance penalty of that right now.
-                is_global_or_static_variable = false;
-                // if (attributes.ExtractFormValueAtIndex(dwarf, i,
-                //                                        form_value)) {
-                //   // If we have valid block data, then we have location
-                //   // expression bytesthat are fixed (not a location list).
-                //   const uint8_t *block_data = form_value.BlockData();
-                //   if (block_data) {
-                //     uint32_t block_length = form_value.Unsigned();
-                //     if (block_length == 1 +
-                //     attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) {
-                //       if (block_data[0] == DW_OP_addr)
-                //         add_die = true;
-                //     }
-                //   }
-                // }
-                parent_die = NULL; // Terminate the while loop.
-                break;
-
-              case DW_TAG_compile_unit:
-              case DW_TAG_partial_unit:
-                is_global_or_static_variable = true;
-                parent_die = NULL; // Terminate the while loop.
-                break;
-
-              default:
-                parent_die =
-                    parent_die->GetParent(); // Keep going in the while loop.
-                break;
-              }
-            }
-          }
-          break;
-
-        case DW_AT_specification:
-          if (attributes.ExtractFormValueAtIndex(i, form_value))
-            specification_die_form = form_value;
-          break;
-        }
-      }
-    }
-
-    switch (tag) {
-    case DW_TAG_subprogram:
-      if (has_address) {
-        if (name) {
-          ObjCLanguage::MethodName objc_method(name, true);
-          if (objc_method.IsValid(true)) {
-            ConstString objc_class_name_with_category(
-                objc_method.GetClassNameWithCategory());
-            ConstString objc_selector_name(objc_method.GetSelector());
-            ConstString objc_fullname_no_category_name(
-                objc_method.GetFullNameWithoutCategory(true));
-            ConstString objc_class_name_no_category(objc_method.GetClassName());
-            func_fullnames.Insert(ConstString(name),
-                                  DIERef(cu_offset, die.GetOffset()));
-            if (objc_class_name_with_category)
-              objc_class_selectors.Insert(objc_class_name_with_category,
-                                          DIERef(cu_offset, die.GetOffset()));
-            if (objc_class_name_no_category &&
-                objc_class_name_no_category != objc_class_name_with_category)
-              objc_class_selectors.Insert(objc_class_name_no_category,
-                                          DIERef(cu_offset, die.GetOffset()));
-            if (objc_selector_name)
-              func_selectors.Insert(objc_selector_name,
-                                    DIERef(cu_offset, die.GetOffset()));
-            if (objc_fullname_no_category_name)
-              func_fullnames.Insert(objc_fullname_no_category_name,
-                                    DIERef(cu_offset, die.GetOffset()));
-          }
-          // 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) {
-            dw_tag_t parent_tag = parent->Tag();
-            if (parent_tag == DW_TAG_class_type ||
-                parent_tag == DW_TAG_structure_type) {
-              is_method = true;
-            } else {
-              if (specification_die_form.IsValid()) {
-                DWARFDIE specification_die =
-                    dwarf_cu->GetSymbolFileDWARF()->DebugInfo()->GetDIE(
-                        DIERef(specification_die_form));
-                if (specification_die.GetParent().IsStructOrClass())
-                  is_method = true;
-              }
-            }
-          }
-
-          if (is_method)
-            func_methods.Insert(ConstString(name),
-                                DIERef(cu_offset, die.GetOffset()));
-          else
-            func_basenames.Insert(ConstString(name),
-                                  DIERef(cu_offset, die.GetOffset()));
-
-          if (!is_method && !mangled_cstr && !objc_method.IsValid(true))
-            func_fullnames.Insert(ConstString(name),
-                                  DIERef(cu_offset, die.GetOffset()));
-        }
-        if (mangled_cstr) {
-          // Make sure our mangled name isn't the same string table entry as
-          // our name. If it starts with '_', then it is ok, else compare the
-          // string to make sure it isn't the same and we don't end up with
-          // duplicate entries
-          if (name && name != mangled_cstr &&
-              ((mangled_cstr[0] == '_') ||
-               (::strcmp(name, mangled_cstr) != 0))) {
-            func_fullnames.Insert(ConstString(mangled_cstr),
-                                  DIERef(cu_offset, die.GetOffset()));
-          }
-        }
-      }
-      break;
-
-    case DW_TAG_inlined_subroutine:
-      if (has_address) {
-        if (name)
-          func_basenames.Insert(ConstString(name),
-                                DIERef(cu_offset, die.GetOffset()));
-        if (mangled_cstr) {
-          // Make sure our mangled name isn't the same string table entry as
-          // our name. If it starts with '_', then it is ok, else compare the
-          // string to make sure it isn't the same and we don't end up with
-          // duplicate entries
-          if (name && name != mangled_cstr &&
-              ((mangled_cstr[0] == '_') ||
-               (::strcmp(name, mangled_cstr) != 0))) {
-            func_fullnames.Insert(ConstString(mangled_cstr),
-                                  DIERef(cu_offset, die.GetOffset()));
-          }
-        } else
-          func_fullnames.Insert(ConstString(name),
-                                DIERef(cu_offset, die.GetOffset()));
-      }
-      break;
-
-    case DW_TAG_array_type:
-    case DW_TAG_base_type:
-    case DW_TAG_class_type:
-    case DW_TAG_constant:
-    case DW_TAG_enumeration_type:
-    case DW_TAG_string_type:
-    case DW_TAG_structure_type:
-    case DW_TAG_subroutine_type:
-    case DW_TAG_typedef:
-    case DW_TAG_union_type:
-    case DW_TAG_unspecified_type:
-      if (name && !is_declaration)
-        types.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
-      if (mangled_cstr && !is_declaration)
-        types.Insert(ConstString(mangled_cstr),
-                     DIERef(cu_offset, die.GetOffset()));
-      break;
-
-    case DW_TAG_namespace:
-      if (name)
-        namespaces.Insert(ConstString(name),
-                          DIERef(cu_offset, die.GetOffset()));
-      break;
-
-    case DW_TAG_variable:
-      if (name && has_location_or_const_value && is_global_or_static_variable) {
-        globals.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
-        // Be sure to include variables by their mangled and demangled names if
-        // they have any since a variable can have a basename "i", a mangled
-        // named "_ZN12_GLOBAL__N_11iE" and a demangled mangled name
-        // "(anonymous namespace)::i"...
-
-        // Make sure our mangled name isn't the same string table entry as our
-        // name. If it starts with '_', then it is ok, else compare the string
-        // to make sure it isn't the same and we don't end up with duplicate
-        // entries
-        if (mangled_cstr && name != mangled_cstr &&
-            ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) {
-          Mangled mangled(ConstString(mangled_cstr), true);
-          globals.Insert(mangled.GetMangledName(),
-                         DIERef(cu_offset, die.GetOffset()));
-          ConstString demangled = mangled.GetDemangledName(cu_language);
-          if (demangled)
-            globals.Insert(demangled, DIERef(cu_offset, die.GetOffset()));
-        }
-      }
-      break;
-
-    default:
-      continue;
-    }
-  }
-}
-
 const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() {
   if (m_func_aranges_ap.get() == NULL) {
     m_func_aranges_ap.reset(new DWARFDebugAranges());

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.h?rev=333178&r1=333177&r2=333178&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFUnit.h Thu May 24 05:12:49 2018
@@ -33,6 +33,9 @@ enum DWARFProducer {
 class DWARFUnit {
   friend class DWARFCompileUnit;
 
+  using die_iterator_range =
+      llvm::iterator_range<DWARFDebugInfoEntry::collection::iterator>;
+
 public:
   virtual ~DWARFUnit();
 
@@ -134,11 +137,6 @@ public:
 
   bool Supports_unnamed_objc_bitfields();
 
-  void Index(NameToDIE &func_basenames, NameToDIE &func_fullnames,
-             NameToDIE &func_methods, NameToDIE &func_selectors,
-             NameToDIE &objc_class_selectors, NameToDIE &globals,
-             NameToDIE &types, NameToDIE &namespaces);
-
   SymbolFileDWARF *GetSymbolFileDWARF() const;
 
   DWARFProducer GetProducer();
@@ -161,6 +159,11 @@ public:
 
   dw_offset_t GetBaseObjOffset() const;
 
+  die_iterator_range dies() {
+    ExtractDIEsIfNeeded(false);
+    return die_iterator_range(m_die_array.begin(), m_die_array.end());
+  }
+
 protected:
   DWARFUnit(SymbolFileDWARF *dwarf);
 
@@ -190,14 +193,6 @@ protected:
   // in the main object file
   dw_offset_t m_base_obj_offset = DW_INVALID_OFFSET;
 
-  static void
-  IndexPrivate(DWARFUnit *dwarf_cu, const lldb::LanguageType cu_language,
-               const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
-               const dw_offset_t cu_offset, NameToDIE &func_basenames,
-               NameToDIE &func_fullnames, NameToDIE &func_methods,
-               NameToDIE &func_selectors, NameToDIE &objc_class_selectors,
-               NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces);
-
   // Offset of the initial length field.
   dw_offset_t m_offset;
 

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=333178&r1=333177&r2=333178&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp Thu May 24 05:12:49 2018
@@ -8,8 +8,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "Plugins/SymbolFile/DWARF/ManualDWARFIndex.h"
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
 #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
 #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
+#include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
+#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Host/TaskPool.h"
 #include "lldb/Symbol/ObjectFile.h"
@@ -48,10 +51,10 @@ void ManualDWARFIndex::Index() {
   auto parser_fn = [&](size_t cu_idx) {
     DWARFUnit *dwarf_cu = debug_info.GetCompileUnitAtIndex(cu_idx);
     if (dwarf_cu) {
-      dwarf_cu->Index(function_basenames[cu_idx], function_fullnames[cu_idx],
-                      function_methods[cu_idx], function_selectors[cu_idx],
-                      objc_class_selectors[cu_idx], globals[cu_idx],
-                      types[cu_idx], namespaces[cu_idx]);
+      IndexUnit(*dwarf_cu, function_basenames[cu_idx],
+                function_fullnames[cu_idx], function_methods[cu_idx],
+                function_selectors[cu_idx], objc_class_selectors[cu_idx],
+                globals[cu_idx], types[cu_idx], namespaces[cu_idx]);
     }
   };
 
@@ -108,6 +111,324 @@ void ManualDWARFIndex::Index() {
   }
 }
 
+void ManualDWARFIndex::IndexUnit(DWARFUnit &unit, NameToDIE &func_basenames,
+                                 NameToDIE &func_fullnames,
+                                 NameToDIE &func_methods,
+                                 NameToDIE &func_selectors,
+                                 NameToDIE &objc_class_selectors,
+                                 NameToDIE &globals, NameToDIE &types,
+                                 NameToDIE &namespaces) {
+  Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS);
+
+  if (log) {
+    m_module.LogMessage(
+        log, "ManualDWARFIndex::IndexUnit for compile unit at .debug_info[0x%8.8x]",
+        unit.GetOffset());
+  }
+
+  const LanguageType cu_language = unit.GetLanguageType();
+  DWARFFormValue::FixedFormSizes fixed_form_sizes = unit.GetFixedFormSizes();
+
+  IndexUnitImpl(unit, cu_language, fixed_form_sizes, unit.GetOffset(),
+                func_basenames, func_fullnames, func_methods, func_selectors,
+                objc_class_selectors, globals, types, namespaces);
+
+  SymbolFileDWARFDwo *dwo_symbol_file = unit.GetDwoSymbolFile();
+  if (dwo_symbol_file && dwo_symbol_file->GetCompileUnit()) {
+    IndexUnitImpl(*dwo_symbol_file->GetCompileUnit(), cu_language,
+                  fixed_form_sizes, unit.GetOffset(), func_basenames,
+                  func_fullnames, func_methods, func_selectors,
+                  objc_class_selectors, globals, types, namespaces);
+  }
+}
+
+void ManualDWARFIndex::IndexUnitImpl(
+    DWARFUnit &unit, const LanguageType cu_language,
+    const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
+    const dw_offset_t cu_offset, NameToDIE &func_basenames,
+    NameToDIE &func_fullnames, NameToDIE &func_methods,
+    NameToDIE &func_selectors, NameToDIE &objc_class_selectors,
+    NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces) {
+  for (const DWARFDebugInfoEntry &die : unit.dies()) {
+    const dw_tag_t tag = die.Tag();
+
+    switch (tag) {
+    case DW_TAG_array_type:
+    case DW_TAG_base_type:
+    case DW_TAG_class_type:
+    case DW_TAG_constant:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_inlined_subroutine:
+    case DW_TAG_namespace:
+    case DW_TAG_string_type:
+    case DW_TAG_structure_type:
+    case DW_TAG_subprogram:
+    case DW_TAG_subroutine_type:
+    case DW_TAG_typedef:
+    case DW_TAG_union_type:
+    case DW_TAG_unspecified_type:
+    case DW_TAG_variable:
+      break;
+
+    default:
+      continue;
+    }
+
+    DWARFAttributes attributes;
+    const char *name = NULL;
+    const char *mangled_cstr = NULL;
+    bool is_declaration = false;
+    // bool is_artificial = false;
+    bool has_address = false;
+    bool has_location_or_const_value = false;
+    bool is_global_or_static_variable = false;
+
+    DWARFFormValue specification_die_form;
+    const size_t num_attributes =
+        die.GetAttributes(&unit, fixed_form_sizes, attributes);
+    if (num_attributes > 0) {
+      for (uint32_t i = 0; i < num_attributes; ++i) {
+        dw_attr_t attr = attributes.AttributeAtIndex(i);
+        DWARFFormValue form_value;
+        switch (attr) {
+        case DW_AT_name:
+          if (attributes.ExtractFormValueAtIndex(i, form_value))
+            name = form_value.AsCString();
+          break;
+
+        case DW_AT_declaration:
+          if (attributes.ExtractFormValueAtIndex(i, form_value))
+            is_declaration = form_value.Unsigned() != 0;
+          break;
+
+        //                case DW_AT_artificial:
+        //                    if (attributes.ExtractFormValueAtIndex(i,
+        //                    form_value))
+        //                        is_artificial = form_value.Unsigned() != 0;
+        //                    break;
+
+        case DW_AT_MIPS_linkage_name:
+        case DW_AT_linkage_name:
+          if (attributes.ExtractFormValueAtIndex(i, form_value))
+            mangled_cstr = form_value.AsCString();
+          break;
+
+        case DW_AT_low_pc:
+        case DW_AT_high_pc:
+        case DW_AT_ranges:
+          has_address = true;
+          break;
+
+        case DW_AT_entry_pc:
+          has_address = true;
+          break;
+
+        case DW_AT_location:
+        case DW_AT_const_value:
+          has_location_or_const_value = true;
+          if (tag == DW_TAG_variable) {
+            const DWARFDebugInfoEntry *parent_die = die.GetParent();
+            while (parent_die != NULL) {
+              switch (parent_die->Tag()) {
+              case DW_TAG_subprogram:
+              case DW_TAG_lexical_block:
+              case DW_TAG_inlined_subroutine:
+                // Even if this is a function level static, we don't add it. We
+                // could theoretically add these if we wanted to by
+                // introspecting into the DW_AT_location and seeing if the
+                // location describes a hard coded address, but we don't want
+                // the performance penalty of that right now.
+                is_global_or_static_variable = false;
+                // if (attributes.ExtractFormValueAtIndex(dwarf, i,
+                //                                        form_value)) {
+                //   // If we have valid block data, then we have location
+                //   // expression bytesthat are fixed (not a location list).
+                //   const uint8_t *block_data = form_value.BlockData();
+                //   if (block_data) {
+                //     uint32_t block_length = form_value.Unsigned();
+                //     if (block_length == 1 +
+                //     attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) {
+                //       if (block_data[0] == DW_OP_addr)
+                //         add_die = true;
+                //     }
+                //   }
+                // }
+                parent_die = NULL; // Terminate the while loop.
+                break;
+
+              case DW_TAG_compile_unit:
+              case DW_TAG_partial_unit:
+                is_global_or_static_variable = true;
+                parent_die = NULL; // Terminate the while loop.
+                break;
+
+              default:
+                parent_die =
+                    parent_die->GetParent(); // Keep going in the while loop.
+                break;
+              }
+            }
+          }
+          break;
+
+        case DW_AT_specification:
+          if (attributes.ExtractFormValueAtIndex(i, form_value))
+            specification_die_form = form_value;
+          break;
+        }
+      }
+    }
+
+    switch (tag) {
+    case DW_TAG_subprogram:
+      if (has_address) {
+        if (name) {
+          ObjCLanguage::MethodName objc_method(name, true);
+          if (objc_method.IsValid(true)) {
+            ConstString objc_class_name_with_category(
+                objc_method.GetClassNameWithCategory());
+            ConstString objc_selector_name(objc_method.GetSelector());
+            ConstString objc_fullname_no_category_name(
+                objc_method.GetFullNameWithoutCategory(true));
+            ConstString objc_class_name_no_category(objc_method.GetClassName());
+            func_fullnames.Insert(ConstString(name),
+                                  DIERef(cu_offset, die.GetOffset()));
+            if (objc_class_name_with_category)
+              objc_class_selectors.Insert(objc_class_name_with_category,
+                                          DIERef(cu_offset, die.GetOffset()));
+            if (objc_class_name_no_category &&
+                objc_class_name_no_category != objc_class_name_with_category)
+              objc_class_selectors.Insert(objc_class_name_no_category,
+                                          DIERef(cu_offset, die.GetOffset()));
+            if (objc_selector_name)
+              func_selectors.Insert(objc_selector_name,
+                                    DIERef(cu_offset, die.GetOffset()));
+            if (objc_fullname_no_category_name)
+              func_fullnames.Insert(objc_fullname_no_category_name,
+                                    DIERef(cu_offset, die.GetOffset()));
+          }
+          // 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) {
+            dw_tag_t parent_tag = parent->Tag();
+            if (parent_tag == DW_TAG_class_type ||
+                parent_tag == DW_TAG_structure_type) {
+              is_method = true;
+            } else {
+              if (specification_die_form.IsValid()) {
+                DWARFDIE specification_die =
+                    unit.GetSymbolFileDWARF()->DebugInfo()->GetDIE(
+                        DIERef(specification_die_form));
+                if (specification_die.GetParent().IsStructOrClass())
+                  is_method = true;
+              }
+            }
+          }
+
+          if (is_method)
+            func_methods.Insert(ConstString(name),
+                                DIERef(cu_offset, die.GetOffset()));
+          else
+            func_basenames.Insert(ConstString(name),
+                                  DIERef(cu_offset, die.GetOffset()));
+
+          if (!is_method && !mangled_cstr && !objc_method.IsValid(true))
+            func_fullnames.Insert(ConstString(name),
+                                  DIERef(cu_offset, die.GetOffset()));
+        }
+        if (mangled_cstr) {
+          // Make sure our mangled name isn't the same string table entry as
+          // our name. If it starts with '_', then it is ok, else compare the
+          // string to make sure it isn't the same and we don't end up with
+          // duplicate entries
+          if (name && name != mangled_cstr &&
+              ((mangled_cstr[0] == '_') ||
+               (::strcmp(name, mangled_cstr) != 0))) {
+            func_fullnames.Insert(ConstString(mangled_cstr),
+                                  DIERef(cu_offset, die.GetOffset()));
+          }
+        }
+      }
+      break;
+
+    case DW_TAG_inlined_subroutine:
+      if (has_address) {
+        if (name)
+          func_basenames.Insert(ConstString(name),
+                                DIERef(cu_offset, die.GetOffset()));
+        if (mangled_cstr) {
+          // Make sure our mangled name isn't the same string table entry as
+          // our name. If it starts with '_', then it is ok, else compare the
+          // string to make sure it isn't the same and we don't end up with
+          // duplicate entries
+          if (name && name != mangled_cstr &&
+              ((mangled_cstr[0] == '_') ||
+               (::strcmp(name, mangled_cstr) != 0))) {
+            func_fullnames.Insert(ConstString(mangled_cstr),
+                                  DIERef(cu_offset, die.GetOffset()));
+          }
+        } else
+          func_fullnames.Insert(ConstString(name),
+                                DIERef(cu_offset, die.GetOffset()));
+      }
+      break;
+
+    case DW_TAG_array_type:
+    case DW_TAG_base_type:
+    case DW_TAG_class_type:
+    case DW_TAG_constant:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_string_type:
+    case DW_TAG_structure_type:
+    case DW_TAG_subroutine_type:
+    case DW_TAG_typedef:
+    case DW_TAG_union_type:
+    case DW_TAG_unspecified_type:
+      if (name && !is_declaration)
+        types.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
+      if (mangled_cstr && !is_declaration)
+        types.Insert(ConstString(mangled_cstr),
+                     DIERef(cu_offset, die.GetOffset()));
+      break;
+
+    case DW_TAG_namespace:
+      if (name)
+        namespaces.Insert(ConstString(name),
+                          DIERef(cu_offset, die.GetOffset()));
+      break;
+
+    case DW_TAG_variable:
+      if (name && has_location_or_const_value && is_global_or_static_variable) {
+        globals.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
+        // Be sure to include variables by their mangled and demangled names if
+        // they have any since a variable can have a basename "i", a mangled
+        // named "_ZN12_GLOBAL__N_11iE" and a demangled mangled name
+        // "(anonymous namespace)::i"...
+
+        // Make sure our mangled name isn't the same string table entry as our
+        // name. If it starts with '_', then it is ok, else compare the string
+        // to make sure it isn't the same and we don't end up with duplicate
+        // entries
+        if (mangled_cstr && name != mangled_cstr &&
+            ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) {
+          Mangled mangled(ConstString(mangled_cstr), true);
+          globals.Insert(mangled.GetMangledName(),
+                         DIERef(cu_offset, die.GetOffset()));
+          ConstString demangled = mangled.GetDemangledName(cu_language);
+          if (demangled)
+            globals.Insert(demangled, DIERef(cu_offset, die.GetOffset()));
+        }
+      }
+      break;
+
+    default:
+      continue;
+    }
+  }
+}
+
 void ManualDWARFIndex::GetGlobalVariables(ConstString name, DIEArray &offsets) {
   Index();
   m_globals.Find(name, offsets);

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h?rev=333178&r1=333177&r2=333178&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h Thu May 24 05:12:49 2018
@@ -53,6 +53,18 @@ public:
 
 private:
   void Index();
+  void IndexUnit(DWARFUnit &unit, NameToDIE &func_basenames,
+                 NameToDIE &func_fullnames, NameToDIE &func_methods,
+                 NameToDIE &func_selectors, NameToDIE &objc_class_selectors,
+                 NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces);
+
+  static void
+  IndexUnitImpl(DWARFUnit &unit, const lldb::LanguageType cu_language,
+                const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
+                const dw_offset_t cu_offset, NameToDIE &func_basenames,
+                NameToDIE &func_fullnames, NameToDIE &func_methods,
+                NameToDIE &func_selectors, NameToDIE &objc_class_selectors,
+                NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces);
 
   /// Non-null value means we haven't built the index yet.
   DWARFDebugInfo *m_debug_info;




More information about the lldb-commits mailing list