[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:31:41 PST 2019
For now I've gone ahead and reverted thusly:
echristo at 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 <echristo at 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 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/373ab187/attachment-0001.html>
More information about the lldb-commits
mailing list