LLDB mainline
CommandObjectDiagnostics.cpp
Go to the documentation of this file.
1//===-- CommandObjectDiagnostics.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
20
21#include "llvm/Support/JSON.h"
22
23using namespace lldb;
24using namespace lldb_private;
25
26#define LLDB_OPTIONS_diagnostics_dump
27#include "CommandOptions.inc"
28
29#define LLDB_OPTIONS_diagnostics_report
30#include "CommandOptions.inc"
31
33public:
34 // Constructors and Destructors
36 : CommandObjectParsed(interpreter, "diagnostics dump",
37 "Dump diagnostics to disk", nullptr) {}
38
39 ~CommandObjectDiagnosticsDump() override = default;
40
41 class CommandOptions : public Options {
42 public:
43 CommandOptions() = default;
44
45 ~CommandOptions() override = default;
46
47 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
48 ExecutionContext *execution_context) override {
50 const int short_option = m_getopt_table[option_idx].val;
51
52 switch (short_option) {
53 case 'd':
54 directory.SetDirectory(option_arg);
55 break;
56 default:
57 llvm_unreachable("Unimplemented option");
58 }
59 return error;
60 }
61
62 void OptionParsingStarting(ExecutionContext *execution_context) override {
63 directory.Clear();
64 }
65
66 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
67 return llvm::ArrayRef(g_diagnostics_dump_options);
68 }
69
71 };
72
73 Options *GetOptions() override { return &m_options; }
74
75protected:
76 llvm::Expected<FileSpec> GetDirectory() {
77 if (m_options.directory) {
78 auto ec =
79 llvm::sys::fs::create_directories(m_options.directory.GetPath());
80 if (ec)
81 return llvm::errorCodeToError(ec);
82 return m_options.directory;
83 }
85 }
86
87 void DoExecute(Args &args, CommandReturnObject &result) override {
88 llvm::Expected<FileSpec> directory = GetDirectory();
89
90 if (!directory) {
91 result.AppendError(llvm::toString(directory.takeError()));
92 return;
93 }
94
95 // Collect the diagnostics bundle into the directory.
96 llvm::Expected<Diagnostics::Report> report =
98 if (!report) {
99 result.AppendErrorWithFormat("failed to write diagnostics to %s",
100 directory->GetPath().c_str());
101 result.AppendError(llvm::toString(report.takeError()));
102 return;
103 }
104
105 // Print the report as JSON so the user can review what a bug report would
106 // carry. The bundle directory and its files are listed under "attachments".
107 result.GetOutputStream().Format("{0:2}\n", toJSON(*report));
108
110 }
111
113};
114
116public:
119 interpreter, "diagnostics report",
120 "Assemble a diagnostics bundle and file it as a bug report.",
121 nullptr) {}
122
124
125 class CommandOptions : public Options {
126 public:
127 CommandOptions() = default;
128
129 ~CommandOptions() override = default;
130
131 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
132 ExecutionContext *execution_context) override {
134 const int short_option = m_getopt_table[option_idx].val;
135
136 switch (short_option) {
137 case 'd':
138 directory.SetDirectory(option_arg);
139 break;
140 case 'n':
141 no_open = true;
142 break;
143 case 'P':
144 plugin = option_arg.str();
145 break;
146 default:
147 llvm_unreachable("Unimplemented option");
148 }
149 return error;
150 }
151
152 void OptionParsingStarting(ExecutionContext *execution_context) override {
153 directory.Clear();
154 no_open = false;
155 plugin.clear();
156 }
157
158 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
159 return llvm::ArrayRef(g_diagnostics_report_options);
160 }
161
163 bool no_open = false;
164 std::string plugin;
165 };
166
167 Options *GetOptions() override { return &m_options; }
168
169protected:
170 llvm::Expected<FileSpec> GetDirectory() {
171 if (m_options.directory) {
172 auto ec =
173 llvm::sys::fs::create_directories(m_options.directory.GetPath());
174 if (ec)
175 return llvm::errorCodeToError(ec);
176 return m_options.directory;
177 }
179 }
180
181 void DoExecute(Args &args, CommandReturnObject &result) override {
182 llvm::Expected<FileSpec> directory = GetDirectory();
183 if (!directory) {
184 result.AppendError(llvm::toString(directory.takeError()));
185 return;
186 }
187
188 llvm::Expected<Diagnostics::Report> report =
190 if (!report) {
191 result.AppendError(llvm::toString(report.takeError()));
192 return;
193 }
194
195 Stream &out = result.GetOutputStream();
196 out << "Bug report written to " << directory->GetPath() << "\n";
197 if (!report->attachments.files.empty()) {
198 out << "Attach the following files to the issue:\n";
199 for (const std::string &file : report->attachments.files)
200 out << " [ ] " << file << "\n";
201 }
202 result.AppendWarning("the report may contain file paths, command history "
203 "and program data. Review it before attaching it to a "
204 "public issue");
205
206 if (m_options.no_open) {
208 return;
209 }
210
211 // No-tracker handling lives in the fallback reporter's File(), not here.
212 std::unique_ptr<BugReporter> reporter =
214 if (!reporter) {
215 if (!m_options.plugin.empty())
216 result.AppendErrorWithFormat("no bug reporter named '%s'",
217 m_options.plugin.c_str());
218 else
219 result.AppendError("no bug reporter is available");
220 return;
221 }
222 if (llvm::Error error = reporter->File(*report)) {
223 result.AppendError(llvm::toString(std::move(error)));
224 return;
225 }
226
227 out << "Opened a pre-filled " << reporter->GetPluginName() << " report.\n";
229 }
230
232};
233
235 CommandInterpreter &interpreter)
236 : CommandObjectMultiword(interpreter, "diagnostics",
237 "Commands controlling LLDB diagnostics.",
238 "diagnostics <subcommand> [<command-options>]") {
240 "dump", CommandObjectSP(new CommandObjectDiagnosticsDump(interpreter)));
242 interpreter)));
243}
244
static llvm::raw_ostream & error(Stream &strm)
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
void OptionParsingStarting(ExecutionContext *execution_context) override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
llvm::Expected< FileSpec > GetDirectory()
void DoExecute(Args &args, CommandReturnObject &result) override
~CommandObjectDiagnosticsDump() override=default
CommandObjectDiagnosticsDump(CommandInterpreter &interpreter)
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
void OptionParsingStarting(ExecutionContext *execution_context) override
CommandObjectDiagnosticsReport(CommandInterpreter &interpreter)
void DoExecute(Args &args, CommandReturnObject &result) override
~CommandObjectDiagnosticsReport() override=default
llvm::Expected< FileSpec > GetDirectory()
A command line argument class.
Definition Args.h:33
CommandObjectDiagnostics(CommandInterpreter &interpreter)
bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override
CommandObjectMultiword(CommandInterpreter &interpreter, const char *name, const char *help=nullptr, const char *syntax=nullptr, uint32_t flags=0)
CommandObjectParsed(CommandInterpreter &interpreter, const char *name, const char *help=nullptr, const char *syntax=nullptr, uint32_t flags=0)
void AppendError(llvm::StringRef in_string)
void SetStatus(lldb::ReturnStatus status)
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
void AppendWarning(llvm::StringRef in_string)
static llvm::Expected< FileSpec > CreateUniqueDirectory()
Create a unique diagnostic directory.
llvm::Expected< Report > Collect(Debugger &debugger, const ExecutionContext &exe_ctx, const FileSpec &dir)
Collect a full diagnostics bundle into dir and return its report.
static Diagnostics & Instance()
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
A file utility class.
Definition FileSpec.h:57
A command line option parsing protocol class.
Definition Options.h:58
std::vector< Option > m_getopt_table
Definition Options.h:198
static std::unique_ptr< BugReporter > CreateBugReporterInstance(llvm::StringRef name={})
An error handling class.
Definition Status.h:118
A stream class that can stream formatted output to a file.
Definition Stream.h:28
void Format(const char *format, Args &&... args)
Forwards the arguments to llvm::formatv and writes to the stream.
Definition Stream.h:370
A class that represents a running process on the host machine.
llvm::json::Value toJSON(const Diagnostics::Report &report)
Render a diagnostics report as JSON, for diagnostics dump's terminal output.
std::shared_ptr< lldb_private::CommandObject > CommandObjectSP
@ eReturnStatusSuccessFinishResult