werat created this revision.
Herald added subscribers: lldb-commits, arphaman.
Herald added a project: LLDB.
werat requested review of this revision.
Herald added a subscriber: JDevlieghere.

Static const/constexpr members might have only DW_TAG_member entry with a
DW_AT_const_value attribute. Since there is no corresponding DW_TAG_variable
entry, these values are currently not indexed in the DWARF index and are not
available via SBTarget::FindGlobalVariables() API.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D92223

Files:
  lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
  lldb/test/API/python_api/target/globals/Makefile
  lldb/test/API/python_api/target/globals/TestTargetGlobals.py
  lldb/test/API/python_api/target/globals/main.cpp

Index: lldb/test/API/python_api/target/globals/main.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/python_api/target/globals/main.cpp
@@ -0,0 +1,15 @@
+struct Foo {
+  static constexpr int static_constexpr_int = 1;
+  static constexpr unsigned int static_constexpr_uint =
+      static_constexpr_int + 1;
+  static const int static_const_out_out_class;
+};
+
+const int Foo::static_const_out_out_class = 3;
+
+char global_var_of_char_type = 'X';
+
+int main() {
+  // Set a break at entry to main.
+  return 0;
+}
Index: lldb/test/API/python_api/target/globals/TestTargetGlobals.py
===================================================================
--- /dev/null
+++ lldb/test/API/python_api/target/globals/TestTargetGlobals.py
@@ -0,0 +1,68 @@
+"""
+Test SBTarget::FindGlobalVariables API.
+"""
+
+from __future__ import print_function
+
+import unittest2
+import os
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TargetAPITestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+        # Find the line number to of function 'main'.
+        self.line = line_number("main.cpp", "// Set a break at entry to main.")
+
+    @add_test_categories(['pyapi'])
+    def test_find_global_variables(self):
+        """Exercise SBTarget.FindGlobalVariables() API."""
+        self.build()
+        self.setTearDownCleanup()
+
+        # Create a target by the debugger.
+        target = self.dbg.CreateTarget(self.getBuildArtifact())
+        self.assertTrue(target, VALID_TARGET)
+
+        # Create the breakpoint inside function 'main'.
+        breakpoint = target.BreakpointCreateByLocation('main.cpp', self.line)
+        self.assertTrue(breakpoint, VALID_BREAKPOINT)
+
+        # Now launch the process, and do not stop at entry point.
+        process = target.LaunchSimple(
+            None, None, self.get_process_working_directory())
+        self.assertTrue(process, PROCESS_IS_VALID)
+        # Make sure we hit our breakpoint:
+        thread = lldbutil.get_one_thread_stopped_at_breakpoint(
+            process, breakpoint)
+        self.assertTrue(thread, "Thread is valid")
+
+        def test_global_var(query, name, type_name, value):
+            value_list = target.FindGlobalVariables(query, 1)
+            self.assertEqual(value_list.GetSize(), 1)
+            var = value_list.GetValueAtIndex(0)
+            self.DebugSBValue(var)
+            self.assertTrue(var)
+            self.assertEqual(var.GetName(), name)
+            self.assertEqual(var.GetTypeName(), type_name)
+            self.assertEqual(var.GetValue(), value)
+
+        test_global_var(
+            "Foo::static_constexpr_int",
+            "Foo::static_constexpr_int", "const int", "1")
+        test_global_var(
+            "Foo::static_constexpr_uint",
+            "Foo::static_constexpr_uint", "const unsigned int", "2")
+        test_global_var(
+            "Foo::static_const_out_out_class",
+            "Foo::static_const_out_out_class", "const int", "3")
+        test_global_var(
+            "global_var_of_char_type",
+            "::global_var_of_char_type", "char", "'X'")
Index: lldb/test/API/python_api/target/globals/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/python_api/target/globals/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -2120,7 +2120,8 @@
       sc.module_sp = m_objfile_sp->GetModule();
     assert(sc.module_sp);
 
-    if (die.Tag() != DW_TAG_variable)
+    // Look only for variables and members with static const data.
+    if (die.Tag() != DW_TAG_variable && die.Tag() != DW_TAG_member)
       return true;
 
     auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU());
@@ -3103,7 +3104,7 @@
   ModuleSP module = GetObjectFile()->GetModule();
 
   if (tag != DW_TAG_variable && tag != DW_TAG_constant &&
-      (tag != DW_TAG_formal_parameter || !sc.function))
+      tag != DW_TAG_member && (tag != DW_TAG_formal_parameter || !sc.function))
     return nullptr;
 
   DWARFAttributes attributes;
@@ -3177,6 +3178,12 @@
     }
   }
 
+  if (tag == DW_TAG_member && !const_value_form.IsValid()) {
+    // Allows only members with DW_AT_const_value attribute, i.e. static const
+    // or static constexr.
+    return nullptr;
+  }
+
   // Prefer DW_AT_location over DW_AT_const_value. Both can be emitted e.g.
   // for static constexpr member variables -- DW_AT_const_value will be
   // present in the class declaration and DW_AT_location in the DIE defining
@@ -3236,10 +3243,11 @@
 
   const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die);
   const dw_tag_t parent_tag = die.GetParent().Tag();
-  bool is_static_member = (parent_tag == DW_TAG_compile_unit ||
-                           parent_tag == DW_TAG_partial_unit) &&
-                          (parent_context_die.Tag() == DW_TAG_class_type ||
-                           parent_context_die.Tag() == DW_TAG_structure_type);
+  bool is_static_member =
+      (parent_tag == DW_TAG_compile_unit || parent_tag == DW_TAG_partial_unit ||
+       tag == DW_TAG_member) &&
+      (parent_context_die.Tag() == DW_TAG_class_type ||
+       parent_context_die.Tag() == DW_TAG_structure_type);
 
   ValueType scope = eValueTypeInvalid;
 
@@ -3259,7 +3267,7 @@
     // able to generate a fully qualified name from the
     // declaration context.
     if ((parent_tag == DW_TAG_compile_unit ||
-         parent_tag == DW_TAG_partial_unit) &&
+         parent_tag == DW_TAG_partial_unit || tag == DW_TAG_member) &&
         Language::LanguageIsCPlusPlus(GetLanguage(*die.GetCU())))
       mangled =
           GetDWARFDeclContext(die).GetQualifiedNameAsConstString().GetCString();
@@ -3367,7 +3375,8 @@
       }
     } else {
       if (location_is_const_value_data &&
-          die.GetDIE()->IsGlobalOrStaticScopeVariable())
+          (die.GetDIE()->IsGlobalOrStaticScopeVariable() ||
+           tag == DW_TAG_member))
         scope = eValueTypeVariableStatic;
       else {
         scope = eValueTypeVariableLocal;
@@ -3506,6 +3515,7 @@
     } else {
       // We haven't already parsed it, lets do that now.
       if ((tag == DW_TAG_variable) || (tag == DW_TAG_constant) ||
+          (tag == DW_TAG_member) ||
           (tag == DW_TAG_formal_parameter && sc.function)) {
         if (variable_list_sp.get() == nullptr) {
           DWARFDIE sc_parent_die = GetParentSymbolContextDIE(orig_die);
Index: lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -152,6 +152,7 @@
     case DW_TAG_constant:
     case DW_TAG_enumeration_type:
     case DW_TAG_inlined_subroutine:
+    case DW_TAG_member:
     case DW_TAG_namespace:
     case DW_TAG_string_type:
     case DW_TAG_structure_type:
@@ -303,8 +304,10 @@
         set.namespaces.Insert(ConstString(name), ref);
       break;
 
+    case DW_TAG_member:
     case DW_TAG_variable:
-      if (name && has_location_or_const_value && is_global_or_static_variable) {
+      if (name && has_location_or_const_value &&
+          (is_global_or_static_variable || tag == DW_TAG_member)) {
         set.globals.Insert(ConstString(name), ref);
         // 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
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to