aboutsummaryrefslogtreecommitdiff
path: root/source/Commands/CommandObjectReproducer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Commands/CommandObjectReproducer.cpp')
-rw-r--r--source/Commands/CommandObjectReproducer.cpp385
1 files changed, 0 insertions, 385 deletions
diff --git a/source/Commands/CommandObjectReproducer.cpp b/source/Commands/CommandObjectReproducer.cpp
deleted file mode 100644
index dc4579c20fc2..000000000000
--- a/source/Commands/CommandObjectReproducer.cpp
+++ /dev/null
@@ -1,385 +0,0 @@
-//===-- CommandObjectReproducer.cpp -----------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "CommandObjectReproducer.h"
-
-#include "lldb/Host/OptionParser.h"
-#include "lldb/Utility/GDBRemote.h"
-#include "lldb/Utility/Reproducer.h"
-
-#include "lldb/Interpreter/CommandInterpreter.h"
-#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Interpreter/OptionArgParser.h"
-#include "lldb/Interpreter/OptionGroupBoolean.h"
-
-using namespace lldb;
-using namespace llvm;
-using namespace lldb_private;
-using namespace lldb_private::repro;
-
-enum ReproducerProvider {
- eReproducerProviderCommands,
- eReproducerProviderFiles,
- eReproducerProviderGDB,
- eReproducerProviderVersion,
- eReproducerProviderWorkingDirectory,
- eReproducerProviderNone
-};
-
-static constexpr OptionEnumValueElement g_reproducer_provider_type[] = {
- {
- eReproducerProviderCommands,
- "commands",
- "Command Interpreter Commands",
- },
- {
- eReproducerProviderFiles,
- "files",
- "Files",
- },
- {
- eReproducerProviderGDB,
- "gdb",
- "GDB Remote Packets",
- },
- {
- eReproducerProviderVersion,
- "version",
- "Version",
- },
- {
- eReproducerProviderWorkingDirectory,
- "cwd",
- "Working Directory",
- },
- {
- eReproducerProviderNone,
- "none",
- "None",
- },
-};
-
-static constexpr OptionEnumValues ReproducerProviderType() {
- return OptionEnumValues(g_reproducer_provider_type);
-}
-
-#define LLDB_OPTIONS_reproducer
-#include "CommandOptions.inc"
-
-class CommandObjectReproducerGenerate : public CommandObjectParsed {
-public:
- CommandObjectReproducerGenerate(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "reproducer generate",
- "Generate reproducer on disk. When the debugger is in capture "
- "mode, this command will output the reproducer to a directory on "
- "disk. In replay mode this command in a no-op.",
- 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 = Reproducer::Instance();
- if (auto generator = r.GetGenerator()) {
- generator->Keep();
- } else if (r.IsReplaying()) {
- // Make this operation a NOP in replay mode.
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- return result.Succeeded();
- } else {
- result.AppendErrorWithFormat("Unable to get the reproducer generator");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- result.GetOutputStream()
- << "Reproducer written to '" << r.GetReproducerPath() << "'\n";
- result.GetOutputStream()
- << "Please have a look at the directory to assess if you're willing to "
- "share the contained information.\n";
-
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return result.Succeeded();
- }
-};
-
-class CommandObjectReproducerStatus : public CommandObjectParsed {
-public:
- CommandObjectReproducerStatus(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "reproducer status",
- "Show the current reproducer status. In capture mode the debugger "
- "is collecting all the information it needs to create a "
- "reproducer. In replay mode the reproducer is replaying a "
- "reproducer. When the reproducers are off, no data is collected "
- "and no reproducer can be generated.",
- nullptr) {}
-
- ~CommandObjectReproducerStatus() 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 = Reproducer::Instance();
- if (r.IsCapturing()) {
- result.GetOutputStream() << "Reproducer is in capture mode.\n";
- } else if (r.IsReplaying()) {
- result.GetOutputStream() << "Reproducer is in replay mode.\n";
- } else {
- result.GetOutputStream() << "Reproducer is off.\n";
- }
-
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return result.Succeeded();
- }
-};
-
-static void SetError(CommandReturnObject &result, Error err) {
- result.GetErrorStream().Printf("error: %s\n",
- toString(std::move(err)).c_str());
- result.SetStatus(eReturnStatusFailed);
-}
-
-class CommandObjectReproducerDump : public CommandObjectParsed {
-public:
- CommandObjectReproducerDump(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "reproducer dump",
- "Dump the information contained in a reproducer. "
- "If no reproducer is specified during replay, it "
- "dumps the content of the current reproducer.",
- nullptr) {}
-
- ~CommandObjectReproducerDump() override = default;
-
- Options *GetOptions() override { return &m_options; }
-
- class CommandOptions : public Options {
- public:
- CommandOptions() : Options(), file() {}
-
- ~CommandOptions() override = default;
-
- Status SetOptionValue(uint32_t option_idx, StringRef option_arg,
- ExecutionContext *execution_context) override {
- Status error;
- const int short_option = m_getopt_table[option_idx].val;
-
- switch (short_option) {
- case 'f':
- file.SetFile(option_arg, FileSpec::Style::native);
- FileSystem::Instance().Resolve(file);
- break;
- case 'p':
- provider = (ReproducerProvider)OptionArgParser::ToOptionEnum(
- option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
- if (!error.Success())
- error.SetErrorStringWithFormat("unrecognized value for provider '%s'",
- option_arg.str().c_str());
- break;
- default:
- llvm_unreachable("Unimplemented option");
- }
-
- return error;
- }
-
- void OptionParsingStarting(ExecutionContext *execution_context) override {
- file.Clear();
- provider = eReproducerProviderNone;
- }
-
- ArrayRef<OptionDefinition> GetDefinitions() override {
- return makeArrayRef(g_reproducer_options);
- }
-
- FileSpec file;
- ReproducerProvider provider = eReproducerProviderNone;
- };
-
-protected:
- bool DoExecute(Args &command, CommandReturnObject &result) override {
- if (!command.empty()) {
- result.AppendErrorWithFormat("'%s' takes no arguments",
- m_cmd_name.c_str());
- return false;
- }
-
- // If no reproducer path is specified, use the loader currently used for
- // replay. Otherwise create a new loader just for dumping.
- llvm::Optional<Loader> loader_storage;
- Loader *loader = nullptr;
- if (!m_options.file) {
- loader = Reproducer::Instance().GetLoader();
- if (loader == nullptr) {
- result.SetError(
- "Not specifying a reproducer is only support during replay.");
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- return false;
- }
- } else {
- loader_storage.emplace(m_options.file);
- loader = &(*loader_storage);
- if (Error err = loader->LoadIndex()) {
- SetError(result, std::move(err));
- return false;
- }
- }
-
- // If we get here we should have a valid loader.
- assert(loader);
-
- switch (m_options.provider) {
- case eReproducerProviderFiles: {
- FileSpec vfs_mapping = loader->GetFile<FileProvider::Info>();
-
- // Read the VFS mapping.
- ErrorOr<std::unique_ptr<MemoryBuffer>> buffer =
- vfs::getRealFileSystem()->getBufferForFile(vfs_mapping.GetPath());
- if (!buffer) {
- SetError(result, errorCodeToError(buffer.getError()));
- return false;
- }
-
- // Initialize a VFS from the given mapping.
- IntrusiveRefCntPtr<vfs::FileSystem> vfs = vfs::getVFSFromYAML(
- std::move(buffer.get()), nullptr, vfs_mapping.GetPath());
-
- // Dump the VFS to a buffer.
- std::string str;
- raw_string_ostream os(str);
- static_cast<vfs::RedirectingFileSystem &>(*vfs).dump(os);
- os.flush();
-
- // Return the string.
- result.AppendMessage(str);
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
- case eReproducerProviderVersion: {
- Expected<std::string> version = loader->LoadBuffer<VersionProvider>();
- if (!version) {
- SetError(result, version.takeError());
- return false;
- }
- result.AppendMessage(*version);
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
- case eReproducerProviderWorkingDirectory: {
- Expected<std::string> cwd =
- loader->LoadBuffer<WorkingDirectoryProvider>();
- if (!cwd) {
- SetError(result, cwd.takeError());
- return false;
- }
- result.AppendMessage(*cwd);
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
- case eReproducerProviderCommands: {
- // Create a new command loader.
- std::unique_ptr<repro::CommandLoader> command_loader =
- repro::CommandLoader::Create(loader);
- if (!command_loader) {
- SetError(result,
- make_error<StringError>(llvm::inconvertibleErrorCode(),
- "Unable to create command loader."));
- return false;
- }
-
- // Iterate over the command files and dump them.
- while (true) {
- llvm::Optional<std::string> command_file =
- command_loader->GetNextFile();
- if (!command_file)
- break;
-
- auto command_buffer = llvm::MemoryBuffer::getFile(*command_file);
- if (auto err = command_buffer.getError()) {
- SetError(result, errorCodeToError(err));
- return false;
- }
- result.AppendMessage((*command_buffer)->getBuffer());
- }
-
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
- case eReproducerProviderGDB: {
- FileSpec gdb_file = loader->GetFile<ProcessGDBRemoteProvider::Info>();
- auto error_or_file = MemoryBuffer::getFile(gdb_file.GetPath());
- if (auto err = error_or_file.getError()) {
- SetError(result, errorCodeToError(err));
- return false;
- }
-
- std::vector<GDBRemotePacket> packets;
- yaml::Input yin((*error_or_file)->getBuffer());
- yin >> packets;
-
- if (auto err = yin.error()) {
- SetError(result, errorCodeToError(err));
- return false;
- }
-
- for (GDBRemotePacket &packet : packets) {
- packet.Dump(result.GetOutputStream());
- }
-
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
- case eReproducerProviderNone:
- result.SetError("No valid provider specified.");
- return false;
- }
-
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- return result.Succeeded();
- }
-
-private:
- CommandOptions m_options;
-};
-
-CommandObjectReproducer::CommandObjectReproducer(
- CommandInterpreter &interpreter)
- : CommandObjectMultiword(
- interpreter, "reproducer",
- "Commands for manipulating reproducers. Reproducers make it possible "
- "to capture full debug sessions with all its dependencies. The "
- "resulting reproducer is used to replay the debug session while "
- "debugging the debugger.\n"
- "Because reproducers need the whole the debug session from "
- "beginning to end, you need to launch the debugger in capture or "
- "replay mode, commonly though the command line driver.\n"
- "Reproducers are unrelated record-replay debugging, as you cannot "
- "interact with the debugger during replay.\n",
- "reproducer <subcommand> [<subcommand-options>]") {
- LoadSubCommand(
- "generate",
- CommandObjectSP(new CommandObjectReproducerGenerate(interpreter)));
- LoadSubCommand("status", CommandObjectSP(
- new CommandObjectReproducerStatus(interpreter)));
- LoadSubCommand("dump",
- CommandObjectSP(new CommandObjectReproducerDump(interpreter)));
-}
-
-CommandObjectReproducer::~CommandObjectReproducer() = default;