[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