https://github.com/zhyty updated https://github.com/llvm/llvm-project/pull/71000
>From c6900333c54d1c3f5dd3e6a88f0627b65ff0efca Mon Sep 17 00:00:00 2001 From: Tom Yang <toy...@fb.com> Date: Wed, 1 Nov 2023 00:53:19 -0700 Subject: [PATCH 1/3] [lldb] Add --errors-only argument separate-debug-info list --- lldb/include/lldb/Symbol/SymbolFile.h | 6 +++++- lldb/source/Commands/CommandObjectTarget.cpp | 20 +++++++++++++------ lldb/source/Commands/Options.td | 4 +++- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 6 ++++-- .../SymbolFile/DWARF/SymbolFileDWARF.h | 3 ++- .../DWARF/SymbolFileDWARFDebugMap.cpp | 5 +++-- .../DWARF/SymbolFileDWARFDebugMap.h | 3 ++- .../dwo/TestDumpDwo.py | 20 ++++++++++++------- .../oso/TestDumpOso.py | 18 ++++++++++++----- 9 files changed, 59 insertions(+), 26 deletions(-) diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index b40d0f03b6e0130..9fc90ad49361be8 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -445,7 +445,11 @@ class SymbolFile : public PluginInterface { /// contains the keys "type", "symfile", and "separate-debug-info-files". /// "type" can be used to assume the structure of each object in /// "separate-debug-info-files". - virtual bool GetSeparateDebugInfo(StructuredData::Dictionary &d) { + /// \param errors_only + /// If true, then only return separate debug info files that encountered + /// errors during loading. + virtual bool GetSeparateDebugInfo(StructuredData::Dictionary &d, + bool errors_only) { return false; }; diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index c84a6550d6c75cc..ca8484cc79d4054 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -1452,11 +1452,11 @@ static bool DumpModuleSymbolFile(Stream &strm, Module *module) { } static bool GetSeparateDebugInfoList(StructuredData::Array &list, - Module *module) { + Module *module, bool errors_only) { if (module) { if (SymbolFile *symbol_file = module->GetSymbolFile(/*can_create=*/true)) { StructuredData::Dictionary d; - if (symbol_file->GetSeparateDebugInfo(d)) { + if (symbol_file->GetSeparateDebugInfo(d, errors_only)) { list.AddItem( std::make_shared<StructuredData::Dictionary>(std::move(d))); return true; @@ -2561,7 +2561,10 @@ class CommandObjectTargetModulesDumpSeparateDebugInfoFiles m_json.SetCurrentValue(true); m_json.SetOptionWasSet(); break; - + case 'e': + m_errors_only.SetCurrentValue(true); + m_errors_only.SetOptionWasSet(); + break; default: llvm_unreachable("Unimplemented option"); } @@ -2570,6 +2573,7 @@ class CommandObjectTargetModulesDumpSeparateDebugInfoFiles void OptionParsingStarting(ExecutionContext *execution_context) override { m_json.Clear(); + m_errors_only.Clear(); } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { @@ -2577,6 +2581,7 @@ class CommandObjectTargetModulesDumpSeparateDebugInfoFiles } OptionValueBoolean m_json = false; + OptionValueBoolean m_errors_only = false; }; protected: @@ -2607,7 +2612,8 @@ class CommandObjectTargetModulesDumpSeparateDebugInfoFiles break; if (GetSeparateDebugInfoList(separate_debug_info_lists_by_module, - module_sp.get())) + module_sp.get(), + bool(m_options.m_errors_only))) num_dumped++; } } else { @@ -2628,7 +2634,7 @@ class CommandObjectTargetModulesDumpSeparateDebugInfoFiles break; Module *module = module_list.GetModulePointerAtIndex(i); if (GetSeparateDebugInfoList(separate_debug_info_lists_by_module, - module)) + module, bool(m_options.m_errors_only))) num_dumped++; } } else @@ -2639,11 +2645,13 @@ class CommandObjectTargetModulesDumpSeparateDebugInfoFiles if (num_dumped > 0) { Stream &strm = result.GetOutputStream(); + // Display the debug info files in some format. if (m_options.m_json) { + // JSON format separate_debug_info_lists_by_module.Dump(strm, /*pretty_print=*/true); } else { - // List the debug info files in human readable form. + // Human-readable table format separate_debug_info_lists_by_module.ForEach( [&result, &strm](StructuredData::Object *obj) { if (!obj) { diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index 078b23e09e4fa83..542c78be5a12dad 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -10,7 +10,9 @@ let Command = "target modules dump symtab" in { let Command = "target modules dump separate debug info" in { def tm_json : Option<"json", "j">, Group<1>, - Desc<"Output the details in JSON format.">; + Desc<"Output the details in JSON format.">; + def tm_errors_only : Option<"errors-only", "e">, Group<1>, + Desc<"Filter to show only debug info files with errors.">; } let Command = "help" in { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index ee7164d2f050ed1..97c7dd933201d98 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -4243,7 +4243,8 @@ void SymbolFileDWARF::DumpClangAST(Stream &s) { clang->Dump(s.AsRawOstream()); } -bool SymbolFileDWARF::GetSeparateDebugInfo(StructuredData::Dictionary &d) { +bool SymbolFileDWARF::GetSeparateDebugInfo(StructuredData::Dictionary &d, + bool errors_only) { StructuredData::Array separate_debug_info_files; DWARFDebugInfo &info = DebugInfo(); const size_t num_cus = info.GetNumUnits(); @@ -4296,7 +4297,8 @@ bool SymbolFileDWARF::GetSeparateDebugInfo(StructuredData::Dictionary &d) { dwarf_cu->GetDwoError().AsCString("unknown")); } dwo_data->AddBooleanItem("loaded", dwo_symfile != nullptr); - separate_debug_info_files.AddItem(dwo_data); + if (!errors_only || (errors_only && dwo_data->HasKey("error"))) + separate_debug_info_files.AddItem(dwo_data); } d.AddStringItem("type", "dwo"); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 069a2050f0eaadc..28430ccb87924b5 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -268,7 +268,8 @@ class SymbolFileDWARF : public SymbolFileCommon { void DumpClangAST(Stream &s) override; /// List separate dwo files. - bool GetSeparateDebugInfo(StructuredData::Dictionary &d) override; + bool GetSeparateDebugInfo(StructuredData::Dictionary &d, + bool errors_only) override; DWARFContext &GetDWARFContext() { return m_context; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 2135ed784252f41..3eecd2005a1b2ef 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1278,7 +1278,7 @@ void SymbolFileDWARFDebugMap::DumpClangAST(Stream &s) { } bool SymbolFileDWARFDebugMap::GetSeparateDebugInfo( - lldb_private::StructuredData::Dictionary &d) { + lldb_private::StructuredData::Dictionary &d, bool errors_only) { StructuredData::Array separate_debug_info_files; const uint32_t cu_count = GetNumCompileUnits(); for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) { @@ -1302,7 +1302,8 @@ bool SymbolFileDWARFDebugMap::GetSeparateDebugInfo( oso_data->AddStringItem("error", info.oso_load_error.AsCString()); } oso_data->AddBooleanItem("loaded", loaded_successfully); - separate_debug_info_files.AddItem(oso_data); + if (!errors_only || (errors_only && oso_data->HasKey("error"))) + separate_debug_info_files.AddItem(oso_data); } d.AddStringItem("type", "oso"); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index a337a76b7a69a66..13f94f6d93e9168 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -136,7 +136,8 @@ class SymbolFileDWARFDebugMap : public SymbolFileCommon { void DumpClangAST(Stream &s) override; /// List separate oso files. - bool GetSeparateDebugInfo(StructuredData::Dictionary &d) override; + bool GetSeparateDebugInfo(StructuredData::Dictionary &d, + bool errors_only) override; // PluginInterface protocol llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } diff --git a/lldb/test/API/commands/target/dump-separate-debug-info/dwo/TestDumpDwo.py b/lldb/test/API/commands/target/dump-separate-debug-info/dwo/TestDumpDwo.py index 3d9d8e8e77adbf9..163f5a112367693 100644 --- a/lldb/test/API/commands/target/dump-separate-debug-info/dwo/TestDumpDwo.py +++ b/lldb/test/API/commands/target/dump-separate-debug-info/dwo/TestDumpDwo.py @@ -12,7 +12,7 @@ class TestDumpDWO(lldbtest.TestBase): NO_DEBUG_INFO_TESTCASE = True - def get_dwos_from_json(self): + def get_dwos_from_json_output(self): """Returns a dictionary of `symfile` -> {`dwo_name` -> dwo_info object}.""" result = {} output = json.loads(self.res.GetOutput()) @@ -42,7 +42,7 @@ def test_dwos_loaded_json_output(self): self.runCmd("target modules dump separate-debug-info --json") # Check the output - output = self.get_dwos_from_json() + output = self.get_dwos_from_json_output() self.assertTrue(output[exe]["main.dwo"]["loaded"]) self.assertTrue(output[exe]["foo.dwo"]["loaded"]) @@ -55,9 +55,8 @@ def test_dwos_not_loaded_json_output(self): main_dwo = self.getBuildArtifact("main.dwo") foo_dwo = self.getBuildArtifact("foo.dwo") - # REMOVE the dwo files + # REMOVE one of the dwo files os.unlink(main_dwo) - os.unlink(foo_dwo) target = self.dbg.CreateTarget(exe) self.assertTrue(target, lldbtest.VALID_TARGET) @@ -65,11 +64,18 @@ def test_dwos_not_loaded_json_output(self): self.runCmd("target modules dump separate-debug-info --json") # Check the output - output = self.get_dwos_from_json() + output = self.get_dwos_from_json_output() + self.assertFalse(output[exe]["main.dwo"]["loaded"]) + self.assertIn("error", output[exe]["main.dwo"]) + self.assertTrue(output[exe]["foo.dwo"]["loaded"]) + self.assertNotIn("error", output[exe]["foo.dwo"]) + + # Check with --errors-only + self.runCmd("target modules dump separate-debug-info --json --errors-only") + output = self.get_dwos_from_json_output() self.assertFalse(output[exe]["main.dwo"]["loaded"]) - self.assertFalse(output[exe]["foo.dwo"]["loaded"]) self.assertIn("error", output[exe]["main.dwo"]) - self.assertIn("error", output[exe]["foo.dwo"]) + self.assertNotIn("foo.dwo", output[exe]) @skipIfRemote @skipIfDarwin diff --git a/lldb/test/API/commands/target/dump-separate-debug-info/oso/TestDumpOso.py b/lldb/test/API/commands/target/dump-separate-debug-info/oso/TestDumpOso.py index 05beed0eacfb00b..b69938454659bda 100644 --- a/lldb/test/API/commands/target/dump-separate-debug-info/oso/TestDumpOso.py +++ b/lldb/test/API/commands/target/dump-separate-debug-info/oso/TestDumpOso.py @@ -12,7 +12,7 @@ class TestDumpOso(lldbtest.TestBase): NO_DEBUG_INFO_TESTCASE = True - def get_osos_from_json(self): + def get_osos_from_json_output(self): """Returns a dictionary of `symfile` -> {`OSO_PATH` -> oso_info object}.""" result = {} output = json.loads(self.res.GetOutput()) @@ -41,7 +41,7 @@ def test_shows_oso_loaded_json_output(self): self.runCmd("target modules dump separate-debug-info --json") # Check the output - osos = self.get_osos_from_json() + osos = self.get_osos_from_json_output() self.assertTrue(osos[exe][main_o]["loaded"]) self.assertTrue(osos[exe][foo_o]["loaded"]) @@ -55,7 +55,6 @@ def test_shows_oso_not_loaded_json_output(self): # REMOVE the o files os.unlink(main_o) - os.unlink(foo_o) target = self.dbg.CreateTarget(exe) self.assertTrue(target, lldbtest.VALID_TARGET) @@ -63,9 +62,18 @@ def test_shows_oso_not_loaded_json_output(self): self.runCmd("target modules dump separate-debug-info --json") # Check the output - osos = self.get_osos_from_json() + osos = self.get_osos_from_json_output() self.assertFalse(osos[exe][main_o]["loaded"]) - self.assertFalse(osos[exe][foo_o]["loaded"]) + self.assertIn("error", osos[exe][main_o]) + self.assertTrue(osos[exe][foo_o]["loaded"]) + self.assertNotIn("error", osos[exe][foo_o]) + + # Check with --errors-only + self.runCmd("target modules dump separate-debug-info --json --errors-only") + output = self.get_osos_from_json_output() + self.assertFalse(output[exe][main_o]["loaded"]) + self.assertIn("error", output[exe][main_o]) + self.assertNotIn(foo_o, output[exe]) @skipIfRemote @skipUnlessDarwin >From 21ccefeac228f4a7312e4becc36fd275b906b028 Mon Sep 17 00:00:00 2001 From: Tom Yang <toy...@fb.com> Date: Wed, 1 Nov 2023 23:41:07 -0700 Subject: [PATCH 2/3] simplify errors_only if condition --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 2 +- .../source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 97c7dd933201d98..63b2c3a0c883097 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -4297,7 +4297,7 @@ bool SymbolFileDWARF::GetSeparateDebugInfo(StructuredData::Dictionary &d, dwarf_cu->GetDwoError().AsCString("unknown")); } dwo_data->AddBooleanItem("loaded", dwo_symfile != nullptr); - if (!errors_only || (errors_only && dwo_data->HasKey("error"))) + if (!errors_only || dwo_data->HasKey("error")) separate_debug_info_files.AddItem(dwo_data); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 3eecd2005a1b2ef..263ada9cbb87f16 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1302,7 +1302,7 @@ bool SymbolFileDWARFDebugMap::GetSeparateDebugInfo( oso_data->AddStringItem("error", info.oso_load_error.AsCString()); } oso_data->AddBooleanItem("loaded", loaded_successfully); - if (!errors_only || (errors_only && oso_data->HasKey("error"))) + if (!errors_only || oso_data->HasKey("error")) separate_debug_info_files.AddItem(oso_data); } >From 386ed7bac78a1780ec6fec040b327f0a65d6d792 Mon Sep 17 00:00:00 2001 From: Tom Yang <toy...@fb.com> Date: Thu, 2 Nov 2023 11:05:48 -0700 Subject: [PATCH 3/3] clarify `errors_only` param --- lldb/include/lldb/Symbol/SymbolFile.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index 9fc90ad49361be8..a546b05bfd31811 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -447,7 +447,8 @@ class SymbolFile : public PluginInterface { /// "separate-debug-info-files". /// \param errors_only /// If true, then only return separate debug info files that encountered - /// errors during loading. + /// errors during loading. If false, then return all expected separate + /// debug info files, regardless of whether they were successfully loaded. virtual bool GetSeparateDebugInfo(StructuredData::Dictionary &d, bool errors_only) { return false; _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits