diff --git a/lldb/include/lldb/Core/IOHandler.h b/lldb/include/lldb/Core/IOHandler.h index f29482c0c97a..c96dc1cd1888 100644 --- a/lldb/include/lldb/Core/IOHandler.h +++ b/lldb/include/lldb/Core/IOHandler.h @@ -15,7 +15,6 @@ #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Flags.h" #include "lldb/Utility/Predicate.h" -#include "lldb/Utility/Reproducer.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StringList.h" #include "lldb/lldb-defines.h" @@ -32,6 +31,9 @@ namespace lldb_private { class Debugger; +namespace repro { +class DataRecorder; +} } namespace curses { diff --git a/lldb/include/lldb/Utility/GDBRemote.h b/lldb/include/lldb/Utility/GDBRemote.h index f5749b7e6eaf..2ee706efbea2 100644 --- a/lldb/include/lldb/Utility/GDBRemote.h +++ b/lldb/include/lldb/Utility/GDBRemote.h @@ -10,7 +10,7 @@ #define LLDB_UTILITY_GDBREMOTE_H #include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Reproducer.h" +#include "lldb/Utility/ReproducerProvider.h" #include "lldb/Utility/StreamString.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-public.h" diff --git a/lldb/include/lldb/Utility/ProcessInfo.h b/lldb/include/lldb/Utility/ProcessInfo.h index ec91060cda54..8f5a5f6d21fb 100644 --- a/lldb/include/lldb/Utility/ProcessInfo.h +++ b/lldb/include/lldb/Utility/ProcessInfo.h @@ -14,7 +14,6 @@ #include "lldb/Utility/Environment.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/NameMatches.h" -#include "lldb/Utility/Reproducer.h" #include "llvm/Support/YAMLTraits.h" #include @@ -217,40 +216,7 @@ protected: }; namespace repro { -class ProcessInfoRecorder : public AbstractRecorder { -public: - ProcessInfoRecorder(const FileSpec &filename, std::error_code &ec) - : AbstractRecorder(filename, ec) {} - - static llvm::Expected> - Create(const FileSpec &filename); - - void Record(const ProcessInstanceInfoList &process_infos); -}; - -class ProcessInfoProvider : public repro::Provider { -public: - struct Info { - static const char *name; - static const char *file; - }; - - ProcessInfoProvider(const FileSpec &directory) : Provider(directory) {} - - ProcessInfoRecorder *GetNewProcessInfoRecorder(); - - void Keep() override; - void Discard() override; - - static char ID; - -private: - std::unique_ptr m_stream_up; - std::vector> m_process_info_recorders; -}; - llvm::Optional GetReplayProcessInstanceInfoList(); - } // namespace repro } // namespace lldb_private diff --git a/lldb/include/lldb/Utility/Reproducer.h b/lldb/include/lldb/Utility/Reproducer.h index 8a406658fdfb..4dc6ddd51394 100644 --- a/lldb/include/lldb/Utility/Reproducer.h +++ b/lldb/include/lldb/Utility/Reproducer.h @@ -13,7 +13,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" -#include "llvm/Support/FileCollector.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/YAMLTraits.h" #include @@ -84,250 +84,6 @@ protected: using ProviderBase::ProviderBase; // Inherit constructor. }; -class FileProvider : public Provider { -public: - struct Info { - static const char *name; - static const char *file; - }; - - FileProvider(const FileSpec &directory) - : Provider(directory), - m_collector(std::make_shared( - directory.CopyByAppendingPathComponent("root").GetPath(), - directory.GetPath())) {} - - std::shared_ptr GetFileCollector() { - return m_collector; - } - - void RecordInterestingDirectory(const llvm::Twine &dir); - void RecordInterestingDirectoryRecursive(const llvm::Twine &dir); - - void Keep() override { - auto mapping = GetRoot().CopyByAppendingPathComponent(Info::file); - // Temporary files that are removed during execution can cause copy errors. - if (auto ec = m_collector->copyFiles(/*stop_on_error=*/false)) - return; - m_collector->writeMapping(mapping.GetPath()); - } - - static char ID; - -private: - std::shared_ptr m_collector; -}; - -/// Provider for the LLDB version number. -/// -/// When the reproducer is kept, it writes the lldb version to a file named -/// version.txt in the reproducer root. -class VersionProvider : public Provider { -public: - VersionProvider(const FileSpec &directory) : Provider(directory) {} - struct Info { - static const char *name; - static const char *file; - }; - void SetVersion(std::string version) { - assert(m_version.empty()); - m_version = std::move(version); - } - void Keep() override; - std::string m_version; - static char ID; -}; - -/// Abstract provider to storing directory paths. -template class DirectoryProvider : public repro::Provider { -public: - DirectoryProvider(const FileSpec &root) : Provider(root) {} - void SetDirectory(std::string directory) { - m_directory = std::move(directory); - } - llvm::StringRef GetDirectory() { return m_directory; } - - void Keep() override { - FileSpec file = this->GetRoot().CopyByAppendingPathComponent(T::Info::file); - std::error_code ec; - llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text); - if (ec) - return; - os << m_directory << "\n"; - } - -protected: - std::string m_directory; -}; - -/// Provider for the current working directory. -/// -/// When the reproducer is kept, it writes lldb's current working directory to -/// a file named cwd.txt in the reproducer root. -class WorkingDirectoryProvider - : public DirectoryProvider { -public: - WorkingDirectoryProvider(const FileSpec &directory) - : DirectoryProvider(directory) { - llvm::SmallString<128> cwd; - if (std::error_code EC = llvm::sys::fs::current_path(cwd)) - return; - SetDirectory(std::string(cwd)); - } - struct Info { - static const char *name; - static const char *file; - }; - 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 { -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. -class AbstractRecorder { -protected: - AbstractRecorder(const FileSpec &filename, std::error_code &ec) - : m_filename(filename.GetFilename().GetStringRef()), - m_os(filename.GetPath(), ec, llvm::sys::fs::OF_Text), m_record(true) {} - -public: - const FileSpec &GetFilename() { return m_filename; } - - void Stop() { - assert(m_record); - m_record = false; - } - -private: - FileSpec m_filename; - -protected: - llvm::raw_fd_ostream m_os; - bool m_record; -}; - -/// Recorder that records its data as text to a file. -class DataRecorder : public AbstractRecorder { -public: - DataRecorder(const FileSpec &filename, std::error_code &ec) - : AbstractRecorder(filename, ec) {} - - static llvm::Expected> - Create(const FileSpec &filename); - - template void Record(const T &t, bool newline = false) { - if (!m_record) - return; - m_os << t; - if (newline) - m_os << '\n'; - m_os.flush(); - } -}; - -/// Recorder that records its data as YAML to a file. -class YamlRecorder : public AbstractRecorder { -public: - YamlRecorder(const FileSpec &filename, std::error_code &ec) - : AbstractRecorder(filename, ec) {} - - static llvm::Expected> - Create(const FileSpec &filename); - - template void Record(const T &t) { - if (!m_record) - return; - llvm::yaml::Output yout(m_os); - // The YAML traits are defined as non-const because they are used for - // serialization and deserialization. The cast is safe because - // serialization doesn't modify the object. - yout << const_cast(t); - m_os.flush(); - } -}; - -/// The MultiProvider is a provider that hands out recorder which can be used -/// to capture data for different instances of the same object. The recorders -/// can be passed around or stored as an instance member. -/// -/// The Info::file for the MultiProvider contains an index of files for every -/// recorder. Use the MultiLoader to read the index and get the individual -/// files. -template -class MultiProvider : public repro::Provider { -public: - MultiProvider(const FileSpec &directory) : Provider(directory) {} - - T *GetNewRecorder() { - std::size_t i = m_recorders.size() + 1; - std::string filename = (llvm::Twine(V::Info::name) + llvm::Twine("-") + - llvm::Twine(i) + llvm::Twine(".yaml")) - .str(); - auto recorder_or_error = - T::Create(this->GetRoot().CopyByAppendingPathComponent(filename)); - if (!recorder_or_error) { - llvm::consumeError(recorder_or_error.takeError()); - return nullptr; - } - - m_recorders.push_back(std::move(*recorder_or_error)); - return m_recorders.back().get(); - } - - void Keep() override { - std::vector files; - for (auto &recorder : m_recorders) { - recorder->Stop(); - files.push_back(recorder->GetFilename().GetPath()); - } - - FileSpec file = this->GetRoot().CopyByAppendingPathComponent(V::Info::file); - std::error_code ec; - llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text); - if (ec) - return; - llvm::yaml::Output yout(os); - yout << files; - } - - void Discard() override { m_recorders.clear(); } - -private: - std::vector> m_recorders; -}; - -class CommandProvider : public MultiProvider { -public: - struct Info { - static const char *name; - static const char *file; - }; - - CommandProvider(const FileSpec &directory) - : MultiProvider(directory) {} - - static char ID; -}; - /// The generator is responsible for the logic needed to generate a /// reproducer. For doing so it relies on providers, who serialize data that /// is necessary for reproducing a failure. @@ -469,60 +225,6 @@ private: mutable std::mutex m_mutex; }; -/// Loader for data captured with the MultiProvider. It will read the index and -/// return the path to the files in the index. -template class MultiLoader { -public: - MultiLoader(std::vector files) : m_files(std::move(files)) {} - - static std::unique_ptr Create(Loader *loader) { - if (!loader) - return {}; - - FileSpec file = loader->GetFile(); - if (!file) - return {}; - - auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath()); - if (auto err = error_or_file.getError()) - return {}; - - std::vector files; - llvm::yaml::Input yin((*error_or_file)->getBuffer()); - yin >> files; - - if (auto err = yin.error()) - return {}; - - for (auto &file : files) { - FileSpec absolute_path = - loader->GetRoot().CopyByAppendingPathComponent(file); - file = absolute_path.GetPath(); - } - - return std::make_unique>(std::move(files)); - } - - llvm::Optional GetNextFile() { - if (m_index >= m_files.size()) - return {}; - return m_files[m_index++]; - } - -private: - std::vector m_files; - unsigned m_index = 0; -}; - -/// Helper to read directories written by the DirectoryProvider. -template -llvm::Expected GetDirectoryFrom(repro::Loader *loader) { - llvm::Expected dir = loader->LoadBuffer(); - if (!dir) - return dir.takeError(); - return std::string(llvm::StringRef(*dir).rtrim()); -} - } // namespace repro } // namespace lldb_private diff --git a/lldb/include/lldb/Utility/ReproducerProvider.h b/lldb/include/lldb/Utility/ReproducerProvider.h new file mode 100644 index 000000000000..b84b8a67c4ca --- /dev/null +++ b/lldb/include/lldb/Utility/ReproducerProvider.h @@ -0,0 +1,360 @@ +//===-- Reproducer.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_UTILITY_REPRODUCER_PROVIDER_H +#define LLDB_UTILITY_REPRODUCER_PROVIDER_H + +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/ProcessInfo.h" +#include "lldb/Utility/Reproducer.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/FileCollector.h" +#include "llvm/Support/YAMLTraits.h" + +#include +#include +#include + +namespace lldb_private { +namespace repro { + +/// 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. +class AbstractRecorder { +protected: + AbstractRecorder(const FileSpec &filename, std::error_code &ec) + : m_filename(filename.GetFilename().GetStringRef()), + m_os(filename.GetPath(), ec, llvm::sys::fs::OF_Text), m_record(true) {} + +public: + const FileSpec &GetFilename() { return m_filename; } + + void Stop() { + assert(m_record); + m_record = false; + } + +private: + FileSpec m_filename; + +protected: + llvm::raw_fd_ostream m_os; + bool m_record; +}; + +/// Recorder that records its data as text to a file. +class DataRecorder : public AbstractRecorder { +public: + DataRecorder(const FileSpec &filename, std::error_code &ec) + : AbstractRecorder(filename, ec) {} + + static llvm::Expected> + Create(const FileSpec &filename); + + template void Record(const T &t, bool newline = false) { + if (!m_record) + return; + m_os << t; + if (newline) + m_os << '\n'; + m_os.flush(); + } +}; + +/// Recorder that records its data as YAML to a file. +class YamlRecorder : public AbstractRecorder { +public: + YamlRecorder(const FileSpec &filename, std::error_code &ec) + : AbstractRecorder(filename, ec) {} + + static llvm::Expected> + Create(const FileSpec &filename); + + template void Record(const T &t) { + if (!m_record) + return; + llvm::yaml::Output yout(m_os); + // The YAML traits are defined as non-const because they are used for + // serialization and deserialization. The cast is safe because + // serialization doesn't modify the object. + yout << const_cast(t); + m_os.flush(); + } +}; + +class FileProvider : public Provider { +public: + struct Info { + static const char *name; + static const char *file; + }; + + FileProvider(const FileSpec &directory) + : Provider(directory), + m_collector(std::make_shared( + directory.CopyByAppendingPathComponent("root").GetPath(), + directory.GetPath())) {} + + std::shared_ptr GetFileCollector() { + return m_collector; + } + + void RecordInterestingDirectory(const llvm::Twine &dir); + void RecordInterestingDirectoryRecursive(const llvm::Twine &dir); + + void Keep() override { + auto mapping = GetRoot().CopyByAppendingPathComponent(Info::file); + // Temporary files that are removed during execution can cause copy errors. + if (auto ec = m_collector->copyFiles(/*stop_on_error=*/false)) + return; + m_collector->writeMapping(mapping.GetPath()); + } + + static char ID; + +private: + std::shared_ptr m_collector; +}; + +/// Provider for the LLDB version number. +/// +/// When the reproducer is kept, it writes the lldb version to a file named +/// version.txt in the reproducer root. +class VersionProvider : public Provider { +public: + VersionProvider(const FileSpec &directory) : Provider(directory) {} + struct Info { + static const char *name; + static const char *file; + }; + void SetVersion(std::string version) { + assert(m_version.empty()); + m_version = std::move(version); + } + void Keep() override; + std::string m_version; + static char ID; +}; + +/// Abstract provider to storing directory paths. +template class DirectoryProvider : public repro::Provider { +public: + DirectoryProvider(const FileSpec &root) : Provider(root) {} + void SetDirectory(std::string directory) { + m_directory = std::move(directory); + } + llvm::StringRef GetDirectory() { return m_directory; } + + void Keep() override { + FileSpec file = this->GetRoot().CopyByAppendingPathComponent(T::Info::file); + std::error_code ec; + llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text); + if (ec) + return; + os << m_directory << "\n"; + } + +protected: + std::string m_directory; +}; + +/// Provider for the current working directory. +/// +/// When the reproducer is kept, it writes lldb's current working directory to +/// a file named cwd.txt in the reproducer root. +class WorkingDirectoryProvider + : public DirectoryProvider { +public: + WorkingDirectoryProvider(const FileSpec &directory) + : DirectoryProvider(directory) { + llvm::SmallString<128> cwd; + if (std::error_code EC = llvm::sys::fs::current_path(cwd)) + return; + SetDirectory(std::string(cwd)); + } + struct Info { + static const char *name; + static const char *file; + }; + 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 { +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 MultiProvider is a provider that hands out recorder which can be used +/// to capture data for different instances of the same object. The recorders +/// can be passed around or stored as an instance member. +/// +/// The Info::file for the MultiProvider contains an index of files for every +/// recorder. Use the MultiLoader to read the index and get the individual +/// files. +template +class MultiProvider : public repro::Provider { +public: + MultiProvider(const FileSpec &directory) : Provider(directory) {} + + T *GetNewRecorder() { + std::size_t i = m_recorders.size() + 1; + std::string filename = (llvm::Twine(V::Info::name) + llvm::Twine("-") + + llvm::Twine(i) + llvm::Twine(".yaml")) + .str(); + auto recorder_or_error = + T::Create(this->GetRoot().CopyByAppendingPathComponent(filename)); + if (!recorder_or_error) { + llvm::consumeError(recorder_or_error.takeError()); + return nullptr; + } + + m_recorders.push_back(std::move(*recorder_or_error)); + return m_recorders.back().get(); + } + + void Keep() override { + std::vector files; + for (auto &recorder : m_recorders) { + recorder->Stop(); + files.push_back(recorder->GetFilename().GetPath()); + } + + FileSpec file = this->GetRoot().CopyByAppendingPathComponent(V::Info::file); + std::error_code ec; + llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text); + if (ec) + return; + llvm::yaml::Output yout(os); + yout << files; + } + + void Discard() override { m_recorders.clear(); } + +private: + std::vector> m_recorders; +}; + +class CommandProvider : public MultiProvider { +public: + struct Info { + static const char *name; + static const char *file; + }; + + CommandProvider(const FileSpec &directory) + : MultiProvider(directory) {} + + static char ID; +}; + +class ProcessInfoRecorder : public AbstractRecorder { +public: + ProcessInfoRecorder(const FileSpec &filename, std::error_code &ec) + : AbstractRecorder(filename, ec) {} + + static llvm::Expected> + Create(const FileSpec &filename); + + void Record(const ProcessInstanceInfoList &process_infos); +}; + +class ProcessInfoProvider : public repro::Provider { +public: + struct Info { + static const char *name; + static const char *file; + }; + + ProcessInfoProvider(const FileSpec &directory) : Provider(directory) {} + + ProcessInfoRecorder *GetNewProcessInfoRecorder(); + + void Keep() override; + void Discard() override; + + static char ID; + +private: + std::unique_ptr m_stream_up; + std::vector> m_process_info_recorders; +}; + +/// Loader for data captured with the MultiProvider. It will read the index and +/// return the path to the files in the index. +template class MultiLoader { +public: + MultiLoader(std::vector files) : m_files(std::move(files)) {} + + static std::unique_ptr Create(Loader *loader) { + if (!loader) + return {}; + + FileSpec file = loader->GetFile(); + if (!file) + return {}; + + auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath()); + if (auto err = error_or_file.getError()) + return {}; + + std::vector files; + llvm::yaml::Input yin((*error_or_file)->getBuffer()); + yin >> files; + + if (auto err = yin.error()) + return {}; + + for (auto &file : files) { + FileSpec absolute_path = + loader->GetRoot().CopyByAppendingPathComponent(file); + file = absolute_path.GetPath(); + } + + return std::make_unique>(std::move(files)); + } + + llvm::Optional GetNextFile() { + if (m_index >= m_files.size()) + return {}; + return m_files[m_index++]; + } + +private: + std::vector m_files; + unsigned m_index = 0; +}; + +/// Helper to read directories written by the DirectoryProvider. +template +llvm::Expected GetDirectoryFrom(repro::Loader *loader) { + llvm::Expected dir = loader->LoadBuffer(); + if (!dir) + return dir.takeError(); + return std::string(llvm::StringRef(*dir).rtrim()); +} + +} // namespace repro +} // namespace lldb_private + +#endif // LLDB_UTILITY_REPRODUCER_PROVIDER_H diff --git a/lldb/source/API/SBReproducerPrivate.h b/lldb/source/API/SBReproducerPrivate.h index a4c6eb94627b..02ac31c2ad89 100644 --- a/lldb/source/API/SBReproducerPrivate.h +++ b/lldb/source/API/SBReproducerPrivate.h @@ -16,6 +16,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/Reproducer.h" #include "lldb/Utility/ReproducerInstrumentation.h" +#include "lldb/Utility/ReproducerProvider.h" #include "llvm/ADT/DenseMap.h" diff --git a/lldb/source/Core/IOHandler.cpp b/lldb/source/Core/IOHandler.cpp index ca35d9fb315d..0648cf41f28a 100644 --- a/lldb/source/Core/IOHandler.cpp +++ b/lldb/source/Core/IOHandler.cpp @@ -18,6 +18,7 @@ #include "lldb/Host/Config.h" #include "lldb/Host/File.h" #include "lldb/Utility/Predicate.h" +#include "lldb/Utility/ReproducerProvider.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StringList.h" diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp index 4128fa19c142..71c2983ab00f 100644 --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -60,6 +60,7 @@ #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Predicate.h" +#include "lldb/Utility/ReproducerProvider.h" #include "lldb/Utility/Status.h" #include "lldb/lldb-private-forward.h" #include "llvm/ADT/SmallString.h" diff --git a/lldb/source/Initialization/SystemInitializerCommon.cpp b/lldb/source/Initialization/SystemInitializerCommon.cpp index 4d72f6e2ad33..d352173e1158 100644 --- a/lldb/source/Initialization/SystemInitializerCommon.cpp +++ b/lldb/source/Initialization/SystemInitializerCommon.cpp @@ -14,7 +14,7 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Host/Socket.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/Reproducer.h" +#include "lldb/Utility/ReproducerProvider.h" #include "lldb/Utility/Timer.h" #include "lldb/lldb-private.h" diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index b3b0277ec667..e25c24ccd401 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -46,6 +46,7 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/StreamFile.h" #include "lldb/Utility/Log.h" +#include "lldb/Utility/Reproducer.h" #include "lldb/Utility/State.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/Timer.h" diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 6ff028cf6980..202eb87cca3d 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -85,7 +85,7 @@ #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/Reproducer.h" +#include "lldb/Utility/ReproducerProvider.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StringList.h" diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp index 95acb883774d..6bd2d4425b7b 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -33,7 +33,7 @@ #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/Reproducer.h" +#include "lldb/Utility/ReproducerProvider.h" #include "lldb/Utility/StreamString.h" #include diff --git a/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp b/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp index 336538241b6a..10c1b7cc1351 100644 --- a/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp +++ b/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp @@ -20,7 +20,7 @@ #include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Target.h" -#include "lldb/Utility/Reproducer.h" +#include "lldb/Utility/ReproducerProvider.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" diff --git a/lldb/source/Utility/CMakeLists.txt b/lldb/source/Utility/CMakeLists.txt index c89d4f9e0072..1e3d859e2a6c 100644 --- a/lldb/source/Utility/CMakeLists.txt +++ b/lldb/source/Utility/CMakeLists.txt @@ -50,6 +50,7 @@ add_lldb_library(lldbUtility RegularExpression.cpp Reproducer.cpp ReproducerInstrumentation.cpp + ReproducerProvider.cpp Scalar.cpp SelectHelper.cpp State.cpp diff --git a/lldb/source/Utility/ProcessInfo.cpp b/lldb/source/Utility/ProcessInfo.cpp index aae48d6a4872..310d2b22b174 100644 --- a/lldb/source/Utility/ProcessInfo.cpp +++ b/lldb/source/Utility/ProcessInfo.cpp @@ -9,6 +9,7 @@ #include "lldb/Utility/ProcessInfo.h" #include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/ReproducerProvider.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/UserIDResolver.h" @@ -347,57 +348,6 @@ void llvm::yaml::MappingTraits::mapping( io.mapRequired("parent-pid", Info.m_parent_pid); } -llvm::Expected> -ProcessInfoRecorder::Create(const FileSpec &filename) { - std::error_code ec; - auto recorder = - std::make_unique(std::move(filename), ec); - if (ec) - return llvm::errorCodeToError(ec); - return std::move(recorder); -} - -void ProcessInfoProvider::Keep() { - std::vector files; - for (auto &recorder : m_process_info_recorders) { - recorder->Stop(); - files.push_back(recorder->GetFilename().GetPath()); - } - - FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file); - std::error_code ec; - llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text); - if (ec) - return; - llvm::yaml::Output yout(os); - yout << files; -} - -void ProcessInfoProvider::Discard() { m_process_info_recorders.clear(); } - -ProcessInfoRecorder *ProcessInfoProvider::GetNewProcessInfoRecorder() { - std::size_t i = m_process_info_recorders.size() + 1; - std::string filename = (llvm::Twine(Info::name) + llvm::Twine("-") + - llvm::Twine(i) + llvm::Twine(".yaml")) - .str(); - auto recorder_or_error = ProcessInfoRecorder::Create( - GetRoot().CopyByAppendingPathComponent(filename)); - if (!recorder_or_error) { - llvm::consumeError(recorder_or_error.takeError()); - return nullptr; - } - - m_process_info_recorders.push_back(std::move(*recorder_or_error)); - return m_process_info_recorders.back().get(); -} - -void ProcessInfoRecorder::Record(const ProcessInstanceInfoList &process_infos) { - if (!m_record) - return; - llvm::yaml::Output yout(m_os); - yout << const_cast(process_infos); - m_os.flush(); -} llvm::Optional repro::GetReplayProcessInstanceInfoList() { @@ -425,7 +375,3 @@ repro::GetReplayProcessInstanceInfoList() { return infos; } - -char ProcessInfoProvider::ID = 0; -const char *ProcessInfoProvider::Info::file = "process-info.yaml"; -const char *ProcessInfoProvider::Info::name = "process-info"; diff --git a/lldb/source/Utility/Reproducer.cpp b/lldb/source/Utility/Reproducer.cpp index 35d145e4d61b..9276c7449d7b 100644 --- a/lldb/source/Utility/Reproducer.cpp +++ b/lldb/source/Utility/Reproducer.cpp @@ -8,6 +8,7 @@ #include "lldb/Utility/Reproducer.h" #include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/ReproducerProvider.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Threading.h" @@ -263,58 +264,3 @@ bool Loader::HasFile(StringRef file) { auto it = std::lower_bound(m_files.begin(), m_files.end(), file.str()); return (it != m_files.end()) && (*it == file); } - -llvm::Expected> -DataRecorder::Create(const FileSpec &filename) { - std::error_code ec; - auto recorder = std::make_unique(std::move(filename), ec); - if (ec) - return llvm::errorCodeToError(ec); - return std::move(recorder); -} - -llvm::Expected> -YamlRecorder::Create(const FileSpec &filename) { - std::error_code ec; - auto recorder = std::make_unique(std::move(filename), ec); - if (ec) - return llvm::errorCodeToError(ec); - return std::move(recorder); -} - -void VersionProvider::Keep() { - FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file); - std::error_code ec; - llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text); - if (ec) - return; - os << m_version << "\n"; -} - -void FileProvider::RecordInterestingDirectory(const llvm::Twine &dir) { - if (m_collector) - m_collector->addFile(dir); -} - -void FileProvider::RecordInterestingDirectoryRecursive(const llvm::Twine &dir) { - if (m_collector) - m_collector->addDirectory(dir); -} - -void ProviderBase::anchor() {} -char CommandProvider::ID = 0; -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"; -const char *FileProvider::Info::name = "files"; -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/source/Utility/ReproducerProvider.cpp b/lldb/source/Utility/ReproducerProvider.cpp new file mode 100644 index 000000000000..54f3a870b7dd --- /dev/null +++ b/lldb/source/Utility/ReproducerProvider.cpp @@ -0,0 +1,127 @@ +//===-- Reproducer.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/Utility/ReproducerProvider.h" +#include "lldb/Utility/ProcessInfo.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/raw_ostream.h" + +using namespace lldb_private; +using namespace lldb_private::repro; +using namespace llvm; +using namespace llvm::yaml; + +llvm::Expected> +DataRecorder::Create(const FileSpec &filename) { + std::error_code ec; + auto recorder = std::make_unique(std::move(filename), ec); + if (ec) + return llvm::errorCodeToError(ec); + return std::move(recorder); +} + +llvm::Expected> +YamlRecorder::Create(const FileSpec &filename) { + std::error_code ec; + auto recorder = std::make_unique(std::move(filename), ec); + if (ec) + return llvm::errorCodeToError(ec); + return std::move(recorder); +} + +void VersionProvider::Keep() { + FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file); + std::error_code ec; + llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text); + if (ec) + return; + os << m_version << "\n"; +} + +void FileProvider::RecordInterestingDirectory(const llvm::Twine &dir) { + if (m_collector) + m_collector->addFile(dir); +} + +void FileProvider::RecordInterestingDirectoryRecursive(const llvm::Twine &dir) { + if (m_collector) + m_collector->addDirectory(dir); +} + +llvm::Expected> +ProcessInfoRecorder::Create(const FileSpec &filename) { + std::error_code ec; + auto recorder = + std::make_unique(std::move(filename), ec); + if (ec) + return llvm::errorCodeToError(ec); + return std::move(recorder); +} + +void ProcessInfoProvider::Keep() { + std::vector files; + for (auto &recorder : m_process_info_recorders) { + recorder->Stop(); + files.push_back(recorder->GetFilename().GetPath()); + } + + FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file); + std::error_code ec; + llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text); + if (ec) + return; + llvm::yaml::Output yout(os); + yout << files; +} + +void ProcessInfoProvider::Discard() { m_process_info_recorders.clear(); } + +ProcessInfoRecorder *ProcessInfoProvider::GetNewProcessInfoRecorder() { + std::size_t i = m_process_info_recorders.size() + 1; + std::string filename = (llvm::Twine(Info::name) + llvm::Twine("-") + + llvm::Twine(i) + llvm::Twine(".yaml")) + .str(); + auto recorder_or_error = ProcessInfoRecorder::Create( + GetRoot().CopyByAppendingPathComponent(filename)); + if (!recorder_or_error) { + llvm::consumeError(recorder_or_error.takeError()); + return nullptr; + } + + m_process_info_recorders.push_back(std::move(*recorder_or_error)); + return m_process_info_recorders.back().get(); +} + +void ProcessInfoRecorder::Record(const ProcessInstanceInfoList &process_infos) { + if (!m_record) + return; + llvm::yaml::Output yout(m_os); + yout << const_cast(process_infos); + m_os.flush(); +} + +void ProviderBase::anchor() {} +char CommandProvider::ID = 0; +char FileProvider::ID = 0; +char ProviderBase::ID = 0; +char VersionProvider::ID = 0; +char WorkingDirectoryProvider::ID = 0; +char HomeDirectoryProvider::ID = 0; +char ProcessInfoProvider::ID = 0; +const char *CommandProvider::Info::file = "command-interpreter.yaml"; +const char *CommandProvider::Info::name = "command-interpreter"; +const char *FileProvider::Info::file = "files.yaml"; +const char *FileProvider::Info::name = "files"; +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"; +const char *ProcessInfoProvider::Info::file = "process-info.yaml"; +const char *ProcessInfoProvider::Info::name = "process-info"; diff --git a/lldb/unittests/Utility/ReproducerTest.cpp b/lldb/unittests/Utility/ReproducerTest.cpp index 5a9dea3450f0..b276de3bf1af 100644 --- a/lldb/unittests/Utility/ReproducerTest.cpp +++ b/lldb/unittests/Utility/ReproducerTest.cpp @@ -9,13 +9,13 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Reproducer.h" +#include "lldb/Utility/ReproducerProvider.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/Support/Error.h" #include "llvm/Testing/Support/Error.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Reproducer.h" - using namespace llvm; using namespace lldb_private; using namespace lldb_private::repro;