xref: /freebsd/contrib/llvm-project/lldb/source/Commands/CommandObjectStats.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- CommandObjectStats.cpp --------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "CommandObjectStats.h"
10 #include "lldb/Core/Debugger.h"
11 #include "lldb/Host/OptionParser.h"
12 #include "lldb/Interpreter/CommandInterpreter.h"
13 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
14 #include "lldb/Interpreter/CommandReturnObject.h"
15 #include "lldb/Interpreter/OptionArgParser.h"
16 #include "lldb/Target/Target.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 class CommandObjectStatsEnable : public CommandObjectParsed {
22 public:
CommandObjectStatsEnable(CommandInterpreter & interpreter)23   CommandObjectStatsEnable(CommandInterpreter &interpreter)
24       : CommandObjectParsed(interpreter, "enable",
25                             "Enable statistics collection", nullptr,
26                             eCommandProcessMustBePaused) {}
27 
28   ~CommandObjectStatsEnable() override = default;
29 
30 protected:
DoExecute(Args & command,CommandReturnObject & result)31   void DoExecute(Args &command, CommandReturnObject &result) override {
32     if (DebuggerStats::GetCollectingStats()) {
33       result.AppendError("statistics already enabled");
34       return;
35     }
36 
37     DebuggerStats::SetCollectingStats(true);
38     result.SetStatus(eReturnStatusSuccessFinishResult);
39   }
40 };
41 
42 class CommandObjectStatsDisable : public CommandObjectParsed {
43 public:
CommandObjectStatsDisable(CommandInterpreter & interpreter)44   CommandObjectStatsDisable(CommandInterpreter &interpreter)
45       : CommandObjectParsed(interpreter, "disable",
46                             "Disable statistics collection", nullptr,
47                             eCommandProcessMustBePaused) {}
48 
49   ~CommandObjectStatsDisable() override = default;
50 
51 protected:
DoExecute(Args & command,CommandReturnObject & result)52   void DoExecute(Args &command, CommandReturnObject &result) override {
53     if (!DebuggerStats::GetCollectingStats()) {
54       result.AppendError("need to enable statistics before disabling them");
55       return;
56     }
57 
58     DebuggerStats::SetCollectingStats(false);
59     result.SetStatus(eReturnStatusSuccessFinishResult);
60   }
61 };
62 
63 #define LLDB_OPTIONS_statistics_dump
64 #include "CommandOptions.inc"
65 
66 class CommandObjectStatsDump : public CommandObjectParsed {
67   class CommandOptions : public Options {
68   public:
CommandOptions()69     CommandOptions() { OptionParsingStarting(nullptr); }
70 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)71     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
72                           ExecutionContext *execution_context) override {
73       Status error;
74       const int short_option = m_getopt_table[option_idx].val;
75 
76       switch (short_option) {
77       case 'a':
78         m_all_targets = true;
79         break;
80       case 's':
81         m_stats_options.SetSummaryOnly(true);
82         break;
83       case 'f':
84         m_stats_options.SetLoadAllDebugInfo(true);
85         break;
86       case 'r':
87         if (llvm::Expected<bool> bool_or_error =
88                 OptionArgParser::ToBoolean("--targets", option_arg))
89           m_stats_options.SetIncludeTargets(*bool_or_error);
90         else
91           error = Status::FromError(bool_or_error.takeError());
92         break;
93       case 'm':
94         if (llvm::Expected<bool> bool_or_error =
95                 OptionArgParser::ToBoolean("--modules", option_arg))
96           m_stats_options.SetIncludeModules(*bool_or_error);
97         else
98           error = Status::FromError(bool_or_error.takeError());
99         break;
100       case 't':
101         if (llvm::Expected<bool> bool_or_error =
102                 OptionArgParser::ToBoolean("--transcript", option_arg))
103           m_stats_options.SetIncludeTranscript(*bool_or_error);
104         else
105           error = Status::FromError(bool_or_error.takeError());
106         break;
107       case 'p':
108         if (llvm::Expected<bool> bool_or_error =
109                 OptionArgParser::ToBoolean("--plugins", option_arg))
110           m_stats_options.SetIncludePlugins(*bool_or_error);
111         else
112           error = Status::FromError(bool_or_error.takeError());
113         break;
114       default:
115         llvm_unreachable("Unimplemented option");
116       }
117       return error;
118     }
119 
OptionParsingStarting(ExecutionContext * execution_context)120     void OptionParsingStarting(ExecutionContext *execution_context) override {
121       m_all_targets = false;
122       m_stats_options = StatisticsOptions();
123     }
124 
GetDefinitions()125     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
126       return llvm::ArrayRef(g_statistics_dump_options);
127     }
128 
GetStatisticsOptions()129     const StatisticsOptions &GetStatisticsOptions() { return m_stats_options; }
130 
131     bool m_all_targets = false;
132     StatisticsOptions m_stats_options = StatisticsOptions();
133   };
134 
135 public:
CommandObjectStatsDump(CommandInterpreter & interpreter)136   CommandObjectStatsDump(CommandInterpreter &interpreter)
137       : CommandObjectParsed(
138             interpreter, "statistics dump", "Dump metrics in JSON format",
139             "statistics dump [<options>]", eCommandRequiresTarget) {}
140 
141   ~CommandObjectStatsDump() override = default;
142 
GetOptions()143   Options *GetOptions() override { return &m_options; }
144 
145 protected:
DoExecute(Args & command,CommandReturnObject & result)146   void DoExecute(Args &command, CommandReturnObject &result) override {
147     Target *target = nullptr;
148     if (!m_options.m_all_targets)
149       target = m_exe_ctx.GetTargetPtr();
150 
151     // Check if transcript is requested but transcript saving is disabled
152     const StatisticsOptions &stats_options = m_options.GetStatisticsOptions();
153     if (stats_options.GetIncludeTranscript() &&
154         !GetDebugger().GetCommandInterpreter().GetSaveTranscript()) {
155       result.AppendWarning(
156           "transcript requested but none was saved. Enable with "
157           "'settings set interpreter.save-transcript true'");
158     }
159 
160     result.AppendMessageWithFormatv(
161         "{0:2}",
162         DebuggerStats::ReportStatistics(GetDebugger(), target, stats_options));
163     result.SetStatus(eReturnStatusSuccessFinishResult);
164   }
165 
166   CommandOptions m_options;
167 };
168 
CommandObjectStats(CommandInterpreter & interpreter)169 CommandObjectStats::CommandObjectStats(CommandInterpreter &interpreter)
170     : CommandObjectMultiword(interpreter, "statistics",
171                              "Print statistics about a debugging session",
172                              "statistics <subcommand> [<subcommand-options>]") {
173   LoadSubCommand("enable",
174                  CommandObjectSP(new CommandObjectStatsEnable(interpreter)));
175   LoadSubCommand("disable",
176                  CommandObjectSP(new CommandObjectStatsDisable(interpreter)));
177   LoadSubCommand("dump",
178                  CommandObjectSP(new CommandObjectStatsDump(interpreter)));
179 }
180 
181 CommandObjectStats::~CommandObjectStats() = default;
182