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 
9 #include "CommandObjectDiagnostics.h"
10 #include "lldb/Host/OptionParser.h"
11 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
12 #include "lldb/Interpreter/CommandReturnObject.h"
13 #include "lldb/Interpreter/OptionArgParser.h"
14 #include "lldb/Interpreter/OptionValueEnumeration.h"
15 #include "lldb/Interpreter/OptionValueUInt64.h"
16 #include "lldb/Interpreter/Options.h"
17 #include "lldb/Utility/Diagnostics.h"
18 
19 using namespace lldb;
20 using namespace lldb_private;
21 
22 #define LLDB_OPTIONS_diagnostics_dump
23 #include "CommandOptions.inc"
24 
25 class CommandObjectDiagnosticsDump : public CommandObjectParsed {
26 public:
27   // Constructors and Destructors
28   CommandObjectDiagnosticsDump(CommandInterpreter &interpreter)
29       : CommandObjectParsed(interpreter, "diagnostics dump",
30                             "Dump diagnostics to disk", nullptr) {}
31 
32   ~CommandObjectDiagnosticsDump() override = default;
33 
34   class CommandOptions : public Options {
35   public:
36     CommandOptions() = default;
37 
38     ~CommandOptions() override = default;
39 
40     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
41                           ExecutionContext *execution_context) override {
42       Status error;
43       const int short_option = m_getopt_table[option_idx].val;
44 
45       switch (short_option) {
46       case 'd':
47         directory.SetDirectory(option_arg);
48         break;
49       default:
50         llvm_unreachable("Unimplemented option");
51       }
52       return error;
53     }
54 
55     void OptionParsingStarting(ExecutionContext *execution_context) override {
56       directory.Clear();
57     }
58 
59     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
60       return llvm::ArrayRef(g_diagnostics_dump_options);
61     }
62 
63     FileSpec directory;
64   };
65 
66   Options *GetOptions() override { return &m_options; }
67 
68 protected:
69   llvm::Expected<FileSpec> GetDirectory() {
70     if (m_options.directory) {
71       auto ec =
72           llvm::sys::fs::create_directories(m_options.directory.GetPath());
73       if (ec)
74         return llvm::errorCodeToError(ec);
75       return m_options.directory;
76     }
77     return Diagnostics::CreateUniqueDirectory();
78   }
79 
80   void DoExecute(Args &args, CommandReturnObject &result) override {
81     llvm::Expected<FileSpec> directory = GetDirectory();
82 
83     if (!directory) {
84       result.AppendError(llvm::toString(directory.takeError()));
85       return;
86     }
87 
88     llvm::Error error = Diagnostics::Instance().Create(*directory);
89     if (error) {
90       result.AppendErrorWithFormat("failed to write diagnostics to %s",
91                                    directory->GetPath().c_str());
92       result.AppendError(llvm::toString(std::move(error)));
93       return;
94     }
95 
96     result.GetOutputStream() << "diagnostics written to " << *directory << '\n';
97 
98     result.SetStatus(eReturnStatusSuccessFinishResult);
99     return;
100   }
101 
102   CommandOptions m_options;
103 };
104 
105 CommandObjectDiagnostics::CommandObjectDiagnostics(
106     CommandInterpreter &interpreter)
107     : CommandObjectMultiword(interpreter, "diagnostics",
108                              "Commands controlling LLDB diagnostics.",
109                              "diagnostics <subcommand> [<command-options>]") {
110   LoadSubCommand(
111       "dump", CommandObjectSP(new CommandObjectDiagnosticsDump(interpreter)));
112 }
113 
114 CommandObjectDiagnostics::~CommandObjectDiagnostics() = default;
115