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 {
41       result.AppendErrorWithFormat("Unable to get the reproducer generator");
42       return false;
43     }
44 
45     result.GetOutputStream()
46         << "Reproducer written to '" << r.GetReproducerPath() << "'\n";
47 
48     result.SetStatus(eReturnStatusSuccessFinishResult);
49     return result.Succeeded();
50   }
51 };
52 
53 class CommandObjectReproducerStatus : public CommandObjectParsed {
54 public:
55   CommandObjectReproducerStatus(CommandInterpreter &interpreter)
56       : CommandObjectParsed(interpreter, "reproducer status",
57                             "Show the current reproducer status.", nullptr) {}
58 
59   ~CommandObjectReproducerStatus() override = default;
60 
61 protected:
62   bool DoExecute(Args &command, CommandReturnObject &result) override {
63     if (!command.empty()) {
64       result.AppendErrorWithFormat("'%s' takes no arguments",
65                                    m_cmd_name.c_str());
66       return false;
67     }
68 
69     auto &r = repro::Reproducer::Instance();
70     if (auto generator = r.GetGenerator()) {
71       result.GetOutputStream() << "Reproducer is in capture mode.\n";
72     } else if (auto generator = r.GetLoader()) {
73       result.GetOutputStream() << "Reproducer is in replay mode.\n";
74     } else {
75 
76       result.GetOutputStream() << "Reproducer is off.\n";
77     }
78 
79     result.SetStatus(eReturnStatusSuccessFinishResult);
80     return result.Succeeded();
81   }
82 };
83 
84 CommandObjectReproducer::CommandObjectReproducer(
85     CommandInterpreter &interpreter)
86     : CommandObjectMultiword(interpreter, "reproducer",
87                              "Commands controlling LLDB reproducers.",
88                              "log <subcommand> [<command-options>]") {
89   LoadSubCommand(
90       "generate",
91       CommandObjectSP(new CommandObjectReproducerGenerate(interpreter)));
92   LoadSubCommand("status", CommandObjectSP(
93                                new CommandObjectReproducerStatus(interpreter)));
94 }
95 
96 CommandObjectReproducer::~CommandObjectReproducer() = default;
97