1bb894b97SJonas Devlieghere //===-- Reproducer.cpp ----------------------------------------------------===//
2bb894b97SJonas Devlieghere //
3bb894b97SJonas Devlieghere // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bb894b97SJonas Devlieghere // See https://llvm.org/LICENSE.txt for license information.
5bb894b97SJonas Devlieghere // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bb894b97SJonas Devlieghere //
7bb894b97SJonas Devlieghere //===----------------------------------------------------------------------===//
8bb894b97SJonas Devlieghere
9bb894b97SJonas Devlieghere #include "lldb/Utility/ReproducerProvider.h"
10bb894b97SJonas Devlieghere #include "lldb/Utility/ProcessInfo.h"
1173811d32SJonas Devlieghere #include "llvm/ADT/ScopeExit.h"
12bb894b97SJonas Devlieghere #include "llvm/Support/FileSystem.h"
1337469061SJonas Devlieghere #include "llvm/Support/WithColor.h"
14bb894b97SJonas Devlieghere #include "llvm/Support/raw_ostream.h"
15bb894b97SJonas Devlieghere
16bb894b97SJonas Devlieghere using namespace lldb_private;
17bb894b97SJonas Devlieghere using namespace lldb_private::repro;
18bb894b97SJonas Devlieghere using namespace llvm;
19bb894b97SJonas Devlieghere using namespace llvm::yaml;
20bb894b97SJonas Devlieghere
21bb894b97SJonas Devlieghere llvm::Expected<std::unique_ptr<DataRecorder>>
Create(const FileSpec & filename)22bb894b97SJonas Devlieghere DataRecorder::Create(const FileSpec &filename) {
23bb894b97SJonas Devlieghere std::error_code ec;
24bb894b97SJonas Devlieghere auto recorder = std::make_unique<DataRecorder>(std::move(filename), ec);
25bb894b97SJonas Devlieghere if (ec)
26bb894b97SJonas Devlieghere return llvm::errorCodeToError(ec);
27bb894b97SJonas Devlieghere return std::move(recorder);
28bb894b97SJonas Devlieghere }
29bb894b97SJonas Devlieghere
30bb894b97SJonas Devlieghere llvm::Expected<std::unique_ptr<YamlRecorder>>
Create(const FileSpec & filename)31bb894b97SJonas Devlieghere YamlRecorder::Create(const FileSpec &filename) {
32bb894b97SJonas Devlieghere std::error_code ec;
33bb894b97SJonas Devlieghere auto recorder = std::make_unique<YamlRecorder>(std::move(filename), ec);
34bb894b97SJonas Devlieghere if (ec)
35bb894b97SJonas Devlieghere return llvm::errorCodeToError(ec);
36bb894b97SJonas Devlieghere return std::move(recorder);
37bb894b97SJonas Devlieghere }
38bb894b97SJonas Devlieghere
Keep()39bb894b97SJonas Devlieghere void VersionProvider::Keep() {
40bb894b97SJonas Devlieghere FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file);
41bb894b97SJonas Devlieghere std::error_code ec;
4282b3e28eSAbhina Sreeskantharajan llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_TextWithCRLF);
43bb894b97SJonas Devlieghere if (ec)
44bb894b97SJonas Devlieghere return;
45bb894b97SJonas Devlieghere os << m_version << "\n";
46bb894b97SJonas Devlieghere }
47bb894b97SJonas Devlieghere
RecordInterestingDirectory(const llvm::Twine & dir)48bb894b97SJonas Devlieghere void FileProvider::RecordInterestingDirectory(const llvm::Twine &dir) {
49bb894b97SJonas Devlieghere if (m_collector)
50bb894b97SJonas Devlieghere m_collector->addFile(dir);
51bb894b97SJonas Devlieghere }
52bb894b97SJonas Devlieghere
RecordInterestingDirectoryRecursive(const llvm::Twine & dir)53bb894b97SJonas Devlieghere void FileProvider::RecordInterestingDirectoryRecursive(const llvm::Twine &dir) {
54bb894b97SJonas Devlieghere if (m_collector)
55bb894b97SJonas Devlieghere m_collector->addDirectory(dir);
56bb894b97SJonas Devlieghere }
57bb894b97SJonas Devlieghere
Keep()588b3b66eaSJonas Devlieghere void FileProvider::Keep() {
598b3b66eaSJonas Devlieghere if (m_collector) {
608b3b66eaSJonas Devlieghere FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file);
618b3b66eaSJonas Devlieghere m_collector->writeMapping(file.GetPath());
628b3b66eaSJonas Devlieghere }
638b3b66eaSJonas Devlieghere }
648b3b66eaSJonas Devlieghere
65bb894b97SJonas Devlieghere llvm::Expected<std::unique_ptr<ProcessInfoRecorder>>
Create(const FileSpec & filename)66bb894b97SJonas Devlieghere ProcessInfoRecorder::Create(const FileSpec &filename) {
67bb894b97SJonas Devlieghere std::error_code ec;
68bb894b97SJonas Devlieghere auto recorder =
69bb894b97SJonas Devlieghere std::make_unique<ProcessInfoRecorder>(std::move(filename), ec);
70bb894b97SJonas Devlieghere if (ec)
71bb894b97SJonas Devlieghere return llvm::errorCodeToError(ec);
72bb894b97SJonas Devlieghere return std::move(recorder);
73bb894b97SJonas Devlieghere }
74bb894b97SJonas Devlieghere
Keep()75bb894b97SJonas Devlieghere void ProcessInfoProvider::Keep() {
76bb894b97SJonas Devlieghere std::vector<std::string> files;
77bb894b97SJonas Devlieghere for (auto &recorder : m_process_info_recorders) {
78bb894b97SJonas Devlieghere recorder->Stop();
79bb894b97SJonas Devlieghere files.push_back(recorder->GetFilename().GetPath());
80bb894b97SJonas Devlieghere }
81bb894b97SJonas Devlieghere
82bb894b97SJonas Devlieghere FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file);
83bb894b97SJonas Devlieghere std::error_code ec;
8482b3e28eSAbhina Sreeskantharajan llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_TextWithCRLF);
85bb894b97SJonas Devlieghere if (ec)
86bb894b97SJonas Devlieghere return;
87bb894b97SJonas Devlieghere llvm::yaml::Output yout(os);
88bb894b97SJonas Devlieghere yout << files;
89bb894b97SJonas Devlieghere }
90bb894b97SJonas Devlieghere
Discard()91bb894b97SJonas Devlieghere void ProcessInfoProvider::Discard() { m_process_info_recorders.clear(); }
92bb894b97SJonas Devlieghere
GetNewProcessInfoRecorder()93bb894b97SJonas Devlieghere ProcessInfoRecorder *ProcessInfoProvider::GetNewProcessInfoRecorder() {
94bb894b97SJonas Devlieghere std::size_t i = m_process_info_recorders.size() + 1;
95bb894b97SJonas Devlieghere std::string filename = (llvm::Twine(Info::name) + llvm::Twine("-") +
96bb894b97SJonas Devlieghere llvm::Twine(i) + llvm::Twine(".yaml"))
97bb894b97SJonas Devlieghere .str();
98bb894b97SJonas Devlieghere auto recorder_or_error = ProcessInfoRecorder::Create(
99bb894b97SJonas Devlieghere GetRoot().CopyByAppendingPathComponent(filename));
100bb894b97SJonas Devlieghere if (!recorder_or_error) {
101bb894b97SJonas Devlieghere llvm::consumeError(recorder_or_error.takeError());
102bb894b97SJonas Devlieghere return nullptr;
103bb894b97SJonas Devlieghere }
104bb894b97SJonas Devlieghere
105bb894b97SJonas Devlieghere m_process_info_recorders.push_back(std::move(*recorder_or_error));
106bb894b97SJonas Devlieghere return m_process_info_recorders.back().get();
107bb894b97SJonas Devlieghere }
108bb894b97SJonas Devlieghere
Record(const ProcessInstanceInfoList & process_infos)109bb894b97SJonas Devlieghere void ProcessInfoRecorder::Record(const ProcessInstanceInfoList &process_infos) {
110bb894b97SJonas Devlieghere if (!m_record)
111bb894b97SJonas Devlieghere return;
112bb894b97SJonas Devlieghere llvm::yaml::Output yout(m_os);
113bb894b97SJonas Devlieghere yout << const_cast<ProcessInstanceInfoList &>(process_infos);
114bb894b97SJonas Devlieghere m_os.flush();
115bb894b97SJonas Devlieghere }
116bb894b97SJonas Devlieghere
AddSymbolFile(const UUID * uuid,const FileSpec & module_file,const FileSpec & symbol_file)117a842950bSJonas Devlieghere void SymbolFileProvider::AddSymbolFile(const UUID *uuid,
118a842950bSJonas Devlieghere const FileSpec &module_file,
119a842950bSJonas Devlieghere const FileSpec &symbol_file) {
120a842950bSJonas Devlieghere if (!uuid || (!module_file && !symbol_file))
121a842950bSJonas Devlieghere return;
122a842950bSJonas Devlieghere m_symbol_files.emplace_back(uuid->GetAsString(), module_file.GetPath(),
123a842950bSJonas Devlieghere symbol_file.GetPath());
124a842950bSJonas Devlieghere }
125a842950bSJonas Devlieghere
Keep()126a842950bSJonas Devlieghere void SymbolFileProvider::Keep() {
127a842950bSJonas Devlieghere FileSpec file = this->GetRoot().CopyByAppendingPathComponent(Info::file);
128a842950bSJonas Devlieghere std::error_code ec;
12982b3e28eSAbhina Sreeskantharajan llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_TextWithCRLF);
130a842950bSJonas Devlieghere if (ec)
131a842950bSJonas Devlieghere return;
132a842950bSJonas Devlieghere
133a842950bSJonas Devlieghere // Remove duplicates.
134*cd9a5cfdSDmitri Gribenko llvm::sort(m_symbol_files);
135a842950bSJonas Devlieghere m_symbol_files.erase(
136a842950bSJonas Devlieghere std::unique(m_symbol_files.begin(), m_symbol_files.end()),
137a842950bSJonas Devlieghere m_symbol_files.end());
138a842950bSJonas Devlieghere
139a842950bSJonas Devlieghere llvm::yaml::Output yout(os);
140a842950bSJonas Devlieghere yout << m_symbol_files;
141a842950bSJonas Devlieghere }
142a842950bSJonas Devlieghere
SymbolFileLoader(Loader * loader)143a842950bSJonas Devlieghere SymbolFileLoader::SymbolFileLoader(Loader *loader) {
144a842950bSJonas Devlieghere if (!loader)
145a842950bSJonas Devlieghere return;
146a842950bSJonas Devlieghere
147a842950bSJonas Devlieghere FileSpec file = loader->GetFile<SymbolFileProvider::Info>();
148a842950bSJonas Devlieghere if (!file)
149a842950bSJonas Devlieghere return;
150a842950bSJonas Devlieghere
151a842950bSJonas Devlieghere auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath());
152a842950bSJonas Devlieghere if (auto err = error_or_file.getError())
153a842950bSJonas Devlieghere return;
154a842950bSJonas Devlieghere
155a842950bSJonas Devlieghere llvm::yaml::Input yin((*error_or_file)->getBuffer());
156a842950bSJonas Devlieghere yin >> m_symbol_files;
157a842950bSJonas Devlieghere }
158a842950bSJonas Devlieghere
159a842950bSJonas Devlieghere std::pair<FileSpec, FileSpec>
GetPaths(const UUID * uuid) const160a842950bSJonas Devlieghere SymbolFileLoader::GetPaths(const UUID *uuid) const {
161a842950bSJonas Devlieghere if (!uuid)
162a842950bSJonas Devlieghere return {};
163a842950bSJonas Devlieghere
164a842950bSJonas Devlieghere auto it = std::lower_bound(m_symbol_files.begin(), m_symbol_files.end(),
165a842950bSJonas Devlieghere SymbolFileProvider::Entry(uuid->GetAsString()));
166a842950bSJonas Devlieghere if (it == m_symbol_files.end())
167a842950bSJonas Devlieghere return {};
168a842950bSJonas Devlieghere return std::make_pair<FileSpec, FileSpec>(FileSpec(it->module_path),
169a842950bSJonas Devlieghere FileSpec(it->symbol_path));
170a842950bSJonas Devlieghere }
171a842950bSJonas Devlieghere
anchor()172bb894b97SJonas Devlieghere void ProviderBase::anchor() {}
173bb894b97SJonas Devlieghere char CommandProvider::ID = 0;
174bb894b97SJonas Devlieghere char FileProvider::ID = 0;
175bb894b97SJonas Devlieghere char ProviderBase::ID = 0;
176bb894b97SJonas Devlieghere char VersionProvider::ID = 0;
177bb894b97SJonas Devlieghere char WorkingDirectoryProvider::ID = 0;
178bb894b97SJonas Devlieghere char HomeDirectoryProvider::ID = 0;
179bb894b97SJonas Devlieghere char ProcessInfoProvider::ID = 0;
180a842950bSJonas Devlieghere char SymbolFileProvider::ID = 0;
181bb894b97SJonas Devlieghere const char *CommandProvider::Info::file = "command-interpreter.yaml";
182bb894b97SJonas Devlieghere const char *CommandProvider::Info::name = "command-interpreter";
183bb894b97SJonas Devlieghere const char *FileProvider::Info::file = "files.yaml";
184bb894b97SJonas Devlieghere const char *FileProvider::Info::name = "files";
185bb894b97SJonas Devlieghere const char *VersionProvider::Info::file = "version.txt";
186bb894b97SJonas Devlieghere const char *VersionProvider::Info::name = "version";
187bb894b97SJonas Devlieghere const char *WorkingDirectoryProvider::Info::file = "cwd.txt";
188bb894b97SJonas Devlieghere const char *WorkingDirectoryProvider::Info::name = "cwd";
189bb894b97SJonas Devlieghere const char *HomeDirectoryProvider::Info::file = "home.txt";
190bb894b97SJonas Devlieghere const char *HomeDirectoryProvider::Info::name = "home";
191bb894b97SJonas Devlieghere const char *ProcessInfoProvider::Info::file = "process-info.yaml";
192bb894b97SJonas Devlieghere const char *ProcessInfoProvider::Info::name = "process-info";
193a842950bSJonas Devlieghere const char *SymbolFileProvider::Info::file = "symbol-files.yaml";
194a842950bSJonas Devlieghere const char *SymbolFileProvider::Info::name = "symbol-files";
195