19e046f02SJonas Devlieghere //===-- CommandObjectReproducer.cpp -----------------------------*- C++ -*-===//
29e046f02SJonas Devlieghere //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69e046f02SJonas Devlieghere //
79e046f02SJonas Devlieghere //===----------------------------------------------------------------------===//
89e046f02SJonas Devlieghere 
99e046f02SJonas Devlieghere #include "CommandObjectReproducer.h"
109e046f02SJonas Devlieghere 
119e046f02SJonas Devlieghere #include "lldb/Utility/Reproducer.h"
129e046f02SJonas Devlieghere 
13df14b942SJonas Devlieghere #include "lldb/Interpreter/CommandInterpreter.h"
149e046f02SJonas Devlieghere #include "lldb/Interpreter/CommandReturnObject.h"
159e046f02SJonas Devlieghere #include "lldb/Interpreter/OptionArgParser.h"
169e046f02SJonas Devlieghere #include "lldb/Interpreter/OptionGroupBoolean.h"
179e046f02SJonas Devlieghere 
189e046f02SJonas Devlieghere using namespace lldb;
199e046f02SJonas Devlieghere using namespace lldb_private;
209e046f02SJonas Devlieghere 
219e046f02SJonas Devlieghere class CommandObjectReproducerGenerate : public CommandObjectParsed {
229e046f02SJonas Devlieghere public:
239e046f02SJonas Devlieghere   CommandObjectReproducerGenerate(CommandInterpreter &interpreter)
24973d66eeSJonas Devlieghere       : CommandObjectParsed(
25973d66eeSJonas Devlieghere             interpreter, "reproducer generate",
26973d66eeSJonas Devlieghere             "Generate reproducer on disk. When the debugger is in capture "
27973d66eeSJonas Devlieghere             "mode, this command will output the reproducer to a directory on "
28973d66eeSJonas Devlieghere             "disk. In replay mode this command in a no-op.",
29973d66eeSJonas Devlieghere             nullptr) {}
309e046f02SJonas Devlieghere 
319e046f02SJonas Devlieghere   ~CommandObjectReproducerGenerate() override = default;
329e046f02SJonas Devlieghere 
339e046f02SJonas Devlieghere protected:
349e046f02SJonas Devlieghere   bool DoExecute(Args &command, CommandReturnObject &result) override {
359e046f02SJonas Devlieghere     if (!command.empty()) {
369e046f02SJonas Devlieghere       result.AppendErrorWithFormat("'%s' takes no arguments",
379e046f02SJonas Devlieghere                                    m_cmd_name.c_str());
389e046f02SJonas Devlieghere       return false;
399e046f02SJonas Devlieghere     }
409e046f02SJonas Devlieghere 
419e046f02SJonas Devlieghere     auto &r = repro::Reproducer::Instance();
429e046f02SJonas Devlieghere     if (auto generator = r.GetGenerator()) {
439e046f02SJonas Devlieghere       generator->Keep();
442dca6538SJonas Devlieghere     } else if (r.GetLoader()) {
452dca6538SJonas Devlieghere       // Make this operation a NOP in replay mode.
462dca6538SJonas Devlieghere       result.SetStatus(eReturnStatusSuccessFinishNoResult);
472dca6538SJonas Devlieghere       return result.Succeeded();
489e046f02SJonas Devlieghere     } else {
499e046f02SJonas Devlieghere       result.AppendErrorWithFormat("Unable to get the reproducer generator");
502dca6538SJonas Devlieghere       result.SetStatus(eReturnStatusFailed);
519e046f02SJonas Devlieghere       return false;
529e046f02SJonas Devlieghere     }
539e046f02SJonas Devlieghere 
549e046f02SJonas Devlieghere     result.GetOutputStream()
559e046f02SJonas Devlieghere         << "Reproducer written to '" << r.GetReproducerPath() << "'\n";
561c5250abSJonas Devlieghere     result.GetOutputStream()
571c5250abSJonas Devlieghere         << "Please have a look at the directory to assess if you're willing to "
581c5250abSJonas Devlieghere            "share the contained information.\n";
599e046f02SJonas Devlieghere 
609e046f02SJonas Devlieghere     result.SetStatus(eReturnStatusSuccessFinishResult);
619e046f02SJonas Devlieghere     return result.Succeeded();
629e046f02SJonas Devlieghere   }
639e046f02SJonas Devlieghere };
649e046f02SJonas Devlieghere 
6515eacd74SJonas Devlieghere class CommandObjectReproducerStatus : public CommandObjectParsed {
669e046f02SJonas Devlieghere public:
6715eacd74SJonas Devlieghere   CommandObjectReproducerStatus(CommandInterpreter &interpreter)
68973d66eeSJonas Devlieghere       : CommandObjectParsed(
69973d66eeSJonas Devlieghere             interpreter, "reproducer status",
70973d66eeSJonas Devlieghere             "Show the current reproducer status. In capture mode the debugger "
71973d66eeSJonas Devlieghere             "is collecting all the information it needs to create a "
72973d66eeSJonas Devlieghere             "reproducer.  In replay mode the reproducer is replaying a "
73973d66eeSJonas Devlieghere             "reproducer. When the reproducers are off, no data is collected "
74973d66eeSJonas Devlieghere             "and no reproducer can be generated.",
75973d66eeSJonas Devlieghere             nullptr) {}
769e046f02SJonas Devlieghere 
7715eacd74SJonas Devlieghere   ~CommandObjectReproducerStatus() override = default;
789e046f02SJonas Devlieghere 
799e046f02SJonas Devlieghere protected:
809e046f02SJonas Devlieghere   bool DoExecute(Args &command, CommandReturnObject &result) override {
8115eacd74SJonas Devlieghere     if (!command.empty()) {
8215eacd74SJonas Devlieghere       result.AppendErrorWithFormat("'%s' takes no arguments",
839e046f02SJonas Devlieghere                                    m_cmd_name.c_str());
849e046f02SJonas Devlieghere       return false;
859e046f02SJonas Devlieghere     }
869e046f02SJonas Devlieghere 
879e046f02SJonas Devlieghere     auto &r = repro::Reproducer::Instance();
8852f8f343SZachary Turner     if (r.GetGenerator()) {
8915eacd74SJonas Devlieghere       result.GetOutputStream() << "Reproducer is in capture mode.\n";
9052f8f343SZachary Turner     } else if (r.GetLoader()) {
9115eacd74SJonas Devlieghere       result.GetOutputStream() << "Reproducer is in replay mode.\n";
9215eacd74SJonas Devlieghere     } else {
9315eacd74SJonas Devlieghere       result.GetOutputStream() << "Reproducer is off.\n";
949e046f02SJonas Devlieghere     }
959e046f02SJonas Devlieghere 
9615eacd74SJonas Devlieghere     result.SetStatus(eReturnStatusSuccessFinishResult);
979e046f02SJonas Devlieghere     return result.Succeeded();
989e046f02SJonas Devlieghere   }
999e046f02SJonas Devlieghere };
1009e046f02SJonas Devlieghere 
1019e046f02SJonas Devlieghere CommandObjectReproducer::CommandObjectReproducer(
1029e046f02SJonas Devlieghere     CommandInterpreter &interpreter)
103973d66eeSJonas Devlieghere     : CommandObjectMultiword(
104973d66eeSJonas Devlieghere           interpreter, "reproducer",
105*130ec068SJonas Devlieghere           "Commands for manipulate the reproducer functionality.",
106*130ec068SJonas Devlieghere           "reproducer <subcommand> [<subcommand-options>]") {
1079e046f02SJonas Devlieghere   LoadSubCommand(
1089e046f02SJonas Devlieghere       "generate",
1099e046f02SJonas Devlieghere       CommandObjectSP(new CommandObjectReproducerGenerate(interpreter)));
11015eacd74SJonas Devlieghere   LoadSubCommand("status", CommandObjectSP(
11115eacd74SJonas Devlieghere                                new CommandObjectReproducerStatus(interpreter)));
1129e046f02SJonas Devlieghere }
1139e046f02SJonas Devlieghere 
1149e046f02SJonas Devlieghere CommandObjectReproducer::~CommandObjectReproducer() = default;
115