[Lldb-commits] [lldb] [lldb][split-dwarf] Add --errors-only argument separate-debug-info list (PR #71000)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Nov 1 16:06:49 PDT 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Tom Yang (zhyty)
<details>
<summary>Changes</summary>
Often, we only care about the split-dwarf files that have failed to load. This can be useful when diagnosing binaries with many separate debug info files where only some have errors.
```
(lldb) help image dump separate-debug-info
List the separate debug info symbol files for one or more target modules.
Syntax: target modules dump separate-debug-info <cmd-options> [<filename> [<filename> [...]]]
Command Options Usage:
target modules dump separate-debug-info [-ej] [<filename> [<filename> [...]]]
-e ( --errors-only )
Filter to show only debug info files with errors.
-j ( --json )
Output the details in JSON format.
This command takes options and free-form arguments. If your arguments
resemble option specifiers (i.e., they start with a - or --), you must use
' -- ' between the end of the command options and the beginning of the
arguments.
'image' is an abbreviation for 'target modules'
```
I updated the following tests
```
# on Linux
bin/lldb-dotest -p TestDumpDwo
# on Mac
bin/lldb-dotest -p TestDumpOso
```
This change applies to both the table and JSON outputs.
---
Full diff: https://github.com/llvm/llvm-project/pull/71000.diff
9 Files Affected:
- (modified) lldb/include/lldb/Symbol/SymbolFile.h (+5-1)
- (modified) lldb/source/Commands/CommandObjectTarget.cpp (+14-6)
- (modified) lldb/source/Commands/Options.td (+3-1)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (+4-2)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h (+2-1)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp (+3-2)
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h (+2-1)
- (modified) lldb/test/API/commands/target/dump-separate-debug-info/dwo/TestDumpDwo.py (+13-7)
- (modified) lldb/test/API/commands/target/dump-separate-debug-info/oso/TestDumpOso.py (+13-5)
``````````diff
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
``````````
</details>
https://github.com/llvm/llvm-project/pull/71000
More information about the lldb-commits
mailing list