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( 25 interpreter, "reproducer generate", 26 "Generate reproducer on disk. When the debugger is in capture " 27 "mode, this command will output the reproducer to a directory on " 28 "disk. In replay mode this command in a no-op.", 29 nullptr) {} 30 31 ~CommandObjectReproducerGenerate() override = default; 32 33 protected: 34 bool DoExecute(Args &command, CommandReturnObject &result) override { 35 if (!command.empty()) { 36 result.AppendErrorWithFormat("'%s' takes no arguments", 37 m_cmd_name.c_str()); 38 return false; 39 } 40 41 auto &r = repro::Reproducer::Instance(); 42 if (auto generator = r.GetGenerator()) { 43 generator->Keep(); 44 } else if (r.GetLoader()) { 45 // Make this operation a NOP in replay mode. 46 result.SetStatus(eReturnStatusSuccessFinishNoResult); 47 return result.Succeeded(); 48 } else { 49 result.AppendErrorWithFormat("Unable to get the reproducer generator"); 50 result.SetStatus(eReturnStatusFailed); 51 return false; 52 } 53 54 result.GetOutputStream() 55 << "Reproducer written to '" << r.GetReproducerPath() << "'\n"; 56 result.GetOutputStream() 57 << "Please have a look at the directory to assess if you're willing to " 58 "share the contained information.\n"; 59 60 result.SetStatus(eReturnStatusSuccessFinishResult); 61 return result.Succeeded(); 62 } 63 }; 64 65 class CommandObjectReproducerStatus : public CommandObjectParsed { 66 public: 67 CommandObjectReproducerStatus(CommandInterpreter &interpreter) 68 : CommandObjectParsed( 69 interpreter, "reproducer status", 70 "Show the current reproducer status. In capture mode the debugger " 71 "is collecting all the information it needs to create a " 72 "reproducer. In replay mode the reproducer is replaying a " 73 "reproducer. When the reproducers are off, no data is collected " 74 "and no reproducer can be generated.", 75 nullptr) {} 76 77 ~CommandObjectReproducerStatus() override = default; 78 79 protected: 80 bool DoExecute(Args &command, CommandReturnObject &result) override { 81 if (!command.empty()) { 82 result.AppendErrorWithFormat("'%s' takes no arguments", 83 m_cmd_name.c_str()); 84 return false; 85 } 86 87 auto &r = repro::Reproducer::Instance(); 88 if (r.GetGenerator()) { 89 result.GetOutputStream() << "Reproducer is in capture mode.\n"; 90 } else if (r.GetLoader()) { 91 result.GetOutputStream() << "Reproducer is in replay mode.\n"; 92 } else { 93 result.GetOutputStream() << "Reproducer is off.\n"; 94 } 95 96 result.SetStatus(eReturnStatusSuccessFinishResult); 97 return result.Succeeded(); 98 } 99 }; 100 101 CommandObjectReproducer::CommandObjectReproducer( 102 CommandInterpreter &interpreter) 103 : CommandObjectMultiword( 104 interpreter, "reproducer", 105 "Commands to inspect and manipulate the reproducer functionality.", 106 "log <subcommand> [<command-options>]") { 107 LoadSubCommand( 108 "generate", 109 CommandObjectSP(new CommandObjectReproducerGenerate(interpreter))); 110 LoadSubCommand("status", CommandObjectSP( 111 new CommandObjectReproducerStatus(interpreter))); 112 } 113 114 CommandObjectReproducer::~CommandObjectReproducer() = default; 115