aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Utility/Reproducer.cpp
diff options
context:
space:
mode:
authorJonas Devlieghere <jonas@devlieghere.com>2019-03-02 00:20:26 +0000
committerJonas Devlieghere <jonas@devlieghere.com>2019-03-02 00:20:26 +0000
commitd77c2e09266304864ca95434bb8f4eb1605f057a (patch)
tree88c19efefcc36015f00e954d592c6f313f6f40ff /lldb/source/Utility/Reproducer.cpp
parent70f5fc13691d503df28f885f8742f30d83a83307 (diff)
downloadllvm-d77c2e09266304864ca95434bb8f4eb1605f057a.tar.gz
llvm-d77c2e09266304864ca95434bb8f4eb1605f057a.tar.bz2
llvm-d77c2e09266304864ca95434bb8f4eb1605f057a.zip
[Reproducers] Capture and replay interpreter commands.
This patch adds the necessary logic to capture and replay commands entered into the command interpreter. A DataRecorder shadows the input and writes its data to a know file. During replay this file is used as the command interpreter's input. It's possible to the command interpreter more than once, with a different input source. We support this scenario by using multiple buffers. The synchronization for this takes place at the SB layer, where we create a new recorder every time the debugger input is changed. During replay we use the corresponding buffer as input. Differential revision: https://reviews.llvm.org/D58564 llvm-svn: 355249
Diffstat (limited to 'lldb/source/Utility/Reproducer.cpp')
-rw-r--r--lldb/source/Utility/Reproducer.cpp46
1 files changed, 46 insertions, 0 deletions
diff --git a/lldb/source/Utility/Reproducer.cpp b/lldb/source/Utility/Reproducer.cpp
index 9f749aac36a2..b09248061d11 100644
--- a/lldb/source/Utility/Reproducer.cpp
+++ b/lldb/source/Utility/Reproducer.cpp
@@ -220,8 +220,54 @@ bool Loader::HasFile(StringRef file) {
return (it != m_files.end()) && (*it == file);
}
+llvm::Expected<std::unique_ptr<DataRecorder>>
+DataRecorder::Create(FileSpec filename) {
+ std::error_code ec;
+ auto recorder = llvm::make_unique<DataRecorder>(std::move(filename), ec);
+ if (ec)
+ return llvm::errorCodeToError(ec);
+ return recorder;
+}
+
+DataRecorder *CommandProvider::GetNewDataRecorder() {
+ std::size_t i = m_data_recorders.size() + 1;
+ std::string filename = (llvm::Twine(info::name) + llvm::Twine("-") +
+ llvm::Twine(i) + llvm::Twine(".txt"))
+ .str();
+ auto recorder_or_error =
+ DataRecorder::Create(GetRoot().CopyByAppendingPathComponent(filename));
+ if (!recorder_or_error) {
+ llvm::consumeError(recorder_or_error.takeError());
+ return nullptr;
+ }
+
+ m_data_recorders.push_back(std::move(*recorder_or_error));
+ return m_data_recorders.back().get();
+}
+
+void CommandProvider::Keep() {
+ std::vector<std::string> files;
+ for (auto &recorder : m_data_recorders)
+ files.push_back(recorder->GetFilename().GetPath());
+
+ FileSpec file = GetRoot().CopyByAppendingPathComponent(info::file);
+ std::error_code ec;
+ llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::F_Text);
+ if (ec)
+ return;
+ yaml::Output yout(os);
+ yout << files;
+
+ m_data_recorders.clear();
+}
+
+void CommandProvider::Discard() { m_data_recorders.clear(); }
+
void ProviderBase::anchor() {}
char ProviderBase::ID = 0;
char FileProvider::ID = 0;
+char CommandProvider::ID = 0;
const char *FileInfo::name = "files";
const char *FileInfo::file = "files.yaml";
+const char *CommandInfo::name = "command-interpreter";
+const char *CommandInfo::file = "command-interpreter.yaml";