LLDB  mainline
Reproducer.h
Go to the documentation of this file.
1 //===-- Reproducer.h --------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_UTILITY_REPRODUCER_H
10 #define LLDB_UTILITY_REPRODUCER_H
11 
12 #include "lldb/Utility/FileSpec.h"
13 #include "llvm/ADT/DenseMap.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/Support/Error.h"
16 #include "llvm/Support/VirtualFileSystem.h"
17 #include "llvm/Support/YAMLTraits.h"
18 
19 #include <mutex>
20 #include <string>
21 #include <utility>
22 #include <vector>
23 
24 namespace lldb_private {
25 class UUID;
26 namespace repro {
27 
28 class Reproducer;
29 
30 enum class ReproducerMode {
31  Capture,
32  Replay,
34  Off,
35 };
36 
37 /// The provider defines an interface for generating files needed for
38 /// reproducing.
39 ///
40 /// Different components will implement different providers.
41 class ProviderBase {
42 public:
43  virtual ~ProviderBase() = default;
44 
45  const FileSpec &GetRoot() const { return m_root; }
46 
47  /// The Keep method is called when it is decided that we need to keep the
48  /// data in order to provide a reproducer.
49  virtual void Keep(){};
50 
51  /// The Discard method is called when it is decided that we do not need to
52  /// keep any information and will not generate a reproducer.
53  virtual void Discard(){};
54 
55  // Returns the class ID for this type.
56  static const void *ClassID() { return &ID; }
57 
58  // Returns the class ID for the dynamic type of this Provider instance.
59  virtual const void *DynamicClassID() const = 0;
60 
61  virtual llvm::StringRef GetName() const = 0;
62  virtual llvm::StringRef GetFile() const = 0;
63 
64 protected:
65  ProviderBase(const FileSpec &root) : m_root(root) {}
66 
67 private:
68  /// Every provider knows where to dump its potential files.
70 
71  virtual void anchor();
72  static char ID;
73 };
74 
75 template <typename ThisProviderT> class Provider : public ProviderBase {
76 public:
77  static const void *ClassID() { return &ThisProviderT::ID; }
78 
79  const void *DynamicClassID() const override { return &ThisProviderT::ID; }
80 
81  llvm::StringRef GetName() const override { return ThisProviderT::Info::name; }
82  llvm::StringRef GetFile() const override { return ThisProviderT::Info::file; }
83 
84 protected:
85  using ProviderBase::ProviderBase; // Inherit constructor.
86 };
87 
88 /// The generator is responsible for the logic needed to generate a
89 /// reproducer. For doing so it relies on providers, who serialize data that
90 /// is necessary for reproducing a failure.
91 class Generator final {
92 
93 public:
94  Generator(FileSpec root);
95  ~Generator();
96 
97  /// Method to indicate we want to keep the reproducer. If reproducer
98  /// generation is disabled, this does nothing.
99  void Keep();
100 
101  /// Method to indicate we do not want to keep the reproducer. This is
102  /// unaffected by whether or not generation reproduction is enabled, as we
103  /// might need to clean up files already written to disk.
104  void Discard();
105 
106  /// Enable or disable auto generate.
107  void SetAutoGenerate(bool b);
108 
109  /// Return whether auto generate is enabled.
110  bool IsAutoGenerate() const;
111 
112  /// Create and register a new provider.
113  template <typename T> T *Create() {
114  std::unique_ptr<ProviderBase> provider = std::make_unique<T>(m_root);
115  return static_cast<T *>(Register(std::move(provider)));
116  }
117 
118  /// Get an existing provider.
119  template <typename T> T *Get() {
120  auto it = m_providers.find(T::ClassID());
121  if (it == m_providers.end())
122  return nullptr;
123  return static_cast<T *>(it->second.get());
124  }
125 
126  /// Get a provider if it exists, otherwise create it.
127  template <typename T> T &GetOrCreate() {
128  auto *provider = Get<T>();
129  if (provider)
130  return *provider;
131  return *Create<T>();
132  }
133 
134  const FileSpec &GetRoot() const;
135 
136 private:
137  friend Reproducer;
138 
139  ProviderBase *Register(std::unique_ptr<ProviderBase> provider);
140 
141  /// Builds and index with provider info.
142  void AddProvidersToIndex();
143 
144  /// Map of provider IDs to provider instances.
145  llvm::DenseMap<const void *, std::unique_ptr<ProviderBase>> m_providers;
146  std::mutex m_providers_mutex;
147 
148  /// The reproducer root directory.
150 
151  /// Flag to ensure that we never call both keep and discard.
152  bool m_done = false;
153 
154  /// Flag to auto generate a reproducer when it would otherwise be discarded.
155  bool m_auto_generate = false;
156 };
157 
158 class Loader final {
159 public:
160  Loader(FileSpec root, bool passive = false);
161 
162  template <typename T> FileSpec GetFile() {
163  if (!HasFile(T::file))
164  return {};
165 
166  return GetRoot().CopyByAppendingPathComponent(T::file);
167  }
168 
169  template <typename T> llvm::Expected<std::string> LoadBuffer() {
170  FileSpec file = GetFile<typename T::Info>();
171  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer =
172  llvm::vfs::getRealFileSystem()->getBufferForFile(file.GetPath());
173  if (!buffer)
174  return llvm::errorCodeToError(buffer.getError());
175  return (*buffer)->getBuffer().str();
176  }
177 
179 
180  const FileSpec &GetRoot() const { return m_root; }
181 
182  bool IsPassiveReplay() const { return m_passive_replay; }
183 
184 private:
185  bool HasFile(llvm::StringRef file);
186 
188  std::vector<std::string> m_files;
189  bool m_loaded;
191 };
192 
193 /// The reproducer enables clients to obtain access to the Generator and
194 /// Loader.
195 class Reproducer {
196 public:
197  static Reproducer &Instance();
199  llvm::Optional<FileSpec> root);
200  static void Initialize();
201  static bool Initialized();
202  static void Terminate();
203 
204  Reproducer() = default;
205 
207  Loader *GetLoader();
208 
209  const Generator *GetGenerator() const;
210  const Loader *GetLoader() const;
211 
212  FileSpec GetReproducerPath() const;
213 
214  bool IsCapturing() { return static_cast<bool>(m_generator); };
215  bool IsReplaying() { return static_cast<bool>(m_loader); };
216 
217 protected:
218  llvm::Error SetCapture(llvm::Optional<FileSpec> root);
219  llvm::Error SetReplay(llvm::Optional<FileSpec> root, bool passive = false);
220 
221 private:
222  static llvm::Optional<Reproducer> &InstanceImpl();
223 
224  llvm::Optional<Generator> m_generator;
225  llvm::Optional<Loader> m_loader;
226 
227  mutable std::mutex m_mutex;
228 };
229 
230 class Verifier {
231 public:
232  Verifier(Loader *loader) : m_loader(loader) {}
233  void Verify(llvm::function_ref<void(llvm::StringRef)> error_callback,
234  llvm::function_ref<void(llvm::StringRef)> warning_callback,
235  llvm::function_ref<void(llvm::StringRef)> note_callback) const;
236 
237 private:
239 };
240 
242  bool verify = true;
243  bool check_version = true;
244 };
245 
246 llvm::Error Finalize(Loader *loader);
247 llvm::Error Finalize(const FileSpec &root);
248 
249 } // namespace repro
250 } // namespace lldb_private
251 
252 #endif // LLDB_UTILITY_REPRODUCER_H
lldb_private::repro::Loader::LoadIndex
llvm::Error LoadIndex()
Definition: Reproducer.cpp:228
lldb_private::repro::ProviderBase::m_root
FileSpec m_root
Every provider knows where to dump its potential files.
Definition: Reproducer.h:69
lldb_private::repro::Generator::Discard
void Discard()
Method to indicate we do not want to keep the reproducer.
Definition: Reproducer.cpp:189
lldb_private::repro::Loader::m_passive_replay
bool m_passive_replay
Definition: Reproducer.h:190
lldb_private::repro::Generator::Get
T * Get()
Get an existing provider.
Definition: Reproducer.h:119
lldb_private::repro::Loader::m_files
std::vector< std::string > m_files
Definition: Reproducer.h:188
lldb_private::repro::Reproducer::InstanceImpl
static llvm::Optional< Reproducer > & InstanceImpl()
Definition: Reproducer.cpp:69
lldb_private::repro::Reproducer::m_generator
llvm::Optional< Generator > m_generator
Definition: Reproducer.h:224
lldb_private::repro::Reproducer::Initialize
static void Initialize()
Definition: Reproducer.cpp:58
lldb_private::repro::Generator::m_providers
llvm::DenseMap< const void *, std::unique_ptr< ProviderBase > > m_providers
Map of provider IDs to provider instances.
Definition: Reproducer.h:145
lldb_private::repro::Verifier::m_loader
Loader * m_loader
Definition: Reproducer.h:238
lldb_private::repro::Loader::Loader
Loader(FileSpec root, bool passive=false)
Definition: Reproducer.cpp:224
lldb_private::repro::Loader::m_loaded
bool m_loaded
Definition: Reproducer.h:189
lldb_private::repro::Reproducer::IsReplaying
bool IsReplaying()
Definition: Reproducer.h:215
lldb_private::repro::ProviderBase::GetName
virtual llvm::StringRef GetName() const =0
lldb_private::repro::ReplayOptions::check_version
bool check_version
Definition: Reproducer.h:243
lldb_private::repro::ReproducerMode::Off
@ Off
lldb_private::repro::Verifier::Verifier
Verifier(Loader *loader)
Definition: Reproducer.h:232
lldb_private::repro::Reproducer::SetReplay
llvm::Error SetReplay(llvm::Optional< FileSpec > root, bool passive=false)
Definition: Reproducer.cpp:119
lldb_private::repro::Provider
Definition: Reproducer.h:75
lldb_private::repro::Generator::SetAutoGenerate
void SetAutoGenerate(bool b)
Enable or disable auto generate.
Definition: Reproducer.cpp:200
lldb_private::repro::Reproducer::GetLoader
Loader * GetLoader()
Definition: Reproducer.cpp:81
lldb_private::repro::ProviderBase::anchor
virtual void anchor()
Definition: ReproducerProvider.cpp:199
lldb_private::repro::Loader
Definition: Reproducer.h:158
lldb_private::repro::Generator::m_done
bool m_done
Flag to ensure that we never call both keep and discard.
Definition: Reproducer.h:152
lldb_private::repro::ProviderBase::GetFile
virtual llvm::StringRef GetFile() const =0
lldb_private::repro::Generator::AddProvidersToIndex
void AddProvidersToIndex()
Builds and index with provider info.
Definition: Reproducer.cpp:206
lldb_private::repro::Generator::Reproducer
friend Reproducer
Definition: Reproducer.h:137
lldb_private::repro::Provider::ClassID
static const void * ClassID()
Definition: Reproducer.h:77
lldb_private::FileSpec
Definition: FileSpec.h:56
lldb_private::repro::Generator::GetOrCreate
T & GetOrCreate()
Get a provider if it exists, otherwise create it.
Definition: Reproducer.h:127
lldb_private::repro::Reproducer::m_loader
llvm::Optional< Loader > m_loader
Definition: Reproducer.h:225
ID
static char ID
Definition: IRDynamicChecks.cpp:32
lldb_private::repro::Verifier::Verify
void Verify(llvm::function_ref< void(llvm::StringRef)> error_callback, llvm::function_ref< void(llvm::StringRef)> warning_callback, llvm::function_ref< void(llvm::StringRef)> note_callback) const
Definition: Reproducer.cpp:258
lldb_private::repro::Generator::m_auto_generate
bool m_auto_generate
Flag to auto generate a reproducer when it would otherwise be discarded.
Definition: Reproducer.h:155
lldb_private::repro::ReplayOptions::verify
bool verify
Definition: Reproducer.h:242
lldb_private::repro::Loader::LoadBuffer
llvm::Expected< std::string > LoadBuffer()
Definition: Reproducer.h:169
lldb_private::repro::Reproducer::GetReproducerPath
FileSpec GetReproducerPath() const
Definition: Reproducer.cpp:139
lldb_private::repro::ProviderBase::Discard
virtual void Discard()
The Discard method is called when it is decided that we do not need to keep any information and will ...
Definition: Reproducer.h:53
lldb_private::repro::Finalize
llvm::Error Finalize(Loader *loader)
Definition: Reproducer.cpp:365
lldb_private::repro::Reproducer::IsCapturing
bool IsCapturing()
Definition: Reproducer.h:214
lldb_private::repro::Generator::Generator
Generator(FileSpec root)
Definition: Reproducer.cpp:154
lldb_private::repro::ReproducerMode
ReproducerMode
Definition: Reproducer.h:30
lldb_private::repro::Generator::m_root
FileSpec m_root
The reproducer root directory.
Definition: Reproducer.h:149
lldb_private::repro::Generator::m_providers_mutex
std::mutex m_providers_mutex
Definition: Reproducer.h:146
lldb_private::FileSpec::CopyByAppendingPathComponent
FileSpec CopyByAppendingPathComponent(llvm::StringRef component) const
Definition: FileSpec.cpp:400
lldb_private::repro::ProviderBase::Keep
virtual void Keep()
The Keep method is called when it is decided that we need to keep the data in order to provide a repr...
Definition: Reproducer.h:49
lldb_private::repro::Loader::m_root
FileSpec m_root
Definition: Reproducer.h:187
lldb_private::repro::ProviderBase::ProviderBase
ProviderBase(const FileSpec &root)
Definition: Reproducer.h:65
lldb_private::repro::Reproducer::Terminate
static void Terminate()
Definition: Reproducer.cpp:64
lldb_private::repro::ReproducerMode::PassiveReplay
@ PassiveReplay
lldb_private::repro::Reproducer::SetCapture
llvm::Error SetCapture(llvm::Optional< FileSpec > root)
Definition: Reproducer.cpp:102
lldb_private::repro::Generator::GetRoot
const FileSpec & GetRoot() const
Definition: Reproducer.cpp:204
lldb_private::repro::Reproducer::Initialized
static bool Initialized()
Definition: Reproducer.cpp:62
lldb_private::repro::ProviderBase::DynamicClassID
virtual const void * DynamicClassID() const =0
lldb_private::repro::ProviderBase::ClassID
static const void * ClassID()
Definition: Reproducer.h:56
lldb_private::repro::Reproducer::GetGenerator
Generator * GetGenerator()
Definition: Reproducer.cpp:74
lldb_private::repro::Generator::IsAutoGenerate
bool IsAutoGenerate() const
Return whether auto generate is enabled.
Definition: Reproducer.cpp:202
lldb_private::repro::ReproducerMode::Replay
@ Replay
lldb_private::repro::Loader::HasFile
bool HasFile(llvm::StringRef file)
Definition: Reproducer.cpp:252
lldb_private::repro::Provider::GetFile
llvm::StringRef GetFile() const override
Definition: Reproducer.h:82
lldb_private::repro::Generator::Create
T * Create()
Create and register a new provider.
Definition: Reproducer.h:113
lldb_private::repro::Generator::Keep
void Keep()
Method to indicate we want to keep the reproducer.
Definition: Reproducer.cpp:178
lldb_private::repro::ReproducerMode::Capture
@ Capture
lldb_private::repro::Verifier
Definition: Reproducer.h:230
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:29
lldb_private::repro::ProviderBase
The provider defines an interface for generating files needed for reproducing.
Definition: Reproducer.h:41
FileSpec.h
lldb_private::repro::Loader::IsPassiveReplay
bool IsPassiveReplay() const
Definition: Reproducer.h:182
lldb_private::repro::Reproducer::Reproducer
Reproducer()=default
lldb_private::repro::Loader::GetFile
FileSpec GetFile()
Definition: Reproducer.h:162
lldb_private::repro::ProviderBase::ID
static char ID
Definition: Reproducer.h:72
lldb_private::repro::Reproducer
The reproducer enables clients to obtain access to the Generator and Loader.
Definition: Reproducer.h:195
lldb_private::repro::ProviderBase::GetRoot
const FileSpec & GetRoot() const
Definition: Reproducer.h:45
lldb_private::repro::ReplayOptions
Definition: Reproducer.h:241
lldb_private::FileSpec::GetPath
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:348
lldb_private::repro::Loader::GetRoot
const FileSpec & GetRoot() const
Definition: Reproducer.h:180
lldb_private::repro::Reproducer::Instance
static Reproducer & Instance()
Definition: Reproducer.cpp:23
lldb_private::repro::Generator
The generator is responsible for the logic needed to generate a reproducer.
Definition: Reproducer.h:91
lldb_private::repro::ProviderBase::~ProviderBase
virtual ~ProviderBase()=default
lldb_private::repro::Generator::Register
ProviderBase * Register(std::unique_ptr< ProviderBase > provider)
Definition: Reproducer.cpp:170
lldb_private::repro::Generator::~Generator
~Generator()
Definition: Reproducer.cpp:159
lldb_private::repro::Provider::GetName
llvm::StringRef GetName() const override
Definition: Reproducer.h:81
lldb_private::repro::Reproducer::m_mutex
std::mutex m_mutex
Definition: Reproducer.h:227
lldb_private::repro::Provider::DynamicClassID
const void * DynamicClassID() const override
Definition: Reproducer.h:79