JDevlieghere updated this revision to Diff 188244.
JDevlieghere marked 4 inline comments as done.
JDevlieghere added a comment.
Add comments
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D58564/new/
https://reviews.llvm.org/D58564
Files:
lldb/include/lldb/Interpreter/CommandInterpreter.h
lldb/source/Commands/CommandObjectReproducer.cpp
lldb/source/Interpreter/CommandInterpreter.cpp
Index: lldb/source/Interpreter/CommandInterpreter.cpp
===================================================================
--- lldb/source/Interpreter/CommandInterpreter.cpp
+++ lldb/source/Interpreter/CommandInterpreter.cpp
@@ -45,6 +45,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Reproducer.h"
#include "lldb/Utility/State.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
@@ -74,6 +75,7 @@
using namespace lldb;
using namespace lldb_private;
+using namespace llvm;
static const char *k_white_space = " \t\v";
@@ -116,6 +118,51 @@
eEchoCommentCommands = 5
};
+/// Provider for the command interpreter. Every command is logged to file which
+/// is used as input during replay. The latter takes place at the SB API layer
+/// by changing the input file handle.
+class lldb_private::CommandProvider
+ : public repro::Provider<lldb_private::CommandProvider> {
+public:
+ typedef CommandProviderInfo info;
+
+ CommandProvider(const FileSpec &directory) : Provider(directory) {}
+
+ /// Capture a single command.
+ void CaptureCommand(std::string command) {
+ m_commands.push_back(std::move(command));
+ }
+
+ /// Commands are kept in memory and written to a file when the reproducer
+ /// needs to be kept.
+ void Keep() override {
+ FileSpec file =
+ GetRoot().CopyByAppendingPathComponent(CommandProviderInfo::file);
+
+ std::error_code ec;
+ llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::F_Text);
+
+ if (ec)
+ return;
+
+ for (auto &command : m_commands)
+ os << command << '\n';
+ }
+
+ /// Commands are kept in memory and are cleared when the reproducer is
+ /// discarded.
+ void Discard() override { m_commands.clear(); }
+
+ static char ID;
+
+private:
+ std::vector<std::string> m_commands;
+};
+
+char CommandProvider::ID = 0;
+const char *CommandProviderInfo::name = "command-interpreter";
+const char *CommandProviderInfo::file = "command-interpreter.txt";
+
ConstString &CommandInterpreter::GetStaticBroadcasterClass() {
static ConstString class_name("lldb.commandInterpreter");
return class_name;
@@ -141,6 +188,9 @@
SetEventName(eBroadcastBitQuitCommandReceived, "quit");
CheckInWithManager();
m_collection_sp->Initialize(g_properties);
+
+ if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator())
+ m_provider = &g->GetOrCreate<CommandProvider>();
}
bool CommandInterpreter::GetExpandRegexAliases() const {
@@ -1694,6 +1744,9 @@
Status error(PreprocessCommand(command_string));
+ if (m_provider)
+ m_provider->CaptureCommand(original_command_string);
+
if (error.Fail()) {
result.AppendError(error.AsCString());
result.SetStatus(eReturnStatusFailed);
Index: lldb/source/Commands/CommandObjectReproducer.cpp
===================================================================
--- lldb/source/Commands/CommandObjectReproducer.cpp
+++ lldb/source/Commands/CommandObjectReproducer.cpp
@@ -37,8 +37,13 @@
auto &r = repro::Reproducer::Instance();
if (auto generator = r.GetGenerator()) {
generator->Keep();
+ } else if (r.GetLoader()) {
+ // Make this operation a NOP in replay mode.
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ return result.Succeeded();
} else {
result.AppendErrorWithFormat("Unable to get the reproducer generator");
+ result.SetStatus(eReturnStatusFailed);
return false;
}
Index: lldb/include/lldb/Interpreter/CommandInterpreter.h
===================================================================
--- lldb/include/lldb/Interpreter/CommandInterpreter.h
+++ lldb/include/lldb/Interpreter/CommandInterpreter.h
@@ -27,6 +27,14 @@
namespace lldb_private {
+/// Reproducer provider for the command interpreter. The info struct needs to
+/// be public because replay takes place at the SB API layer.
+class CommandProvider;
+struct CommandProviderInfo {
+ static const char *name;
+ static const char *file;
+};
+
class CommandInterpreterRunOptions {
public:
//------------------------------------------------------------------
@@ -606,6 +614,9 @@
bool m_quit_requested;
bool m_stopped_for_crash;
+ /// Reproducer provider.
+ CommandProvider *m_provider = nullptr;
+
// The exit code the user has requested when calling the 'quit' command.
// No value means the user hasn't set a custom exit code so far.
llvm::Optional<int> m_quit_exit_code;
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits