summaryrefslogtreecommitdiff
path: root/include/lldb/Utility/Reproducer.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/lldb/Utility/Reproducer.h')
-rw-r--r--include/lldb/Utility/Reproducer.h154
1 files changed, 121 insertions, 33 deletions
diff --git a/include/lldb/Utility/Reproducer.h b/include/lldb/Utility/Reproducer.h
index ea315ad771a6..670041d06bba 100644
--- a/include/lldb/Utility/Reproducer.h
+++ b/include/lldb/Utility/Reproducer.h
@@ -1,15 +1,15 @@
//===-- Reproducer.h --------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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_H
#define LLDB_UTILITY_REPRODUCER_H
+#include "lldb/Utility/FileCollector.h"
#include "lldb/Utility/FileSpec.h"
#include "llvm/ADT/DenseMap.h"
@@ -31,24 +31,14 @@ enum class ReproducerMode {
Off,
};
-/// Abstraction for information associated with a provider. This information
-/// is serialized into an index which is used by the loader.
-struct ProviderInfo {
- std::string name;
- std::vector<std::string> files;
-};
-
/// The provider defines an interface for generating files needed for
-/// reproducing. The provider must populate its ProviderInfo to communicate
-/// its name and files to the index, before registering with the generator,
-/// i.e. in the constructor.
+/// reproducing.
///
/// Different components will implement different providers.
class ProviderBase {
public:
virtual ~ProviderBase() = default;
- const ProviderInfo &GetInfo() const { return m_info; }
const FileSpec &GetRoot() const { return m_root; }
/// The Keep method is called when it is decided that we need to keep the
@@ -65,11 +55,12 @@ public:
// Returns the class ID for the dynamic type of this Provider instance.
virtual const void *DynamicClassID() const = 0;
+ virtual llvm::StringRef GetName() const = 0;
+ virtual llvm::StringRef GetFile() const = 0;
+
protected:
ProviderBase(const FileSpec &root) : m_root(root) {}
- /// Every provider keeps track of its own files.
- ProviderInfo m_info;
private:
/// Every provider knows where to dump its potential files.
FileSpec m_root;
@@ -84,10 +75,112 @@ public:
const void *DynamicClassID() const override { return &ThisProviderT::ID; }
+ llvm::StringRef GetName() const override { return ThisProviderT::Info::name; }
+ llvm::StringRef GetFile() const override { return ThisProviderT::Info::file; }
+
protected:
using ProviderBase::ProviderBase; // Inherit constructor.
};
+class FileProvider : public Provider<FileProvider> {
+public:
+ struct Info {
+ static const char *name;
+ static const char *file;
+ };
+
+ FileProvider(const FileSpec &directory)
+ : Provider(directory),
+ m_collector(directory.CopyByAppendingPathComponent("root"), directory) {
+ }
+
+ FileCollector &GetFileCollector() { return m_collector; }
+
+ 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);
+ }
+
+ static char ID;
+
+private:
+ FileCollector 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<VersionProvider> {
+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;
+};
+
+class DataRecorder {
+public:
+ DataRecorder(const FileSpec &filename, std::error_code &ec)
+ : m_filename(filename.GetFilename().GetStringRef()),
+ m_os(filename.GetPath(), ec, llvm::sys::fs::F_Text), m_record(true) {}
+
+ static llvm::Expected<std::unique_ptr<DataRecorder>>
+ Create(const FileSpec &filename);
+
+ template <typename T> void Record(const T &t, bool newline = false) {
+ if (!m_record)
+ return;
+ m_os << t;
+ if (newline)
+ m_os << '\n';
+ m_os.flush();
+ }
+
+ const FileSpec &GetFilename() { return m_filename; }
+
+ void Stop() {
+ assert(m_record);
+ m_record = false;
+ }
+
+private:
+ FileSpec m_filename;
+ llvm::raw_fd_ostream m_os;
+ bool m_record;
+};
+
+class CommandProvider : public Provider<CommandProvider> {
+public:
+ struct Info {
+ static const char *name;
+ static const char *file;
+ };
+
+ CommandProvider(const FileSpec &directory) : Provider(directory) {}
+
+ DataRecorder *GetNewDataRecorder();
+
+ void Keep() override;
+ void Discard() override;
+
+ static char ID;
+
+private:
+ std::vector<std::unique_ptr<DataRecorder>> m_data_recorders;
+};
+
/// 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.
@@ -152,14 +245,22 @@ class Loader final {
public:
Loader(const FileSpec &root);
- llvm::Optional<ProviderInfo> GetProviderInfo(llvm::StringRef name);
+ template <typename T> FileSpec GetFile() {
+ if (!HasFile(T::file))
+ return {};
+
+ return GetRoot().CopyByAppendingPathComponent(T::file);
+ }
+
llvm::Error LoadIndex();
const FileSpec &GetRoot() const { return m_root; }
private:
- llvm::StringMap<ProviderInfo> m_provider_info;
+ bool HasFile(llvm::StringRef file);
+
FileSpec m_root;
+ std::vector<std::string> m_files;
bool m_loaded;
};
@@ -170,6 +271,7 @@ public:
static Reproducer &Instance();
static llvm::Error Initialize(ReproducerMode mode,
llvm::Optional<FileSpec> root);
+ static bool Initialized();
static void Terminate();
Reproducer() = default;
@@ -198,18 +300,4 @@ private:
} // namespace repro
} // namespace lldb_private
-LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(lldb_private::repro::ProviderInfo)
-
-namespace llvm {
-namespace yaml {
-
-template <> struct MappingTraits<lldb_private::repro::ProviderInfo> {
- static void mapping(IO &io, lldb_private::repro::ProviderInfo &info) {
- io.mapRequired("name", info.name);
- io.mapOptional("files", info.files);
- }
-};
-} // namespace yaml
-} // namespace llvm
-
#endif // LLDB_UTILITY_REPRODUCER_H