diff options
author | Jonas Devlieghere <jonas@devlieghere.com> | 2022-09-19 10:47:09 -0700 |
---|---|---|
committer | Jonas Devlieghere <jonas@devlieghere.com> | 2022-09-19 14:43:31 -0700 |
commit | 70599d70273b671b1b2e6a0e0b9c11e413209647 (patch) | |
tree | 2868dfff6c1a64e576d001efc8aa0731bde242e2 /lldb/source/Commands | |
parent | 2e8817b90a9aa38c681ca1bb9075f9e8eed3f6e8 (diff) | |
download | llvm-70599d70273b671b1b2e6a0e0b9c11e413209647.zip llvm-70599d70273b671b1b2e6a0e0b9c11e413209647.tar.gz llvm-70599d70273b671b1b2e6a0e0b9c11e413209647.tar.bz2 |
[lldb] Remove LLDB reproducers
This patch removes the remaining reproducer code. The SBReproducer class
remains for ABI stability but is just an empty shell. This completes the
removal process outlined on the mailing list [1].
[1] https://lists.llvm.org/pipermail/lldb-dev/2021-September/017045.html
Diffstat (limited to 'lldb/source/Commands')
-rw-r--r-- | lldb/source/Commands/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectCommands.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectExpression.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectReproducer.cpp | 503 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectReproducer.h | 27 | ||||
-rw-r--r-- | lldb/source/Commands/Options.td | 21 |
6 files changed, 2 insertions, 554 deletions
diff --git a/lldb/source/Commands/CMakeLists.txt b/lldb/source/Commands/CMakeLists.txt index 494249b..a7d64a3 100644 --- a/lldb/source/Commands/CMakeLists.txt +++ b/lldb/source/Commands/CMakeLists.txt @@ -24,7 +24,6 @@ add_lldb_library(lldbCommands CommandObjectQuit.cpp CommandObjectRegexCommand.cpp CommandObjectRegister.cpp - CommandObjectReproducer.cpp CommandObjectScript.cpp CommandObjectSession.cpp CommandObjectSettings.cpp diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index 97a8833..3d4893d 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -891,7 +891,7 @@ protected: llvm::StringRef(), // Continuation prompt multiple_lines, color_prompt, 0, // Don't show line numbers - *this, nullptr)); + *this)); if (io_handler_sp) { debugger.RunIOHandlerAsync(io_handler_sp); diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 0833091..b7d129e 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -509,7 +509,7 @@ void CommandObjectExpression::GetMultilineExpression() { llvm::StringRef(), // Continuation prompt multiple_lines, color_prompt, 1, // Show line numbers starting at 1 - *this, nullptr)); + *this)); StreamFileSP output_sp = io_handler_sp->GetOutputStreamFileSP(); if (output_sp) { diff --git a/lldb/source/Commands/CommandObjectReproducer.cpp b/lldb/source/Commands/CommandObjectReproducer.cpp deleted file mode 100644 index 6160a83..0000000 --- a/lldb/source/Commands/CommandObjectReproducer.cpp +++ /dev/null @@ -1,503 +0,0 @@ -//===-- CommandObjectReproducer.cpp ---------------------------------------===// -// -// 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/HostInfo.h" -#include "lldb/Host/OptionParser.h" -#include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Interpreter/CommandOptionArgumentTable.h" -#include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/OptionArgParser.h" -#include "lldb/Utility/GDBRemote.h" -#include "lldb/Utility/ProcessInfo.h" -#include "lldb/Utility/Reproducer.h" - -#include <csignal> - -using namespace lldb; -using namespace llvm; -using namespace lldb_private; -using namespace lldb_private::repro; - -#define LLDB_OPTIONS_reproducer_dump -#include "CommandOptions.inc" - -#define LLDB_OPTIONS_reproducer_xcrash -#include "CommandOptions.inc" - -#define LLDB_OPTIONS_reproducer_verify -#include "CommandOptions.inc" - -template <typename T> -llvm::Expected<T> static ReadFromYAML(StringRef filename) { - auto error_or_file = MemoryBuffer::getFile(filename); - if (auto err = error_or_file.getError()) { - return errorCodeToError(err); - } - - T t; - yaml::Input yin((*error_or_file)->getBuffer()); - yin >> t; - - if (auto err = yin.error()) { - return errorCodeToError(err); - } - - return t; -} - -static void SetError(CommandReturnObject &result, Error err) { - result.AppendError(toString(std::move(err))); -} - -/// Create a loader from the given path if specified. Otherwise use the current -/// loader used for replay. -static Loader * -GetLoaderFromPathOrCurrent(llvm::Optional<Loader> &loader_storage, - CommandReturnObject &result, - FileSpec reproducer_path) { - if (reproducer_path) { - loader_storage.emplace(reproducer_path); - Loader *loader = &(*loader_storage); - if (Error err = loader->LoadIndex()) { - // This is a hard error and will set the result to eReturnStatusFailed. - SetError(result, std::move(err)); - return nullptr; - } - return loader; - } - - if (Loader *loader = Reproducer::Instance().GetLoader()) - return loader; - - // This is a soft error because this is expected to fail during capture. - result.AppendError( - "Not specifying a reproducer is only support during replay."); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return nullptr; -} - -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 and quit. In replay mode this command in a no-op.", - nullptr) {} - - ~CommandObjectReproducerGenerate() override = default; - -protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { - auto &r = 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.GetOutputStream() - << "Please have a look at the directory to assess if you're willing to " - "share the contained information.\n"; - - m_interpreter.BroadcastEvent( - CommandInterpreter::eBroadcastBitQuitCommandReceived); - result.SetStatus(eReturnStatusQuit); - return result.Succeeded(); - } -}; - -class CommandObjectReproducerXCrash : public CommandObjectParsed { -public: - CommandObjectReproducerXCrash(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "reproducer xcrash", - "Intentionally force the debugger to crash in " - "order to trigger and test reproducer generation.", - nullptr) {} - - ~CommandObjectReproducerXCrash() override = default; - - Options *GetOptions() override { return &m_options; } - - class CommandOptions : public Options { - public: - CommandOptions() = default; - - ~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 's': - signal = (ReproducerCrashSignal)OptionArgParser::ToOptionEnum( - option_arg, GetDefinitions()[option_idx].enum_values, 0, error); - if (!error.Success()) - error.SetErrorStringWithFormat("unrecognized value for signal '%s'", - option_arg.str().c_str()); - break; - default: - llvm_unreachable("Unimplemented option"); - } - - return error; - } - - void OptionParsingStarting(ExecutionContext *execution_context) override { - signal = eReproducerCrashSigsegv; - } - - ArrayRef<OptionDefinition> GetDefinitions() override { - return makeArrayRef(g_reproducer_xcrash_options); - } - - ReproducerCrashSignal signal = eReproducerCrashSigsegv; - }; - -protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { - auto &r = Reproducer::Instance(); - - if (!r.IsCapturing()) { - result.AppendError( - "forcing a crash is only supported when capturing a reproducer."); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return false; - } - - switch (m_options.signal) { - case eReproducerCrashSigill: - std::raise(SIGILL); - break; - case eReproducerCrashSigsegv: - std::raise(SIGSEGV); - break; - } - - result.SetStatus(eReturnStatusQuit); - return result.Succeeded(); - } - -private: - CommandOptions m_options; -}; - -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 { - auto &r = Reproducer::Instance(); - if (r.IsCapturing()) { - result.GetOutputStream() << "Reproducer is in capture mode.\n"; - result.GetOutputStream() - << "Path: " << r.GetReproducerPath().GetPath() << '\n'; - } else { - result.GetOutputStream() << "Reproducer is off.\n"; - } - - // Auto generate is hidden unless enabled because this is mostly for - // development and testing. - if (Generator *g = r.GetGenerator()) { - if (g->IsAutoGenerate()) - result.GetOutputStream() << "Auto generate: on\n"; - } - - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); - } -}; - -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() = default; - - ~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_dump_options); - } - - FileSpec file; - ReproducerProvider provider = eReproducerProviderNone; - }; - -protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { - llvm::Optional<Loader> loader_storage; - Loader *loader = - GetLoaderFromPathOrCurrent(loader_storage, result, m_options.file); - if (!loader) - return false; - - 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).print(os); - os.flush(); - - // Return the string. - result.AppendMessage(str); - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - case eReproducerProviderSymbolFiles: { - Expected<std::string> symbol_files = - loader->LoadBuffer<SymbolFileProvider>(); - if (!symbol_files) { - SetError(result, symbol_files.takeError()); - return false; - } - - std::vector<SymbolFileProvider::Entry> entries; - llvm::yaml::Input yin(*symbol_files); - yin >> entries; - - for (const auto &entry : entries) { - result.AppendMessageWithFormat("- uuid: %s\n", - entry.uuid.c_str()); - result.AppendMessageWithFormat(" module path: %s\n", - entry.module_path.c_str()); - result.AppendMessageWithFormat(" symbol path: %s\n", - entry.symbol_path.c_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 = - repro::GetDirectoryFrom<WorkingDirectoryProvider>(loader); - if (!cwd) { - SetError(result, cwd.takeError()); - return false; - } - result.AppendMessage(*cwd); - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - case eReproducerProviderHomeDirectory: { - Expected<std::string> home = - repro::GetDirectoryFrom<HomeDirectoryProvider>(loader); - if (!home) { - SetError(result, home.takeError()); - return false; - } - result.AppendMessage(*home); - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - case eReproducerProviderCommands: { - std::unique_ptr<repro::MultiLoader<repro::CommandProvider>> multi_loader = - repro::MultiLoader<repro::CommandProvider>::Create(loader); - if (!multi_loader) { - SetError(result, - make_error<StringError>("Unable to create command loader.", - llvm::inconvertibleErrorCode())); - return false; - } - - // Iterate over the command files and dump them. - llvm::Optional<std::string> command_file; - while ((command_file = multi_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: { - std::unique_ptr<repro::MultiLoader<repro::GDBRemoteProvider>> - multi_loader = - repro::MultiLoader<repro::GDBRemoteProvider>::Create(loader); - - if (!multi_loader) { - SetError(result, - make_error<StringError>("Unable to create GDB loader.", - llvm::inconvertibleErrorCode())); - return false; - } - - llvm::Optional<std::string> gdb_file; - while ((gdb_file = multi_loader->GetNextFile())) { - if (llvm::Expected<std::vector<GDBRemotePacket>> packets = - ReadFromYAML<std::vector<GDBRemotePacket>>(*gdb_file)) { - for (GDBRemotePacket &packet : *packets) { - packet.Dump(result.GetOutputStream()); - } - } else { - SetError(result, packets.takeError()); - return false; - } - } - - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - case eReproducerProviderProcessInfo: { - std::unique_ptr<repro::MultiLoader<repro::ProcessInfoProvider>> - multi_loader = - repro::MultiLoader<repro::ProcessInfoProvider>::Create(loader); - - if (!multi_loader) { - SetError(result, make_error<StringError>( - llvm::inconvertibleErrorCode(), - "Unable to create process info loader.")); - return false; - } - - llvm::Optional<std::string> process_file; - while ((process_file = multi_loader->GetNextFile())) { - if (llvm::Expected<ProcessInstanceInfoList> infos = - ReadFromYAML<ProcessInstanceInfoList>(*process_file)) { - for (ProcessInstanceInfo info : *infos) - info.Dump(result.GetOutputStream(), HostInfo::GetUserIDResolver()); - } else { - SetError(result, infos.takeError()); - return false; - } - } - - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - case eReproducerProviderNone: - result.AppendError("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))); - LoadSubCommand("xcrash", CommandObjectSP( - new CommandObjectReproducerXCrash(interpreter))); -} - -CommandObjectReproducer::~CommandObjectReproducer() = default; diff --git a/lldb/source/Commands/CommandObjectReproducer.h b/lldb/source/Commands/CommandObjectReproducer.h deleted file mode 100644 index bdee8053..0000000 --- a/lldb/source/Commands/CommandObjectReproducer.h +++ /dev/null @@ -1,27 +0,0 @@ -//===-- CommandObjectReproducer.h -------------------------------*- 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 -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTREPRODUCER_H -#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTREPRODUCER_H - -#include "lldb/Interpreter/CommandObjectMultiword.h" - -namespace lldb_private { - -// CommandObjectReproducer - -class CommandObjectReproducer : public CommandObjectMultiword { -public: - CommandObjectReproducer(CommandInterpreter &interpreter); - - ~CommandObjectReproducer() override; -}; - -} // namespace lldb_private - -#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTREPRODUCER_H diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index 0b5791d..eafe85f 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -466,27 +466,6 @@ let Command = "log dump" in { Desc<"Set the destination file to dump to.">; } -let Command = "reproducer dump" in { - def reproducer_provider : Option<"provider", "p">, Group<1>, - EnumArg<"ReproducerProvider">, - Required, Desc<"The reproducer provider to dump.">; - def reproducer_file : Option<"file", "f">, Group<1>, Arg<"Filename">, - Desc<"The reproducer path. If a reproducer is replayed and no path is " - "provided, that reproducer is dumped.">; -} - -let Command = "reproducer verify" in { - def reproducer_verify_file : Option<"file", "f">, Group<1>, Arg<"Filename">, - Desc<"The reproducer path. If a reproducer is replayed and no path is " - "provided, that reproducer is dumped.">; -} - -let Command = "reproducer xcrash" in { - def reproducer_signal : Option<"signal", "s">, Group<1>, - EnumArg<"ReproducerSignal">, - Required, Desc<"The signal to crash the debugger.">; -} - let Command = "memory read" in { def memory_read_num_per_line : Option<"num-per-line", "l">, Group<1>, Arg<"NumberPerLine">, Desc<"The number of items per line to display.">; |