JDevlieghere created this revision.
JDevlieghere added reviewers: labath, friss.
Herald added a subscriber: mgorny.
Herald added a project: LLDB.

This patch introduces a small new tool `(lldb-repro`) to transparently capture 
and replay debugger sessions from the driver. The goal is to run the shell 
tests, generate a reproducers for each one of them, and then run the shell 
tests again, this time replaying the reproducer. I could've implemented all 
this in LLDB, but I felt a separate tool would be better.

Right now this requires you to swap out `lldb` and `lldb-repro`. I hope to find 
a way to automate that so you can pass `--param=run_with_lldb_repro=capture` 
and `--param=run_with_lldb_repro=replay` to lit directly.


Repository:
  rLLDB LLDB

https://reviews.llvm.org/D72823

Files:
  lldb/test/Shell/Reproducer/lit.local.cfg
  lldb/test/Shell/lit.cfg.py
  lldb/tools/CMakeLists.txt
  lldb/tools/lldb-repro/CMakeLists.txt
  lldb/tools/lldb-repro/lldb-repro.cpp
  lldb/tools/lldb-repro/lldb-repro.h.cmake

Index: lldb/tools/lldb-repro/lldb-repro.h.cmake
===================================================================
--- /dev/null
+++ lldb/tools/lldb-repro/lldb-repro.h.cmake
@@ -0,0 +1,14 @@
+//===-- lldb-repro.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_TOOLS_LLDB_REPRO_H
+#define LLDB_TOOLS_LLDB_REPRO_H
+
+#cmakedefine LLDB_TEST_EXECUTABLE "${LLDB_TEST_EXECUTABLE}"
+
+#endif
Index: lldb/tools/lldb-repro/lldb-repro.cpp
===================================================================
--- /dev/null
+++ lldb/tools/lldb-repro/lldb-repro.cpp
@@ -0,0 +1,76 @@
+//===-- lldb-repro.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb-repro.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DJB.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+using namespace llvm;
+
+unsigned ComputerHash(StringRef args, StringRef cwd) {
+  const unsigned hash = djbHash(cwd);
+  return djbHash(args, hash);
+}
+
+int main(int argc, const char **argv) {
+  std::string arg_str;
+  for (int i = 1; i < argc; ++i)
+    arg_str.append(argv[i]);
+
+  SmallString<256> cwd_str;
+  sys::fs::current_path(cwd_str);
+
+  // Compute the hash.
+  const unsigned hash = ComputerHash(arg_str, cwd_str.str());
+
+  // Compute the reproducer directory.
+  const char *tmpdir = getenv("TMPDIR");
+  if (!tmpdir) {
+    WithColor::error() << "unable to get the temp directory form TMPDIR\n";
+    return 1;
+  }
+
+  SmallString<256> repro_dir;
+  llvm::sys::path::system_temp_directory(true, repro_dir);
+  sys::path::append(repro_dir, std::to_string(hash));
+
+  // Construct the lldb argument list.
+  std::vector<StringRef> args;
+  args.push_back(LLDB_TEST_EXECUTABLE);
+  if (getenv("LLDB_REPRO_REPLAY")) {
+    args.push_back("--replay");
+    args.push_back(repro_dir.c_str());
+  } else if (getenv("LLDB_REPRO_CAPTURE")) {
+    // Remove any previous reproducer.
+    sys::fs::remove_directories(repro_dir);
+
+    args.push_back("--capture");
+    args.push_back("--capture-path");
+    args.push_back(repro_dir.c_str());
+    args.push_back("--reproducer-auto-generate");
+
+    // Append the original arguments.
+    for (int i = 1; i < argc; ++i)
+      args.push_back(argv[i]);
+  } else {
+    WithColor::error()
+        << "enable capture or replay by setting the environment variables "
+           "LLDB_REPRO_CAPTURE and LLDB_REPRO_REPLAY respectively\n";
+    return 1;
+  }
+
+  return llvm::sys::ExecuteAndWait(LLDB_TEST_EXECUTABLE, args);
+}
Index: lldb/tools/lldb-repro/CMakeLists.txt
===================================================================
--- /dev/null
+++ lldb/tools/lldb-repro/CMakeLists.txt
@@ -0,0 +1,10 @@
+set(lldb_repro_input ${CMAKE_CURRENT_SOURCE_DIR}/lldb-repro.h.cmake)
+set(lldb_repro_output ${CMAKE_CURRENT_BINARY_DIR}/lldb-repro.h)
+configure_file(${lldb_repro_input} ${lldb_repro_output})
+
+add_lldb_tool(lldb-repro
+  lldb-repro.cpp
+
+  LINK_COMPONENTS
+    Support
+  )
Index: lldb/tools/CMakeLists.txt
===================================================================
--- lldb/tools/CMakeLists.txt
+++ lldb/tools/CMakeLists.txt
@@ -7,7 +7,11 @@
 # example is `check-lldb`. So, we pass EXCLUDE_FROM_ALL here.
 add_subdirectory(lldb-test EXCLUDE_FROM_ALL)
 
-add_lldb_tool_subdirectory(lldb-instr)
+if(LLDB_INCLUDE_TESTS)
+  add_lldb_tool_subdirectory(lldb-instr)
+endif()
+
+add_lldb_tool_subdirectory(lldb-repro)
 add_lldb_tool_subdirectory(lldb-vscode)
 
 if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
Index: lldb/test/Shell/lit.cfg.py
===================================================================
--- lldb/test/Shell/lit.cfg.py
+++ lldb/test/Shell/lit.cfg.py
@@ -38,10 +38,15 @@
 # test_exec_root: The root path where tests should be run.
 config.test_exec_root = os.path.join(config.lldb_obj_root, 'test')
 
-# Propagate LLDB_CAPTURE_REPRODUCER
+# Propagate reproducer environment vars.
 if 'LLDB_CAPTURE_REPRODUCER' in os.environ:
   config.environment['LLDB_CAPTURE_REPRODUCER'] = os.environ[
       'LLDB_CAPTURE_REPRODUCER']
+if 'LLDB_REPRO_CAPTURE' in os.environ:
+  config.environment['LLDB_REPRO_CAPTURE'] = os.environ['LLDB_REPRO_CAPTURE']
+
+if 'LLDB_REPRO_REPLAY' in os.environ:
+  config.environment['LLDB_REPRO_REPLAY'] = os.environ['LLDB_REPRO_REPLAY']
 
 llvm_config.use_default_substitutions()
 toolchain.use_lldb_substitutions(config)
Index: lldb/test/Shell/Reproducer/lit.local.cfg
===================================================================
--- lldb/test/Shell/Reproducer/lit.local.cfg
+++ lldb/test/Shell/Reproducer/lit.local.cfg
@@ -4,3 +4,7 @@
 
 if 'LLDB_CAPTURE_REPRODUCER' in config.environment:
   del config.environment['LLDB_CAPTURE_REPRODUCER']
+
+if 'LLDB_REPRO_CAPTURE' in config.environment or \
+   'LLDB_REPRO_REPLAY' in config.environment:
+  config.unsupported = True
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to