clayborg created this revision.
clayborg added a reviewer: yinghuitan.
Herald added a reviewer: shafik.
Herald added a project: All.
clayborg requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

A previous patch added the ability for us to tell if types were forcefully 
completed. This patch adds the ability to see which modules have forcefully 
completed types and aggregates the number of modules with forcefully completed 
types at the root level.

We add a module specific setting named "debugInfoHadIncompleteTypes" that is a 
boolean value. We also aggregate the number of modules at the root level that 
had incomplete debug info with a key named 
"totalModuleCountWithIncompleteTypes" that is a count of number of modules that 
had incomplete types.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D138638

Files:
  lldb/include/lldb/Symbol/TypeSystem.h
  lldb/include/lldb/Target/Statistics.h
  lldb/packages/Python/lldbsuite/test/lldbtest.py
  lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
  lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
  lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
  lldb/source/Target/Statistics.cpp
  lldb/test/API/commands/statistics/basic/TestStats.py
  lldb/test/API/functionalities/limit-debug-info/TestLimitDebugInfo.py

Index: lldb/test/API/functionalities/limit-debug-info/TestLimitDebugInfo.py
===================================================================
--- lldb/test/API/functionalities/limit-debug-info/TestLimitDebugInfo.py
+++ lldb/test/API/functionalities/limit-debug-info/TestLimitDebugInfo.py
@@ -30,6 +30,23 @@
         self._check_type(target, "InheritsFromOne")
         self._check_type(target, "InheritsFromTwo")
 
+        # Check that the statistics show that we had incomplete debug info.
+        stats = self.get_stats()
+        # Find the a.out module info in the stats and verify it has the
+        # "debugInfoHadIncompleteTypes" key value pair set to True
+        exe_module_found = False
+        for module in stats['modules']:
+            if module['path'].endswith('a.out'):
+                self.assertTrue(module['debugInfoHadIncompleteTypes'])
+                exe_module_found = True
+                break
+        self.assertTrue(exe_module_found)
+        # Verify that "totalModuleCountWithIncompleteTypes" at the top level
+        # is greater than zero which shows we had incomplete debug info in a
+        # module
+        self.assertGreater(stats['totalModuleCountWithIncompleteTypes'], 0)
+
+
     def _check_incomplete_frame_variable_output(self):
         # Check that the display of the "frame variable" output identifies the
         # incomplete types. Currently the expression parser will find the real
Index: lldb/test/API/commands/statistics/basic/TestStats.py
===================================================================
--- lldb/test/API/commands/statistics/basic/TestStats.py
+++ lldb/test/API/commands/statistics/basic/TestStats.py
@@ -55,30 +55,6 @@
         self.assertEqual(success_fail_dict['failures'], num_fails,
                          'make sure success count')
 
-    def get_stats(self, options=None, log_path=None):
-        """
-            Get the output of the "statistics dump" with optional extra options
-            and return the JSON as a python dictionary.
-        """
-        # If log_path is set, open the path and emit the output of the command
-        # for debugging purposes.
-        if log_path is not None:
-            f = open(log_path, 'w')
-        else:
-            f = None
-        return_obj = lldb.SBCommandReturnObject()
-        command = "statistics dump "
-        if options is not None:
-            command += options
-        if f:
-            f.write('(lldb) %s\n' % (command))
-        self.ci.HandleCommand(command, return_obj, False)
-        metrics_json = return_obj.GetOutput()
-        if f:
-            f.write(metrics_json)
-        return json.loads(metrics_json)
-
-
     def get_target_stats(self, debug_stats):
         if "targets" in debug_stats:
             return debug_stats["targets"][0]
@@ -509,7 +485,6 @@
         exe_name = 'a.out'
         exe = self.getBuildArtifact(exe_name)
         dsym = self.getBuildArtifact(exe_name + ".dSYM")
-        print("carp: dsym = '%s'" % (dsym))
         # Make sure the executable file exists after building.
         self.assertEqual(os.path.exists(exe), True)
         # Make sure the dSYM file doesn't exist after building.
@@ -563,7 +538,6 @@
         exe = self.getBuildArtifact(exe_name)
         dsym = self.getBuildArtifact(exe_name + ".dSYM")
         main_obj = self.getBuildArtifact('main.o')
-        print("carp: dsym = '%s'" % (dsym))
         # Make sure the executable file exists after building.
         self.assertEqual(os.path.exists(exe), True)
         # Make sure the dSYM file doesn't exist after building.
Index: lldb/source/Target/Statistics.cpp
===================================================================
--- lldb/source/Target/Statistics.cpp
+++ lldb/source/Target/Statistics.cpp
@@ -65,6 +65,8 @@
   module.try_emplace("debugInfoEnabled", debug_info_enabled);
   module.try_emplace("debugInfoHadVariableErrors",
                      debug_info_had_variable_errors);
+  module.try_emplace("debugInfoHadIncompleteTypes",
+                     debug_info_had_incomplete_types);
   module.try_emplace("symbolTableStripped", symtab_stripped);
   if (!symfile_path.empty())
     module.try_emplace("symbolFilePath", symfile_path);
@@ -207,6 +209,7 @@
   uint32_t num_debug_info_enabled_modules = 0;
   uint32_t num_modules_has_debug_info = 0;
   uint32_t num_modules_with_variable_errors = 0;
+  uint32_t num_modules_with_incomplete_types = 0;
   uint32_t num_stripped_modules = 0;
   for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
     Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
@@ -273,8 +276,13 @@
     module->ForEachTypeSystem([&](lldb::TypeSystemSP ts) {
       if (auto stats = ts->ReportStatistics())
         module_stat.type_system_stats.insert({ts->GetPluginName(), *stats});
+      if (ts->GetHasForcefullyCompletedTypes())
+        module_stat.debug_info_had_incomplete_types = true;
       return true;
     });
+    if (module_stat.debug_info_had_incomplete_types)
+      ++num_modules_with_incomplete_types;
+
     json_modules.emplace_back(module_stat.ToJSON());
   }
 
@@ -299,6 +307,7 @@
       {"totalModuleCount", num_modules},
       {"totalModuleCountHasDebugInfo", num_modules_has_debug_info},
       {"totalModuleCountWithVariableErrors", num_modules_with_variable_errors},
+      {"totalModuleCountWithIncompleteTypes", num_modules_with_incomplete_types},
       {"totalDebugInfoEnabled", num_debug_info_enabled_modules},
       {"totalSymbolTableStripped", num_stripped_modules},
   };
Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
===================================================================
--- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -1063,6 +1063,8 @@
   /// complete (base class, member, etc.).
   static void RequireCompleteType(CompilerType type);
 
+  bool SetDeclIsForcefullyCompleted(const clang::TagDecl *td);
+
 private:
   /// Returns the PrintingPolicy used when generating the internal type names.
   /// These type names are mostly used for the formatter selection.
Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
===================================================================
--- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -9859,7 +9859,7 @@
   const clang::TagDecl *td = ClangUtil::GetAsTagDecl(type);
   auto ts = type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>();
   if (ts)
-    ts->GetMetadata(td)->SetIsForcefullyCompleted();
+    ts->SetDeclIsForcefullyCompleted(td);
 }
 
 namespace {
@@ -10062,3 +10062,14 @@
   }
   return false;
 }
+
+bool TypeSystemClang::SetDeclIsForcefullyCompleted(const clang::TagDecl *td) {
+  if (td == nullptr)
+    return false;
+  ClangASTMetadata *metadata = GetMetadata(td);
+  if (metadata == nullptr)
+    return false;
+  m_has_forcefully_completed_types = true;
+  metadata->SetIsForcefullyCompleted();
+  return true;
+}
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -226,7 +226,7 @@
   auto ts_sp = type.GetTypeSystem();
   auto ts = ts_sp.dyn_cast_or_null<TypeSystemClang>();
   if (ts)
-    ts->GetMetadata(td)->SetIsForcefullyCompleted();
+    ts->SetDeclIsForcefullyCompleted(td);
 }
 
 /// This function serves a similar purpose as RequireCompleteType above, but it
Index: lldb/packages/Python/lldbsuite/test/lldbtest.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/lldbtest.py
+++ lldb/packages/Python/lldbsuite/test/lldbtest.py
@@ -37,6 +37,7 @@
 import gc
 import glob
 import io
+import json
 import os.path
 import re
 import shutil
@@ -1648,6 +1649,19 @@
         err = platform.Run(shell_command)
         return (err, shell_command.GetStatus(), shell_command.GetOutput())
 
+    def get_stats(self, options=None):
+        """
+            Get the output of the "statistics dump" with optional extra options
+            and return the JSON as a python dictionary.
+        """
+        return_obj = lldb.SBCommandReturnObject()
+        command = "statistics dump "
+        if options is not None:
+            command += options
+        self.ci.HandleCommand(command, return_obj, False)
+        metrics_json = return_obj.GetOutput()
+        return json.loads(metrics_json)
+
 # Metaclass for TestBase to change the list of test metods when a new TestCase is loaded.
 # We change the test methods to create a new test method for each test for each debug info we are
 # testing. The name of the new test method will be '<original-name>_<debug-info>' and with adding
@@ -2489,7 +2503,7 @@
             error = obj.GetError()
             self.fail(self._formatMessage(msg,
                 "'{}' is not success".format(error)))
-            
+
     """Assert two states are equal"""
     def assertState(self, first, second, msg=None):
         if first != second:
Index: lldb/include/lldb/Target/Statistics.h
===================================================================
--- lldb/include/lldb/Target/Statistics.h
+++ lldb/include/lldb/Target/Statistics.h
@@ -121,6 +121,7 @@
   bool debug_info_enabled = true;
   bool symtab_stripped = false;
   bool debug_info_had_variable_errors = false;
+  bool debug_info_had_incomplete_types = false;
 };
 
 struct ConstStringStats {
Index: lldb/include/lldb/Symbol/TypeSystem.h
===================================================================
--- lldb/include/lldb/Symbol/TypeSystem.h
+++ lldb/include/lldb/Symbol/TypeSystem.h
@@ -90,7 +90,7 @@
   /// Free up any resources associated with this TypeSystem.  Done before
   /// removing all the TypeSystems from the TypeSystemMap.
   virtual void Finalize() {}
- 
+
   virtual DWARFASTParser *GetDWARFParser() { return nullptr; }
   virtual PDBASTParser *GetPDBParser() { return nullptr; }
   virtual npdb::PdbAstBuilder *GetNativePDBParser() { return nullptr; }
@@ -516,8 +516,13 @@
 
   virtual llvm::Optional<llvm::json::Value> ReportStatistics();
 
+  bool GetHasForcefullyCompletedTypes() const {
+    return m_has_forcefully_completed_types;
+  }
 protected:
   SymbolFile *m_sym_file = nullptr;
+  /// Used for reporting statistics.
+  bool m_has_forcefully_completed_types = false;
 };
 
 class TypeSystemMap {
@@ -541,6 +546,9 @@
   GetTypeSystemForLanguage(lldb::LanguageType language, Target *target,
                            bool can_create);
 
+  /// Check all type systems in the map to see if any have forcefully completed
+  /// types;
+  bool GetHasForcefullyCompletedTypes() const;
 protected:
   typedef llvm::DenseMap<uint16_t, lldb::TypeSystemSP> collection;
   mutable std::mutex m_mutex; ///< A mutex to keep this object happy in
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
  • [Lldb-commits] [PATCH] D1386... Greg Clayton via Phabricator via lldb-commits

Reply via email to