Skip to content

Commit 70f41a8

Browse files
authored
[lldb] Add/change options in statistics dump to control what sections are dumped (#95075)
# Added/changed options The following options are **added** to the `statistics dump` command: * `--targets=bool`: Boolean. Dumps the `targets` section. * `--modules=bool`: Boolean. Dumps the `modules` section. When both options are given, the field `moduleIdentifiers` will be dumped for each target in the `targets` section. The following options are **changed**: * `--transcript=bool`: Changed to a boolean. Dumps the `transcript` section. # Behavior of `statistics dump` with various options The behavior is **backward compatible**: - When no options are provided, `statistics dump` dumps all sections. - When `--summary` is provided, only dumps the summary info. **New** behavior: - `--targets=bool`, `--modules=bool`, `--transcript=bool` overrides the above "default". For **example**: - `statistics dump --modules=false` dumps summary + targets + transcript. No modules. - `statistics dump --summary --targets=true --transcript=true` dumps summary + targets (in summary mode) + transcript. # Added options into public API In `SBStatisticsOptions`, add: * `Set/GetIncludeTargets` * `Set/GetIncludeModules` * `Set/GetIncludeTranscript` **Alternative considered**: Thought about adding `Set/GetIncludeSections(string sections_spec)`, which receives a comma-separated list of section names to be included ("targets", "modules", "transcript"). The **benefit** of this approach is that the API is more future-proof when it comes to possible adding/changing of section names. **However**, I feel the section names are likely to remain unchanged for a while - it's not like we plan to make big changes to the output of `statistics dump` any time soon. The **downsides** of this approach are: 1\ the readability of the API is worse (requires reading doc to understand what string can be accepted), 2\ string input are more prone to human error (e.g. typo "target" instead of expected "targets"). # Tests ``` bin/llvm-lit -sv ../external/llvm-project/lldb/test/API/commands/statistics/basic/TestStats.py ``` ``` ./tools/lldb/unittests/Interpreter/InterpreterTests ``` New test cases have been added to verify: * Different sections are dumped/not dumped when different `StatisticsOptions` are given through command line (CLI or `HandleCommand`; see `test_sections_existence_through_command`) or API (see `test_sections_existence_through_api`). * The order in which the options are given in command line does not matter (see `test_order_of_options_do_not_matter`). --------- Co-authored-by: Roy Shi <royshi@meta.com>
1 parent 8ea31db commit 70f41a8

File tree

10 files changed

+463
-33
lines changed

10 files changed

+463
-33
lines changed

lldb/include/lldb/API/SBStatisticsOptions.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,46 @@ class LLDB_API SBStatisticsOptions {
2222

2323
const SBStatisticsOptions &operator=(const lldb::SBStatisticsOptions &rhs);
2424

25+
/// If true, dump only high-level summary statistics. Exclude details like
26+
/// targets, modules, breakpoints, etc. This turns off `IncludeTargets`,
27+
/// `IncludeModules` and `IncludeTranscript` by default.
28+
///
29+
/// Defaults to false.
2530
void SetSummaryOnly(bool b);
2631
bool GetSummaryOnly();
2732

33+
/// If true, dump statistics for the targets, including breakpoints,
34+
/// expression evaluations, frame variables, etc.
35+
///
36+
/// Defaults to true, unless the `SummaryOnly` mode is enabled, in which case
37+
/// this is turned off unless specified.
38+
///
39+
/// If both `IncludeTargets` and `IncludeModules` are true, a list of module
40+
/// identifiers will be added to the "targets" section.
41+
void SetIncludeTargets(bool b);
42+
bool GetIncludeTargets() const;
43+
44+
/// If true, dump statistics for the modules, including time and size of
45+
/// various aspects of the module and debug information, type system, path,
46+
/// etc.
47+
///
48+
/// Defaults to true, unless the `SummaryOnly` mode is enabled, in which case
49+
/// this is turned off unless specified.
50+
///
51+
/// If both `IncludeTargets` and `IncludeModules` are true, a list of module
52+
/// identifiers will be added to the "targets" section.
53+
void SetIncludeModules(bool b);
54+
bool GetIncludeModules() const;
55+
56+
/// If true and the setting `interpreter.save-transcript` is enabled, include
57+
/// a JSON array with all commands the user and/or scripts executed during a
58+
/// debug session.
59+
///
60+
/// Defaults to true, unless the `SummaryOnly` mode is enabled, in which case
61+
/// this is turned off unless specified.
62+
void SetIncludeTranscript(bool b);
63+
bool GetIncludeTranscript() const;
64+
2865
/// If set to true, the debugger will load all debug info that is available
2966
/// and report statistics on the total amount. If this is set to false, then
3067
/// only report statistics on the currently loaded debug information.

lldb/include/lldb/Interpreter/OptionArgParser.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ struct OptionArgParser {
2929

3030
static bool ToBoolean(llvm::StringRef s, bool fail_value, bool *success_ptr);
3131

32+
static llvm::Expected<bool> ToBoolean(llvm::StringRef option_name,
33+
llvm::StringRef option_arg);
34+
3235
static char ToChar(llvm::StringRef s, char fail_value, bool *success_ptr);
3336

3437
static int64_t ToOptionEnum(llvm::StringRef s,

lldb/include/lldb/Target/Statistics.h

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,48 @@ struct ConstStringStats {
131131
};
132132

133133
struct StatisticsOptions {
134-
bool summary_only = false;
135-
bool load_all_debug_info = false;
136-
bool include_transcript = false;
134+
public:
135+
void SetSummaryOnly(bool value) { m_summary_only = value; }
136+
bool GetSummaryOnly() const { return m_summary_only.value_or(false); }
137+
138+
void SetLoadAllDebugInfo(bool value) { m_load_all_debug_info = value; }
139+
bool GetLoadAllDebugInfo() const {
140+
return m_load_all_debug_info.value_or(false);
141+
}
142+
143+
void SetIncludeTargets(bool value) { m_include_targets = value; }
144+
bool GetIncludeTargets() const {
145+
if (m_include_targets.has_value())
146+
return m_include_targets.value();
147+
// `m_include_targets` has no value set, so return a value based on
148+
// `m_summary_only`.
149+
return !GetSummaryOnly();
150+
}
151+
152+
void SetIncludeModules(bool value) { m_include_modules = value; }
153+
bool GetIncludeModules() const {
154+
if (m_include_modules.has_value())
155+
return m_include_modules.value();
156+
// `m_include_modules` has no value set, so return a value based on
157+
// `m_summary_only`.
158+
return !GetSummaryOnly();
159+
}
160+
161+
void SetIncludeTranscript(bool value) { m_include_transcript = value; }
162+
bool GetIncludeTranscript() const {
163+
if (m_include_transcript.has_value())
164+
return m_include_transcript.value();
165+
// `m_include_transcript` has no value set, so return a value based on
166+
// `m_summary_only`.
167+
return !GetSummaryOnly();
168+
}
169+
170+
private:
171+
std::optional<bool> m_summary_only;
172+
std::optional<bool> m_load_all_debug_info;
173+
std::optional<bool> m_include_targets;
174+
std::optional<bool> m_include_modules;
175+
std::optional<bool> m_include_transcript;
137176
};
138177

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

lldb/source/API/SBStatisticsOptions.cpp

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ using namespace lldb_private;
1818
SBStatisticsOptions::SBStatisticsOptions()
1919
: m_opaque_up(new StatisticsOptions()) {
2020
LLDB_INSTRUMENT_VA(this);
21-
m_opaque_up->summary_only = false;
2221
}
2322

2423
SBStatisticsOptions::SBStatisticsOptions(const SBStatisticsOptions &rhs) {
@@ -39,17 +38,43 @@ SBStatisticsOptions::operator=(const SBStatisticsOptions &rhs) {
3938
}
4039

4140
void SBStatisticsOptions::SetSummaryOnly(bool b) {
42-
m_opaque_up->summary_only = b;
41+
m_opaque_up->SetSummaryOnly(b);
4342
}
4443

45-
bool SBStatisticsOptions::GetSummaryOnly() { return m_opaque_up->summary_only; }
44+
bool SBStatisticsOptions::GetSummaryOnly() {
45+
return m_opaque_up->GetSummaryOnly();
46+
}
47+
48+
void SBStatisticsOptions::SetIncludeTargets(bool b) {
49+
m_opaque_up->SetIncludeTargets(b);
50+
}
51+
52+
bool SBStatisticsOptions::GetIncludeTargets() const {
53+
return m_opaque_up->GetIncludeTargets();
54+
}
55+
56+
void SBStatisticsOptions::SetIncludeModules(bool b) {
57+
m_opaque_up->SetIncludeModules(b);
58+
}
59+
60+
bool SBStatisticsOptions::GetIncludeModules() const {
61+
return m_opaque_up->GetIncludeModules();
62+
}
63+
64+
void SBStatisticsOptions::SetIncludeTranscript(bool b) {
65+
m_opaque_up->SetIncludeTranscript(b);
66+
}
67+
68+
bool SBStatisticsOptions::GetIncludeTranscript() const {
69+
return m_opaque_up->GetIncludeTranscript();
70+
}
4671

4772
void SBStatisticsOptions::SetReportAllAvailableDebugInfo(bool b) {
48-
m_opaque_up->load_all_debug_info = b;
73+
m_opaque_up->SetLoadAllDebugInfo(b);
4974
}
5075

5176
bool SBStatisticsOptions::GetReportAllAvailableDebugInfo() {
52-
return m_opaque_up->load_all_debug_info;
77+
return m_opaque_up->GetLoadAllDebugInfo();
5378
}
5479

5580
const lldb_private::StatisticsOptions &SBStatisticsOptions::ref() const {

lldb/source/Commands/CommandObjectStats.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "lldb/Host/OptionParser.h"
1212
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
1313
#include "lldb/Interpreter/CommandReturnObject.h"
14+
#include "lldb/Interpreter/OptionArgParser.h"
1415
#include "lldb/Target/Target.h"
1516

1617
using namespace lldb;
@@ -76,13 +77,31 @@ class CommandObjectStatsDump : public CommandObjectParsed {
7677
m_all_targets = true;
7778
break;
7879
case 's':
79-
m_stats_options.summary_only = true;
80+
m_stats_options.SetSummaryOnly(true);
8081
break;
8182
case 'f':
82-
m_stats_options.load_all_debug_info = true;
83+
m_stats_options.SetLoadAllDebugInfo(true);
84+
break;
85+
case 'r':
86+
if (llvm::Expected<bool> bool_or_error =
87+
OptionArgParser::ToBoolean("--targets", option_arg))
88+
m_stats_options.SetIncludeTargets(*bool_or_error);
89+
else
90+
error = bool_or_error.takeError();
91+
break;
92+
case 'm':
93+
if (llvm::Expected<bool> bool_or_error =
94+
OptionArgParser::ToBoolean("--modules", option_arg))
95+
m_stats_options.SetIncludeModules(*bool_or_error);
96+
else
97+
error = bool_or_error.takeError();
8398
break;
8499
case 't':
85-
m_stats_options.include_transcript = true;
100+
if (llvm::Expected<bool> bool_or_error =
101+
OptionArgParser::ToBoolean("--transcript", option_arg))
102+
m_stats_options.SetIncludeTranscript(*bool_or_error);
103+
else
104+
error = bool_or_error.takeError();
86105
break;
87106
default:
88107
llvm_unreachable("Unimplemented option");

lldb/source/Commands/Options.td

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,8 +1425,28 @@ let Command = "statistics dump" in {
14251425
Desc<"Dump the total possible debug info statistics. "
14261426
"Force loading all the debug information if not yet loaded, and collect "
14271427
"statistics with those.">;
1428+
def statistics_dump_targets: Option<"targets", "r">, Group<1>,
1429+
Arg<"Boolean">,
1430+
Desc<"Dump statistics for the targets, including breakpoints, expression "
1431+
"evaluations, frame variables, etc. "
1432+
"Defaults to true, unless the '--summary' mode is enabled, in which case "
1433+
"this is turned off unless specified. "
1434+
"If both the '--targets' and the '--modules' options are 'true', a list "
1435+
"of module identifiers will be added to the 'targets' section.">;
1436+
def statistics_dump_modules: Option<"modules", "m">, Group<1>,
1437+
Arg<"Boolean">,
1438+
Desc<"Dump statistics for the modules, including time and size of various "
1439+
"aspects of the module and debug information, type system, path, etc. "
1440+
"Defaults to true, unless the '--summary' mode is enabled, in which case "
1441+
"this is turned off unless specified. "
1442+
"If both the '--targets' and the '--modules' options are 'true', a list "
1443+
"of module identifiers will be added to the 'targets' section.">;
14281444
def statistics_dump_transcript: Option<"transcript", "t">, Group<1>,
1445+
Arg<"Boolean">,
14291446
Desc<"If the setting interpreter.save-transcript is enabled and this "
1430-
"option is specified, include a JSON array with all commands the user and/"
1431-
"or scripts executed during a debug session.">;
1447+
"option is 'true', include a JSON array with all commands the user and/or "
1448+
"scripts executed during a debug session. "
1449+
"Defaults to true, unless the '--summary' mode is enabled, in which case "
1450+
"this is turned off unless specified.">;
1451+
14321452
}

lldb/source/Interpreter/OptionArgParser.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,20 @@ bool OptionArgParser::ToBoolean(llvm::StringRef ref, bool fail_value,
3535
return fail_value;
3636
}
3737

38+
llvm::Expected<bool> OptionArgParser::ToBoolean(llvm::StringRef option_name,
39+
llvm::StringRef option_arg) {
40+
bool parse_success;
41+
const bool option_value =
42+
ToBoolean(option_arg, false /* doesn't matter */, &parse_success);
43+
if (parse_success)
44+
return option_value;
45+
else
46+
return llvm::createStringError(
47+
"Invalid boolean value for option '%s': '%s'",
48+
option_name.str().c_str(),
49+
option_arg.empty() ? "<null>" : option_arg.str().c_str());
50+
}
51+
3852
char OptionArgParser::ToChar(llvm::StringRef s, char fail_value,
3953
bool *success_ptr) {
4054
if (success_ptr)

lldb/source/Target/Statistics.cpp

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ TargetStats::ToJSON(Target &target,
107107
const lldb_private::StatisticsOptions &options) {
108108
json::Object target_metrics_json;
109109
ProcessSP process_sp = target.GetProcessSP();
110-
const bool summary_only = options.summary_only;
110+
const bool summary_only = options.GetSummaryOnly();
111+
const bool include_modules = options.GetIncludeModules();
111112
if (!summary_only) {
112113
CollectStats(target);
113114

@@ -117,8 +118,9 @@ TargetStats::ToJSON(Target &target,
117118

118119
target_metrics_json.try_emplace(m_expr_eval.name, m_expr_eval.ToJSON());
119120
target_metrics_json.try_emplace(m_frame_var.name, m_frame_var.ToJSON());
120-
target_metrics_json.try_emplace("moduleIdentifiers",
121-
std::move(json_module_uuid_array));
121+
if (include_modules)
122+
target_metrics_json.try_emplace("moduleIdentifiers",
123+
std::move(json_module_uuid_array));
122124

123125
if (m_launch_or_attach_time && m_first_private_stop_time) {
124126
double elapsed_time =
@@ -224,9 +226,11 @@ llvm::json::Value DebuggerStats::ReportStatistics(
224226
Debugger &debugger, Target *target,
225227
const lldb_private::StatisticsOptions &options) {
226228

227-
const bool summary_only = options.summary_only;
228-
const bool load_all_debug_info = options.load_all_debug_info;
229-
const bool include_transcript = options.include_transcript;
229+
const bool summary_only = options.GetSummaryOnly();
230+
const bool load_all_debug_info = options.GetLoadAllDebugInfo();
231+
const bool include_targets = options.GetIncludeTargets();
232+
const bool include_modules = options.GetIncludeModules();
233+
const bool include_transcript = options.GetIncludeTranscript();
230234

231235
json::Array json_targets;
232236
json::Array json_modules;
@@ -314,7 +318,7 @@ llvm::json::Value DebuggerStats::ReportStatistics(
314318
if (module_stat.debug_info_had_incomplete_types)
315319
++num_modules_with_incomplete_types;
316320

317-
if (!summary_only) {
321+
if (include_modules) {
318322
module_stat.identifier = (intptr_t)module;
319323
module_stat.path = module->GetFileSpec().GetPath();
320324
if (ConstString object_name = module->GetObjectName()) {
@@ -347,13 +351,15 @@ llvm::json::Value DebuggerStats::ReportStatistics(
347351
{"totalSymbolTableStripped", num_stripped_modules},
348352
};
349353

350-
if (target) {
351-
json_targets.emplace_back(target->ReportStatistics(options));
352-
} else {
353-
for (const auto &target : debugger.GetTargetList().Targets())
354+
if (include_targets) {
355+
if (target) {
354356
json_targets.emplace_back(target->ReportStatistics(options));
357+
} else {
358+
for (const auto &target : debugger.GetTargetList().Targets())
359+
json_targets.emplace_back(target->ReportStatistics(options));
360+
}
361+
global_stats.try_emplace("targets", std::move(json_targets));
355362
}
356-
global_stats.try_emplace("targets", std::move(json_targets));
357363

358364
ConstStringStats const_string_stats;
359365
json::Object json_memory{
@@ -362,10 +368,13 @@ llvm::json::Value DebuggerStats::ReportStatistics(
362368
global_stats.try_emplace("memory", std::move(json_memory));
363369
if (!summary_only) {
364370
json::Value cmd_stats = debugger.GetCommandInterpreter().GetStatistics();
365-
global_stats.try_emplace("modules", std::move(json_modules));
366371
global_stats.try_emplace("commands", std::move(cmd_stats));
367372
}
368373

374+
if (include_modules) {
375+
global_stats.try_emplace("modules", std::move(json_modules));
376+
}
377+
369378
if (include_transcript) {
370379
// When transcript is available, add it to the to-be-returned statistics.
371380
//

0 commit comments

Comments
 (0)