1*9e046f02SJonas Devlieghere //===-- CommandObjectReproducer.cpp -----------------------------*- C++ -*-===// 2*9e046f02SJonas Devlieghere // 3*9e046f02SJonas Devlieghere // The LLVM Compiler Infrastructure 4*9e046f02SJonas Devlieghere // 5*9e046f02SJonas Devlieghere // This file is distributed under the University of Illinois Open Source 6*9e046f02SJonas Devlieghere // License. See LICENSE.TXT for details. 7*9e046f02SJonas Devlieghere // 8*9e046f02SJonas Devlieghere //===----------------------------------------------------------------------===// 9*9e046f02SJonas Devlieghere 10*9e046f02SJonas Devlieghere #include "CommandObjectReproducer.h" 11*9e046f02SJonas Devlieghere 12*9e046f02SJonas Devlieghere #include "lldb/Utility/Reproducer.h" 13*9e046f02SJonas Devlieghere 14*9e046f02SJonas Devlieghere #include "lldb/Interpreter/CommandReturnObject.h" 15*9e046f02SJonas Devlieghere #include "lldb/Interpreter/OptionArgParser.h" 16*9e046f02SJonas Devlieghere #include "lldb/Interpreter/OptionGroupBoolean.h" 17*9e046f02SJonas Devlieghere 18*9e046f02SJonas Devlieghere using namespace lldb; 19*9e046f02SJonas Devlieghere using namespace lldb_private; 20*9e046f02SJonas Devlieghere 21*9e046f02SJonas Devlieghere static void AppendErrorToResult(llvm::Error e, CommandReturnObject &result) { 22*9e046f02SJonas Devlieghere std::string error_str = llvm::toString(std::move(e)); 23*9e046f02SJonas Devlieghere result.AppendErrorWithFormat("%s", error_str.c_str()); 24*9e046f02SJonas Devlieghere } 25*9e046f02SJonas Devlieghere 26*9e046f02SJonas Devlieghere class CommandObjectReproducerCaptureEnable : public CommandObjectParsed { 27*9e046f02SJonas Devlieghere public: 28*9e046f02SJonas Devlieghere CommandObjectReproducerCaptureEnable(CommandInterpreter &interpreter) 29*9e046f02SJonas Devlieghere : CommandObjectParsed(interpreter, "reproducer capture enable", 30*9e046f02SJonas Devlieghere "Enable gathering information for reproducer", 31*9e046f02SJonas Devlieghere nullptr) {} 32*9e046f02SJonas Devlieghere 33*9e046f02SJonas Devlieghere ~CommandObjectReproducerCaptureEnable() override = default; 34*9e046f02SJonas Devlieghere 35*9e046f02SJonas Devlieghere protected: 36*9e046f02SJonas Devlieghere bool DoExecute(Args &command, CommandReturnObject &result) override { 37*9e046f02SJonas Devlieghere if (!command.empty()) { 38*9e046f02SJonas Devlieghere result.AppendErrorWithFormat("'%s' takes no arguments", 39*9e046f02SJonas Devlieghere m_cmd_name.c_str()); 40*9e046f02SJonas Devlieghere return false; 41*9e046f02SJonas Devlieghere } 42*9e046f02SJonas Devlieghere 43*9e046f02SJonas Devlieghere auto &r = repro::Reproducer::Instance(); 44*9e046f02SJonas Devlieghere if (auto e = r.SetGenerateReproducer(true)) { 45*9e046f02SJonas Devlieghere AppendErrorToResult(std::move(e), result); 46*9e046f02SJonas Devlieghere return false; 47*9e046f02SJonas Devlieghere } 48*9e046f02SJonas Devlieghere 49*9e046f02SJonas Devlieghere result.SetStatus(eReturnStatusSuccessFinishNoResult); 50*9e046f02SJonas Devlieghere return result.Succeeded(); 51*9e046f02SJonas Devlieghere } 52*9e046f02SJonas Devlieghere }; 53*9e046f02SJonas Devlieghere 54*9e046f02SJonas Devlieghere class CommandObjectReproducerCaptureDisable : public CommandObjectParsed { 55*9e046f02SJonas Devlieghere public: 56*9e046f02SJonas Devlieghere CommandObjectReproducerCaptureDisable(CommandInterpreter &interpreter) 57*9e046f02SJonas Devlieghere : CommandObjectParsed(interpreter, "reproducer capture enable", 58*9e046f02SJonas Devlieghere "Disable gathering information for reproducer", 59*9e046f02SJonas Devlieghere nullptr) {} 60*9e046f02SJonas Devlieghere 61*9e046f02SJonas Devlieghere ~CommandObjectReproducerCaptureDisable() override = default; 62*9e046f02SJonas Devlieghere 63*9e046f02SJonas Devlieghere protected: 64*9e046f02SJonas Devlieghere bool DoExecute(Args &command, CommandReturnObject &result) override { 65*9e046f02SJonas Devlieghere if (!command.empty()) { 66*9e046f02SJonas Devlieghere result.AppendErrorWithFormat("'%s' takes no arguments", 67*9e046f02SJonas Devlieghere m_cmd_name.c_str()); 68*9e046f02SJonas Devlieghere return false; 69*9e046f02SJonas Devlieghere } 70*9e046f02SJonas Devlieghere 71*9e046f02SJonas Devlieghere auto &r = repro::Reproducer::Instance(); 72*9e046f02SJonas Devlieghere if (auto e = r.SetGenerateReproducer(false)) { 73*9e046f02SJonas Devlieghere AppendErrorToResult(std::move(e), result); 74*9e046f02SJonas Devlieghere return false; 75*9e046f02SJonas Devlieghere } 76*9e046f02SJonas Devlieghere 77*9e046f02SJonas Devlieghere result.SetStatus(eReturnStatusSuccessFinishNoResult); 78*9e046f02SJonas Devlieghere return result.Succeeded(); 79*9e046f02SJonas Devlieghere } 80*9e046f02SJonas Devlieghere }; 81*9e046f02SJonas Devlieghere 82*9e046f02SJonas Devlieghere class CommandObjectReproducerGenerate : public CommandObjectParsed { 83*9e046f02SJonas Devlieghere public: 84*9e046f02SJonas Devlieghere CommandObjectReproducerGenerate(CommandInterpreter &interpreter) 85*9e046f02SJonas Devlieghere : CommandObjectParsed(interpreter, "reproducer generate", 86*9e046f02SJonas Devlieghere "Generate reproducer on disk.", nullptr) {} 87*9e046f02SJonas Devlieghere 88*9e046f02SJonas Devlieghere ~CommandObjectReproducerGenerate() override = default; 89*9e046f02SJonas Devlieghere 90*9e046f02SJonas Devlieghere protected: 91*9e046f02SJonas Devlieghere bool DoExecute(Args &command, CommandReturnObject &result) override { 92*9e046f02SJonas Devlieghere if (!command.empty()) { 93*9e046f02SJonas Devlieghere result.AppendErrorWithFormat("'%s' takes no arguments", 94*9e046f02SJonas Devlieghere m_cmd_name.c_str()); 95*9e046f02SJonas Devlieghere return false; 96*9e046f02SJonas Devlieghere } 97*9e046f02SJonas Devlieghere 98*9e046f02SJonas Devlieghere auto &r = repro::Reproducer::Instance(); 99*9e046f02SJonas Devlieghere if (auto generator = r.GetGenerator()) { 100*9e046f02SJonas Devlieghere generator->Keep(); 101*9e046f02SJonas Devlieghere } else { 102*9e046f02SJonas Devlieghere result.AppendErrorWithFormat("Unable to get the reproducer generator"); 103*9e046f02SJonas Devlieghere return false; 104*9e046f02SJonas Devlieghere } 105*9e046f02SJonas Devlieghere 106*9e046f02SJonas Devlieghere result.GetOutputStream() 107*9e046f02SJonas Devlieghere << "Reproducer written to '" << r.GetReproducerPath() << "'\n"; 108*9e046f02SJonas Devlieghere 109*9e046f02SJonas Devlieghere result.SetStatus(eReturnStatusSuccessFinishResult); 110*9e046f02SJonas Devlieghere return result.Succeeded(); 111*9e046f02SJonas Devlieghere } 112*9e046f02SJonas Devlieghere }; 113*9e046f02SJonas Devlieghere 114*9e046f02SJonas Devlieghere class CommandObjectReproducerReplay : public CommandObjectParsed { 115*9e046f02SJonas Devlieghere public: 116*9e046f02SJonas Devlieghere CommandObjectReproducerReplay(CommandInterpreter &interpreter) 117*9e046f02SJonas Devlieghere : CommandObjectParsed(interpreter, "reproducer capture", 118*9e046f02SJonas Devlieghere "Enable or disable gathering of information needed " 119*9e046f02SJonas Devlieghere "to generate a reproducer.", 120*9e046f02SJonas Devlieghere nullptr) { 121*9e046f02SJonas Devlieghere CommandArgumentEntry arg1; 122*9e046f02SJonas Devlieghere CommandArgumentData path_arg; 123*9e046f02SJonas Devlieghere 124*9e046f02SJonas Devlieghere // Define the first (and only) variant of this arg. 125*9e046f02SJonas Devlieghere path_arg.arg_type = eArgTypePath; 126*9e046f02SJonas Devlieghere path_arg.arg_repetition = eArgRepeatPlain; 127*9e046f02SJonas Devlieghere 128*9e046f02SJonas Devlieghere // There is only one variant this argument could be; put it into the 129*9e046f02SJonas Devlieghere // argument entry. 130*9e046f02SJonas Devlieghere arg1.push_back(path_arg); 131*9e046f02SJonas Devlieghere 132*9e046f02SJonas Devlieghere // Push the data for the first argument into the m_arguments vector. 133*9e046f02SJonas Devlieghere m_arguments.push_back(arg1); 134*9e046f02SJonas Devlieghere } 135*9e046f02SJonas Devlieghere 136*9e046f02SJonas Devlieghere ~CommandObjectReproducerReplay() override = default; 137*9e046f02SJonas Devlieghere 138*9e046f02SJonas Devlieghere protected: 139*9e046f02SJonas Devlieghere bool DoExecute(Args &command, CommandReturnObject &result) override { 140*9e046f02SJonas Devlieghere if (command.empty()) { 141*9e046f02SJonas Devlieghere result.AppendErrorWithFormat( 142*9e046f02SJonas Devlieghere "'%s' takes a single argument: the reproducer path", 143*9e046f02SJonas Devlieghere m_cmd_name.c_str()); 144*9e046f02SJonas Devlieghere return false; 145*9e046f02SJonas Devlieghere } 146*9e046f02SJonas Devlieghere 147*9e046f02SJonas Devlieghere auto &r = repro::Reproducer::Instance(); 148*9e046f02SJonas Devlieghere 149*9e046f02SJonas Devlieghere if (auto e = r.SetReplayReproducer(true)) { 150*9e046f02SJonas Devlieghere std::string error_str = llvm::toString(std::move(e)); 151*9e046f02SJonas Devlieghere result.AppendErrorWithFormat("%s", error_str.c_str()); 152*9e046f02SJonas Devlieghere return false; 153*9e046f02SJonas Devlieghere } 154*9e046f02SJonas Devlieghere 155*9e046f02SJonas Devlieghere if (auto loader = r.GetLoader()) { 156*9e046f02SJonas Devlieghere const char *repro_path = command.GetArgumentAtIndex(0); 157*9e046f02SJonas Devlieghere if (auto e = loader->LoadIndex(FileSpec(repro_path))) { 158*9e046f02SJonas Devlieghere std::string error_str = llvm::toString(std::move(e)); 159*9e046f02SJonas Devlieghere result.AppendErrorWithFormat("Unable to load reproducer: %s", 160*9e046f02SJonas Devlieghere error_str.c_str()); 161*9e046f02SJonas Devlieghere return false; 162*9e046f02SJonas Devlieghere } 163*9e046f02SJonas Devlieghere } else { 164*9e046f02SJonas Devlieghere result.AppendErrorWithFormat("Unable to get the reproducer loader"); 165*9e046f02SJonas Devlieghere return false; 166*9e046f02SJonas Devlieghere } 167*9e046f02SJonas Devlieghere 168*9e046f02SJonas Devlieghere result.SetStatus(eReturnStatusSuccessFinishNoResult); 169*9e046f02SJonas Devlieghere return result.Succeeded(); 170*9e046f02SJonas Devlieghere } 171*9e046f02SJonas Devlieghere }; 172*9e046f02SJonas Devlieghere 173*9e046f02SJonas Devlieghere class CommandObjectReproducerCapture : public CommandObjectMultiword { 174*9e046f02SJonas Devlieghere private: 175*9e046f02SJonas Devlieghere public: 176*9e046f02SJonas Devlieghere CommandObjectReproducerCapture(CommandInterpreter &interpreter) 177*9e046f02SJonas Devlieghere : CommandObjectMultiword( 178*9e046f02SJonas Devlieghere interpreter, "reproducer capture", 179*9e046f02SJonas Devlieghere "Manage gathering of information needed to generate a reproducer.", 180*9e046f02SJonas Devlieghere NULL) { 181*9e046f02SJonas Devlieghere LoadSubCommand( 182*9e046f02SJonas Devlieghere "enable", 183*9e046f02SJonas Devlieghere CommandObjectSP(new CommandObjectReproducerCaptureEnable(interpreter))); 184*9e046f02SJonas Devlieghere LoadSubCommand("disable", 185*9e046f02SJonas Devlieghere CommandObjectSP( 186*9e046f02SJonas Devlieghere new CommandObjectReproducerCaptureDisable(interpreter))); 187*9e046f02SJonas Devlieghere } 188*9e046f02SJonas Devlieghere 189*9e046f02SJonas Devlieghere ~CommandObjectReproducerCapture() {} 190*9e046f02SJonas Devlieghere }; 191*9e046f02SJonas Devlieghere 192*9e046f02SJonas Devlieghere CommandObjectReproducer::CommandObjectReproducer( 193*9e046f02SJonas Devlieghere CommandInterpreter &interpreter) 194*9e046f02SJonas Devlieghere : CommandObjectMultiword(interpreter, "reproducer", 195*9e046f02SJonas Devlieghere "Commands controlling LLDB reproducers.", 196*9e046f02SJonas Devlieghere "log <subcommand> [<command-options>]") { 197*9e046f02SJonas Devlieghere LoadSubCommand("capture", CommandObjectSP(new CommandObjectReproducerCapture( 198*9e046f02SJonas Devlieghere interpreter))); 199*9e046f02SJonas Devlieghere LoadSubCommand( 200*9e046f02SJonas Devlieghere "generate", 201*9e046f02SJonas Devlieghere CommandObjectSP(new CommandObjectReproducerGenerate(interpreter))); 202*9e046f02SJonas Devlieghere LoadSubCommand("replay", CommandObjectSP( 203*9e046f02SJonas Devlieghere new CommandObjectReproducerReplay(interpreter))); 204*9e046f02SJonas Devlieghere } 205*9e046f02SJonas Devlieghere 206*9e046f02SJonas Devlieghere CommandObjectReproducer::~CommandObjectReproducer() = default; 207