Skip to content

Commit dd7386d

Browse files
authored
[Reland] Report only loaded debug info in statistics dump (#81706) (#82207)
Updates: - The previous patch changed the default behavior to not load dwos in `DWARFUnit` ~~`SymbolFileDWARFDwo *GetDwoSymbolFile(bool load_all_debug_info = false);`~~ `SymbolFileDWARFDwo *GetDwoSymbolFile(bool load_all_debug_info = true);` - This broke some lldb-shell tests (see https://green.lab.llvm.org/green/view/LLDB/job/as-lldb-cmake/16273/) - TestDebugInfoSize.py - with symbol on-demand, by default statistics dump only reports skeleton debug info size - `statistics dump -f` will load all dwos. debug info = skeleton debug info + all dwo debug info Currently running `statistics dump` will trigger lldb to load debug info that's not yet loaded (eg. dwo files). Resulted in a delay in the command return, which, can be interrupting. This patch also added a new option `--load-all-debug-info` asking statistics to dump all possible debug info, which will force loading all debug info available if not yet loaded.
1 parent 50b82ef commit dd7386d

25 files changed

+691
-21
lines changed

lldb/bindings/interface/SBStatisticsOptionsDocstrings.i

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,9 @@
66
) lldb::SBStatisticsOptions::SetSummaryOnly;
77
%feature("docstring", "Gets whether the statistics only dump a summary."
88
) lldb::SBStatisticsOptions::GetSummaryOnly;
9+
%feature("docstring", "
10+
Sets whether the statistics will force loading all possible debug info."
11+
) lldb::SBStatisticsOptions::SetReportAllAvailableDebugInfo;
12+
%feature("docstring", "
13+
Gets whether the statistics will force loading all possible debug info."
14+
) lldb::SBStatisticsOptions::GetReportAllAvailableDebugInfo;

lldb/include/lldb/API/SBStatisticsOptions.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ class LLDB_API SBStatisticsOptions {
2525
void SetSummaryOnly(bool b);
2626
bool GetSummaryOnly();
2727

28+
/// If set to true, the debugger will load all debug info that is available
29+
/// and report statistics on the total amount. If this is set to false, then
30+
/// only report statistics on the currently loaded debug information.
31+
/// This can avoid loading debug info from separate files just so it can
32+
/// report the total size which can slow down statistics reporting.
33+
void SetReportAllAvailableDebugInfo(bool b);
34+
bool GetReportAllAvailableDebugInfo();
35+
2836
protected:
2937
friend class SBTarget;
3038
const lldb_private::StatisticsOptions &ref() const;

lldb/include/lldb/Symbol/SymbolFile.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,8 @@ class SymbolFile : public PluginInterface {
381381

382382
/// Metrics gathering functions
383383

384-
/// Return the size in bytes of all debug information in the symbol file.
384+
/// Return the size in bytes of all loaded debug information or total possible
385+
/// debug info in the symbol file.
385386
///
386387
/// If the debug information is contained in sections of an ObjectFile, then
387388
/// this call should add the size of all sections that contain debug
@@ -391,7 +392,14 @@ class SymbolFile : public PluginInterface {
391392
/// entire file should be returned. The default implementation of this
392393
/// function will iterate over all sections in a module and add up their
393394
/// debug info only section byte sizes.
394-
virtual uint64_t GetDebugInfoSize() = 0;
395+
///
396+
/// \param load_all_debug_info
397+
/// If true, force loading any symbol files if they are not yet loaded and
398+
/// add to the total size. Default to false.
399+
///
400+
/// \returns
401+
/// Total currently loaded debug info size in bytes
402+
virtual uint64_t GetDebugInfoSize(bool load_all_debug_info = false) = 0;
395403

396404
/// Return the time taken to parse the debug information.
397405
///
@@ -534,7 +542,7 @@ class SymbolFileCommon : public SymbolFile {
534542

535543
void Dump(Stream &s) override;
536544

537-
uint64_t GetDebugInfoSize() override;
545+
uint64_t GetDebugInfoSize(bool load_all_debug_info = false) override;
538546

539547
bool GetDebugInfoIndexWasLoadedFromCache() const override {
540548
return m_index_was_loaded_from_cache;

lldb/include/lldb/Symbol/SymbolFileOnDemand.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ class SymbolFileOnDemand : public lldb_private::SymbolFile {
178178

179179
void PreloadSymbols() override;
180180

181-
uint64_t GetDebugInfoSize() override;
181+
uint64_t GetDebugInfoSize(bool load_all_debug_info = false) override;
182182
lldb_private::StatsDuration::Duration GetDebugInfoParseTime() override;
183183
lldb_private::StatsDuration::Duration GetDebugInfoIndexTime() override;
184184

lldb/include/lldb/Target/Statistics.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ struct ConstStringStats {
132132

133133
struct StatisticsOptions {
134134
bool summary_only = false;
135+
bool load_all_debug_info = false;
135136
};
136137

137138
/// A class that represents statistics for a since lldb_private::Target.

lldb/source/API/SBStatisticsOptions.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ void SBStatisticsOptions::SetSummaryOnly(bool b) {
4444

4545
bool SBStatisticsOptions::GetSummaryOnly() { return m_opaque_up->summary_only; }
4646

47+
void SBStatisticsOptions::SetReportAllAvailableDebugInfo(bool b) {
48+
m_opaque_up->load_all_debug_info = b;
49+
}
50+
51+
bool SBStatisticsOptions::GetReportAllAvailableDebugInfo() {
52+
return m_opaque_up->load_all_debug_info;
53+
}
54+
4755
const lldb_private::StatisticsOptions &SBStatisticsOptions::ref() const {
4856
return *m_opaque_up;
4957
}

lldb/source/Commands/CommandObjectStats.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ class CommandObjectStatsDump : public CommandObjectParsed {
7878
case 's':
7979
m_stats_options.summary_only = true;
8080
break;
81+
case 'f':
82+
m_stats_options.load_all_debug_info = true;
83+
break;
8184
default:
8285
llvm_unreachable("Unimplemented option");
8386
}

lldb/source/Commands/Options.td

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1419,6 +1419,10 @@ let Command = "statistics dump" in {
14191419
def statistics_dump_all: Option<"all-targets", "a">, Group<1>,
14201420
Desc<"Include statistics for all targets.">;
14211421
def statistics_dump_summary: Option<"summary", "s">, Group<1>,
1422-
Desc<"Dump only high-level summary statistics."
1422+
Desc<"Dump only high-level summary statistics. "
14231423
"Exclude targets, modules, breakpoints etc... details.">;
1424+
def statistics_dump_force: Option<"load-all-debug-info", "f">, Group<1>,
1425+
Desc<"Dump the total possible debug info statistics. "
1426+
"Force loading all the debug information if not yet loaded, and collect "
1427+
"statistics with those.">;
14241428
}

lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,7 @@ void SymbolFileBreakpad::ParseUnwindData() {
918918
m_unwind_data->win.Sort();
919919
}
920920

921-
uint64_t SymbolFileBreakpad::GetDebugInfoSize() {
921+
uint64_t SymbolFileBreakpad::GetDebugInfoSize(bool load_all_debug_info) {
922922
// Breakpad files are all debug info.
923923
return m_objfile_sp->GetByteSize();
924924
}

lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ class SymbolFileBreakpad : public SymbolFileCommon {
141141

142142
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
143143

144-
uint64_t GetDebugInfoSize() override;
144+
uint64_t GetDebugInfoSize(bool load_all_debug_info = false) override;
145145

146146
private:
147147
// A class representing a position in the breakpad file. Useful for

lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -896,8 +896,9 @@ void DWARFUnit::ComputeAbsolutePath() {
896896
m_file_spec->MakeAbsolute(GetCompilationDirectory());
897897
}
898898

899-
SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() {
900-
ExtractUnitDIEIfNeeded();
899+
SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile(bool load_all_debug_info) {
900+
if (load_all_debug_info)
901+
ExtractUnitDIEIfNeeded();
901902
if (m_dwo)
902903
return &llvm::cast<SymbolFileDWARFDwo>(m_dwo->GetSymbolFileDWARF());
903904
return nullptr;

lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ class DWARFUnit : public UserID {
241241
FileSpec GetFile(size_t file_idx);
242242
FileSpec::Style GetPathStyle();
243243

244-
SymbolFileDWARFDwo *GetDwoSymbolFile();
244+
SymbolFileDWARFDwo *GetDwoSymbolFile(bool load_all_debug_info = true);
245245

246246
die_iterator_range dies() {
247247
ExtractDIEsIfNeeded();

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2672,7 +2672,7 @@ static bool UpdateCompilerContextForSimpleTemplateNames(TypeQuery &match) {
26722672
return any_context_updated;
26732673
}
26742674

2675-
uint64_t SymbolFileDWARF::GetDebugInfoSize() {
2675+
uint64_t SymbolFileDWARF::GetDebugInfoSize(bool load_all_debug_info) {
26762676
DWARFDebugInfo &info = DebugInfo();
26772677
uint32_t num_comp_units = info.GetNumUnits();
26782678

@@ -2687,7 +2687,7 @@ uint64_t SymbolFileDWARF::GetDebugInfoSize() {
26872687
if (cu == nullptr)
26882688
continue;
26892689

2690-
SymbolFileDWARFDwo *dwo = cu->GetDwoSymbolFile();
2690+
SymbolFileDWARFDwo *dwo = cu->GetDwoSymbolFile(load_all_debug_info);
26912691
if (dwo)
26922692
debug_info_size += dwo->GetDebugInfoSize();
26932693
}

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ class SymbolFileDWARF : public SymbolFileCommon {
186186
GetMangledNamesForFunction(const std::string &scope_qualified_name,
187187
std::vector<ConstString> &mangled_names) override;
188188

189-
uint64_t GetDebugInfoSize() override;
189+
uint64_t GetDebugInfoSize(bool load_all_debug_info = false) override;
190190

191191
void FindTypes(const lldb_private::TypeQuery &match,
192192
lldb_private::TypeResults &results) override;

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ lldb::offset_t SymbolFileDWARFDwo::GetVendorDWARFOpcodeSize(
8585
return GetBaseSymbolFile().GetVendorDWARFOpcodeSize(data, data_offset, op);
8686
}
8787

88-
uint64_t SymbolFileDWARFDwo::GetDebugInfoSize() {
88+
uint64_t SymbolFileDWARFDwo::GetDebugInfoSize(bool load_all_debug_info) {
8989
// Directly get debug info from current dwo object file's section list
9090
// instead of asking SymbolFileCommon::GetDebugInfo() which parses from
9191
// owning module which is wrong.

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF {
4747
const lldb::offset_t data_offset,
4848
const uint8_t op) const override;
4949

50-
uint64_t GetDebugInfoSize() override;
50+
uint64_t GetDebugInfoSize(bool load_all_debug_info = false) override;
5151

5252
bool ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes,
5353
lldb::offset_t &offset,

lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2156,7 +2156,7 @@ SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {
21562156
return type_system_or_err;
21572157
}
21582158

2159-
uint64_t SymbolFileNativePDB::GetDebugInfoSize() {
2159+
uint64_t SymbolFileNativePDB::GetDebugInfoSize(bool load_all_debug_info) {
21602160
// PDB files are a separate file that contains all debug info.
21612161
return m_index->pdb().getFileSize();
21622162
}

lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class SymbolFileNativePDB : public SymbolFileCommon {
7777

7878
void InitializeObject() override;
7979

80-
uint64_t GetDebugInfoSize() override;
80+
uint64_t GetDebugInfoSize(bool load_all_debug_info = false) override;
8181

8282
// Compile Unit function calls
8383

lldb/source/Symbol/SymbolFile.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ SymbolFileCommon::GetTypeSystemForLanguage(lldb::LanguageType language) {
227227
return type_system_or_err;
228228
}
229229

230-
uint64_t SymbolFileCommon::GetDebugInfoSize() {
230+
uint64_t SymbolFileCommon::GetDebugInfoSize(bool load_all_debug_info) {
231231
if (!m_objfile_sp)
232232
return 0;
233233
ModuleSP module_sp(m_objfile_sp->GetModule());

lldb/source/Symbol/SymbolFileOnDemand.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -535,11 +535,11 @@ void SymbolFileOnDemand::PreloadSymbols() {
535535
return m_sym_file_impl->PreloadSymbols();
536536
}
537537

538-
uint64_t SymbolFileOnDemand::GetDebugInfoSize() {
538+
uint64_t SymbolFileOnDemand::GetDebugInfoSize(bool load_all_debug_info) {
539539
// Always return the real debug info size.
540540
LLDB_LOG(GetLog(), "[{0}] {1} is not skipped", GetSymbolFileName(),
541541
__FUNCTION__);
542-
return m_sym_file_impl->GetDebugInfoSize();
542+
return m_sym_file_impl->GetDebugInfoSize(load_all_debug_info);
543543
}
544544

545545
StatsDuration::Duration SymbolFileOnDemand::GetDebugInfoParseTime() {

lldb/source/Target/Statistics.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ llvm::json::Value DebuggerStats::ReportStatistics(
224224
const lldb_private::StatisticsOptions &options) {
225225

226226
const bool summary_only = options.summary_only;
227+
const bool load_all_debug_info = options.load_all_debug_info;
227228

228229
json::Array json_targets;
229230
json::Array json_modules;
@@ -280,7 +281,8 @@ llvm::json::Value DebuggerStats::ReportStatistics(
280281
++debug_index_saved;
281282
module_stat.debug_index_time = sym_file->GetDebugInfoIndexTime().count();
282283
module_stat.debug_parse_time = sym_file->GetDebugInfoParseTime().count();
283-
module_stat.debug_info_size = sym_file->GetDebugInfoSize();
284+
module_stat.debug_info_size =
285+
sym_file->GetDebugInfoSize(load_all_debug_info);
284286
module_stat.symtab_stripped = module->GetObjectFile()->IsStripped();
285287
if (module_stat.symtab_stripped)
286288
++num_stripped_modules;

lldb/test/API/commands/target/debuginfo/TestDebugInfoSize.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ def test_dwos_loaded_symbols_on_demand(self):
120120
target = self.dbg.CreateTarget(exe)
121121
self.assertTrue(target, lldbtest.VALID_TARGET)
122122

123+
# By default dwo files will not be loaded
123124
stats = target.GetStatistics()
124125
stream = lldb.SBStream()
125126
res = stats.GetAsJSON(stream)
@@ -129,6 +130,15 @@ def test_dwos_loaded_symbols_on_demand(self):
129130
debug_stats,
130131
'Make sure the "totalDebugInfoByteSize" key is in target.GetStatistics()',
131132
)
133+
self.assertEqual(debug_stats["totalDebugInfoByteSize"], SKELETON_DEBUGINFO_SIZE)
134+
135+
# Force loading all the dwo files
136+
stats_options = lldb.SBStatisticsOptions()
137+
stats_options.SetReportAllAvailableDebugInfo(True)
138+
stats = target.GetStatistics(stats_options)
139+
stream = lldb.SBStream()
140+
stats.GetAsJSON(stream)
141+
debug_stats = json.loads(stream.GetData())
132142
self.assertEqual(
133143
debug_stats["totalDebugInfoByteSize"],
134144
SKELETON_DEBUGINFO_SIZE + MAIN_DWO_DEBUGINFO_SIZE + FOO_DWO_DEBUGINFO_SIZE,

lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,42 @@ def test_command_stats_api(self):
117117
self.assertNotIn("bt", command_stats)
118118
# Verify bt's regex command is not duplicatedly captured.
119119
self.assertNotIn("_regexp-bt", command_stats)
120+
121+
@add_test_categories(["dwo"])
122+
def test_command_stats_force(self):
123+
"""
124+
Test reporting all pssible debug info stats by force loading all debug
125+
info. For example, dwo files
126+
"""
127+
src_dir = self.getSourceDir()
128+
dwo_yaml_path = os.path.join(src_dir, "main-main.dwo.yaml")
129+
exe_yaml_path = os.path.join(src_dir, "main.yaml")
130+
dwo_path = self.getBuildArtifact("main-main.dwo")
131+
exe_path = self.getBuildArtifact("main")
132+
self.yaml2obj(dwo_yaml_path, dwo_path)
133+
self.yaml2obj(exe_yaml_path, exe_path)
134+
135+
# Turn on symbols on-demand loading
136+
self.runCmd("settings set symbols.load-on-demand true")
137+
138+
# We need the current working directory to be set to the build directory
139+
os.chdir(self.getBuildDir())
140+
# Create a target with the object file we just created from YAML
141+
target = self.dbg.CreateTarget(exe_path)
142+
self.assertTrue(target, VALID_TARGET)
143+
144+
# Get statistics
145+
stats_options = lldb.SBStatisticsOptions()
146+
stats = target.GetStatistics(stats_options)
147+
stream = lldb.SBStream()
148+
stats.GetAsJSON(stream)
149+
debug_stats = json.loads(stream.GetData())
150+
self.assertEqual(debug_stats["totalDebugInfoByteSize"], 193)
151+
152+
# Get statistics with force loading
153+
stats_options.SetReportAllAvailableDebugInfo(True)
154+
stats_force = target.GetStatistics(stats_options)
155+
stream_force = lldb.SBStream()
156+
stats_force.GetAsJSON(stream_force)
157+
debug_stats_force = json.loads(stream_force.GetData())
158+
self.assertEqual(debug_stats_force["totalDebugInfoByteSize"], 445)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--- !ELF
2+
FileHeader:
3+
Class: ELFCLASS64
4+
Data: ELFDATA2LSB
5+
Type: ET_REL
6+
Machine: EM_X86_64
7+
SectionHeaderStringTable: .strtab
8+
Sections:
9+
- Name: .debug_str.dwo
10+
Type: SHT_PROGBITS
11+
Flags: [ SHF_EXCLUDE, SHF_MERGE, SHF_STRINGS ]
12+
AddressAlign: 0x1
13+
EntSize: 0x1
14+
Content: 5F5A33666F6F7600666F6F006D61696E00696E7400636C616E672076657273696F6E2031372E302E36202843656E744F532031372E302E362D342E656C3929006D61696E2E637070006D61696E2D6D61696E2E64776F00
15+
- Name: .debug_str_offsets.dwo
16+
Type: SHT_PROGBITS
17+
Flags: [ SHF_EXCLUDE ]
18+
AddressAlign: 0x1
19+
Content: 00000000080000000C00000011000000150000004000000049000000
20+
- Name: .debug_info.dwo
21+
Type: SHT_PROGBITS
22+
Flags: [ SHF_EXCLUDE ]
23+
AddressAlign: 0x1
24+
Content: 3500000004000000000008010421000506939F5FCB7816797B02000600000001560001010103011C0000000156020105340000000403050400
25+
- Name: .debug_abbrev.dwo
26+
Type: SHT_PROGBITS
27+
Flags: [ SHF_EXCLUDE ]
28+
AddressAlign: 0x1
29+
Content: 01110125823E130503823EB042823EB142070000022E0011813E120640186E823E03823E3A0B3B0B3F190000032E0011813E1206401803823E3A0B3B0B49133F19000004240003823E3E0B0B0B000000
30+
- Type: SectionHeaderTable
31+
Sections:
32+
- Name: .strtab
33+
- Name: .debug_str.dwo
34+
- Name: .debug_str_offsets.dwo
35+
- Name: .debug_info.dwo
36+
- Name: .debug_abbrev.dwo
37+
...

0 commit comments

Comments
 (0)