diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Utility/ReproducerProvider.cpp')
-rw-r--r-- | contrib/llvm-project/lldb/source/Utility/ReproducerProvider.cpp | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/source/Utility/ReproducerProvider.cpp b/contrib/llvm-project/lldb/source/Utility/ReproducerProvider.cpp new file mode 100644 index 000000000000..ed016820db21 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Utility/ReproducerProvider.cpp @@ -0,0 +1,221 @@ +//===-- 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/ADT/ScopeExit.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/WithColor.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<std::unique_ptr<DataRecorder>> +DataRecorder::Create(const FileSpec &filename) { + std::error_code ec; + auto recorder = std::make_unique<DataRecorder>(std::move(filename), ec); + if (ec) + return llvm::errorCodeToError(ec); + return std::move(recorder); +} + +llvm::Expected<std::unique_ptr<YamlRecorder>> +YamlRecorder::Create(const FileSpec &filename) { + std::error_code ec; + auto recorder = std::make_unique<YamlRecorder>(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"; +} + +FlushingFileCollector::FlushingFileCollector(llvm::StringRef files_path, + llvm::StringRef dirs_path, + std::error_code &ec) { + auto clear = llvm::make_scope_exit([this]() { + m_files_os.reset(); + m_dirs_os.reset(); + }); + m_files_os.emplace(files_path, ec, llvm::sys::fs::OF_Append); + if (ec) + return; + m_dirs_os.emplace(dirs_path, ec, llvm::sys::fs::OF_Append); + if (ec) + return; + clear.release(); +} + +void FlushingFileCollector::addFileImpl(StringRef file) { + if (m_files_os) { + *m_files_os << file << '\0'; + m_files_os->flush(); + } +} + +llvm::vfs::directory_iterator +FlushingFileCollector::addDirectoryImpl(const Twine &dir, + IntrusiveRefCntPtr<vfs::FileSystem> vfs, + std::error_code &dir_ec) { + if (m_dirs_os) { + *m_dirs_os << dir << '\0'; + m_dirs_os->flush(); + } + return vfs->dir_begin(dir, dir_ec); +} + +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<std::unique_ptr<ProcessInfoRecorder>> +ProcessInfoRecorder::Create(const FileSpec &filename) { + std::error_code ec; + auto recorder = + std::make_unique<ProcessInfoRecorder>(std::move(filename), ec); + if (ec) + return llvm::errorCodeToError(ec); + return std::move(recorder); +} + +void ProcessInfoProvider::Keep() { + std::vector<std::string> 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<ProcessInstanceInfoList &>(process_infos); + m_os.flush(); +} + +void SymbolFileProvider::AddSymbolFile(const UUID *uuid, + const FileSpec &module_file, + const FileSpec &symbol_file) { + if (!uuid || (!module_file && !symbol_file)) + return; + m_symbol_files.emplace_back(uuid->GetAsString(), module_file.GetPath(), + symbol_file.GetPath()); +} + +void SymbolFileProvider::Keep() { + FileSpec file = this->GetRoot().CopyByAppendingPathComponent(Info::file); + std::error_code ec; + llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text); + if (ec) + return; + + // Remove duplicates. + llvm::sort(m_symbol_files.begin(), m_symbol_files.end()); + m_symbol_files.erase( + std::unique(m_symbol_files.begin(), m_symbol_files.end()), + m_symbol_files.end()); + + llvm::yaml::Output yout(os); + yout << m_symbol_files; +} + +SymbolFileLoader::SymbolFileLoader(Loader *loader) { + if (!loader) + return; + + FileSpec file = loader->GetFile<SymbolFileProvider::Info>(); + if (!file) + return; + + auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath()); + if (auto err = error_or_file.getError()) + return; + + llvm::yaml::Input yin((*error_or_file)->getBuffer()); + yin >> m_symbol_files; +} + +std::pair<FileSpec, FileSpec> +SymbolFileLoader::GetPaths(const UUID *uuid) const { + if (!uuid) + return {}; + + auto it = std::lower_bound(m_symbol_files.begin(), m_symbol_files.end(), + SymbolFileProvider::Entry(uuid->GetAsString())); + if (it == m_symbol_files.end()) + return {}; + return std::make_pair<FileSpec, FileSpec>(FileSpec(it->module_path), + FileSpec(it->symbol_path)); +} + +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; +char SymbolFileProvider::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"; +const char *SymbolFileProvider::Info::file = "symbol-files.yaml"; +const char *SymbolFileProvider::Info::name = "symbol-files"; |