[Lldb-commits] [lldb] 73af341 - [lldb] Capture and load home directory from the reproducer.

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Thu Aug 20 18:09:08 PDT 2020


Author: Jonas Devlieghere
Date: 2020-08-20T18:08:59-07:00
New Revision: 73af341beb8435c7da1dd5e7a8abacb2de6a236d

URL: https://github.com/llvm/llvm-project/commit/73af341beb8435c7da1dd5e7a8abacb2de6a236d
DIFF: https://github.com/llvm/llvm-project/commit/73af341beb8435c7da1dd5e7a8abacb2de6a236d.diff

LOG: [lldb] Capture and load home directory from the reproducer.

When replaying the reproducer, lldb should source the .lldbinit file
that was captured by the reproducer and not the one in the current home
directory. This requires that we store the home directory as part of the
reproducer. By returning the virtual home directory during replay, we
ensure the correct virtual path gets constructed which the VFS can then
find and remap to the correct file in the reproducer root.

This patch adds a new HomeDirectoryProvider, similar to the existing
WorkingDirectoryProvider. As the home directory is not part of the VFS,
it is stored in LLDB's FileSystem instance.

Added: 
    lldb/test/Shell/Reproducer/Inputs/HomeDir.in
    lldb/test/Shell/Reproducer/TestHomeDir.test

Modified: 
    lldb/include/lldb/Host/FileSystem.h
    lldb/include/lldb/Utility/Reproducer.h
    lldb/source/Commands/CommandObjectReproducer.cpp
    lldb/source/Host/common/FileSystem.cpp
    lldb/source/Initialization/SystemInitializerCommon.cpp
    lldb/source/Utility/Reproducer.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Host/FileSystem.h b/lldb/include/lldb/Host/FileSystem.h
index aff752699923..811a10e47f1c 100644
--- a/lldb/include/lldb/Host/FileSystem.h
+++ b/lldb/include/lldb/Host/FileSystem.h
@@ -33,13 +33,14 @@ class FileSystem {
 
   FileSystem()
       : m_fs(llvm::vfs::getRealFileSystem()), m_collector(nullptr),
-        m_mapped(false) {}
+        m_home_directory(), m_mapped(false) {}
   FileSystem(std::shared_ptr<llvm::FileCollector> collector)
       : m_fs(llvm::vfs::getRealFileSystem()), m_collector(std::move(collector)),
-        m_mapped(false) {}
+        m_home_directory(), m_mapped(false) {}
   FileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,
              bool mapped = false)
-      : m_fs(std::move(fs)), m_collector(nullptr), m_mapped(mapped) {}
+      : m_fs(std::move(fs)), m_collector(nullptr), m_home_directory(),
+        m_mapped(mapped) {}
 
   FileSystem(const FileSystem &fs) = delete;
   FileSystem &operator=(const FileSystem &fs) = delete;
@@ -193,10 +194,13 @@ class FileSystem {
   void Collect(const FileSpec &file_spec);
   void Collect(const llvm::Twine &file);
 
+  void SetHomeDirectory(std::string home_directory);
+
 private:
   static llvm::Optional<FileSystem> &InstanceImpl();
   llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> m_fs;
   std::shared_ptr<llvm::FileCollector> m_collector;
+  std::string m_home_directory;
   bool m_mapped;
 };
 } // namespace lldb_private

diff  --git a/lldb/include/lldb/Utility/Reproducer.h b/lldb/include/lldb/Utility/Reproducer.h
index da8fd6754a20..8a406658fdfb 100644
--- a/lldb/include/lldb/Utility/Reproducer.h
+++ b/lldb/include/lldb/Utility/Reproducer.h
@@ -181,6 +181,25 @@ class WorkingDirectoryProvider
   static char ID;
 };
 
+/// Provider for the home directory.
+///
+/// When the reproducer is kept, it writes the user's home directory to a file
+/// a file named home.txt in the reproducer root.
+class HomeDirectoryProvider : public DirectoryProvider<HomeDirectoryProvider> {
+public:
+  HomeDirectoryProvider(const FileSpec &directory)
+      : DirectoryProvider(directory) {
+    llvm::SmallString<128> home_dir;
+    llvm::sys::path::home_directory(home_dir);
+    SetDirectory(std::string(home_dir));
+  }
+  struct Info {
+    static const char *name;
+    static const char *file;
+  };
+  static char ID;
+};
+
 /// The recorder is a small object handed out by a provider to record data. It
 /// is commonly used in combination with a MultiProvider which is meant to
 /// record information for multiple instances of the same source of data.
@@ -495,6 +514,15 @@ template <typename T> class MultiLoader {
   unsigned m_index = 0;
 };
 
+/// Helper to read directories written by the DirectoryProvider.
+template <typename T>
+llvm::Expected<std::string> GetDirectoryFrom(repro::Loader *loader) {
+  llvm::Expected<std::string> dir = loader->LoadBuffer<T>();
+  if (!dir)
+    return dir.takeError();
+  return std::string(llvm::StringRef(*dir).rtrim());
+}
+
 } // namespace repro
 } // namespace lldb_private
 

diff  --git a/lldb/source/Commands/CommandObjectReproducer.cpp b/lldb/source/Commands/CommandObjectReproducer.cpp
index 104130b70b2b..9add2df52985 100644
--- a/lldb/source/Commands/CommandObjectReproducer.cpp
+++ b/lldb/source/Commands/CommandObjectReproducer.cpp
@@ -31,6 +31,7 @@ enum ReproducerProvider {
   eReproducerProviderProcessInfo,
   eReproducerProviderVersion,
   eReproducerProviderWorkingDirectory,
+  eReproducerProviderHomeDirectory,
   eReproducerProviderNone
 };
 
@@ -65,6 +66,11 @@ static constexpr OptionEnumValueElement g_reproducer_provider_type[] = {
         "cwd",
         "Working Directory",
     },
+    {
+        eReproducerProviderHomeDirectory,
+        "home",
+        "Home Directory",
+    },
     {
         eReproducerProviderNone,
         "none",
@@ -433,7 +439,7 @@ class CommandObjectReproducerDump : public CommandObjectParsed {
     }
     case eReproducerProviderWorkingDirectory: {
       Expected<std::string> cwd =
-          loader->LoadBuffer<WorkingDirectoryProvider>();
+          repro::GetDirectoryFrom<WorkingDirectoryProvider>(loader);
       if (!cwd) {
         SetError(result, cwd.takeError());
         return false;
@@ -442,6 +448,17 @@ class CommandObjectReproducerDump : public CommandObjectParsed {
       result.SetStatus(eReturnStatusSuccessFinishResult);
       return true;
     }
+    case eReproducerProviderHomeDirectory: {
+      Expected<std::string> home =
+          repro::GetDirectoryFrom<HomeDirectoryProvider>(loader);
+      if (!home) {
+        SetError(result, home.takeError());
+        return false;
+      }
+      result.AppendMessage(*home);
+      result.SetStatus(eReturnStatusSuccessFinishResult);
+      return true;
+    }
     case eReproducerProviderCommands: {
       std::unique_ptr<repro::MultiLoader<repro::CommandProvider>> multi_loader =
           repro::MultiLoader<repro::CommandProvider>::Create(loader);

diff  --git a/lldb/source/Host/common/FileSystem.cpp b/lldb/source/Host/common/FileSystem.cpp
index d295c01e6967..b8c962cb182f 100644
--- a/lldb/source/Host/common/FileSystem.cpp
+++ b/lldb/source/Host/common/FileSystem.cpp
@@ -361,6 +361,10 @@ bool FileSystem::ResolveExecutableLocation(FileSpec &file_spec) {
 }
 
 bool FileSystem::GetHomeDirectory(SmallVectorImpl<char> &path) const {
+  if (!m_home_directory.empty()) {
+    path.assign(m_home_directory.begin(), m_home_directory.end());
+    return true;
+  }
   return llvm::sys::path::home_directory(path);
 }
 
@@ -507,3 +511,7 @@ void FileSystem::Collect(const llvm::Twine &file) {
   else
     m_collector->addFile(file);
 }
+
+void FileSystem::SetHomeDirectory(std::string home_directory) {
+  m_home_directory = std::move(home_directory);
+}

diff  --git a/lldb/source/Initialization/SystemInitializerCommon.cpp b/lldb/source/Initialization/SystemInitializerCommon.cpp
index c3bef4139bcc..4d72f6e2ad33 100644
--- a/lldb/source/Initialization/SystemInitializerCommon.cpp
+++ b/lldb/source/Initialization/SystemInitializerCommon.cpp
@@ -51,18 +51,24 @@ static llvm::Error InitializeFileSystem() {
       FileSystem::Initialize();
     }
 
-    llvm::Expected<std::string> cwd =
-        loader->LoadBuffer<WorkingDirectoryProvider>();
-    if (!cwd)
-      return cwd.takeError();
-
-    llvm::StringRef working_dir = llvm::StringRef(*cwd).rtrim();
+    // Set the current working directory form the reproducer.
+    llvm::Expected<std::string> working_dir =
+        repro::GetDirectoryFrom<WorkingDirectoryProvider>(loader);
+    if (!working_dir)
+      return working_dir.takeError();
     if (std::error_code ec = FileSystem::Instance()
                                  .GetVirtualFileSystem()
-                                 ->setCurrentWorkingDirectory(working_dir)) {
+                                 ->setCurrentWorkingDirectory(*working_dir)) {
       return llvm::errorCodeToError(ec);
     }
 
+    // Set the home directory from the reproducer.
+    llvm::Expected<std::string> home_dir =
+        repro::GetDirectoryFrom<HomeDirectoryProvider>(loader);
+    if (!home_dir)
+      return home_dir.takeError();
+    FileSystem::Instance().SetHomeDirectory(*home_dir);
+
     return llvm::Error::success();
   }
 

diff  --git a/lldb/source/Utility/Reproducer.cpp b/lldb/source/Utility/Reproducer.cpp
index 935e41a08a4e..35d145e4d61b 100644
--- a/lldb/source/Utility/Reproducer.cpp
+++ b/lldb/source/Utility/Reproducer.cpp
@@ -166,6 +166,7 @@ static FileSpec MakeAbsolute(const FileSpec &file_spec) {
 
 Generator::Generator(FileSpec root) : m_root(MakeAbsolute(std::move(root))) {
   GetOrCreate<repro::WorkingDirectoryProvider>();
+  GetOrCreate<repro::HomeDirectoryProvider>();
 }
 
 Generator::~Generator() {
@@ -306,6 +307,7 @@ char FileProvider::ID = 0;
 char ProviderBase::ID = 0;
 char VersionProvider::ID = 0;
 char WorkingDirectoryProvider::ID = 0;
+char HomeDirectoryProvider::ID = 0;
 const char *CommandProvider::Info::file = "command-interpreter.yaml";
 const char *CommandProvider::Info::name = "command-interpreter";
 const char *FileProvider::Info::file = "files.yaml";
@@ -314,3 +316,5 @@ const char *VersionProvider::Info::file = "version.txt";
 const char *VersionProvider::Info::name = "version";
 const char *WorkingDirectoryProvider::Info::file = "cwd.txt";
 const char *WorkingDirectoryProvider::Info::name = "cwd";
+const char *HomeDirectoryProvider::Info::file = "home.txt";
+const char *HomeDirectoryProvider::Info::name = "home";

diff  --git a/lldb/test/Shell/Reproducer/Inputs/HomeDir.in b/lldb/test/Shell/Reproducer/Inputs/HomeDir.in
new file mode 100644
index 000000000000..246ed7bef69d
--- /dev/null
+++ b/lldb/test/Shell/Reproducer/Inputs/HomeDir.in
@@ -0,0 +1,2 @@
+reproducer status
+reproducer generate

diff  --git a/lldb/test/Shell/Reproducer/TestHomeDir.test b/lldb/test/Shell/Reproducer/TestHomeDir.test
new file mode 100644
index 000000000000..b4665e54fb6a
--- /dev/null
+++ b/lldb/test/Shell/Reproducer/TestHomeDir.test
@@ -0,0 +1,14 @@
+# RUN: echo "CHECK: %t.home" > %t.check
+
+# RUN: rm -rf %t.repro
+# RUN: rm -rf %t.home
+# RUN: mkdir -p %t.repro
+# RUN: mkdir -p %t.home
+# RUN: echo "print 95000 + 126" > %t.home/.lldbinit
+# RUN: env HOME=%t.home %lldb-init -b -s %S/Inputs/HomeDir.in --capture --capture-path %t.repro | FileCheck %s
+
+# RUN: cat %t.repro/home.txt | FileCheck %t.check
+# RUN: %lldb -b -o 'reproducer dump -p home -f %t.repro' | FileCheck %t.check
+
+# RUN: %lldb --replay %t.repro | FileCheck %s
+# CHECK: 95126


        


More information about the lldb-commits mailing list