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