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