For now I've gone ahead and reverted thusly: echristo@athyra ~/r/llvm-project> git push To github.com:llvm/llvm-project.git a2602bdd731..c9e0b354e27 master -> master
Sorry for the very quick turnaround. -eric On Tue, Dec 10, 2019 at 12:21 PM Eric Christopher <echri...@gmail.com> wrote: > 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