LLDB  mainline
ReproducerProvider.cpp
Go to the documentation of this file.
1 //===-- Reproducer.cpp ----------------------------------------------------===//
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 
11 #include "llvm/ADT/ScopeExit.h"
12 #include "llvm/Support/FileSystem.h"
13 #include "llvm/Support/WithColor.h"
14 #include "llvm/Support/raw_ostream.h"
15 
16 using namespace lldb_private;
17 using namespace lldb_private::repro;
18 using namespace llvm;
19 using namespace llvm::yaml;
20 
21 llvm::Expected<std::unique_ptr<DataRecorder>>
22 DataRecorder::Create(const FileSpec &filename) {
23  std::error_code ec;
24  auto recorder = std::make_unique<DataRecorder>(std::move(filename), ec);
25  if (ec)
26  return llvm::errorCodeToError(ec);
27  return std::move(recorder);
28 }
29 
30 llvm::Expected<std::unique_ptr<YamlRecorder>>
31 YamlRecorder::Create(const FileSpec &filename) {
32  std::error_code ec;
33  auto recorder = std::make_unique<YamlRecorder>(std::move(filename), ec);
34  if (ec)
35  return llvm::errorCodeToError(ec);
36  return std::move(recorder);
37 }
38 
40  FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file);
41  std::error_code ec;
42  llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_TextWithCRLF);
43  if (ec)
44  return;
45  os << m_version << "\n";
46 }
47 
49  llvm::StringRef dirs_path,
50  std::error_code &ec) {
51  auto clear = llvm::make_scope_exit([this]() {
52  m_files_os.reset();
53  m_dirs_os.reset();
54  });
55  m_files_os.emplace(files_path, ec, llvm::sys::fs::OF_Append);
56  if (ec)
57  return;
58  m_dirs_os.emplace(dirs_path, ec, llvm::sys::fs::OF_Append);
59  if (ec)
60  return;
61  clear.release();
62 }
63 
64 void FlushingFileCollector::addFileImpl(StringRef file) {
65  if (m_files_os) {
66  *m_files_os << file << '\0';
67  m_files_os->flush();
68  }
69 }
70 
71 llvm::vfs::directory_iterator
73  IntrusiveRefCntPtr<vfs::FileSystem> vfs,
74  std::error_code &dir_ec) {
75  if (m_dirs_os) {
76  *m_dirs_os << dir << '\0';
77  m_dirs_os->flush();
78  }
79  return vfs->dir_begin(dir, dir_ec);
80 }
81 
82 void FileProvider::RecordInterestingDirectory(const llvm::Twine &dir) {
83  if (m_collector)
84  m_collector->addFile(dir);
85 }
86 
88  if (m_collector)
89  m_collector->addDirectory(dir);
90 }
91 
92 llvm::Expected<std::unique_ptr<ProcessInfoRecorder>>
94  std::error_code ec;
95  auto recorder =
96  std::make_unique<ProcessInfoRecorder>(std::move(filename), ec);
97  if (ec)
98  return llvm::errorCodeToError(ec);
99  return std::move(recorder);
100 }
101 
103  std::vector<std::string> files;
104  for (auto &recorder : m_process_info_recorders) {
105  recorder->Stop();
106  files.push_back(recorder->GetFilename().GetPath());
107  }
108 
109  FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file);
110  std::error_code ec;
111  llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_TextWithCRLF);
112  if (ec)
113  return;
114  llvm::yaml::Output yout(os);
115  yout << files;
116 }
117 
118 void ProcessInfoProvider::Discard() { m_process_info_recorders.clear(); }
119 
121  std::size_t i = m_process_info_recorders.size() + 1;
122  std::string filename = (llvm::Twine(Info::name) + llvm::Twine("-") +
123  llvm::Twine(i) + llvm::Twine(".yaml"))
124  .str();
125  auto recorder_or_error = ProcessInfoRecorder::Create(
126  GetRoot().CopyByAppendingPathComponent(filename));
127  if (!recorder_or_error) {
128  llvm::consumeError(recorder_or_error.takeError());
129  return nullptr;
130  }
131 
132  m_process_info_recorders.push_back(std::move(*recorder_or_error));
133  return m_process_info_recorders.back().get();
134 }
135 
137  if (!m_record)
138  return;
139  llvm::yaml::Output yout(m_os);
140  yout << const_cast<ProcessInstanceInfoList &>(process_infos);
141  m_os.flush();
142 }
143 
145  const FileSpec &module_file,
146  const FileSpec &symbol_file) {
147  if (!uuid || (!module_file && !symbol_file))
148  return;
149  m_symbol_files.emplace_back(uuid->GetAsString(), module_file.GetPath(),
150  symbol_file.GetPath());
151 }
152 
154  FileSpec file = this->GetRoot().CopyByAppendingPathComponent(Info::file);
155  std::error_code ec;
156  llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_TextWithCRLF);
157  if (ec)
158  return;
159 
160  // Remove duplicates.
161  llvm::sort(m_symbol_files.begin(), m_symbol_files.end());
162  m_symbol_files.erase(
163  std::unique(m_symbol_files.begin(), m_symbol_files.end()),
164  m_symbol_files.end());
165 
166  llvm::yaml::Output yout(os);
167  yout << m_symbol_files;
168 }
169 
171  if (!loader)
172  return;
173 
174  FileSpec file = loader->GetFile<SymbolFileProvider::Info>();
175  if (!file)
176  return;
177 
178  auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath());
179  if (auto err = error_or_file.getError())
180  return;
181 
182  llvm::yaml::Input yin((*error_or_file)->getBuffer());
183  yin >> m_symbol_files;
184 }
185 
186 std::pair<FileSpec, FileSpec>
187 SymbolFileLoader::GetPaths(const UUID *uuid) const {
188  if (!uuid)
189  return {};
190 
191  auto it = std::lower_bound(m_symbol_files.begin(), m_symbol_files.end(),
193  if (it == m_symbol_files.end())
194  return {};
195  return std::make_pair<FileSpec, FileSpec>(FileSpec(it->module_path),
196  FileSpec(it->symbol_path));
197 }
198 
200 char CommandProvider::ID = 0;
201 char FileProvider::ID = 0;
202 char ProviderBase::ID = 0;
203 char VersionProvider::ID = 0;
206 char ProcessInfoProvider::ID = 0;
207 char SymbolFileProvider::ID = 0;
208 const char *CommandProvider::Info::file = "command-interpreter.yaml";
209 const char *CommandProvider::Info::name = "command-interpreter";
210 const char *FileProvider::Info::file = "files.yaml";
211 const char *FileProvider::Info::name = "files";
212 const char *VersionProvider::Info::file = "version.txt";
213 const char *VersionProvider::Info::name = "version";
214 const char *WorkingDirectoryProvider::Info::file = "cwd.txt";
215 const char *WorkingDirectoryProvider::Info::name = "cwd";
216 const char *HomeDirectoryProvider::Info::file = "home.txt";
217 const char *HomeDirectoryProvider::Info::name = "home";
218 const char *ProcessInfoProvider::Info::file = "process-info.yaml";
219 const char *ProcessInfoProvider::Info::name = "process-info";
220 const char *SymbolFileProvider::Info::file = "symbol-files.yaml";
221 const char *SymbolFileProvider::Info::name = "symbol-files";
lldb_private::repro::FileProvider::Info::file
static const char * file
Definition: ReproducerProvider.h:115
lldb_private::repro::SymbolFileProvider::Entry
Definition: ReproducerProvider.h:232
lldb_private::repro::ProcessInfoProvider::Info::name
static const char * name
Definition: ReproducerProvider.h:334
lldb_private::UUID
Definition: UUID.h:23
lldb_private::repro::WorkingDirectoryProvider::Info::name
static const char * name
Definition: ReproducerProvider.h:197
llvm
Definition: Debugger.h:49
lldb_private::repro::FlushingFileCollector::FlushingFileCollector
FlushingFileCollector(llvm::StringRef files_path, llvm::StringRef dirs_path, std::error_code &ec)
Definition: ReproducerProvider.cpp:48
lldb_private::repro::FileProvider::RecordInterestingDirectory
void RecordInterestingDirectory(const llvm::Twine &dir)
Definition: ReproducerProvider.cpp:82
lldb_private::repro::VersionProvider::ID
static char ID
Definition: ReproducerProvider.h:157
lldb_private::repro::SymbolFileProvider::AddSymbolFile
void AddSymbolFile(const UUID *uuid, const FileSpec &module_path, const FileSpec &symbol_path)
Definition: ReproducerProvider.cpp:144
lldb_private::repro::ProcessInfoRecorder::Create
static llvm::Expected< std::unique_ptr< ProcessInfoRecorder > > Create(const FileSpec &filename)
Definition: ReproducerProvider.cpp:93
lldb_private::repro::SymbolFileProvider::Info
Definition: ReproducerProvider.h:247
lldb_private::repro::ProcessInfoRecorder::Record
void Record(const ProcessInstanceInfoList &process_infos)
Definition: ReproducerProvider.cpp:136
lldb_private::repro::YamlRecorder::Create
static llvm::Expected< std::unique_ptr< YamlRecorder > > Create(const FileSpec &filename)
Definition: ReproducerProvider.cpp:31
lldb_private::repro::FileProvider::Info::name
static const char * name
Definition: ReproducerProvider.h:114
lldb_private::repro::HomeDirectoryProvider::Info::file
static const char * file
Definition: ReproducerProvider.h:217
lldb_private::repro::SymbolFileProvider::Info::file
static const char * file
Definition: ReproducerProvider.h:249
lldb_private::repro::ProviderBase::anchor
virtual void anchor()
Definition: ReproducerProvider.cpp:199
lldb_private::repro::Loader
Definition: Reproducer.h:158
lldb_private::repro::ProcessInfoRecorder
Definition: ReproducerProvider.h:320
lldb_private::UUID::GetAsString
std::string GetAsString(llvm::StringRef separator="-") const
Definition: UUID.cpp:48
lldb_private::repro::ProcessInfoProvider::ID
static char ID
Definition: ReproducerProvider.h:345
ReproducerProvider.h
lldb_private::FileSpec
Definition: FileSpec.h:56
ProcessInfo.h
lldb_private::repro::CommandProvider::Info::file
static const char * file
Definition: ReproducerProvider.h:311
lldb_private::repro::VersionProvider::Keep
void Keep() override
The Keep method is called when it is decided that we need to keep the data in order to provide a repr...
Definition: ReproducerProvider.cpp:39
lldb_private::repro::DataRecorder::Create
static llvm::Expected< std::unique_ptr< DataRecorder > > Create(const FileSpec &filename)
Definition: ReproducerProvider.cpp:22
lldb_private::repro::SymbolFileLoader::SymbolFileLoader
SymbolFileLoader(Loader *loader)
Definition: ReproducerProvider.cpp:170
lldb_private::repro::FlushingFileCollector::addDirectoryImpl
llvm::vfs::directory_iterator addDirectoryImpl(const llvm::Twine &dir, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > vfs, std::error_code &dir_ec) override
Definition: ReproducerProvider.cpp:72
lldb_private::repro::CommandProvider::Info::name
static const char * name
Definition: ReproducerProvider.h:310
lldb_private::repro::HomeDirectoryProvider::ID
static char ID
Definition: ReproducerProvider.h:219
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:38
lldb_private::repro::SymbolFileProvider::Info::name
static const char * name
Definition: ReproducerProvider.h:248
lldb_private::repro::HomeDirectoryProvider::Info::name
static const char * name
Definition: ReproducerProvider.h:216
lldb_private::FileSpec::CopyByAppendingPathComponent
FileSpec CopyByAppendingPathComponent(llvm::StringRef component) const
Definition: FileSpec.cpp:400
lldb_private::repro::VersionProvider::Info::name
static const char * name
Definition: ReproducerProvider.h:148
lldb_private::repro::SymbolFileProvider::ID
static char ID
Definition: ReproducerProvider.h:251
lldb_private::repro::ProcessInfoProvider::GetNewProcessInfoRecorder
ProcessInfoRecorder * GetNewProcessInfoRecorder()
Definition: ReproducerProvider.cpp:120
lldb_private::repro::FileProvider::RecordInterestingDirectoryRecursive
void RecordInterestingDirectoryRecursive(const llvm::Twine &dir)
Definition: ReproducerProvider.cpp:87
lldb_private::repro::CommandProvider::ID
static char ID
Definition: ReproducerProvider.h:317
lldb_private::repro::FileProvider::ID
static char ID
Definition: ReproducerProvider.h:134
lldb_private::repro::WorkingDirectoryProvider::Info::file
static const char * file
Definition: ReproducerProvider.h:198
lldb_private::repro
Definition: SBReproducer.h:15
lldb_private::repro::ProcessInfoProvider::Keep
void Keep() override
The Keep method is called when it is decided that we need to keep the data in order to provide a repr...
Definition: ReproducerProvider.cpp:102
llvm::yaml
Definition: ArchSpec.h:556
lldb_private::repro::VersionProvider::Info::file
static const char * file
Definition: ReproducerProvider.h:149
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::repro::FlushingFileCollector::addFileImpl
void addFileImpl(llvm::StringRef file) override
Definition: ReproducerProvider.cpp:64
lldb_private::repro::Loader::GetFile
FileSpec GetFile()
Definition: Reproducer.h:162
lldb_private::repro::SymbolFileProvider::Keep
void Keep() override
The Keep method is called when it is decided that we need to keep the data in order to provide a repr...
Definition: ReproducerProvider.cpp:153
lldb_private::repro::ProviderBase::ID
static char ID
Definition: Reproducer.h:72
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::ProcessInstanceInfoList
std::vector< ProcessInstanceInfo > ProcessInstanceInfoList
Definition: Host.h:30
lldb_private::repro::ProcessInfoProvider::Discard
void Discard() override
The Discard method is called when it is decided that we do not need to keep any information and will ...
Definition: ReproducerProvider.cpp:118
lldb_private::repro::ProcessInfoProvider::Info::file
static const char * file
Definition: ReproducerProvider.h:335
lldb_private::repro::SymbolFileLoader::GetPaths
std::pair< FileSpec, FileSpec > GetPaths(const UUID *uuid) const
Definition: ReproducerProvider.cpp:187
lldb_private::repro::WorkingDirectoryProvider::ID
static char ID
Definition: ReproducerProvider.h:200