forked from OSchip/llvm-project
207 lines
6.9 KiB
C++
207 lines
6.9 KiB
C++
|
//===-- CommandObjectReproducer.cpp -----------------------------*- C++ -*-===//
|
||
|
//
|
||
|
// The LLVM Compiler Infrastructure
|
||
|
//
|
||
|
// This file is distributed under the University of Illinois Open Source
|
||
|
// License. See LICENSE.TXT for details.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#include "CommandObjectReproducer.h"
|
||
|
|
||
|
#include "lldb/Utility/Reproducer.h"
|
||
|
|
||
|
#include "lldb/Interpreter/CommandReturnObject.h"
|
||
|
#include "lldb/Interpreter/OptionArgParser.h"
|
||
|
#include "lldb/Interpreter/OptionGroupBoolean.h"
|
||
|
|
||
|
using namespace lldb;
|
||
|
using namespace lldb_private;
|
||
|
|
||
|
static void AppendErrorToResult(llvm::Error e, CommandReturnObject &result) {
|
||
|
std::string error_str = llvm::toString(std::move(e));
|
||
|
result.AppendErrorWithFormat("%s", error_str.c_str());
|
||
|
}
|
||
|
|
||
|
class CommandObjectReproducerCaptureEnable : public CommandObjectParsed {
|
||
|
public:
|
||
|
CommandObjectReproducerCaptureEnable(CommandInterpreter &interpreter)
|
||
|
: CommandObjectParsed(interpreter, "reproducer capture enable",
|
||
|
"Enable gathering information for reproducer",
|
||
|
nullptr) {}
|
||
|
|
||
|
~CommandObjectReproducerCaptureEnable() override = default;
|
||
|
|
||
|
protected:
|
||
|
bool DoExecute(Args &command, CommandReturnObject &result) override {
|
||
|
if (!command.empty()) {
|
||
|
result.AppendErrorWithFormat("'%s' takes no arguments",
|
||
|
m_cmd_name.c_str());
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
auto &r = repro::Reproducer::Instance();
|
||
|
if (auto e = r.SetGenerateReproducer(true)) {
|
||
|
AppendErrorToResult(std::move(e), result);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
||
|
return result.Succeeded();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class CommandObjectReproducerCaptureDisable : public CommandObjectParsed {
|
||
|
public:
|
||
|
CommandObjectReproducerCaptureDisable(CommandInterpreter &interpreter)
|
||
|
: CommandObjectParsed(interpreter, "reproducer capture enable",
|
||
|
"Disable gathering information for reproducer",
|
||
|
nullptr) {}
|
||
|
|
||
|
~CommandObjectReproducerCaptureDisable() override = default;
|
||
|
|
||
|
protected:
|
||
|
bool DoExecute(Args &command, CommandReturnObject &result) override {
|
||
|
if (!command.empty()) {
|
||
|
result.AppendErrorWithFormat("'%s' takes no arguments",
|
||
|
m_cmd_name.c_str());
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
auto &r = repro::Reproducer::Instance();
|
||
|
if (auto e = r.SetGenerateReproducer(false)) {
|
||
|
AppendErrorToResult(std::move(e), result);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
||
|
return result.Succeeded();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class CommandObjectReproducerGenerate : public CommandObjectParsed {
|
||
|
public:
|
||
|
CommandObjectReproducerGenerate(CommandInterpreter &interpreter)
|
||
|
: CommandObjectParsed(interpreter, "reproducer generate",
|
||
|
"Generate reproducer on disk.", nullptr) {}
|
||
|
|
||
|
~CommandObjectReproducerGenerate() override = default;
|
||
|
|
||
|
protected:
|
||
|
bool DoExecute(Args &command, CommandReturnObject &result) override {
|
||
|
if (!command.empty()) {
|
||
|
result.AppendErrorWithFormat("'%s' takes no arguments",
|
||
|
m_cmd_name.c_str());
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
auto &r = repro::Reproducer::Instance();
|
||
|
if (auto generator = r.GetGenerator()) {
|
||
|
generator->Keep();
|
||
|
} else {
|
||
|
result.AppendErrorWithFormat("Unable to get the reproducer generator");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
result.GetOutputStream()
|
||
|
<< "Reproducer written to '" << r.GetReproducerPath() << "'\n";
|
||
|
|
||
|
result.SetStatus(eReturnStatusSuccessFinishResult);
|
||
|
return result.Succeeded();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class CommandObjectReproducerReplay : public CommandObjectParsed {
|
||
|
public:
|
||
|
CommandObjectReproducerReplay(CommandInterpreter &interpreter)
|
||
|
: CommandObjectParsed(interpreter, "reproducer capture",
|
||
|
"Enable or disable gathering of information needed "
|
||
|
"to generate a reproducer.",
|
||
|
nullptr) {
|
||
|
CommandArgumentEntry arg1;
|
||
|
CommandArgumentData path_arg;
|
||
|
|
||
|
// Define the first (and only) variant of this arg.
|
||
|
path_arg.arg_type = eArgTypePath;
|
||
|
path_arg.arg_repetition = eArgRepeatPlain;
|
||
|
|
||
|
// There is only one variant this argument could be; put it into the
|
||
|
// argument entry.
|
||
|
arg1.push_back(path_arg);
|
||
|
|
||
|
// Push the data for the first argument into the m_arguments vector.
|
||
|
m_arguments.push_back(arg1);
|
||
|
}
|
||
|
|
||
|
~CommandObjectReproducerReplay() override = default;
|
||
|
|
||
|
protected:
|
||
|
bool DoExecute(Args &command, CommandReturnObject &result) override {
|
||
|
if (command.empty()) {
|
||
|
result.AppendErrorWithFormat(
|
||
|
"'%s' takes a single argument: the reproducer path",
|
||
|
m_cmd_name.c_str());
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
auto &r = repro::Reproducer::Instance();
|
||
|
|
||
|
if (auto e = r.SetReplayReproducer(true)) {
|
||
|
std::string error_str = llvm::toString(std::move(e));
|
||
|
result.AppendErrorWithFormat("%s", error_str.c_str());
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (auto loader = r.GetLoader()) {
|
||
|
const char *repro_path = command.GetArgumentAtIndex(0);
|
||
|
if (auto e = loader->LoadIndex(FileSpec(repro_path))) {
|
||
|
std::string error_str = llvm::toString(std::move(e));
|
||
|
result.AppendErrorWithFormat("Unable to load reproducer: %s",
|
||
|
error_str.c_str());
|
||
|
return false;
|
||
|
}
|
||
|
} else {
|
||
|
result.AppendErrorWithFormat("Unable to get the reproducer loader");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
||
|
return result.Succeeded();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class CommandObjectReproducerCapture : public CommandObjectMultiword {
|
||
|
private:
|
||
|
public:
|
||
|
CommandObjectReproducerCapture(CommandInterpreter &interpreter)
|
||
|
: CommandObjectMultiword(
|
||
|
interpreter, "reproducer capture",
|
||
|
"Manage gathering of information needed to generate a reproducer.",
|
||
|
NULL) {
|
||
|
LoadSubCommand(
|
||
|
"enable",
|
||
|
CommandObjectSP(new CommandObjectReproducerCaptureEnable(interpreter)));
|
||
|
LoadSubCommand("disable",
|
||
|
CommandObjectSP(
|
||
|
new CommandObjectReproducerCaptureDisable(interpreter)));
|
||
|
}
|
||
|
|
||
|
~CommandObjectReproducerCapture() {}
|
||
|
};
|
||
|
|
||
|
CommandObjectReproducer::CommandObjectReproducer(
|
||
|
CommandInterpreter &interpreter)
|
||
|
: CommandObjectMultiword(interpreter, "reproducer",
|
||
|
"Commands controlling LLDB reproducers.",
|
||
|
"log <subcommand> [<command-options>]") {
|
||
|
LoadSubCommand("capture", CommandObjectSP(new CommandObjectReproducerCapture(
|
||
|
interpreter)));
|
||
|
LoadSubCommand(
|
||
|
"generate",
|
||
|
CommandObjectSP(new CommandObjectReproducerGenerate(interpreter)));
|
||
|
LoadSubCommand("replay", CommandObjectSP(
|
||
|
new CommandObjectReproducerReplay(interpreter)));
|
||
|
}
|
||
|
|
||
|
CommandObjectReproducer::~CommandObjectReproducer() = default;
|