[Lldb-commits] [lldb] e81268d - [lldb/Reproducers] Support multiple GDB remotes

Eric Christopher via lldb-commits lldb-commits at lists.llvm.org
Tue Dec 10 12:21:03 PST 2019


Hi Jonas,

This appears to be causing crashes in a release asserts build:

 #3 0x00007efe57b613a0 __restore_rt
(/lib/x86_64-linux-gnu/libpthread.so.0+0x123a0)
 #4 0x00007efe54178d00 llvm::raw_ostream::operator<<(llvm::StringRef)
sources/llvm-project/llvm/include/llvm/Support/raw_ostream.h:190:7
 #5 0x00007efe54178d00 llvm::yaml::Output::output(llvm::StringRef)
sources/llvm-project/llvm/lib/Support/YAMLTraits.cpp:751:7
 #6 0x00007efe54178d00
llvm::yaml::Output::outputUpToEndOfLine(llvm::StringRef)
sources/llvm-project/llvm/lib/Support/YAMLTraits.cpp:755:3
 #7 0x00007efe54178d00 llvm::yaml::Output::beginDocuments()
sources/llvm-project/llvm/lib/Support/YAMLTraits.cpp:537:3
 #8 0x00007efe53fc5d7e
std::enable_if<has_MappingTraits<lldb_private::GDBRemotePacket,
llvm::yaml::EmptyContext>::value, llvm::yaml::Output&>::type
llvm::yaml::operator<<<lldb_private::GDBRemotePacket>(llvm::yaml::Output&,
lldb_private::GDBRemotePacket&)
sources/llvm-project/llvm/include/llvm/Support/YAMLTraits.h:1796:13
 #9 0x00007efe53fc5d7e
lldb_private::GDBRemotePacket::Serialize(llvm::raw_ostream&) const
sources/llvm-project/lldb/source/Utility/GDBRemote.cpp:50:8
...

want to revert and see what's going on? Happy to help if you can't
duplicate?

Thanks!

-eric

On Tue, Dec 10, 2019 at 11:17 AM Jonas Devlieghere via lldb-commits <
lldb-commits at lists.llvm.org> wrote:

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


More information about the lldb-commits mailing list