diff options
author | Jonas Devlieghere <jonas@devlieghere.com> | 2018-11-13 19:18:16 +0000 |
---|---|---|
committer | Jonas Devlieghere <jonas@devlieghere.com> | 2018-11-13 19:18:16 +0000 |
commit | 9e046f02e34fbb93eea1bd8b4136da7fd8d06612 (patch) | |
tree | a5fcd26ec570e8a3262ab7ea7e312930e9014cdd /lldb/source/Commands/CommandObjectReproducer.cpp | |
parent | 3bea50aeb35704798aefa9acbb8973c7864f3732 (diff) | |
download | bcm5719-llvm-9e046f02e34fbb93eea1bd8b4136da7fd8d06612.tar.gz bcm5719-llvm-9e046f02e34fbb93eea1bd8b4136da7fd8d06612.zip |
Add GDB remote packet reproducer.
llvm-svn: 346780
Diffstat (limited to 'lldb/source/Commands/CommandObjectReproducer.cpp')
-rw-r--r-- | lldb/source/Commands/CommandObjectReproducer.cpp | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/lldb/source/Commands/CommandObjectReproducer.cpp b/lldb/source/Commands/CommandObjectReproducer.cpp new file mode 100644 index 00000000000..e69a6308892 --- /dev/null +++ b/lldb/source/Commands/CommandObjectReproducer.cpp @@ -0,0 +1,206 @@ +//===-- 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; |