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 bool 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 result.Succeeded(); 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 result.Succeeded(); 94 } 95 96 result.GetOutputStream() << "diagnostics written to " << *directory << '\n'; 97 98 result.SetStatus(eReturnStatusSuccessFinishResult); 99 return result.Succeeded(); 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