diff options
Diffstat (limited to 'source/Commands/CommandObjectReproducer.cpp')
| -rw-r--r-- | source/Commands/CommandObjectReproducer.cpp | 385 |
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; |
