1 //===-- CommandObjectReproducer.cpp -----------------------------*- C++ -*-===// 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 "CommandObjectReproducer.h" 10 11 #include "lldb/Utility/Reproducer.h" 12 13 #include "lldb/Interpreter/CommandInterpreter.h" 14 #include "lldb/Interpreter/CommandReturnObject.h" 15 #include "lldb/Interpreter/OptionArgParser.h" 16 #include "lldb/Interpreter/OptionGroupBoolean.h" 17 18 using namespace lldb; 19 using namespace lldb_private; 20 21 class CommandObjectReproducerGenerate : public CommandObjectParsed { 22 public: 23 CommandObjectReproducerGenerate(CommandInterpreter &interpreter) 24 : CommandObjectParsed(interpreter, "reproducer generate", 25 "Generate reproducer on disk.", nullptr) {} 26 27 ~CommandObjectReproducerGenerate() override = default; 28 29 protected: 30 bool DoExecute(Args &command, CommandReturnObject &result) override { 31 if (!command.empty()) { 32 result.AppendErrorWithFormat("'%s' takes no arguments", 33 m_cmd_name.c_str()); 34 return false; 35 } 36 37 auto &r = repro::Reproducer::Instance(); 38 if (auto generator = r.GetGenerator()) { 39 generator->Keep(); 40 } else if (r.GetLoader()) { 41 // Make this operation a NOP in replay mode. 42 result.SetStatus(eReturnStatusSuccessFinishNoResult); 43 return result.Succeeded(); 44 } else { 45 result.AppendErrorWithFormat("Unable to get the reproducer generator"); 46 result.SetStatus(eReturnStatusFailed); 47 return false; 48 } 49 50 result.GetOutputStream() 51 << "Reproducer written to '" << r.GetReproducerPath() << "'\n"; 52 result.GetOutputStream() 53 << "Please have a look at the directory to assess if you're willing to " 54 "share the contained information.\n"; 55 56 result.SetStatus(eReturnStatusSuccessFinishResult); 57 return result.Succeeded(); 58 } 59 }; 60 61 class CommandObjectReproducerStatus : public CommandObjectParsed { 62 public: 63 CommandObjectReproducerStatus(CommandInterpreter &interpreter) 64 : CommandObjectParsed(interpreter, "reproducer status", 65 "Show the current reproducer status.", nullptr) {} 66 67 ~CommandObjectReproducerStatus() override = default; 68 69 protected: 70 bool DoExecute(Args &command, CommandReturnObject &result) override { 71 if (!command.empty()) { 72 result.AppendErrorWithFormat("'%s' takes no arguments", 73 m_cmd_name.c_str()); 74 return false; 75 } 76 77 auto &r = repro::Reproducer::Instance(); 78 if (r.GetGenerator()) { 79 result.GetOutputStream() << "Reproducer is in capture mode.\n"; 80 } else if (r.GetLoader()) { 81 result.GetOutputStream() << "Reproducer is in replay mode.\n"; 82 } else { 83 result.GetOutputStream() << "Reproducer is off.\n"; 84 } 85 86 result.SetStatus(eReturnStatusSuccessFinishResult); 87 return result.Succeeded(); 88 } 89 }; 90 91 CommandObjectReproducer::CommandObjectReproducer( 92 CommandInterpreter &interpreter) 93 : CommandObjectMultiword(interpreter, "reproducer", 94 "Commands controlling LLDB reproducers.", 95 "log <subcommand> [<command-options>]") { 96 LoadSubCommand( 97 "generate", 98 CommandObjectSP(new CommandObjectReproducerGenerate(interpreter))); 99 LoadSubCommand("status", CommandObjectSP( 100 new CommandObjectReproducerStatus(interpreter))); 101 } 102 103 CommandObjectReproducer::~CommandObjectReproducer() = default; 104