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@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@lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits >
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits