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 
9 #include "lldb/Utility/ReproducerProvider.h"
10 #include "lldb/Utility/ProcessInfo.h"
11 #include "llvm/Support/FileSystem.h"
12 #include "llvm/Support/raw_ostream.h"
13 
14 using namespace lldb_private;
15 using namespace lldb_private::repro;
16 using namespace llvm;
17 using namespace llvm::yaml;
18 
19 llvm::Expected<std::unique_ptr<DataRecorder>>
20 DataRecorder::Create(const FileSpec &filename) {
21   std::error_code ec;
22   auto recorder = std::make_unique<DataRecorder>(std::move(filename), ec);
23   if (ec)
24     return llvm::errorCodeToError(ec);
25   return std::move(recorder);
26 }
27 
28 llvm::Expected<std::unique_ptr<YamlRecorder>>
29 YamlRecorder::Create(const FileSpec &filename) {
30   std::error_code ec;
31   auto recorder = std::make_unique<YamlRecorder>(std::move(filename), ec);
32   if (ec)
33     return llvm::errorCodeToError(ec);
34   return std::move(recorder);
35 }
36 
37 void VersionProvider::Keep() {
38   FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file);
39   std::error_code ec;
40   llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text);
41   if (ec)
42     return;
43   os << m_version << "\n";
44 }
45 
46 void FileProvider::RecordInterestingDirectory(const llvm::Twine &dir) {
47   if (m_collector)
48     m_collector->addFile(dir);
49 }
50 
51 void FileProvider::RecordInterestingDirectoryRecursive(const llvm::Twine &dir) {
52   if (m_collector)
53     m_collector->addDirectory(dir);
54 }
55 
56 llvm::Expected<std::unique_ptr<ProcessInfoRecorder>>
57 ProcessInfoRecorder::Create(const FileSpec &filename) {
58   std::error_code ec;
59   auto recorder =
60       std::make_unique<ProcessInfoRecorder>(std::move(filename), ec);
61   if (ec)
62     return llvm::errorCodeToError(ec);
63   return std::move(recorder);
64 }
65 
66 void ProcessInfoProvider::Keep() {
67   std::vector<std::string> files;
68   for (auto &recorder : m_process_info_recorders) {
69     recorder->Stop();
70     files.push_back(recorder->GetFilename().GetPath());
71   }
72 
73   FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file);
74   std::error_code ec;
75   llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text);
76   if (ec)
77     return;
78   llvm::yaml::Output yout(os);
79   yout << files;
80 }
81 
82 void ProcessInfoProvider::Discard() { m_process_info_recorders.clear(); }
83 
84 ProcessInfoRecorder *ProcessInfoProvider::GetNewProcessInfoRecorder() {
85   std::size_t i = m_process_info_recorders.size() + 1;
86   std::string filename = (llvm::Twine(Info::name) + llvm::Twine("-") +
87                           llvm::Twine(i) + llvm::Twine(".yaml"))
88                              .str();
89   auto recorder_or_error = ProcessInfoRecorder::Create(
90       GetRoot().CopyByAppendingPathComponent(filename));
91   if (!recorder_or_error) {
92     llvm::consumeError(recorder_or_error.takeError());
93     return nullptr;
94   }
95 
96   m_process_info_recorders.push_back(std::move(*recorder_or_error));
97   return m_process_info_recorders.back().get();
98 }
99 
100 void ProcessInfoRecorder::Record(const ProcessInstanceInfoList &process_infos) {
101   if (!m_record)
102     return;
103   llvm::yaml::Output yout(m_os);
104   yout << const_cast<ProcessInstanceInfoList &>(process_infos);
105   m_os.flush();
106 }
107 
108 void ProviderBase::anchor() {}
109 char CommandProvider::ID = 0;
110 char FileProvider::ID = 0;
111 char ProviderBase::ID = 0;
112 char VersionProvider::ID = 0;
113 char WorkingDirectoryProvider::ID = 0;
114 char HomeDirectoryProvider::ID = 0;
115 char ProcessInfoProvider::ID = 0;
116 const char *CommandProvider::Info::file = "command-interpreter.yaml";
117 const char *CommandProvider::Info::name = "command-interpreter";
118 const char *FileProvider::Info::file = "files.yaml";
119 const char *FileProvider::Info::name = "files";
120 const char *VersionProvider::Info::file = "version.txt";
121 const char *VersionProvider::Info::name = "version";
122 const char *WorkingDirectoryProvider::Info::file = "cwd.txt";
123 const char *WorkingDirectoryProvider::Info::name = "cwd";
124 const char *HomeDirectoryProvider::Info::file = "home.txt";
125 const char *HomeDirectoryProvider::Info::name = "home";
126 const char *ProcessInfoProvider::Info::file = "process-info.yaml";
127 const char *ProcessInfoProvider::Info::name = "process-info";
128