[Lldb-commits] [lldb] e81268d - [lldb/Reproducers] Support multiple GDB remotes
Eric Christopher via lldb-commits
lldb-commits at lists.llvm.org
Tue Dec 10 12:21:03 PST 2019
Hi Jonas,
This appears to be causing crashes in a release asserts build:
#3 0x00007efe57b613a0 __restore_rt
(/lib/x86_64-linux-gnu/libpthread.so.0+0x123a0)
#4 0x00007efe54178d00 llvm::raw_ostream::operator<<(llvm::StringRef)
sources/llvm-project/llvm/include/llvm/Support/raw_ostream.h:190:7
#5 0x00007efe54178d00 llvm::yaml::Output::output(llvm::StringRef)
sources/llvm-project/llvm/lib/Support/YAMLTraits.cpp:751:7
#6 0x00007efe54178d00
llvm::yaml::Output::outputUpToEndOfLine(llvm::StringRef)
sources/llvm-project/llvm/lib/Support/YAMLTraits.cpp:755:3
#7 0x00007efe54178d00 llvm::yaml::Output::beginDocuments()
sources/llvm-project/llvm/lib/Support/YAMLTraits.cpp:537:3
#8 0x00007efe53fc5d7e
std::enable_if<has_MappingTraits<lldb_private::GDBRemotePacket,
llvm::yaml::EmptyContext>::value, llvm::yaml::Output&>::type
llvm::yaml::operator<<<lldb_private::GDBRemotePacket>(llvm::yaml::Output&,
lldb_private::GDBRemotePacket&)
sources/llvm-project/llvm/include/llvm/Support/YAMLTraits.h:1796:13
#9 0x00007efe53fc5d7e
lldb_private::GDBRemotePacket::Serialize(llvm::raw_ostream&) const
sources/llvm-project/lldb/source/Utility/GDBRemote.cpp:50:8
...
want to revert and see what's going on? Happy to help if you can't
duplicate?
Thanks!
-eric
On Tue, Dec 10, 2019 at 11:17 AM Jonas Devlieghere via lldb-commits <
lldb-commits at lists.llvm.org> wrote:
>
> Author: Jonas Devlieghere
> Date: 2019-12-10T11:16:52-08:00
> New Revision: e81268d03e73aef4f9c7bd8ece8ad02f5b017dcf
>
> URL:
> https://github.com/llvm/llvm-project/commit/e81268d03e73aef4f9c7bd8ece8ad02f5b017dcf
> DIFF:
> https://github.com/llvm/llvm-project/commit/e81268d03e73aef4f9c7bd8ece8ad02f5b017dcf.diff
>
> LOG: [lldb/Reproducers] Support multiple GDB remotes
>
> When running the test suite with always capture on, a handful of tests
> are failing because they have multiple targets and therefore multiple
> GDB remote connections. The current reproducer infrastructure is capable
> of dealing with that.
>
> This patch reworks the GDB remote provider to support multiple GDB
> remote connections, similar to how the reproducers support shadowing
> multiple command interpreter inputs. The provider now keeps a list of
> packet recorders which deal with a single GDB remote connection. During
> replay we rely on the order of creation to match the number of packets
> to the GDB remote connection.
>
> Differential revision: https://reviews.llvm.org/D71105
>
> Added:
> lldb/test/Shell/Reproducer/Inputs/MultipleTargetsCapture.in
> lldb/test/Shell/Reproducer/TestMultipleTargets.test
>
> Modified:
> lldb/include/lldb/Utility/GDBRemote.h
> lldb/include/lldb/Utility/Reproducer.h
> lldb/source/API/SBDebugger.cpp
> lldb/source/Commands/CommandObjectReproducer.cpp
> lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
> lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
>
> lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
> lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
> lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
> lldb/source/Utility/GDBRemote.cpp
> lldb/source/Utility/Reproducer.cpp
>
> Removed:
>
>
>
>
> ################################################################################
> diff --git a/lldb/include/lldb/Utility/GDBRemote.h
> b/lldb/include/lldb/Utility/GDBRemote.h
> index b4adeb368524..21b2c8cd73cd 100644
> --- a/lldb/include/lldb/Utility/GDBRemote.h
> +++ b/lldb/include/lldb/Utility/GDBRemote.h
> @@ -9,6 +9,8 @@
> #ifndef liblldb_GDBRemote_h_
> #define liblldb_GDBRemote_h_
>
> +#include "lldb/Utility/FileSpec.h"
> +#include "lldb/Utility/Reproducer.h"
> #include "lldb/Utility/StreamString.h"
> #include "lldb/lldb-enumerations.h"
> #include "lldb/lldb-public.h"
> @@ -69,7 +71,6 @@ struct GDBRemotePacket {
> std::string data;
> };
>
> - void Serialize(llvm::raw_ostream &strm) const;
> void Dump(Stream &strm) const;
>
> BinaryData packet;
> @@ -82,6 +83,46 @@ struct GDBRemotePacket {
> llvm::StringRef GetTypeStr() const;
> };
>
> +namespace repro {
> +class PacketRecorder : public AbstractRecorder {
> +public:
> + PacketRecorder(const FileSpec &filename, std::error_code &ec)
> + : AbstractRecorder(filename, ec) {}
> +
> + static llvm::Expected<std::unique_ptr<PacketRecorder>>
> + Create(const FileSpec &filename);
> +
> + void Record(const GDBRemotePacket &packet);
> +};
> +
> +class GDBRemoteProvider : public repro::Provider<GDBRemoteProvider> {
> +public:
> + struct Info {
> + static const char *name;
> + static const char *file;
> + };
> +
> + GDBRemoteProvider(const FileSpec &directory) : Provider(directory) {}
> +
> + llvm::raw_ostream *GetHistoryStream();
> + PacketRecorder *GetNewPacketRecorder();
> +
> + void SetCallback(std::function<void()> callback) {
> + m_callback = std::move(callback);
> + }
> +
> + void Keep() override;
> + void Discard() override;
> +
> + static char ID;
> +
> +private:
> + std::function<void()> m_callback;
> + std::unique_ptr<llvm::raw_fd_ostream> m_stream_up;
> + std::vector<std::unique_ptr<PacketRecorder>> m_packet_recorders;
> +};
> +
> +} // namespace repro
> } // namespace lldb_private
>
> LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(lldb_private::GDBRemotePacket)
>
> diff --git a/lldb/include/lldb/Utility/Reproducer.h
> b/lldb/include/lldb/Utility/Reproducer.h
> index ddb1f45a7219..0d23fe8571ff 100644
> --- a/lldb/include/lldb/Utility/Reproducer.h
> +++ b/lldb/include/lldb/Utility/Reproducer.h
> @@ -153,24 +153,13 @@ class WorkingDirectoryProvider : public
> Provider<WorkingDirectoryProvider> {
> static char ID;
> };
>
> -class DataRecorder {
> -public:
> - DataRecorder(const FileSpec &filename, std::error_code &ec)
> +class AbstractRecorder {
> +protected:
> + AbstractRecorder(const FileSpec &filename, std::error_code &ec)
> : m_filename(filename.GetFilename().GetStringRef()),
> m_os(filename.GetPath(), ec, llvm::sys::fs::OF_Text),
> m_record(true) {}
>
> - static llvm::Expected<std::unique_ptr<DataRecorder>>
> - Create(const FileSpec &filename);
> -
> - template <typename T> void Record(const T &t, bool newline = false) {
> - if (!m_record)
> - return;
> - m_os << t;
> - if (newline)
> - m_os << '\n';
> - m_os.flush();
> - }
> -
> +public:
> const FileSpec &GetFilename() { return m_filename; }
>
> void Stop() {
> @@ -180,10 +169,30 @@ class DataRecorder {
>
> private:
> FileSpec m_filename;
> +
> +protected:
> llvm::raw_fd_ostream m_os;
> bool m_record;
> };
>
> +class DataRecorder : public AbstractRecorder {
> +public:
> + DataRecorder(const FileSpec &filename, std::error_code &ec)
> + : AbstractRecorder(filename, ec) {}
> +
> + static llvm::Expected<std::unique_ptr<DataRecorder>>
> + Create(const FileSpec &filename);
> +
> + template <typename T> void Record(const T &t, bool newline = false) {
> + if (!m_record)
> + return;
> + m_os << t;
> + if (newline)
> + m_os << '\n';
> + m_os.flush();
> + }
> +};
> +
> class CommandProvider : public Provider<CommandProvider> {
> public:
> struct Info {
> @@ -204,32 +213,6 @@ class CommandProvider : public
> Provider<CommandProvider> {
> std::vector<std::unique_ptr<DataRecorder>> m_data_recorders;
> };
>
> -class ProcessGDBRemoteProvider
> - : public repro::Provider<ProcessGDBRemoteProvider> {
> -public:
> - struct Info {
> - static const char *name;
> - static const char *file;
> - };
> -
> - ProcessGDBRemoteProvider(const FileSpec &directory) :
> Provider(directory) {}
> -
> - llvm::raw_ostream *GetHistoryStream();
> -
> - void SetCallback(std::function<void()> callback) {
> - m_callback = std::move(callback);
> - }
> -
> - void Keep() override { m_callback(); }
> - void Discard() override { m_callback(); }
> -
> - static char ID;
> -
> -private:
> - std::function<void()> m_callback;
> - std::unique_ptr<llvm::raw_fd_ostream> m_stream_up;
> -};
> -
> /// The generator is responsible for the logic needed to generate a
> /// reproducer. For doing so it relies on providers, who serialize data
> that
> /// is necessary for reproducing a failure.
> @@ -359,13 +342,43 @@ class Reproducer {
> mutable std::mutex m_mutex;
> };
>
> -/// Helper class for replaying commands through the reproducer.
> -class CommandLoader {
> +template <typename T> class MultiLoader {
> public:
> - CommandLoader(std::vector<std::string> files) : m_files(files) {}
> + MultiLoader(std::vector<std::string> files) : m_files(files) {}
> +
> + static std::unique_ptr<MultiLoader> Create(Loader *loader) {
> + if (!loader)
> + return {};
> +
> + FileSpec file = loader->GetFile<typename T::Info>();
> + if (!file)
> + return {};
> +
> + auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath());
> + if (auto err = error_or_file.getError())
> + return {};
>
> - static std::unique_ptr<CommandLoader> Create(Loader *loader);
> - llvm::Optional<std::string> GetNextFile();
> + std::vector<std::string> files;
> + llvm::yaml::Input yin((*error_or_file)->getBuffer());
> + yin >> files;
> +
> + if (auto err = yin.error())
> + return {};
> +
> + for (auto &file : files) {
> + FileSpec absolute_path =
> + loader->GetRoot().CopyByAppendingPathComponent(file);
> + file = absolute_path.GetPath();
> + }
> +
> + return std::make_unique<MultiLoader<T>>(std::move(files));
> + }
> +
> + llvm::Optional<std::string> GetNextFile() {
> + if (m_index >= m_files.size())
> + return {};
> + return m_files[m_index++];
> + }
>
> private:
> std::vector<std::string> m_files;
>
> diff --git a/lldb/source/API/SBDebugger.cpp
> b/lldb/source/API/SBDebugger.cpp
> index 090a3a57a2f4..e938727391e0 100644
> --- a/lldb/source/API/SBDebugger.cpp
> +++ b/lldb/source/API/SBDebugger.cpp
> @@ -315,8 +315,9 @@ SBError SBDebugger::SetInputFile(SBFile file) {
>
> FileSP file_sp = file.m_opaque_sp;
>
> - static std::unique_ptr<repro::CommandLoader> loader =
> -
> repro::CommandLoader::Create(repro::Reproducer::Instance().GetLoader());
> + static std::unique_ptr<repro::MultiLoader<repro::CommandProvider>>
> loader =
> + repro::MultiLoader<repro::CommandProvider>::Create(
> + repro::Reproducer::Instance().GetLoader());
> if (loader) {
> llvm::Optional<std::string> nextfile = loader->GetNextFile();
> FILE *fh = nextfile ? FileSystem::Instance().Fopen(nextfile->c_str(),
> "r")
>
> diff --git a/lldb/source/Commands/CommandObjectReproducer.cpp
> b/lldb/source/Commands/CommandObjectReproducer.cpp
> index a4c69db492da..0f05c564a0d1 100644
> --- a/lldb/source/Commands/CommandObjectReproducer.cpp
> +++ b/lldb/source/Commands/CommandObjectReproducer.cpp
> @@ -407,10 +407,9 @@ class CommandObjectReproducerDump : public
> CommandObjectParsed {
> return true;
> }
> case eReproducerProviderCommands: {
> - // Create a new command loader.
> - std::unique_ptr<repro::CommandLoader> command_loader =
> - repro::CommandLoader::Create(loader);
> - if (!command_loader) {
> + std::unique_ptr<repro::MultiLoader<repro::CommandProvider>>
> multi_loader =
> + repro::MultiLoader<repro::CommandProvider>::Create(loader);
> + if (!multi_loader) {
> SetError(result,
> make_error<StringError>(llvm::inconvertibleErrorCode(),
> "Unable to create command
> loader."));
> @@ -418,9 +417,8 @@ class CommandObjectReproducerDump : public
> CommandObjectParsed {
> }
>
> // Iterate over the command files and dump them.
> - while (true) {
> - llvm::Optional<std::string> command_file =
> - command_loader->GetNextFile();
> + llvm::Optional<std::string> command_file;
> + while ((command_file = multi_loader->GetNextFile())) {
> if (!command_file)
> break;
>
> @@ -436,24 +434,29 @@ class CommandObjectReproducerDump : public
> CommandObjectParsed {
> 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::unique_ptr<repro::MultiLoader<repro::GDBRemoteProvider>>
> + multi_loader =
> +
> repro::MultiLoader<repro::GDBRemoteProvider>::Create(loader);
> + 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));
> + return false;
> + }
>
> - std::vector<GDBRemotePacket> packets;
> - yaml::Input yin((*error_or_file)->getBuffer());
> - yin >> packets;
> + std::vector<GDBRemotePacket> packets;
> + yaml::Input yin((*error_or_file)->getBuffer());
> + yin >> packets;
>
> - if (auto err = yin.error()) {
> - SetError(result, errorCodeToError(err));
> - return false;
> - }
> + if (auto err = yin.error()) {
> + SetError(result, errorCodeToError(err));
> + return false;
> + }
>
> - for (GDBRemotePacket &packet : packets) {
> - packet.Dump(result.GetOutputStream());
> + for (GDBRemotePacket &packet : packets) {
> + packet.Dump(result.GetOutputStream());
> + }
> }
>
> result.SetStatus(eReturnStatusSuccessFinishResult);
>
> diff --git
> a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
> b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
> index 144ae103faa4..0a98f6a15d75 100644
> --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
> +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
> @@ -31,6 +31,7 @@
> #include "lldb/Utility/FileSpec.h"
> #include "lldb/Utility/Log.h"
> #include "lldb/Utility/RegularExpression.h"
> +#include "lldb/Utility/Reproducer.h"
> #include "lldb/Utility/StreamString.h"
> #include "llvm/ADT/SmallString.h"
> #include "llvm/Support/ScopedPrinter.h"
> @@ -1243,8 +1244,9 @@ Status
> GDBRemoteCommunication::StartDebugserverProcess(
>
> void GDBRemoteCommunication::DumpHistory(Stream &strm) {
> m_history.Dump(strm); }
>
> -void GDBRemoteCommunication::SetHistoryStream(llvm::raw_ostream *strm) {
> - m_history.SetStream(strm);
> +void GDBRemoteCommunication::SetPacketRecorder(
> + repro::PacketRecorder *recorder) {
> + m_history.SetRecorder(recorder);
> }
>
> llvm::Error
>
> diff --git
> a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
> b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
> index bb777a5c26a7..0b670018bd69 100644
> --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
> +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
> @@ -27,6 +27,9 @@
> #include "lldb/lldb-public.h"
>
> namespace lldb_private {
> +namespace repro {
> +class PacketRecorder;
> +}
> namespace process_gdb_remote {
>
> enum GDBStoppointType {
> @@ -133,7 +136,8 @@ class GDBRemoteCommunication : public Communication {
> // fork/exec to avoid having to connect/accept
>
> void DumpHistory(Stream &strm);
> - void SetHistoryStream(llvm::raw_ostream *strm);
> +
> + void SetPacketRecorder(repro::PacketRecorder *recorder);
>
> static llvm::Error ConnectLocally(GDBRemoteCommunication &client,
> GDBRemoteCommunication &server);
>
> diff --git
> a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
> b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
> index d2cc32f63f20..9e5646985f87 100644
> ---
> a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
> +++
> b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
> @@ -40,8 +40,8 @@ void GDBRemoteCommunicationHistory::AddPacket(char
> packet_char,
> m_packets[idx].bytes_transmitted = bytes_transmitted;
> m_packets[idx].packet_idx = m_total_packet_count;
> m_packets[idx].tid = llvm::get_threadid();
> - if (m_stream)
> - m_packets[idx].Serialize(*m_stream);
> + if (m_recorder)
> + m_recorder->Record(m_packets[idx]);
> }
>
> void GDBRemoteCommunicationHistory::AddPacket(const std::string &src,
> @@ -58,8 +58,8 @@ void GDBRemoteCommunicationHistory::AddPacket(const
> std::string &src,
> m_packets[idx].bytes_transmitted = bytes_transmitted;
> m_packets[idx].packet_idx = m_total_packet_count;
> m_packets[idx].tid = llvm::get_threadid();
> - if (m_stream)
> - m_packets[idx].Serialize(*m_stream);
> + if (m_recorder)
> + m_recorder->Record(m_packets[idx]);
> }
>
> void GDBRemoteCommunicationHistory::Dump(Stream &strm) const {
>
> diff --git
> a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
> b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
> index c006fbd34a4b..ee265ef86dff 100644
> ---
> a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
> +++
> b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
> @@ -13,11 +13,15 @@
> #include <vector>
>
> #include "lldb/Utility/GDBRemote.h"
> +#include "lldb/Utility/Reproducer.h"
> #include "lldb/lldb-public.h"
> #include "llvm/Support/YAMLTraits.h"
> #include "llvm/Support/raw_ostream.h"
>
> namespace lldb_private {
> +namespace repro {
> +class PacketRecorder;
> +}
> namespace process_gdb_remote {
>
> /// The history keeps a circular buffer of GDB remote packets. The
> history is
> @@ -41,7 +45,7 @@ class GDBRemoteCommunicationHistory {
> void Dump(Log *log) const;
> bool DidDumpToLog() const { return m_dumped_to_log; }
>
> - void SetStream(llvm::raw_ostream *strm) { m_stream = strm; }
> + void SetRecorder(repro::PacketRecorder *recorder) { m_recorder =
> recorder; }
>
> private:
> uint32_t GetFirstSavedPacketIndex() const {
> @@ -73,7 +77,7 @@ class GDBRemoteCommunicationHistory {
> uint32_t m_curr_idx;
> uint32_t m_total_packet_count;
> mutable bool m_dumped_to_log;
> - llvm::raw_ostream *m_stream = nullptr;
> + repro::PacketRecorder *m_recorder = nullptr;
> };
>
> } // namespace process_gdb_remote
>
> diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
> b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
> index dfef06aa6eaf..95f3d1fcc53a 100644
> --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
> +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
> @@ -279,12 +279,9 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP
> target_sp,
> "async thread did exit");
>
> if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator())
> {
> - repro::ProcessGDBRemoteProvider &provider =
> - g->GetOrCreate<repro::ProcessGDBRemoteProvider>();
> - // Set the history stream to the stream owned by the provider.
> - m_gdb_comm.SetHistoryStream(provider.GetHistoryStream());
> - // Make sure to clear the stream again when we're finished.
> - provider.SetCallback([&]() { m_gdb_comm.SetHistoryStream(nullptr); });
> + repro::GDBRemoteProvider &provider =
> + g->GetOrCreate<repro::GDBRemoteProvider>();
> + m_gdb_comm.SetPacketRecorder(provider.GetNewPacketRecorder());
> }
>
> Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC));
> @@ -3362,17 +3359,20 @@ Status
> ProcessGDBRemote::ConnectToReplayServer(repro::Loader *loader) {
> if (!loader)
> return Status("No loader provided.");
>
> - // Construct replay history path.
> - FileSpec history_file =
> - loader->GetFile<repro::ProcessGDBRemoteProvider::Info>();
> - if (!history_file)
> - return Status("No provider for gdb-remote.");
> + static std::unique_ptr<repro::MultiLoader<repro::GDBRemoteProvider>>
> + multi_loader = repro::MultiLoader<repro::GDBRemoteProvider>::Create(
> + repro::Reproducer::Instance().GetLoader());
>
> - // Enable replay mode.
> - m_replay_mode = true;
> + if (!multi_loader)
> + return Status("No gdb remote provider found.");
> +
> + llvm::Optional<std::string> history_file = multi_loader->GetNextFile();
> + if (!history_file)
> + return Status("No gdb remote packet log found.");
>
> // Load replay history.
> - if (auto error = m_gdb_replay_server.LoadReplayHistory(history_file))
> + if (auto error =
> + m_gdb_replay_server.LoadReplayHistory(FileSpec(*history_file)))
> return Status("Unable to load replay history");
>
> // Make a local connection.
> @@ -3380,6 +3380,9 @@ Status
> ProcessGDBRemote::ConnectToReplayServer(repro::Loader *loader) {
>
> m_gdb_replay_server))
> return Status("Unable to connect to replay server");
>
> + // Enable replay mode.
> + m_replay_mode = true;
> +
> // Start server thread.
> m_gdb_replay_server.StartAsyncThread();
>
>
> diff --git a/lldb/source/Utility/GDBRemote.cpp
> b/lldb/source/Utility/GDBRemote.cpp
> index 85c4bc69a8d1..54f3a3cd8a86 100644
> --- a/lldb/source/Utility/GDBRemote.cpp
> +++ b/lldb/source/Utility/GDBRemote.cpp
> @@ -14,6 +14,7 @@
> #include <stdio.h>
>
> using namespace lldb;
> +using namespace lldb_private::repro;
> using namespace lldb_private;
> using namespace llvm;
>
> @@ -45,12 +46,6 @@ int StreamGDBRemote::PutEscapedBytes(const void *s,
> size_t src_len) {
> return bytes_written;
> }
>
> -void GDBRemotePacket::Serialize(raw_ostream &strm) const {
> - yaml::Output yout(strm);
> - yout << const_cast<GDBRemotePacket &>(*this);
> - strm.flush();
> -}
> -
> llvm::StringRef GDBRemotePacket::GetTypeStr() const {
> switch (type) {
> case GDBRemotePacket::ePacketTypeSend:
> @@ -103,3 +98,66 @@ yaml::MappingTraits<GDBRemotePacket>::validate(IO &io,
>
> return {};
> }
> +
> +void GDBRemoteProvider::Keep() {
> + std::vector<std::string> files;
> + for (auto &recorder : m_packet_recorders) {
> + files.push_back(recorder->GetFilename().GetPath());
> + }
> +
> + FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file);
> + std::error_code ec;
> + llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text);
> + if (ec)
> + return;
> + yaml::Output yout(os);
> + yout << files;
> +}
> +
> +void GDBRemoteProvider::Discard() { m_packet_recorders.clear(); }
> +
> +llvm::Expected<std::unique_ptr<PacketRecorder>>
> +PacketRecorder::Create(const FileSpec &filename) {
> + std::error_code ec;
> + auto recorder = std::make_unique<PacketRecorder>(std::move(filename),
> ec);
> + if (ec)
> + return llvm::errorCodeToError(ec);
> + return std::move(recorder);
> +}
> +
> +PacketRecorder *GDBRemoteProvider::GetNewPacketRecorder() {
> + std::size_t i = m_packet_recorders.size() + 1;
> + std::string filename = (llvm::Twine(Info::name) + llvm::Twine("-") +
> + llvm::Twine(i) + llvm::Twine(".yaml"))
> + .str();
> + auto recorder_or_error =
> +
> PacketRecorder::Create(GetRoot().CopyByAppendingPathComponent(filename));
> + if (!recorder_or_error) {
> + llvm::consumeError(recorder_or_error.takeError());
> + return nullptr;
> + }
> +
> + m_packet_recorders.push_back(std::move(*recorder_or_error));
> + return m_packet_recorders.back().get();
> +}
> +
> +void PacketRecorder::Record(const GDBRemotePacket &packet) {
> + if (!m_record)
> + return;
> + yaml::Output yout(m_os);
> + yout << const_cast<GDBRemotePacket &>(packet);
> + m_os.flush();
> +}
> +
> +llvm::raw_ostream *GDBRemoteProvider::GetHistoryStream() {
> + FileSpec history_file =
> GetRoot().CopyByAppendingPathComponent(Info::file);
> +
> + std::error_code EC;
> + m_stream_up = std::make_unique<raw_fd_ostream>(history_file.GetPath(),
> EC,
> +
> sys::fs::OpenFlags::OF_Text);
> + return m_stream_up.get();
> +}
> +
> +char GDBRemoteProvider::ID = 0;
> +const char *GDBRemoteProvider::Info::file = "gdb-remote.yaml";
> +const char *GDBRemoteProvider::Info::name = "gdb-remote";
>
> diff --git a/lldb/source/Utility/Reproducer.cpp
> b/lldb/source/Utility/Reproducer.cpp
> index 8a28e9b13675..b11e1a577ed2 100644
> --- a/lldb/source/Utility/Reproducer.cpp
> +++ b/lldb/source/Utility/Reproducer.cpp
> @@ -255,7 +255,7 @@ DataRecorder::Create(const FileSpec &filename) {
> DataRecorder *CommandProvider::GetNewDataRecorder() {
> std::size_t i = m_data_recorders.size() + 1;
> std::string filename = (llvm::Twine(Info::name) + llvm::Twine("-") +
> - llvm::Twine(i) + llvm::Twine(".txt"))
> + llvm::Twine(i) + llvm::Twine(".yaml"))
> .str();
> auto recorder_or_error =
>
> DataRecorder::Create(GetRoot().CopyByAppendingPathComponent(filename));
> @@ -304,53 +304,9 @@ void WorkingDirectoryProvider::Keep() {
> os << m_cwd << "\n";
> }
>
> -llvm::raw_ostream *ProcessGDBRemoteProvider::GetHistoryStream() {
> - FileSpec history_file =
> GetRoot().CopyByAppendingPathComponent(Info::file);
> -
> - std::error_code EC;
> - m_stream_up = std::make_unique<raw_fd_ostream>(history_file.GetPath(),
> EC,
> -
> sys::fs::OpenFlags::OF_Text);
> - return m_stream_up.get();
> -}
> -
> -std::unique_ptr<CommandLoader> CommandLoader::Create(Loader *loader) {
> - if (!loader)
> - return {};
> -
> - FileSpec file = loader->GetFile<repro::CommandProvider::Info>();
> - if (!file)
> - return {};
> -
> - auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath());
> - if (auto err = error_or_file.getError())
> - return {};
> -
> - std::vector<std::string> files;
> - llvm::yaml::Input yin((*error_or_file)->getBuffer());
> - yin >> files;
> -
> - if (auto err = yin.error())
> - return {};
> -
> - for (auto &file : files) {
> - FileSpec absolute_path =
> - loader->GetRoot().CopyByAppendingPathComponent(file);
> - file = absolute_path.GetPath();
> - }
> -
> - return std::make_unique<CommandLoader>(std::move(files));
> -}
> -
> -llvm::Optional<std::string> CommandLoader::GetNextFile() {
> - if (m_index >= m_files.size())
> - return {};
> - return m_files[m_index++];
> -}
> -
> void ProviderBase::anchor() {}
> char CommandProvider::ID = 0;
> char FileProvider::ID = 0;
> -char ProcessGDBRemoteProvider::ID = 0;
> char ProviderBase::ID = 0;
> char VersionProvider::ID = 0;
> char WorkingDirectoryProvider::ID = 0;
> @@ -358,8 +314,6 @@ const char *CommandProvider::Info::file =
> "command-interpreter.yaml";
> const char *CommandProvider::Info::name = "command-interpreter";
> const char *FileProvider::Info::file = "files.yaml";
> const char *FileProvider::Info::name = "files";
> -const char *ProcessGDBRemoteProvider::Info::file = "gdb-remote.yaml";
> -const char *ProcessGDBRemoteProvider::Info::name = "gdb-remote";
> const char *VersionProvider::Info::file = "version.txt";
> const char *VersionProvider::Info::name = "version";
> const char *WorkingDirectoryProvider::Info::file = "cwd.txt";
>
> diff --git a/lldb/test/Shell/Reproducer/Inputs/MultipleTargetsCapture.in
> b/lldb/test/Shell/Reproducer/Inputs/MultipleTargetsCapture.in
> new file mode 100644
> index 000000000000..c78d6276c89f
> --- /dev/null
> +++ b/lldb/test/Shell/Reproducer/Inputs/MultipleTargetsCapture.in
> @@ -0,0 +1,12 @@
> +target select 0
> +breakpoint set -f simple.c -l 12
> +run
> +target select 1
> +breakpoint set -f simple.c -l 16
> +run
> +target select 0
> +cont
> +target select 1
> +cont
> +reproducer status
> +reproducer generate
>
> diff --git a/lldb/test/Shell/Reproducer/TestMultipleTargets.test
> b/lldb/test/Shell/Reproducer/TestMultipleTargets.test
> new file mode 100644
> index 000000000000..f36dbf6b5c44
> --- /dev/null
> +++ b/lldb/test/Shell/Reproducer/TestMultipleTargets.test
> @@ -0,0 +1,23 @@
> +# UNSUPPORTED: system-windows, system-freebsd
> +
> +# This tests the replaying with multiple targets.
> +
> +# RUN: %clang_host %S/Inputs/simple.c -g -o %t.out
> +
> +# RUN: rm -rf %t.repro
> +# RUN: %lldb -x -b --capture --capture-path %t.repro -o 'target create
> %t.out' -o 'target create %t.out' -s %S/Inputs/MultipleTargetsCapture.in |
> FileCheck %s --check-prefix CHECK --check-prefix CAPTURE
> +# RUN: env FOO=BAR %lldb --replay %t.repro | FileCheck %s --check-prefix
> CHECK --check-prefix REPLAY
> +
> +# CHECK: Process [[TARGET0:[0-9]+]] stopped
> +# CHECK: stop reason = breakpoint 1.1
> +# CHECK: simple.c:12:5
> +# CHECK: Process [[TARGET1:[0-9]+]] stopped
> +# CHECK: stop reason = breakpoint 1.1
> +# CHECK: simple.c:16:5
> +# CHECK: Process [[TARGET0]] resuming
> +# CHECK: Process [[TARGET0]] exited
> +# CHECK: Process [[TARGET1]] resuming
> +# CHECK: Process [[TARGET1]] exited
> +
> +# CAPTURE: Reproducer is in capture mode.
> +# CAPTURE: Reproducer written
>
>
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-commits/attachments/20191210/c7263058/attachment-0001.html>
More information about the lldb-commits
mailing list