llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Jacob Lalonde (Jlalond)

<details>
<summary>Changes</summary>

Today we can run `target modules dump separate-debug-info --json` to get a json 
blob of all the separate debug info, but it has a few shortcomings when 
developing some scripting against it. Namely, the caller has to know the 
structure of the JSON per architecture that will be returned.

I've been working on a Minidump packing utility where we enumerate symbols and 
source and put them in a package so we can debug with symbols portably, and 
it's been difficult to maintain multiple architectures due to the above 
shortcomings. To address this for myself, I've exposed a simple iterator for 
the SBModule to get all the separate-debug-info as list of filespecs with no 
need for the caller to have context on what kind of data it is.

I also extened the swig interfaces to make writing my test easier and as a nice 
to have.

---
Full diff: https://github.com/llvm/llvm-project/pull/144119.diff


15 Files Affected:

- (modified) lldb/bindings/interface/SBFileSpecListExtensions.i (+4) 
- (modified) lldb/include/lldb/API/SBModule.h (+8) 
- (modified) lldb/include/lldb/Core/Module.h (+2) 
- (modified) lldb/include/lldb/Symbol/SymbolFile.h (+14) 
- (modified) lldb/include/lldb/Symbol/SymbolFileOnDemand.h (+4) 
- (modified) lldb/source/API/SBModule.cpp (+14) 
- (modified) lldb/source/Core/Module.cpp (+9) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (+26) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h (+2) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp 
(+15) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h 
(+2) 
- (modified) lldb/source/Symbol/SymbolFile.cpp (-1) 
- (added) lldb/test/API/python_api/sbmodule/SeperateDebugInfo/Makefile (+3) 
- (added) 
lldb/test/API/python_api/sbmodule/SeperateDebugInfo/TestSBModuleSeparateDebugInfo.py
 (+44) 
- (added) lldb/test/API/python_api/sbmodule/SeperateDebugInfo/main.cpp (+5) 


``````````diff
diff --git a/lldb/bindings/interface/SBFileSpecListExtensions.i 
b/lldb/bindings/interface/SBFileSpecListExtensions.i
index 1e7b897a08d95..f8504e10d4063 100644
--- a/lldb/bindings/interface/SBFileSpecListExtensions.i
+++ b/lldb/bindings/interface/SBFileSpecListExtensions.i
@@ -10,6 +10,10 @@ STRING_EXTENSION_OUTSIDE(SBFileSpecList)
     def __iter__(self):
       '''Iterate over all FileSpecs in a lldb.SBFileSpecList object.'''
       return lldb_iter(self, 'GetSize', 'GetFileSpecAtIndex')
+
+    def __getitem__(self, index):
+      '''Get an lldb.SBFileSpec at a given index, an invalid SBFileSpec will 
be returned if the index is invalid.'''
+      return self.GetFileSpecAtIndex(index)
     %}
 #endif
 }
diff --git a/lldb/include/lldb/API/SBModule.h b/lldb/include/lldb/API/SBModule.h
index 85332066ee687..4091fe1c3cb9e 100644
--- a/lldb/include/lldb/API/SBModule.h
+++ b/lldb/include/lldb/API/SBModule.h
@@ -287,6 +287,14 @@ class LLDB_API SBModule {
   ///     A const reference to the file specification object.
   lldb::SBFileSpec GetSymbolFileSpec() const;
 
+  /// Get a list of filespecs associated with all the separate symbol files
+  /// associated with this module.
+  ///
+  /// \return
+  ///     A list of filespecs associated with all the separate symbol files
+  ///     associated with this module.
+  lldb::SBFileSpecList GetSeparateDebugInfoFiles();
+
   lldb::SBAddress GetObjectFileHeaderAddress() const;
   lldb::SBAddress GetObjectFileEntryPointAddress() const;
 
diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h
index 8bb55c95773bc..9a7d4b2c73205 100644
--- a/lldb/include/lldb/Core/Module.h
+++ b/lldb/include/lldb/Core/Module.h
@@ -482,6 +482,8 @@ class Module : public std::enable_shared_from_this<Module>,
 
   const FileSpec &GetSymbolFileFileSpec() const { return m_symfile_spec; }
 
+  const llvm::StringMap<FileSpec> GetSeparateDebugInfoFiles();
+
   void PreloadSymbols();
 
   void SetSymbolFileFileSpec(const FileSpec &file);
diff --git a/lldb/include/lldb/Symbol/SymbolFile.h 
b/lldb/include/lldb/Symbol/SymbolFile.h
index 75c7f230ddf3d..1020f1a21541a 100644
--- a/lldb/include/lldb/Symbol/SymbolFile.h
+++ b/lldb/include/lldb/Symbol/SymbolFile.h
@@ -27,6 +27,7 @@
 #include "lldb/lldb-private.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringMap.h"
 #include "llvm/Support/Errc.h"
 
 #include <mutex>
@@ -472,6 +473,19 @@ class SymbolFile : public PluginInterface {
     return false;
   };
 
+  /// Return a map of separate debug info files that are loaded.
+  ///
+  /// Unlike GetSeparateDebugInfo(), this function will only return the list of
+  /// files, if there are errors they are simply ignored. This function will
+  /// always return a valid list, even if it is empty.
+  ///
+  /// \return
+  ///     A unique map of all the filespecs, dwos in a dwps would be joined to
+  ///     the dwp path for example.
+  virtual llvm::StringMap<lldb_private::FileSpec> GetSeparateDebugInfoFiles() {
+    return {};
+  }
+
   virtual lldb::TypeSP
   MakeType(lldb::user_id_t uid, ConstString name,
            std::optional<uint64_t> byte_size, SymbolContextScope *context,
diff --git a/lldb/include/lldb/Symbol/SymbolFileOnDemand.h 
b/lldb/include/lldb/Symbol/SymbolFileOnDemand.h
index ba4a7f09afeaa..7e08414725d63 100644
--- a/lldb/include/lldb/Symbol/SymbolFileOnDemand.h
+++ b/lldb/include/lldb/Symbol/SymbolFileOnDemand.h
@@ -223,6 +223,10 @@ class SymbolFileOnDemand : public lldb_private::SymbolFile 
{
     return m_sym_file_impl->SetDebugInfoHadFrameVariableErrors();
   }
 
+  llvm::StringMap<lldb_private::FileSpec> GetSeparateDebugInfoFiles() override 
{
+    return m_sym_file_impl->GetSeparateDebugInfoFiles();
+  }
+
   bool GetSeparateDebugInfo(StructuredData::Dictionary &d,
                             bool errors_only) override {
     return m_sym_file_impl->GetSeparateDebugInfo(d, errors_only);
diff --git a/lldb/source/API/SBModule.cpp b/lldb/source/API/SBModule.cpp
index 985107ec68efd..63deb1446f713 100644
--- a/lldb/source/API/SBModule.cpp
+++ b/lldb/source/API/SBModule.cpp
@@ -633,6 +633,20 @@ lldb::SBFileSpec SBModule::GetSymbolFileSpec() const {
   return sb_file_spec;
 }
 
+lldb::SBFileSpecList SBModule::GetSeparateDebugInfoFiles() {
+  lldb::SBFileSpecList sb_filespeclist;
+  ModuleSP module_sp(GetSP());
+  if (module_sp) {
+    llvm::StringMap<lldb_private::FileSpec> debug_info_files =
+        module_sp->GetSeparateDebugInfoFiles();
+    for (auto &&[_, debug_info_file] : debug_info_files) {
+      sb_filespeclist.Append(debug_info_file);
+    }
+  }
+
+  return sb_filespeclist;
+}
+
 lldb::SBAddress SBModule::GetObjectFileHeaderAddress() const {
   LLDB_INSTRUMENT_VA(this);
 
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index 90997dada3666..5fd21dca8fbf3 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -1644,3 +1644,12 @@ DataFileCache *Module::GetIndexCache() {
                             .GetPath());
   return g_data_file_cache;
 }
+
+const llvm::StringMap<lldb_private::FileSpec>
+Module::GetSeparateDebugInfoFiles() {
+  SymbolFile *symfile = GetSymbolFile(false);
+  if (!symfile)
+    return {};
+
+  return symfile->GetSeparateDebugInfoFiles();
+}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 71f204c03a42a..34bf05690e9e8 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -4138,6 +4138,32 @@ void SymbolFileDWARF::DumpClangAST(Stream &s, 
llvm::StringRef filter) {
   clang->Dump(s.AsRawOstream(), filter);
 }
 
+llvm::StringMap<lldb_private::FileSpec>
+SymbolFileDWARF::GetSeparateDebugInfoFiles() {
+  DWARFDebugInfo &info = DebugInfo();
+  const size_t num_cus = info.GetNumUnits();
+  llvm::StringMap<lldb_private::FileSpec> symbolfile_map;
+  for (uint32_t cu_idx = 0; cu_idx < num_cus; ++cu_idx) {
+    DWARFUnit *unit = info.GetUnitAtIndex(cu_idx);
+    DWARFCompileUnit *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(unit);
+    if (dwarf_cu == nullptr)
+      continue;
+
+    if (!dwarf_cu->GetDWOId().has_value())
+      continue;
+
+    SymbolFile *dwo_symfile = dwarf_cu->GetDwoSymbolFile();
+    if (!dwo_symfile)
+      continue;
+
+    lldb_private::FileSpec symfile_spec =
+        dwo_symfile->GetObjectFile()->GetFileSpec();
+    if (symbolfile_map.find(symfile_spec.GetPath()) == symbolfile_map.end())
+      symbolfile_map[symfile_spec.GetPath()] = symfile_spec;
+  }
+  return symbolfile_map;
+}
+
 bool SymbolFileDWARF::GetSeparateDebugInfo(StructuredData::Dictionary &d,
                                            bool errors_only) {
   StructuredData::Array separate_debug_info_files;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index d2d30d7decb16..efc78cbb177e6 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -278,6 +278,8 @@ class SymbolFileDWARF : public SymbolFileCommon {
 
   void DumpClangAST(Stream &s, llvm::StringRef filter) override;
 
+  llvm::StringMap<lldb_private::FileSpec> GetSeparateDebugInfoFiles() override;
+
   /// List separate dwo files.
   bool GetSeparateDebugInfo(StructuredData::Dictionary &d,
                             bool errors_only) override;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index f3a940b2ee396..c66d3cd548707 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -1277,6 +1277,21 @@ void SymbolFileDWARFDebugMap::DumpClangAST(Stream &s, 
llvm::StringRef filter) {
   });
 }
 
+llvm::StringMap<lldb_private::FileSpec>
+SymbolFileDWARFDebugMap::GetSeparateDebugInfoFiles() {
+  const uint32_t cu_count = GetNumCompileUnits();
+  llvm::StringMap<lldb_private::FileSpec> cu_map;
+  for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) {
+    const auto &info = m_compile_unit_infos[cu_idx];
+    if (info.so_file.GetPath().empty())
+      continue;
+
+    if (cu_map.find(info.oso_path) == cu_map.end())
+      cu_map[info.oso_path] = lldb_private::FileSpec(info.oso_path);
+  }
+  return cu_map;
+}
+
 bool SymbolFileDWARFDebugMap::GetSeparateDebugInfo(
     lldb_private::StructuredData::Dictionary &d, bool errors_only) {
   StructuredData::Array separate_debug_info_files;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h 
b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index 35cbdbbb1692f..f46a17dd469bd 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -131,6 +131,8 @@ class SymbolFileDWARFDebugMap : public SymbolFileCommon {
 
   void DumpClangAST(Stream &s, llvm::StringRef filter) override;
 
+  llvm::StringMap<lldb_private::FileSpec> GetSeparateDebugInfoFiles() override;
+
   /// List separate oso files.
   bool GetSeparateDebugInfo(StructuredData::Dictionary &d,
                             bool errors_only) override;
diff --git a/lldb/source/Symbol/SymbolFile.cpp 
b/lldb/source/Symbol/SymbolFile.cpp
index 870d778dca740..9cc2ea7df3fbc 100644
--- a/lldb/source/Symbol/SymbolFile.cpp
+++ b/lldb/source/Symbol/SymbolFile.cpp
@@ -20,7 +20,6 @@
 #include "lldb/Utility/StreamString.h"
 #include "lldb/Utility/StructuredData.h"
 #include "lldb/lldb-private.h"
-
 #include <future>
 
 using namespace lldb_private;
diff --git a/lldb/test/API/python_api/sbmodule/SeperateDebugInfo/Makefile 
b/lldb/test/API/python_api/sbmodule/SeperateDebugInfo/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/python_api/sbmodule/SeperateDebugInfo/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git 
a/lldb/test/API/python_api/sbmodule/SeperateDebugInfo/TestSBModuleSeparateDebugInfo.py
 
b/lldb/test/API/python_api/sbmodule/SeperateDebugInfo/TestSBModuleSeparateDebugInfo.py
new file mode 100644
index 0000000000000..011928cd0f330
--- /dev/null
+++ 
b/lldb/test/API/python_api/sbmodule/SeperateDebugInfo/TestSBModuleSeparateDebugInfo.py
@@ -0,0 +1,44 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+import os, signal, subprocess
+
+from lldbsuite.test import lldbutil
+
+
+class SBModuleSeparateDebugInfoCase(TestBase):
+    def setUp(self):
+        TestBase.setUp(self)
+        self.background_pid = None
+
+    def tearDown(self):
+        TestBase.tearDown(self)
+        if self.background_pid:
+            os.kill(self.background_pid, signal.SIGKILL)
+
+    @skipIf(debug_info=no_match("dwo"))
+    def test_get_separate_debug_info_files_dwo(self):
+        """Test the SBModule::GetSeparateDebugInfoFiles"""
+        self.build()
+        exe = self.getBuildArtifact("a.out")
+        target = self.dbg.CreateTarget(exe)
+
+        # Target should have a DWO
+        main_module = target.GetModuleAtIndex(0)
+        file_specs = main_module.GetSeparateDebugInfoFiles()
+        self.assertEqual(len(file_specs), 1)
+        self.assertTrue(file_specs[0].GetFilename().endswith(".dwo"))
+
+    @skipUnlessDarwin
+    @skipIf(debug_info=no_match("dwarf"))
+    def test_get_separate_debug_info_files_darwin_dwarf(self):
+        """Test the SBModule::GetSeparateDebugInfoFiles"""
+        self.build()
+        exe = self.getBuildArtifact("a.out")
+        target = self.dbg.CreateTarget(exe)
+
+        # Target should have a DWO
+        main_module = target.GetModuleAtIndex(0)
+        file_specs = main_module.GetSeparateDebugInfoFiles()
+        self.assertEqual(len(file_specs), 1)
+        self.assertTrue(file_specs[0].GetFilename().endswith(".o"))
diff --git a/lldb/test/API/python_api/sbmodule/SeperateDebugInfo/main.cpp 
b/lldb/test/API/python_api/sbmodule/SeperateDebugInfo/main.cpp
new file mode 100644
index 0000000000000..f54a8087e1dc4
--- /dev/null
+++ b/lldb/test/API/python_api/sbmodule/SeperateDebugInfo/main.cpp
@@ -0,0 +1,5 @@
+int main() {
+  int x = 40;
+  x += 2; // break here
+  return x;
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/144119
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to