JDevlieghere created this revision.
JDevlieghere added reviewers: bkramer, bruno, vsapsai, sammccall.
Herald added subscribers: lldb-commits, dexonsmith, hiraditya.
Herald added projects: LLDB, LLVM.

For reproducers it is useful to encode the notion of the current working 
directory in the VFS mapping. This enables us to handle relative files 
transparently, as long as the current working directory doesn't change over 
time.

This change is motivated by a current bug in LLDB's reproducers. When a 
relative path to a binary is passed to the debugger, we fail to resolve it 
during reproducer replay, because the resolved (absolute) path doesn't match 
any entry in the VFS.


Repository:
  rLLDB LLDB

https://reviews.llvm.org/D65677

Files:
  llvm/include/llvm/Support/VirtualFileSystem.h
  llvm/lib/Support/VirtualFileSystem.cpp
  llvm/unittests/Support/VirtualFileSystemTest.cpp

Index: llvm/unittests/Support/VirtualFileSystemTest.cpp
===================================================================
--- llvm/unittests/Support/VirtualFileSystemTest.cpp
+++ llvm/unittests/Support/VirtualFileSystemTest.cpp
@@ -1994,3 +1994,42 @@
   EXPECT_EQ(FS->getRealPath("/non_existing", RealPath),
             errc::no_such_file_or_directory);
 }
+
+TEST_F(VFSFromYAMLTest, CurrentWorkingDirectory) {
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  Lower->addDirectory("//root/");
+  Lower->addDirectory("//root/foo");
+  Lower->addRegularFile("//root/foo/a");
+  Lower->addRegularFile("//root/foo/b");
+  IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
+      "{ 'use-external-names': false,\n"
+      "  'current-working-directory': '//root/bar'\n"
+      "  'roots': [\n"
+      "{\n"
+      "  'type': 'directory',\n"
+      "  'name': '//root/',\n"
+      "  'contents': [ {\n"
+      "                  'type': 'file',\n"
+      "                  'name': 'bar/a',\n"
+      "                  'external-contents': '//root/foo/a'\n"
+      "                }\n"
+      "              ]\n"
+      "}\n"
+      "]\n"
+      "}",
+      Lower);
+  ASSERT_TRUE(FS.get() != nullptr);
+
+  llvm::ErrorOr<std::string> CWD = FS->getCurrentWorkingDirectory();
+  ASSERT_FALSE(CWD.getError());
+  EXPECT_EQ(*CWD, "//root/bar");
+
+  llvm::ErrorOr<vfs::Status> Status = FS->status("./a");
+  ASSERT_FALSE(Status.getError());
+  EXPECT_TRUE(Status->isStatusKnown());
+  EXPECT_FALSE(Status->isDirectory());
+  EXPECT_TRUE(Status->isRegularFile());
+  EXPECT_FALSE(Status->isSymlink());
+  EXPECT_FALSE(Status->isOther());
+  EXPECT_TRUE(Status->exists());
+}
Index: llvm/lib/Support/VirtualFileSystem.cpp
===================================================================
--- llvm/lib/Support/VirtualFileSystem.cpp
+++ llvm/lib/Support/VirtualFileSystem.cpp
@@ -1035,11 +1035,17 @@
 
 llvm::ErrorOr<std::string>
 RedirectingFileSystem::getCurrentWorkingDirectory() const {
+  if (!CurrentWorkingDirectory.empty())
+    return CurrentWorkingDirectory;
   return ExternalFS->getCurrentWorkingDirectory();
 }
 
 std::error_code
 RedirectingFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
+  // Changing the current working directory might have side effects for the
+  // external file system. Unset the special current working directory and have
+  // the external FS deal with them from now on.
+  CurrentWorkingDirectory.clear();
   return ExternalFS->setCurrentWorkingDirectory(Path);
 }
 
@@ -1473,6 +1479,7 @@
         KeyStatusPair("use-external-names", false),
         KeyStatusPair("overlay-relative", false),
         KeyStatusPair("fallthrough", false),
+        KeyStatusPair("current-working-directory", false),
         KeyStatusPair("roots", true),
     };
 
@@ -1533,6 +1540,12 @@
       } else if (Key == "fallthrough") {
         if (!parseScalarBool(I.getValue(), FS->IsFallthrough))
           return false;
+      } else if (Key == "current-working-directory") {
+        StringRef CurrentWorkingDirectory;
+        SmallString<256> Storage;
+        if (!parseScalarString(I.getValue(), CurrentWorkingDirectory, Storage))
+          return false;
+        FS->setCurrentWorkingDirectory(CurrentWorkingDirectory);
       } else {
         llvm_unreachable("key missing from Keys");
       }
@@ -1874,7 +1887,7 @@
 
   void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> UseExternalNames,
              Optional<bool> IsCaseSensitive, Optional<bool> IsOverlayRelative,
-             StringRef OverlayDir);
+             StringRef OverlayDir, StringRef CurrentWorkingDirectory);
 };
 
 } // namespace
@@ -1932,6 +1945,7 @@
                        Optional<bool> UseExternalNames,
                        Optional<bool> IsCaseSensitive,
                        Optional<bool> IsOverlayRelative,
+                       StringRef CurrentWorkingDirectory,
                        StringRef OverlayDir) {
   using namespace llvm::sys;
 
@@ -1949,6 +1963,9 @@
     OS << "  'overlay-relative': '" << (UseOverlayRelative ? "true" : "false")
        << "',\n";
   }
+  if (!CurrentWorkingDirectory.empty())
+    OS << "  'current-working-directory': \""
+       << llvm::yaml::escape(CurrentWorkingDirectory) << "\",\n";
   OS << "  'roots': [\n";
 
   if (!Entries.empty()) {
@@ -2004,7 +2021,7 @@
   });
 
   JSONWriter(OS).write(Mappings, UseExternalNames, IsCaseSensitive,
-                       IsOverlayRelative, OverlayDir);
+                       IsOverlayRelative, OverlayDir, CurrentWorkingDirectory);
 }
 
 VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl(
Index: llvm/include/llvm/Support/VirtualFileSystem.h
===================================================================
--- llvm/include/llvm/Support/VirtualFileSystem.h
+++ llvm/include/llvm/Support/VirtualFileSystem.h
@@ -658,6 +658,10 @@
   /// when reading from YAML files.
   std::string ExternalContentsPrefixDir;
 
+  /// If CurrentWorkingDirectory is set, non-absolute paths are considered
+  /// relative to this path.
+  std::string CurrentWorkingDirectory;
+
   /// @name Configuration
   /// @{
 
@@ -752,6 +756,7 @@
   Optional<bool> IsOverlayRelative;
   Optional<bool> UseExternalNames;
   std::string OverlayDir;
+  std::string CurrentWorkingDirectory;
 
 public:
   YAMLVFSWriter() = default;
@@ -764,6 +769,10 @@
 
   void setUseExternalNames(bool UseExtNames) { UseExternalNames = UseExtNames; }
 
+  void setCurrentWorkingDirectory(std::string CWD) {
+    CurrentWorkingDirectory = std::move(CWD);
+  }
+
   void setOverlayDir(StringRef OverlayDirectory) {
     IsOverlayRelative = true;
     OverlayDir.assign(OverlayDirectory.str());
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to