diff options
| author | Jonas Devlieghere <jonas@devlieghere.com> | 2019-03-02 00:20:26 +0000 |
|---|---|---|
| committer | Jonas Devlieghere <jonas@devlieghere.com> | 2019-03-02 00:20:26 +0000 |
| commit | d77c2e09266304864ca95434bb8f4eb1605f057a (patch) | |
| tree | 88c19efefcc36015f00e954d592c6f313f6f40ff /lldb/source/Utility/Reproducer.cpp | |
| parent | 70f5fc13691d503df28f885f8742f30d83a83307 (diff) | |
| download | llvm-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.cpp | 46 |
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"; |
