JDevlieghere updated this revision to Diff 175993.
JDevlieghere marked 12 inline comments as done.
JDevlieghere added a comment.

Address feedback from Pavel.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55038/new/

https://reviews.llvm.org/D55038

Files:
  include/lldb/API/SBDebugger.h
  include/lldb/API/SBDefines.h
  include/lldb/API/SBFileSpec.h
  include/lldb/API/SBInitializerOptions.h
  include/lldb/Core/Debugger.h
  include/lldb/Host/HostInfoBase.h
  include/lldb/Initialization/SystemInitializer.h
  include/lldb/Initialization/SystemInitializerCommon.h
  include/lldb/Initialization/SystemLifetimeManager.h
  include/lldb/Utility/Reproducer.h
  lit/Reproducer/Inputs/GDBRemoteCapture.in
  lit/Reproducer/Inputs/GDBRemoteReplay.in
  lit/Reproducer/TestGDBRemoteRepro.test
  packages/Python/lldbsuite/test/functionalities/reproducer/gdb-remote/Makefile
  
packages/Python/lldbsuite/test/functionalities/reproducer/gdb-remote/TestGdbRemoteReproducer.py
  scripts/interface/SBDebugger.i
  scripts/interface/SBInitializerOptions.i
  scripts/lldb.swig
  source/API/CMakeLists.txt
  source/API/SBDebugger.cpp
  source/API/SBInitializerOptions.cpp
  source/API/SystemInitializerFull.cpp
  source/API/SystemInitializerFull.h
  source/Commands/CommandObjectReproducer.cpp
  source/Core/Debugger.cpp
  source/Host/common/HostInfoBase.cpp
  source/Initialization/SystemInitializerCommon.cpp
  source/Initialization/SystemLifetimeManager.cpp
  source/Utility/Reproducer.cpp
  tools/driver/Driver.cpp
  tools/driver/Options.td
  tools/lldb-server/SystemInitializerLLGS.cpp
  tools/lldb-server/SystemInitializerLLGS.h
  tools/lldb-server/lldb-server.cpp
  tools/lldb-test/SystemInitializerTest.cpp
  tools/lldb-test/SystemInitializerTest.h
  tools/lldb-test/lldb-test.cpp
  unittests/Utility/ReproducerTest.cpp

Index: unittests/Utility/ReproducerTest.cpp
===================================================================
--- unittests/Utility/ReproducerTest.cpp
+++ unittests/Utility/ReproducerTest.cpp
@@ -32,10 +32,18 @@
   static char ID;
 };
 
+class DummyReproducer : public Reproducer {
+public:
+  DummyReproducer() : Reproducer(){};
+
+  using Reproducer::SetCapture;
+  using Reproducer::SetReplay;
+};
+
 char DummyProvider::ID = 0;
 
 TEST(ReproducerTest, SetCapture) {
-  Reproducer reproducer;
+  DummyReproducer reproducer;
 
   // Initially both generator and loader are unset.
   EXPECT_EQ(nullptr, reproducer.GetGenerator());
@@ -59,7 +67,7 @@
 }
 
 TEST(ReproducerTest, SetReplay) {
-  Reproducer reproducer;
+  DummyReproducer reproducer;
 
   // Initially both generator and loader are unset.
   EXPECT_EQ(nullptr, reproducer.GetGenerator());
@@ -80,7 +88,7 @@
 }
 
 TEST(GeneratorTest, Create) {
-  Reproducer reproducer;
+  DummyReproducer reproducer;
 
   EXPECT_THAT_ERROR(reproducer.SetCapture(FileSpec("/bogus/path")),
                     Succeeded());
@@ -95,7 +103,7 @@
 }
 
 TEST(GeneratorTest, Get) {
-  Reproducer reproducer;
+  DummyReproducer reproducer;
 
   EXPECT_THAT_ERROR(reproducer.SetCapture(FileSpec("/bogus/path")),
                     Succeeded());
@@ -109,7 +117,7 @@
 }
 
 TEST(GeneratorTest, GetOrCreate) {
-  Reproducer reproducer;
+  DummyReproducer reproducer;
 
   EXPECT_THAT_ERROR(reproducer.SetCapture(FileSpec("/bogus/path")),
                     Succeeded());
Index: tools/lldb-test/lldb-test.cpp
===================================================================
--- tools/lldb-test/lldb-test.cpp
+++ tools/lldb-test/lldb-test.cpp
@@ -934,7 +934,7 @@
   cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
 
   SystemLifetimeManager DebuggerLifetime;
-  DebuggerLifetime.Initialize(llvm::make_unique<SystemInitializerTest>(),
+  DebuggerLifetime.Initialize(llvm::make_unique<SystemInitializerTest>(), {},
                               nullptr);
   CleanUp TerminateDebugger([&] { DebuggerLifetime.Terminate(); });
 
Index: tools/lldb-test/SystemInitializerTest.h
===================================================================
--- tools/lldb-test/SystemInitializerTest.h
+++ tools/lldb-test/SystemInitializerTest.h
@@ -26,7 +26,7 @@
   SystemInitializerTest();
   ~SystemInitializerTest() override;
 
-  void Initialize() override;
+  void Initialize(const InitializerOptions &options) override;
   void Terminate() override;
 };
 
Index: tools/lldb-test/SystemInitializerTest.cpp
===================================================================
--- tools/lldb-test/SystemInitializerTest.cpp
+++ tools/lldb-test/SystemInitializerTest.cpp
@@ -111,8 +111,8 @@
 
 SystemInitializerTest::~SystemInitializerTest() {}
 
-void SystemInitializerTest::Initialize() {
-  SystemInitializerCommon::Initialize();
+void SystemInitializerTest::Initialize(const InitializerOptions &options) {
+  SystemInitializerCommon::Initialize(options);
 
   ObjectFileELF::Initialize();
   ObjectFileMachO::Initialize();
Index: tools/lldb-server/lldb-server.cpp
===================================================================
--- tools/lldb-server/lldb-server.cpp
+++ tools/lldb-server/lldb-server.cpp
@@ -39,7 +39,7 @@
 
 static void initialize() {
   g_debugger_lifetime->Initialize(llvm::make_unique<SystemInitializerLLGS>(),
-                                  nullptr);
+                                  {}, nullptr);
 }
 
 static void terminate() { g_debugger_lifetime->Terminate(); }
Index: tools/lldb-server/SystemInitializerLLGS.h
===================================================================
--- tools/lldb-server/SystemInitializerLLGS.h
+++ tools/lldb-server/SystemInitializerLLGS.h
@@ -10,11 +10,12 @@
 #ifndef LLDB_SYSTEMINITIALIZERLLGS_H
 #define LLDB_SYSTEMINITIALIZERLLGS_H
 
+#include "lldb/Initialization/SystemInitializer.h"
 #include "lldb/Initialization/SystemInitializerCommon.h"
 
 class SystemInitializerLLGS : public lldb_private::SystemInitializerCommon {
 public:
-  void Initialize() override;
+  void Initialize(const lldb_private::InitializerOptions &options) override;
   void Terminate() override;
 };
 
Index: tools/lldb-server/SystemInitializerLLGS.cpp
===================================================================
--- tools/lldb-server/SystemInitializerLLGS.cpp
+++ tools/lldb-server/SystemInitializerLLGS.cpp
@@ -22,8 +22,8 @@
 
 using namespace lldb_private;
 
-void SystemInitializerLLGS::Initialize() {
-  SystemInitializerCommon::Initialize();
+void SystemInitializerLLGS::Initialize(const InitializerOptions &options) {
+  SystemInitializerCommon::Initialize(options);
   HostObjectFile::Initialize();
 }
 
Index: tools/driver/Options.td
===================================================================
--- tools/driver/Options.td
+++ tools/driver/Options.td
@@ -209,11 +209,11 @@
   Alias<debug>,
   HelpText<"Alias for --debug">;
 
-def reproducer: Separate<["--", "-"], "reproducer">,
+def capture: Separate<["--", "-"], "capture">,
   MetaVarName<"<filename>">,
-  HelpText<"Tells the debugger to use the fullpath to <filename> as a reproducer.">;
-def: Separate<["-"], "z">,
-  Alias<file>,
-  HelpText<"Alias for --reproducer">;
+  HelpText<"Tells the debugger to capture a reproducer to <filename>.">;
+def replay: Separate<["--", "-"], "replay">,
+  MetaVarName<"<filename>">,
+  HelpText<"Tells the debugger to replay a reproducer from <filename>.">;
 
 def REM : R<["--"], "">;
Index: tools/driver/Driver.cpp
===================================================================
--- tools/driver/Driver.cpp
+++ tools/driver/Driver.cpp
@@ -367,21 +367,6 @@
     m_option_data.m_debug_mode = true;
   }
 
-  if (auto *arg = args.getLastArg(OPT_reproducer)) {
-    auto arg_value = arg->getValue();
-    SBFileSpec file(arg_value);
-    if (file.Exists()) {
-      SBError repro_error = m_debugger.ReplayReproducer(arg_value);
-      if (repro_error.Fail())
-        return repro_error;
-    } else {
-      error.SetErrorStringWithFormat("file specified in --reproducer "
-                                     "(-z) option doesn't exist: '%s'",
-                                     arg_value);
-      return error;
-    }
-  }
-
   if (args.hasArg(OPT_no_use_colors)) {
     m_debugger.SetUseColor(false);
   }
@@ -942,7 +927,21 @@
                          << '\n';
   }
 
-  SBDebugger::Initialize();
+  SBInitializerOptions options;
+
+  if (auto *arg = input_args.getLastArg(OPT_capture)) {
+    auto arg_value = arg->getValue();
+    options.SetReproducerPath(arg_value);
+    options.SetCaptureReproducer(true);
+  }
+
+  if (auto *arg = input_args.getLastArg(OPT_replay)) {
+    auto arg_value = arg->getValue();
+    options.SetReplayReproducer(true);
+    options.SetReproducerPath(arg_value);
+  }
+
+  SBDebugger::Initialize(options);
   SBHostOS::ThreadCreated("<lldb.driver.main-thread>");
 
   signal(SIGINT, sigint_handler);
Index: source/Utility/Reproducer.cpp
===================================================================
--- source/Utility/Reproducer.cpp
+++ source/Utility/Reproducer.cpp
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Utility/Reproducer.h"
+#include "lldb/Utility/LLDBAssert.h"
 
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Threading.h"
@@ -18,11 +19,50 @@
 using namespace llvm;
 using namespace llvm::yaml;
 
-Reproducer &Reproducer::Instance() {
-  static Reproducer g_reproducer;
+Reproducer &Reproducer::Instance() { return *InstanceImpl(); }
+
+void Reproducer::Initialize(ReproducerMode mode,
+                            llvm::Optional<FileSpec> root) {
+  lldbassert(!InstanceImpl() && "Already initialized.");
+  InstanceImpl().emplace(mode, root);
+}
+
+void Reproducer::Terminate() {
+  lldbassert(InstanceImpl() && "Already terminated.");
+  InstanceImpl().reset();
+}
+
+Optional<Reproducer> &Reproducer::InstanceImpl() {
+  static Optional<Reproducer> g_reproducer;
   return g_reproducer;
 }
 
+Reproducer::Reproducer(ReproducerMode mode, llvm::Optional<FileSpec> root) {
+  // It's unfortunate that we have to do so much I/O here that can fail. The
+  // best we can do is not initialize the reproducer.
+  switch (mode) {
+  case ReproducerMode::Capture: {
+    if (!root) {
+      llvm::SmallString<128> repro_dir;
+      auto ec = llvm::sys::fs::createUniqueDirectory("reproducer", repro_dir);
+      if (ec)
+        return;
+      root.emplace(repro_dir);
+    } else {
+      auto ec = llvm::sys::fs::create_directories(root->GetPath());
+      if (ec)
+        return;
+    }
+    llvm::cantFail(SetCapture(root));
+  } break;
+  case ReproducerMode::Replay:
+    llvm::cantFail(SetReplay(root));
+    break;
+  case ReproducerMode::Off:
+    break;
+  };
+}
+
 const Generator *Reproducer::GetGenerator() const {
   std::lock_guard<std::mutex> guard(m_mutex);
   if (m_generator)
@@ -59,11 +99,12 @@
         "cannot generate a reproducer when replay one",
         inconvertibleErrorCode());
 
-  if (root)
-    m_generator.emplace(*root);
-  else
+  if (!root) {
     m_generator.reset();
+    return Error::success();
+  }
 
+  m_generator.emplace(*root);
   return Error::success();
 }
 
@@ -75,14 +116,15 @@
         "cannot replay a reproducer when generating one",
         inconvertibleErrorCode());
 
-  if (root) {
-    m_loader.emplace(*root);
-    if (auto e = m_loader->LoadIndex())
-      return e;
-  } else {
+  if (!root) {
     m_loader.reset();
+    return Error::success();
   }
 
+  m_loader.emplace(*root);
+  if (auto e = m_loader->LoadIndex())
+    return e;
+
   return Error::success();
 }
 
Index: source/Initialization/SystemLifetimeManager.cpp
===================================================================
--- source/Initialization/SystemLifetimeManager.cpp
+++ source/Initialization/SystemLifetimeManager.cpp
@@ -26,7 +26,7 @@
 
 void SystemLifetimeManager::Initialize(
     std::unique_ptr<SystemInitializer> initializer,
-    LoadPluginCallbackType plugin_callback) {
+    const InitializerOptions &options, LoadPluginCallbackType plugin_callback) {
   std::lock_guard<std::recursive_mutex> guard(m_mutex);
   if (!m_initialized) {
     assert(!m_initializer && "Attempting to call "
@@ -35,7 +35,7 @@
     m_initialized = true;
     m_initializer = std::move(initializer);
 
-    m_initializer->Initialize();
+    m_initializer->Initialize(options);
     Debugger::Initialize(plugin_callback);
   }
 }
Index: source/Initialization/SystemInitializerCommon.cpp
===================================================================
--- source/Initialization/SystemInitializerCommon.cpp
+++ source/Initialization/SystemInitializerCommon.cpp
@@ -19,6 +19,7 @@
 #include "lldb/Host/Host.h"
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Utility/Log.h"
+#include "lldb/Utility/Reproducer.h"
 #include "lldb/Utility/Timer.h"
 
 #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
@@ -35,12 +36,13 @@
 #include <string>
 
 using namespace lldb_private;
+using namespace lldb_private::repro;
 
 SystemInitializerCommon::SystemInitializerCommon() {}
 
 SystemInitializerCommon::~SystemInitializerCommon() {}
 
-void SystemInitializerCommon::Initialize() {
+void SystemInitializerCommon::Initialize(const InitializerOptions &options) {
 #if defined(_MSC_VER)
   const char *disable_crash_dialog_var = getenv("LLDB_DISABLE_CRASH_DIALOG");
   if (disable_crash_dialog_var &&
@@ -63,6 +65,13 @@
   }
 #endif
 
+  ReproducerMode mode = ReproducerMode::Off;
+  if (options.reproducer_capture)
+    mode = ReproducerMode::Capture;
+  if (options.reproducer_replay)
+    mode = ReproducerMode::Replay;
+
+  Reproducer::Initialize(mode, FileSpec(options.reproducer_path));
   FileSystem::Initialize();
   Log::Initialize();
   HostInfo::Initialize();
@@ -109,4 +118,5 @@
   HostInfo::Terminate();
   Log::DisableAllLogChannels();
   FileSystem::Terminate();
+  Reproducer::Terminate();
 }
Index: source/Host/common/HostInfoBase.cpp
===================================================================
--- source/Host/common/HostInfoBase.cpp
+++ source/Host/common/HostInfoBase.cpp
@@ -194,19 +194,6 @@
   return success ? g_fields->m_lldb_global_tmp_dir : FileSpec();
 }
 
-FileSpec HostInfoBase::GetReproducerTempDir() {
-  static llvm::once_flag g_once_flag;
-  static bool success = false;
-  llvm::call_once(g_once_flag, []() {
-    success = HostInfo::ComputeReproducerTempFileDirectory(
-        g_fields->m_lldb_global_tmp_dir);
-    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
-    LLDB_LOG(log, "reproducer temp dir -> `{0}`",
-             g_fields->m_lldb_global_tmp_dir);
-  });
-  return success ? g_fields->m_lldb_global_tmp_dir : FileSpec();
-}
-
 ArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) {
   if (triple.empty())
     return ArchSpec();
@@ -289,26 +276,6 @@
   return true;
 }
 
-bool HostInfoBase::ComputeReproducerTempFileDirectory(FileSpec &file_spec) {
-  file_spec.Clear();
-
-  FileSpec temp_file_spec;
-  if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec))
-    return false;
-
-  temp_file_spec.AppendPathComponent("reproducer");
-  if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
-    return false;
-
-  std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())};
-  temp_file_spec.AppendPathComponent(pid_str);
-  if (llvm::sys::fs::create_directory(temp_file_spec.GetPath()))
-    return false;
-
-  file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
-  return true;
-}
-
 bool HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) {
   // TODO(zturner): Figure out how to compute the header directory for all
   // platforms.
Index: source/Core/Debugger.cpp
===================================================================
--- source/Core/Debugger.cpp
+++ source/Core/Debugger.cpp
@@ -418,24 +418,6 @@
   return r.GetReproducerPath().GetCString();
 }
 
-llvm::Error Debugger::SetReproducerReplay(llvm::StringRef p) {
-  llvm::Optional<FileSpec> arg = llvm::None;
-
-  if (!p.empty())
-    arg = FileSpec(p);
-
-  return repro::Reproducer::Instance().SetReplay(arg);
-}
-
-llvm::Error Debugger::SetReproducerCapture(bool b) {
-  llvm::Optional<FileSpec> arg = llvm::None;
-
-  if (b)
-    arg = HostInfo::GetReproducerTempDir();
-
-  return repro::Reproducer::Instance().SetCapture(arg);
-}
-
 const FormatEntity::Entry *Debugger::GetThreadFormat() const {
   const uint32_t idx = ePropertyThreadFormat;
   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
Index: source/Commands/CommandObjectReproducer.cpp
===================================================================
--- source/Commands/CommandObjectReproducer.cpp
+++ source/Commands/CommandObjectReproducer.cpp
@@ -19,65 +19,6 @@
 using namespace lldb;
 using namespace lldb_private;
 
-static void AppendErrorToResult(llvm::Error e, CommandReturnObject &result) {
-  std::string error_str = llvm::toString(std::move(e));
-  result.AppendErrorWithFormat("%s", error_str.c_str());
-}
-
-class CommandObjectReproducerCaptureEnable : public CommandObjectParsed {
-public:
-  CommandObjectReproducerCaptureEnable(CommandInterpreter &interpreter)
-      : CommandObjectParsed(interpreter, "reproducer capture enable",
-                            "Enable gathering information for reproducer",
-                            nullptr) {}
-
-  ~CommandObjectReproducerCaptureEnable() override = default;
-
-protected:
-  bool DoExecute(Args &command, CommandReturnObject &result) override {
-    if (!command.empty()) {
-      result.AppendErrorWithFormat("'%s' takes no arguments",
-                                   m_cmd_name.c_str());
-      return false;
-    }
-
-    if (auto e = m_interpreter.GetDebugger().SetReproducerCapture(true)) {
-      AppendErrorToResult(std::move(e), result);
-      return false;
-    }
-
-    result.SetStatus(eReturnStatusSuccessFinishNoResult);
-    return result.Succeeded();
-  }
-};
-
-class CommandObjectReproducerCaptureDisable : public CommandObjectParsed {
-public:
-  CommandObjectReproducerCaptureDisable(CommandInterpreter &interpreter)
-      : CommandObjectParsed(interpreter, "reproducer capture enable",
-                            "Disable gathering information for reproducer",
-                            nullptr) {}
-
-  ~CommandObjectReproducerCaptureDisable() override = default;
-
-protected:
-  bool DoExecute(Args &command, CommandReturnObject &result) override {
-    if (!command.empty()) {
-      result.AppendErrorWithFormat("'%s' takes no arguments",
-                                   m_cmd_name.c_str());
-      return false;
-    }
-
-    if (auto e = m_interpreter.GetDebugger().SetReproducerCapture(false)) {
-      AppendErrorToResult(std::move(e), result);
-      return false;
-    }
-
-    result.SetStatus(eReturnStatusSuccessFinishNoResult);
-    return result.Succeeded();
-  }
-};
-
 class CommandObjectReproducerGenerate : public CommandObjectParsed {
 public:
   CommandObjectReproducerGenerate(CommandInterpreter &interpreter)
@@ -110,82 +51,47 @@
   }
 };
 
-class CommandObjectReproducerReplay : public CommandObjectParsed {
+class CommandObjectReproducerStatus : public CommandObjectParsed {
 public:
-  CommandObjectReproducerReplay(CommandInterpreter &interpreter)
-      : CommandObjectParsed(interpreter, "reproducer replay",
-                            "Replay a reproducer.", nullptr) {
-    CommandArgumentEntry arg1;
-    CommandArgumentData path_arg;
-
-    // Define the first (and only) variant of this arg.
-    path_arg.arg_type = eArgTypePath;
-    path_arg.arg_repetition = eArgRepeatPlain;
-
-    // There is only one variant this argument could be; put it into the
-    // argument entry.
-    arg1.push_back(path_arg);
-
-    // Push the data for the first argument into the m_arguments vector.
-    m_arguments.push_back(arg1);
-  }
+  CommandObjectReproducerStatus(CommandInterpreter &interpreter)
+      : CommandObjectParsed(interpreter, "reproducer status",
+                            "Show the current reproducer status.", nullptr) {}
 
-  ~CommandObjectReproducerReplay() override = default;
+  ~CommandObjectReproducerStatus() override = default;
 
 protected:
   bool DoExecute(Args &command, CommandReturnObject &result) override {
-    if (command.empty()) {
-      result.AppendErrorWithFormat(
-          "'%s' takes a single argument: the reproducer path",
-          m_cmd_name.c_str());
+    if (!command.empty()) {
+      result.AppendErrorWithFormat("'%s' takes no arguments",
+                                   m_cmd_name.c_str());
       return false;
     }
 
     auto &r = repro::Reproducer::Instance();
+    if (auto generator = r.GetGenerator()) {
+      result.GetOutputStream() << "Reproducer is in capture mode.\n";
+    } else if (auto generator = r.GetLoader()) {
+      result.GetOutputStream() << "Reproducer is in replay mode.\n";
+    } else {
 
-    const char *repro_path = command.GetArgumentAtIndex(0);
-    if (auto e = r.SetReplay(FileSpec(repro_path))) {
-      std::string error_str = llvm::toString(std::move(e));
-      result.AppendErrorWithFormat("%s", error_str.c_str());
-      return false;
+      result.GetOutputStream() << "Reproducer is off.\n";
     }
 
-    result.SetStatus(eReturnStatusSuccessFinishNoResult);
+    result.SetStatus(eReturnStatusSuccessFinishResult);
     return result.Succeeded();
   }
 };
 
-class CommandObjectReproducerCapture : public CommandObjectMultiword {
-private:
-public:
-  CommandObjectReproducerCapture(CommandInterpreter &interpreter)
-      : CommandObjectMultiword(
-            interpreter, "reproducer capture",
-            "Manage gathering of information needed to generate a reproducer.",
-            NULL) {
-    LoadSubCommand(
-        "enable",
-        CommandObjectSP(new CommandObjectReproducerCaptureEnable(interpreter)));
-    LoadSubCommand("disable",
-                   CommandObjectSP(
-                       new CommandObjectReproducerCaptureDisable(interpreter)));
-  }
-
-  ~CommandObjectReproducerCapture() {}
-};
-
 CommandObjectReproducer::CommandObjectReproducer(
     CommandInterpreter &interpreter)
     : CommandObjectMultiword(interpreter, "reproducer",
                              "Commands controlling LLDB reproducers.",
                              "log <subcommand> [<command-options>]") {
-  LoadSubCommand("capture", CommandObjectSP(new CommandObjectReproducerCapture(
-                                interpreter)));
   LoadSubCommand(
       "generate",
       CommandObjectSP(new CommandObjectReproducerGenerate(interpreter)));
-  LoadSubCommand("replay", CommandObjectSP(
-                               new CommandObjectReproducerReplay(interpreter)));
+  LoadSubCommand("status", CommandObjectSP(
+                               new CommandObjectReproducerStatus(interpreter)));
 }
 
 CommandObjectReproducer::~CommandObjectReproducer() = default;
Index: source/API/SystemInitializerFull.h
===================================================================
--- source/API/SystemInitializerFull.h
+++ source/API/SystemInitializerFull.h
@@ -26,7 +26,7 @@
   SystemInitializerFull();
   ~SystemInitializerFull() override;
 
-  void Initialize() override;
+  void Initialize(const InitializerOptions &options) override;
   void Terminate() override;
 
 private:
Index: source/API/SystemInitializerFull.cpp
===================================================================
--- source/API/SystemInitializerFull.cpp
+++ source/API/SystemInitializerFull.cpp
@@ -263,8 +263,8 @@
 
 SystemInitializerFull::~SystemInitializerFull() {}
 
-void SystemInitializerFull::Initialize() {
-  SystemInitializerCommon::Initialize();
+void SystemInitializerFull::Initialize(const InitializerOptions &options) {
+  SystemInitializerCommon::Initialize(options);
 
   ObjectFileELF::Initialize();
   ObjectFileMachO::Initialize();
Index: source/API/SBInitializerOptions.cpp
===================================================================
--- /dev/null
+++ source/API/SBInitializerOptions.cpp
@@ -0,0 +1,49 @@
+//===-- SBInitializerOptions.cpp --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBInitializerOptions.h"
+#include "lldb/Initialization/SystemInitializer.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SBInitializerOptions::SBInitializerOptions(const SBInitializerOptions &rhs) {
+  m_opaque_up.reset(new InitializerOptions());
+  *(m_opaque_up.get()) = rhs.ref();
+}
+
+const SBInitializerOptions &SBInitializerOptions::
+operator=(const SBInitializerOptions &rhs) {
+  if (this != &rhs) {
+    this->ref() = rhs.ref();
+  }
+  return *this;
+}
+
+SBInitializerOptions::~SBInitializerOptions() {}
+
+SBInitializerOptions::SBInitializerOptions() {
+  m_opaque_up.reset(new InitializerOptions());
+}
+
+void SBInitializerOptions::SetCaptureReproducer(bool b) {
+  m_opaque_up->reproducer_capture = b;
+}
+
+void SBInitializerOptions::SetReplayReproducer(bool b) {
+  m_opaque_up->reproducer_replay = b;
+}
+
+void SBInitializerOptions::SetReproducerPath(const char *path) {
+  m_opaque_up->reproducer_path = path;
+}
+
+InitializerOptions &SBInitializerOptions::ref() const {
+  return *(m_opaque_up.get());
+}
Index: source/API/SBDebugger.cpp
===================================================================
--- source/API/SBDebugger.cpp
+++ source/API/SBDebugger.cpp
@@ -125,13 +125,18 @@
 }
 
 void SBDebugger::Initialize() {
+  SBInitializerOptions options;
+  SBDebugger::Initialize(options);
+}
+
+void SBDebugger::Initialize(SBInitializerOptions &options) {
   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
 
   if (log)
     log->Printf("SBDebugger::Initialize ()");
 
   g_debugger_lifetime->Initialize(llvm::make_unique<SystemInitializerFull>(),
-                                  LoadPlugin);
+                                  *options.m_opaque_up, LoadPlugin);
 }
 
 void SBDebugger::Terminate() { g_debugger_lifetime->Terminate(); }
@@ -1057,17 +1062,6 @@
               : nullptr);
 }
 
-SBError SBDebugger::ReplayReproducer(const char *p) {
-  SBError sb_error;
-  if (m_opaque_sp) {
-    auto error =
-        m_opaque_sp->SetReproducerReplay(llvm::StringRef::withNullAsEmpty(p));
-    std::string error_str = llvm::toString(std::move(error));
-    sb_error.ref().SetErrorString(error_str);
-  }
-  return sb_error;
-}
-
 ScriptLanguage SBDebugger::GetScriptLanguage() const {
   return (m_opaque_sp ? m_opaque_sp->GetScriptLanguage() : eScriptLanguageNone);
 }
Index: source/API/CMakeLists.txt
===================================================================
--- source/API/CMakeLists.txt
+++ source/API/CMakeLists.txt
@@ -29,6 +29,7 @@
   SBFrame.cpp
   SBFunction.cpp
   SBHostOS.cpp
+  SBInitializerOptions.cpp
   SBInstruction.cpp
   SBInstructionList.cpp
   SBLanguageRuntime.cpp
Index: scripts/lldb.swig
===================================================================
--- scripts/lldb.swig
+++ scripts/lldb.swig
@@ -187,6 +187,7 @@
 %include "./interface/SBFrame.i"
 %include "./interface/SBFunction.i"
 %include "./interface/SBHostOS.i"
+%include "./interface/SBInitializerOptions.i"
 %include "./interface/SBInstruction.i"
 %include "./interface/SBInstructionList.i"
 %include "./interface/SBLanguageRuntime.i"
Index: scripts/interface/SBInitializerOptions.i
===================================================================
--- /dev/null
+++ scripts/interface/SBInitializerOptions.i
@@ -0,0 +1,24 @@
+//===-- SWIG Interface for SBInitializerOptions -----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+namespace lldb {
+
+class SBInitializerOptions
+{
+public:
+  SBInitializerOptions ();
+  SBInitializerOptions (const lldb::SBInitializerOptions &rhs);
+  ~SBInitializerOptions();
+
+  void SetCaptureReproducer(bool b);
+  void SetReplayReproducer(bool b);
+  void SetReproducerPath(const char* path);
+};
+
+} // namespace lldb
Index: scripts/interface/SBDebugger.i
===================================================================
--- scripts/interface/SBDebugger.i
+++ scripts/interface/SBDebugger.i
@@ -123,6 +123,9 @@
     static void
     Initialize();
 
+    static void
+    Initialize(lldb::SBInitializerOptions& options);
+
     static void
     Terminate();
 
@@ -376,9 +379,6 @@
     const char *
     GetReproducerPath() const;
 
-    lldb::SBError
-    ReplayReproducer (const char *path);
-
     lldb::ScriptLanguage
     GetScriptLanguage() const;
 
Index: packages/Python/lldbsuite/test/functionalities/reproducer/gdb-remote/TestGdbRemoteReproducer.py
===================================================================
--- packages/Python/lldbsuite/test/functionalities/reproducer/gdb-remote/TestGdbRemoteReproducer.py
+++ /dev/null
@@ -1,49 +0,0 @@
-"""
-Test the GDB remote reproducer.
-"""
-
-from __future__ import print_function
-
-import os
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-
-
-class TestGdbRemoteReproducer(TestBase):
-
-    mydir = TestBase.compute_mydir(__file__)
-    NO_DEBUG_INFO_TESTCASE = True
-
-    def test(self):
-        """Test record and replay of gdb-remote packets."""
-        self.build()
-
-        # Create temp directory for the reproducer.
-        exe = self.getBuildArtifact("a.out")
-
-        # First capture a regular debugging session.
-        self.runCmd("reproducer capture enable")
-
-        reproducer_path = self.dbg.GetReproducerPath()
-
-        self.runCmd("file {}".format(exe))
-        self.runCmd("breakpoint set -f main.c -l 13")
-        self.runCmd("run")
-        self.runCmd("bt")
-        self.runCmd("cont")
-
-        # Generate the reproducer and stop capturing.
-        self.runCmd("reproducer generate")
-        self.runCmd("reproducer capture disable")
-
-        # Replay the session from the reproducer.
-        self.runCmd("reproducer replay {}".format(reproducer_path))
-
-        # We have to issue the same commands.
-        self.runCmd("file {}".format(exe))
-        self.runCmd("breakpoint set -f main.c -l 13")
-        self.runCmd("run")
-        self.runCmd("bt")
-        self.expect("cont")
Index: packages/Python/lldbsuite/test/functionalities/reproducer/gdb-remote/Makefile
===================================================================
--- packages/Python/lldbsuite/test/functionalities/reproducer/gdb-remote/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-LEVEL = ../../../make
-
-C_SOURCES := main.c
-
-include $(LEVEL)/Makefile.rules
Index: lit/Reproducer/TestGDBRemoteRepro.test
===================================================================
--- /dev/null
+++ lit/Reproducer/TestGDBRemoteRepro.test
@@ -0,0 +1,26 @@
+# REQUIRES: nowindows
+
+# This tests the replaying of GDB remote packets.
+#
+# We issue the same commands and ensure the output is identical to the original
+# process. To ensure we're not actually running the original binary we check
+# that the string "testing" is not printed.
+
+# RUN: %clang %S/Inputs/simple.c -g -o %t.out
+# RUN: %lldb -x -b -s %S/Inputs/GDBRemoteCapture.in --capture %T/reproducer -- %t.out | FileCheck %s --check-prefix CHECK --check-prefix CAPTURE
+# RUN: %lldb -x -b -s %S/Inputs/GDBRemoteReplay.in --replay %T/reproducer -- %t.out | FileCheck %s --check-prefix CHECK --check-prefix REPLAY
+
+# CHECK: Breakpoint 1
+# CHECK: Process {{.*}} stopped
+# CHECK: Process {{.*}} launched
+# CHECK: thread {{.*}} stop reason = breakpoint
+# CHECK: frame {{.*}} simple.c
+# CHECK: Process {{.*}} resuming
+#
+# CAPTURE: testing
+# REPLAY-NOT: testing
+#
+# CHECK: Process {{.*}} exited
+#
+# CAPTURE: Reproducer is in capture mode.
+# CAPTURE: Reproducer written
Index: lit/Reproducer/Inputs/GDBRemoteReplay.in
===================================================================
--- /dev/null
+++ lit/Reproducer/Inputs/GDBRemoteReplay.in
@@ -0,0 +1,5 @@
+reproducer status
+breakpoint set -f simple.c -l 13
+run
+bt
+cont
Index: lit/Reproducer/Inputs/GDBRemoteCapture.in
===================================================================
--- /dev/null
+++ lit/Reproducer/Inputs/GDBRemoteCapture.in
@@ -0,0 +1,6 @@
+breakpoint set -f simple.c -l 13
+run
+bt
+cont
+reproducer status
+reproducer generate
Index: include/lldb/Utility/Reproducer.h
===================================================================
--- include/lldb/Utility/Reproducer.h
+++ include/lldb/Utility/Reproducer.h
@@ -25,6 +25,12 @@
 
 class Reproducer;
 
+enum class ReproducerMode {
+  Capture,
+  Replay,
+  Off,
+};
+
 /// Abstraction for information associated with a provider. This information
 /// is serialized into an index which is used by the loader.
 struct ProviderInfo {
@@ -159,10 +165,13 @@
 
 /// The reproducer enables clients to obtain access to the Generator and
 /// Loader.
-class Reproducer final {
-
+class Reproducer {
 public:
   static Reproducer &Instance();
+  static void Initialize(ReproducerMode mode, llvm::Optional<FileSpec> root);
+  static void Terminate();
+
+  Reproducer(ReproducerMode mode, llvm::Optional<FileSpec> root);
 
   Generator *GetGenerator();
   Loader *GetLoader();
@@ -170,12 +179,16 @@
   const Generator *GetGenerator() const;
   const Loader *GetLoader() const;
 
+  FileSpec GetReproducerPath() const;
+
+protected:
+  Reproducer() = default;
   llvm::Error SetCapture(llvm::Optional<FileSpec> root);
   llvm::Error SetReplay(llvm::Optional<FileSpec> root);
 
-  FileSpec GetReproducerPath() const;
-
 private:
+  static llvm::Optional<Reproducer> &InstanceImpl();
+
   llvm::Optional<Generator> m_generator;
   llvm::Optional<Loader> m_loader;
 
Index: include/lldb/Initialization/SystemLifetimeManager.h
===================================================================
--- include/lldb/Initialization/SystemLifetimeManager.h
+++ include/lldb/Initialization/SystemLifetimeManager.h
@@ -10,13 +10,13 @@
 #ifndef LLDB_INITIALIZATION_SYSTEM_LIFETIME_MANAGER_H
 #define LLDB_INITIALIZATION_SYSTEM_LIFETIME_MANAGER_H
 
+#include "lldb/Initialization/SystemInitializer.h"
 #include "lldb/lldb-private-types.h"
 
 #include <memory>
 #include <mutex>
 
 namespace lldb_private {
-class SystemInitializer;
 
 class SystemLifetimeManager {
 public:
@@ -24,6 +24,7 @@
   ~SystemLifetimeManager();
 
   void Initialize(std::unique_ptr<SystemInitializer> initializer,
+                  const InitializerOptions &options,
                   LoadPluginCallbackType plugin_callback);
   void Terminate();
 
Index: include/lldb/Initialization/SystemInitializerCommon.h
===================================================================
--- include/lldb/Initialization/SystemInitializerCommon.h
+++ include/lldb/Initialization/SystemInitializerCommon.h
@@ -28,7 +28,7 @@
   SystemInitializerCommon();
   ~SystemInitializerCommon() override;
 
-  void Initialize() override;
+  void Initialize(const InitializerOptions &options) override;
   void Terminate() override;
 };
 
Index: include/lldb/Initialization/SystemInitializer.h
===================================================================
--- include/lldb/Initialization/SystemInitializer.h
+++ include/lldb/Initialization/SystemInitializer.h
@@ -10,13 +10,22 @@
 #ifndef LLDB_INITIALIZATION_SYSTEM_INITIALIZER_H
 #define LLDB_INITIALIZATION_SYSTEM_INITIALIZER_H
 
+#include <string>
+
 namespace lldb_private {
+
+struct InitializerOptions {
+  bool reproducer_capture = false;
+  bool reproducer_replay = false;
+  std::string reproducer_path;
+};
+
 class SystemInitializer {
 public:
   SystemInitializer();
   virtual ~SystemInitializer();
 
-  virtual void Initialize() = 0;
+  virtual void Initialize(const InitializerOptions &options) = 0;
   virtual void Terminate() = 0;
 };
 }
Index: include/lldb/Host/HostInfoBase.h
===================================================================
--- include/lldb/Host/HostInfoBase.h
+++ include/lldb/Host/HostInfoBase.h
@@ -93,12 +93,6 @@
   /// FileSpec is filled in.
   static FileSpec GetGlobalTempDir();
 
-  /// Returns the reproducer temporary directory. This directory will **not**
-  /// be automatically cleaned up when this process exits, but might be removed
-  /// by the reproducer generator. Only the directory member of the FileSpec is
-  /// filled in.
-  static FileSpec GetReproducerTempDir();
-
   //---------------------------------------------------------------------------
   /// If the triple does not specify the vendor, os, and environment parts, we
   /// "augment" these using information from the host and return the resulting
@@ -111,7 +105,6 @@
   static bool ComputeSupportExeDirectory(FileSpec &file_spec);
   static bool ComputeProcessTempFileDirectory(FileSpec &file_spec);
   static bool ComputeGlobalTempFileDirectory(FileSpec &file_spec);
-  static bool ComputeReproducerTempFileDirectory(FileSpec &file_spec);
   static bool ComputeTempFileBaseDirectory(FileSpec &file_spec);
   static bool ComputeHeaderDirectory(FileSpec &file_spec);
   static bool ComputeSystemPluginsDirectory(FileSpec &file_spec);
Index: include/lldb/Core/Debugger.h
===================================================================
--- include/lldb/Core/Debugger.h
+++ include/lldb/Core/Debugger.h
@@ -263,11 +263,6 @@
 
   llvm::StringRef GetReproducerPath() const;
 
-  llvm::Error SetReproducerReplay(llvm::StringRef p);
-  llvm::Error SetReproducerReplay(const char *) = delete;
-
-  llvm::Error SetReproducerCapture(bool b);
-
   bool GetUseExternalEditor() const;
 
   bool SetUseExternalEditor(bool use_external_editor_p);
Index: include/lldb/API/SBInitializerOptions.h
===================================================================
--- /dev/null
+++ include/lldb/API/SBInitializerOptions.h
@@ -0,0 +1,43 @@
+//===-- SBInitializerOptions.h ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SBInitializerOptuions_h_
+#define LLDB_SBInitializerOptuions_h_
+
+#include "lldb/API/SBDefines.h"
+#include "lldb/API/SBFileSpec.h"
+
+namespace lldb_private {
+struct InitializerOptions;
+}
+
+namespace lldb {
+
+class LLDB_API SBInitializerOptions {
+public:
+  SBInitializerOptions();
+  SBInitializerOptions(const lldb::SBInitializerOptions &rhs);
+  ~SBInitializerOptions();
+  const SBInitializerOptions &operator=(const lldb::SBInitializerOptions &rhs);
+
+  void SetCaptureReproducer(bool b);
+  void SetReplayReproducer(bool b);
+  void SetReproducerPath(const char *path);
+
+  lldb_private::InitializerOptions &ref() const;
+
+private:
+  friend class SBDebugger;
+
+  std::unique_ptr<lldb_private::InitializerOptions> m_opaque_up;
+};
+
+} // namespace lldb
+
+#endif // LLDB_SBInitializerOptuions_h_
Index: include/lldb/API/SBFileSpec.h
===================================================================
--- include/lldb/API/SBFileSpec.h
+++ include/lldb/API/SBFileSpec.h
@@ -59,6 +59,7 @@
   friend class SBDeclaration;
   friend class SBFileSpecList;
   friend class SBHostOS;
+  friend class SBInitializerOptions;
   friend class SBLaunchInfo;
   friend class SBLineEntry;
   friend class SBModule;
@@ -67,8 +68,8 @@
   friend class SBProcess;
   friend class SBProcessInfo;
   friend class SBSourceManager;
-  friend class SBThread;
   friend class SBTarget;
+  friend class SBThread;
 
   SBFileSpec(const lldb_private::FileSpec &fspec);
 
Index: include/lldb/API/SBDefines.h
===================================================================
--- include/lldb/API/SBDefines.h
+++ include/lldb/API/SBDefines.h
@@ -51,6 +51,7 @@
 class LLDB_API SBFrame;
 class LLDB_API SBFunction;
 class LLDB_API SBHostOS;
+class LLDB_API SBInitializerOptions;
 class LLDB_API SBInstruction;
 class LLDB_API SBInstructionList;
 class LLDB_API SBLanguageRuntime;
Index: include/lldb/API/SBDebugger.h
===================================================================
--- include/lldb/API/SBDebugger.h
+++ include/lldb/API/SBDebugger.h
@@ -13,6 +13,7 @@
 #include <stdio.h>
 
 #include "lldb/API/SBDefines.h"
+#include "lldb/API/SBInitializerOptions.h"
 #include "lldb/API/SBPlatform.h"
 
 namespace lldb {
@@ -45,6 +46,7 @@
   lldb::SBDebugger &operator=(const lldb::SBDebugger &rhs);
 
   static void Initialize();
+  static void Initialize(SBInitializerOptions &options);
 
   static void Terminate();
 
@@ -228,8 +230,6 @@
 
   const char *GetReproducerPath() const;
 
-  lldb::SBError ReplayReproducer(const char *path);
-
   lldb::ScriptLanguage GetScriptLanguage() const;
 
   void SetScriptLanguage(lldb::ScriptLanguage script_lang);
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to