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 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits