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)
249e046f02SJonas Devlieghere       : CommandObjectParsed(interpreter, "reproducer generate",
259e046f02SJonas Devlieghere                             "Generate reproducer on disk.", nullptr) {}
269e046f02SJonas Devlieghere 
279e046f02SJonas Devlieghere   ~CommandObjectReproducerGenerate() override = default;
289e046f02SJonas Devlieghere 
299e046f02SJonas Devlieghere protected:
309e046f02SJonas Devlieghere   bool DoExecute(Args &command, CommandReturnObject &result) override {
319e046f02SJonas Devlieghere     if (!command.empty()) {
329e046f02SJonas Devlieghere       result.AppendErrorWithFormat("'%s' takes no arguments",
339e046f02SJonas Devlieghere                                    m_cmd_name.c_str());
349e046f02SJonas Devlieghere       return false;
359e046f02SJonas Devlieghere     }
369e046f02SJonas Devlieghere 
379e046f02SJonas Devlieghere     auto &r = repro::Reproducer::Instance();
389e046f02SJonas Devlieghere     if (auto generator = r.GetGenerator()) {
399e046f02SJonas Devlieghere       generator->Keep();
402dca6538SJonas Devlieghere     } else if (r.GetLoader()) {
412dca6538SJonas Devlieghere       // Make this operation a NOP in replay mode.
422dca6538SJonas Devlieghere       result.SetStatus(eReturnStatusSuccessFinishNoResult);
432dca6538SJonas Devlieghere       return result.Succeeded();
449e046f02SJonas Devlieghere     } else {
459e046f02SJonas Devlieghere       result.AppendErrorWithFormat("Unable to get the reproducer generator");
462dca6538SJonas Devlieghere       result.SetStatus(eReturnStatusFailed);
479e046f02SJonas Devlieghere       return false;
489e046f02SJonas Devlieghere     }
499e046f02SJonas Devlieghere 
509e046f02SJonas Devlieghere     result.GetOutputStream()
519e046f02SJonas Devlieghere         << "Reproducer written to '" << r.GetReproducerPath() << "'\n";
52*1c5250abSJonas Devlieghere     result.GetOutputStream()
53*1c5250abSJonas Devlieghere         << "Please have a look at the directory to assess if you're willing to "
54*1c5250abSJonas Devlieghere            "share the contained information.\n";
559e046f02SJonas Devlieghere 
569e046f02SJonas Devlieghere     result.SetStatus(eReturnStatusSuccessFinishResult);
579e046f02SJonas Devlieghere     return result.Succeeded();
589e046f02SJonas Devlieghere   }
599e046f02SJonas Devlieghere };
609e046f02SJonas Devlieghere 
6115eacd74SJonas Devlieghere class CommandObjectReproducerStatus : public CommandObjectParsed {
629e046f02SJonas Devlieghere public:
6315eacd74SJonas Devlieghere   CommandObjectReproducerStatus(CommandInterpreter &interpreter)
6415eacd74SJonas Devlieghere       : CommandObjectParsed(interpreter, "reproducer status",
6515eacd74SJonas Devlieghere                             "Show the current reproducer status.", nullptr) {}
669e046f02SJonas Devlieghere 
6715eacd74SJonas Devlieghere   ~CommandObjectReproducerStatus() override = default;
689e046f02SJonas Devlieghere 
699e046f02SJonas Devlieghere protected:
709e046f02SJonas Devlieghere   bool DoExecute(Args &command, CommandReturnObject &result) override {
7115eacd74SJonas Devlieghere     if (!command.empty()) {
7215eacd74SJonas Devlieghere       result.AppendErrorWithFormat("'%s' takes no arguments",
739e046f02SJonas Devlieghere                                    m_cmd_name.c_str());
749e046f02SJonas Devlieghere       return false;
759e046f02SJonas Devlieghere     }
769e046f02SJonas Devlieghere 
779e046f02SJonas Devlieghere     auto &r = repro::Reproducer::Instance();
7852f8f343SZachary Turner     if (r.GetGenerator()) {
7915eacd74SJonas Devlieghere       result.GetOutputStream() << "Reproducer is in capture mode.\n";
8052f8f343SZachary Turner     } else if (r.GetLoader()) {
8115eacd74SJonas Devlieghere       result.GetOutputStream() << "Reproducer is in replay mode.\n";
8215eacd74SJonas Devlieghere     } else {
8315eacd74SJonas Devlieghere       result.GetOutputStream() << "Reproducer is off.\n";
849e046f02SJonas Devlieghere     }
859e046f02SJonas Devlieghere 
8615eacd74SJonas Devlieghere     result.SetStatus(eReturnStatusSuccessFinishResult);
879e046f02SJonas Devlieghere     return result.Succeeded();
889e046f02SJonas Devlieghere   }
899e046f02SJonas Devlieghere };
909e046f02SJonas Devlieghere 
919e046f02SJonas Devlieghere CommandObjectReproducer::CommandObjectReproducer(
929e046f02SJonas Devlieghere     CommandInterpreter &interpreter)
939e046f02SJonas Devlieghere     : CommandObjectMultiword(interpreter, "reproducer",
949e046f02SJonas Devlieghere                              "Commands controlling LLDB reproducers.",
959e046f02SJonas Devlieghere                              "log <subcommand> [<command-options>]") {
969e046f02SJonas Devlieghere   LoadSubCommand(
979e046f02SJonas Devlieghere       "generate",
989e046f02SJonas Devlieghere       CommandObjectSP(new CommandObjectReproducerGenerate(interpreter)));
9915eacd74SJonas Devlieghere   LoadSubCommand("status", CommandObjectSP(
10015eacd74SJonas Devlieghere                                new CommandObjectReproducerStatus(interpreter)));
1019e046f02SJonas Devlieghere }
1029e046f02SJonas Devlieghere 
1039e046f02SJonas Devlieghere CommandObjectReproducer::~CommandObjectReproducer() = default;
104