-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[lldb][split-dwarf] Add --errors-only argument separate-debug-info list #71000
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+60
−26
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@llvm/pr-subscribers-lldb Author: Tom Yang (zhyty) ChangesOften, 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.
I updated the following tests
This change applies to both the table and JSON outputs. Full diff: https://github.com/llvm/llvm-project/pull/71000.diff 9 Files Affected:
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
|
jeffreytan81
approved these changes
Nov 1, 2023
bulbazord
reviewed
Nov 1, 2023
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
I updated the following tests
This change applies to both the table and JSON outputs.