[Lldb-commits] [lldb] 2c1bea8 - Add Debug Info Size to Symbol Status

Walter Erquinigo via lldb-commits lldb-commits at lists.llvm.org
Fri Jul 24 13:30:31 PDT 2020


Author: Yifan Shen
Date: 2020-07-24T13:30:04-07:00
New Revision: 2c1bea88a5f8334015455aae8b842fdd87f7e34a

URL: https://github.com/llvm/llvm-project/commit/2c1bea88a5f8334015455aae8b842fdd87f7e34a
DIFF: https://github.com/llvm/llvm-project/commit/2c1bea88a5f8334015455aae8b842fdd87f7e34a.diff

LOG: Add Debug Info Size to Symbol Status

If a module has debug info, the size of debug symbol will be displayed after the Symbols Loaded Message for each module in the VScode modules view.{F12335461}

Reviewed By: wallace, clayborg

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

Added: 
    

Modified: 
    lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
    lldb/test/API/tools/lldb-vscode/module/Makefile
    lldb/test/API/tools/lldb-vscode/module/TestVSCode_module.py
    lldb/tools/lldb-vscode/JSONUtils.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
index c1b33c220b4b..fa5a9c0db1eb 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
@@ -53,11 +53,12 @@ def set_function_breakpoints(self, functions, condition=None,
             breakpoint_ids.append('%i' % (breakpoint['id']))
         return breakpoint_ids
 
-    def waitUntil(self, condition):
-        while True:
-            if condition():
-                break
+    def waitUntil(self, condition_callback):
+        for _ in range(20):
+            if condition_callback():
+                return True
             time.sleep(0.5)
+        return False
 
     def verify_breakpoint_hit(self, breakpoint_ids):
         '''Wait for the process we are debugging to stop, and verify we hit

diff  --git a/lldb/test/API/tools/lldb-vscode/module/Makefile b/lldb/test/API/tools/lldb-vscode/module/Makefile
index 1fb944b13893..b30baf48b972 100644
--- a/lldb/test/API/tools/lldb-vscode/module/Makefile
+++ b/lldb/test/API/tools/lldb-vscode/module/Makefile
@@ -2,12 +2,16 @@ DYLIB_NAME := foo
 DYLIB_CXX_SOURCES := foo.cpp
 CXX_SOURCES := main.cpp
 
-all: a.out.stripped
+LD_EXTRAS := -Wl,-rpath "-Wl,$(shell pwd)"
+USE_LIBDL :=1
 
 include Makefile.rules
 
-a.out.stripped: a.out.dSYM
+all: a.out.stripped
+
+a.out.stripped:
 	strip -o a.out.stripped a.out
+
 ifneq "$(CODESIGN)" ""
 	$(CODESIGN) -fs - a.out.stripped
-endif
+endif
\ No newline at end of file

diff  --git a/lldb/test/API/tools/lldb-vscode/module/TestVSCode_module.py b/lldb/test/API/tools/lldb-vscode/module/TestVSCode_module.py
index 40c4145b38e3..a16430fccae1 100644
--- a/lldb/test/API/tools/lldb-vscode/module/TestVSCode_module.py
+++ b/lldb/test/API/tools/lldb-vscode/module/TestVSCode_module.py
@@ -10,56 +10,93 @@
 from lldbsuite.test.lldbtest import *
 from lldbsuite.test import lldbutil
 import lldbvscode_testcase
+import re
 
 class TestVSCode_module(lldbvscode_testcase.VSCodeTestCaseBase):
 
     mydir = TestBase.compute_mydir(__file__)
 
-
-    @skipIfWindows
-    @skipUnlessDarwin
-    @skipIfRemote
-    def test_modules_event(self):
+    def run_test(self, symbol_basename, expect_debug_info_size):
         program_basename = "a.out.stripped"
-        program= self.getBuildArtifact(program_basename)
+        program = self.getBuildArtifact(program_basename)
         self.build_and_launch(program)
         functions = ['foo']
         breakpoint_ids = self.set_function_breakpoints(functions)
-        self.assertEquals(len(breakpoint_ids), len(functions),
-                        'expect one breakpoint')
+        self.assertEquals(len(breakpoint_ids), len(functions), 'expect one breakpoint')
         self.continue_to_breakpoints(breakpoint_ids)
         active_modules = self.vscode.get_active_modules()
-        self.assertIn(program_basename, active_modules, '%s module is in active modules' % (program_basename))
         program_module = active_modules[program_basename]
+        self.assertIn(program_basename, active_modules, '%s module is in active modules' % (program_basename))
         self.assertIn('name', program_module, 'make sure name is in module')
         self.assertEqual(program_basename, program_module['name'])
         self.assertIn('path', program_module, 'make sure path is in module')
         self.assertEqual(program, program_module['path'])
         self.assertTrue('symbolFilePath' not in program_module, 'Make sure a.out.stripped has no debug info')
         self.assertEqual('Symbols not found.', program_module['symbolStatus'])
-        symbol_path = self.getBuildArtifact("a.out")
-        self.vscode.request_evaluate('`%s' % ('target symbols add -s "%s" "%s"' % (program, symbol_path)))
+        symbols_path = self.getBuildArtifact(symbol_basename)
+        self.vscode.request_evaluate('`%s' % ('target symbols add -s "%s" "%s"' % (program, symbols_path)))
 
         def checkSymbolsLoaded():
             active_modules = self.vscode.get_active_modules()
             program_module = active_modules[program_basename]
             return 'Symbols loaded.' == program_module['symbolStatus']
-        self.waitUntil(checkSymbolsLoaded)
 
+        def checkSymbolsLoadedWithSize():
+            active_modules = self.vscode.get_active_modules()
+            program_module = active_modules[program_basename]
+            symbolsStatus = program_module['symbolStatus']
+            symbol_regex = re.compile(r"Symbols loaded. \([0-9]+(\.[0-9]*)?[KMG]?B\)")
+            return symbol_regex.match(program_module['symbolStatus'])
+                
+        if expect_debug_info_size:
+            self.waitUntil(checkSymbolsLoadedWithSize)
+        else:
+            self.waitUntil(checkSymbolsLoaded)
         active_modules = self.vscode.get_active_modules()
         program_module = active_modules[program_basename]
         self.assertEqual(program_basename, program_module['name'])
         self.assertEqual(program, program_module['path'])
-        self.assertEqual('Symbols loaded.', program_module['symbolStatus'])
         self.assertIn('symbolFilePath', program_module)
-        self.assertEqual(symbol_path, program_module['symbolFilePath'])
+        self.assertIn(symbols_path, program_module['symbolFilePath'])
         self.assertIn('addressRange', program_module)
 
+    @skipIfWindows
+    @skipUnlessDarwin
+    @skipIfRemote  
+    #TODO: Update the Makefile so that this test runs on Linux
+    def test_module_event(self):
+        '''
+            Mac or linux.
+
+            On mac, if we load a.out as our symbol file, we will use DWARF with .o files and we will
+            have debug symbols, but we won't see any debug info size because all of the DWARF
+            sections are in .o files.
+
+            On other platforms, we expect a.out to have debug info, so we will expect a size.
+            expect_debug_info_size = platform.system() != 'Darwin'
+            return self.run_test("a.out", expect_debug_info_size)
+        '''
+        expect_debug_info_size = platform.system() != 'Darwin'
+        return self.run_test("a.out", expect_debug_info_size)
+
+    @skipIfWindows
+    @skipUnlessDarwin
+    @skipIfRemote    
+    def test_module_event_dsym(self):
+        '''
+            Darwin only test with dSYM file.
+
+            On mac, if we load a.out.dSYM as our symbol file, we will have debug symbols and we
+            will have DWARF sections added to the module, so we will expect a size.
+            return self.run_test("a.out.dSYM", True)
+        '''
+        return self.run_test("a.out.dSYM", True)
+
     @skipIfWindows
     @skipUnlessDarwin
     @skipIfRemote
     def test_compile_units(self):
-        program= self.getBuildArtifact("a.out")
+        program = self.getBuildArtifact("a.out")
         self.build_and_launch(program)
         source = "main.cpp"
         main_source_path = self.getSourcePath(source)

diff  --git a/lldb/tools/lldb-vscode/JSONUtils.cpp b/lldb/tools/lldb-vscode/JSONUtils.cpp
index 1ebaa5c37712..f6cdcf5a46cf 100644
--- a/lldb/tools/lldb-vscode/JSONUtils.cpp
+++ b/lldb/tools/lldb-vscode/JSONUtils.cpp
@@ -7,6 +7,8 @@
 //===----------------------------------------------------------------------===//
 
 #include <algorithm>
+#include <iomanip>
+#include <sstream>
 
 #include "llvm/ADT/Optional.h"
 #include "llvm/Support/FormatAdapters.h"
@@ -327,6 +329,50 @@ llvm::json::Value CreateBreakpoint(lldb::SBBreakpoint &bp,
   return llvm::json::Value(std::move(object));
 }
 
+static uint64_t GetDebugInfoSizeInSection(lldb::SBSection section) {
+  uint64_t debug_info_size = 0;
+  llvm::StringRef section_name(section.GetName());
+  if (section_name.startswith(".debug") || section_name.startswith("__debug") ||
+      section_name.startswith(".apple") || section_name.startswith("__apple"))
+    debug_info_size += section.GetFileByteSize();
+  size_t num_sub_sections = section.GetNumSubSections();
+  for (size_t i = 0; i < num_sub_sections; i++) {
+    debug_info_size +=
+        GetDebugInfoSizeInSection(section.GetSubSectionAtIndex(i));
+  }
+  return debug_info_size;
+}
+
+static uint64_t GetDebugInfoSize(lldb::SBModule module) {
+  uint64_t debug_info_size = 0;
+  size_t num_sections = module.GetNumSections();
+  for (size_t i = 0; i < num_sections; i++) {
+    debug_info_size += GetDebugInfoSizeInSection(module.GetSectionAtIndex(i));
+  }
+  return debug_info_size;
+}
+
+static std::string ConvertDebugInfoSizeToString(uint64_t debug_info) {
+  std::ostringstream oss;
+  oss << " (";
+  oss << std::fixed << std::setprecision(1);
+
+  if (debug_info < 1024) {
+    oss << debug_info << "B";
+  } else if (debug_info < 1024 * 1024) {
+    double kb = double(debug_info) / 1024.0;
+    oss << kb << "KB";
+  } else if (debug_info < 1024 * 1024 * 1024) {
+    double mb = double(debug_info) / (1024.0 * 1024.0);
+    oss << mb << "MB";
+  } else {
+    double gb = double(debug_info) / (1024.0 * 1024.0 * 1024.0);
+    oss << gb << "GB";
+    ;
+  }
+  oss << ")";
+  return oss.str();
+}
 llvm::json::Value CreateModule(lldb::SBModule &module) {
   llvm::json::Object object;
   if (!module.IsValid())
@@ -339,9 +385,15 @@ llvm::json::Value CreateModule(lldb::SBModule &module) {
   std::string module_path(module_path_arr);
   object.try_emplace("path", module_path);
   if (module.GetNumCompileUnits() > 0) {
-    object.try_emplace("symbolStatus", "Symbols loaded.");
+    std::string symbol_str = "Symbols loaded.";
+    uint64_t debug_info = GetDebugInfoSize(module);
+    if (debug_info > 0) {
+      symbol_str += ConvertDebugInfoSizeToString(debug_info);
+    }
+    object.try_emplace("symbolStatus", symbol_str);
     char symbol_path_arr[PATH_MAX];
-    module.GetSymbolFileSpec().GetPath(symbol_path_arr, sizeof(symbol_path_arr));
+    module.GetSymbolFileSpec().GetPath(symbol_path_arr,
+                                       sizeof(symbol_path_arr));
     std::string symbol_path(symbol_path_arr);
     object.try_emplace("symbolFilePath", symbol_path);
   } else {
@@ -352,8 +404,9 @@ llvm::json::Value CreateModule(lldb::SBModule &module) {
   object.try_emplace("addressRange", loaded_addr);
   std::string version_str;
   uint32_t version_nums[3];
-  uint32_t num_versions = module.GetVersion(version_nums, sizeof(version_nums)/sizeof(uint32_t));
-  for (uint32_t i=0; i<num_versions; ++i) {
+  uint32_t num_versions =
+      module.GetVersion(version_nums, sizeof(version_nums) / sizeof(uint32_t));
+  for (uint32_t i = 0; i < num_versions; ++i) {
     if (!version_str.empty())
       version_str += ".";
     version_str += std::to_string(version_nums[i]);


        


More information about the lldb-commits mailing list