diff options
Diffstat (limited to 'lldb/source/Commands/CommandObjectReproducer.cpp')
-rw-r--r-- | lldb/source/Commands/CommandObjectReproducer.cpp | 99 |
1 files changed, 81 insertions, 18 deletions
diff --git a/lldb/source/Commands/CommandObjectReproducer.cpp b/lldb/source/Commands/CommandObjectReproducer.cpp index d15f622314d9..104130b70b2b 100644 --- a/lldb/source/Commands/CommandObjectReproducer.cpp +++ b/lldb/source/Commands/CommandObjectReproducer.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectReproducer.cpp -----------------------------*- C++ -*-===// +//===-- 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. @@ -8,13 +8,14 @@ #include "CommandObjectReproducer.h" +#include "lldb/Host/HostInfo.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/Utility/GDBRemote.h" +#include "lldb/Utility/ProcessInfo.h" +#include "lldb/Utility/Reproducer.h" #include <csignal> @@ -27,6 +28,7 @@ enum ReproducerProvider { eReproducerProviderCommands, eReproducerProviderFiles, eReproducerProviderGDB, + eReproducerProviderProcessInfo, eReproducerProviderVersion, eReproducerProviderWorkingDirectory, eReproducerProviderNone @@ -49,6 +51,11 @@ static constexpr OptionEnumValueElement g_reproducer_provider_type[] = { "GDB Remote Packets", }, { + eReproducerProviderProcessInfo, + "processes", + "Process Info", + }, + { eReproducerProviderVersion, "version", "Version", @@ -97,6 +104,24 @@ static constexpr OptionEnumValues ReproducerSignalType() { #define LLDB_OPTIONS_reproducer_xcrash #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; +} + class CommandObjectReproducerGenerate : public CommandObjectParsed { public: CommandObjectReproducerGenerate(CommandInterpreter &interpreter) @@ -258,6 +283,18 @@ protected: result.GetOutputStream() << "Reproducer is off.\n"; } + if (r.IsCapturing() || r.IsReplaying()) { + result.GetOutputStream() + << "Path: " << r.GetReproducerPath().GetPath() << '\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(); } @@ -410,8 +447,8 @@ protected: repro::MultiLoader<repro::CommandProvider>::Create(loader); if (!multi_loader) { SetError(result, - make_error<StringError>(llvm::inconvertibleErrorCode(), - "Unable to create command loader.")); + make_error<StringError>("Unable to create command loader.", + llvm::inconvertibleErrorCode())); return false; } @@ -436,26 +473,52 @@ protected: 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())) { - auto error_or_file = MemoryBuffer::getFile(*gdb_file); - if (auto err = error_or_file.getError()) { - SetError(result, errorCodeToError(err)); + 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); - std::vector<GDBRemotePacket> packets; - yaml::Input yin((*error_or_file)->getBuffer()); - yin >> packets; + if (!multi_loader) { + SetError(result, make_error<StringError>( + llvm::inconvertibleErrorCode(), + "Unable to create process info loader.")); + return false; + } - if (auto err = yin.error()) { - SetError(result, errorCodeToError(err)); + 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; } - - for (GDBRemotePacket &packet : packets) { - packet.Dump(result.GetOutputStream()); - } } result.SetStatus(eReturnStatusSuccessFinishResult); |