aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp')
-rw-r--r--contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp400
1 files changed, 245 insertions, 155 deletions
diff --git a/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp b/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp
index e55b25500179..fb503fe0afb0 100644
--- a/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -6,14 +6,12 @@
//
//===----------------------------------------------------------------------===//
+#include <limits>
#include <memory>
#include <stdlib.h>
#include <string>
#include <vector>
-#include "CommandObjectScript.h"
-#include "lldb/Interpreter/CommandObjectRegexCommand.h"
-
#include "Commands/CommandObjectApropos.h"
#include "Commands/CommandObjectBreakpoint.h"
#include "Commands/CommandObjectCommands.h"
@@ -29,13 +27,17 @@
#include "Commands/CommandObjectPlugin.h"
#include "Commands/CommandObjectProcess.h"
#include "Commands/CommandObjectQuit.h"
+#include "Commands/CommandObjectRegexCommand.h"
#include "Commands/CommandObjectRegister.h"
#include "Commands/CommandObjectReproducer.h"
+#include "Commands/CommandObjectScript.h"
+#include "Commands/CommandObjectSession.h"
#include "Commands/CommandObjectSettings.h"
#include "Commands/CommandObjectSource.h"
#include "Commands/CommandObjectStats.h"
#include "Commands/CommandObjectTarget.h"
#include "Commands/CommandObjectThread.h"
+#include "Commands/CommandObjectTrace.h"
#include "Commands/CommandObjectType.h"
#include "Commands/CommandObjectVersion.h"
#include "Commands/CommandObjectWatchpoint.h"
@@ -44,6 +46,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"
@@ -52,6 +55,8 @@
#if LLDB_ENABLE_LIBEDIT
#include "lldb/Host/Editline.h"
#endif
+#include "lldb/Host/File.h"
+#include "lldb/Host/FileCache.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
@@ -63,6 +68,7 @@
#include "lldb/Interpreter/Property.h"
#include "lldb/Utility/Args.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/TargetList.h"
@@ -74,6 +80,7 @@
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/ScopedPrinter.h"
using namespace lldb;
using namespace lldb_private;
@@ -116,7 +123,7 @@ CommandInterpreter::CommandInterpreter(Debugger &debugger,
m_skip_lldbinit_files(false), m_skip_app_init_files(false),
m_command_io_handler_sp(), m_comment_char('#'),
m_batch_command_mode(false), m_truncation_warning(eNoTruncation),
- m_command_source_depth(0), m_result() {
+ m_command_source_depth(0), m_result(), m_transcript_stream() {
SetEventName(eBroadcastBitThreadShouldExit, "thread-should-exit");
SetEventName(eBroadcastBitResetPrompt, "reset-prompt");
SetEventName(eBroadcastBitQuitCommandReceived, "quit");
@@ -142,6 +149,17 @@ void CommandInterpreter::SetPromptOnQuit(bool enable) {
m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, enable);
}
+bool CommandInterpreter::GetSaveSessionOnQuit() const {
+ const uint32_t idx = ePropertySaveSessionOnQuit;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
+}
+
+void CommandInterpreter::SetSaveSessionOnQuit(bool enable) {
+ const uint32_t idx = ePropertySaveSessionOnQuit;
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, enable);
+}
+
bool CommandInterpreter::GetEchoCommands() const {
const uint32_t idx = ePropertyEchoCommands;
return m_collection_sp->GetPropertyAtIndexAsBoolean(
@@ -206,8 +224,7 @@ bool CommandInterpreter::GetSpaceReplPrompts() const {
}
void CommandInterpreter::Initialize() {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
+ LLDB_SCOPED_TIMER();
CommandReturnObject result(m_debugger.GetUseColor());
@@ -217,48 +234,48 @@ void CommandInterpreter::Initialize() {
OptionArgVectorSP alias_arguments_vector_sp(new OptionArgVector);
// Set up some initial aliases.
- CommandObjectSP cmd_obj_sp = GetCommandSPExact("quit", false);
+ CommandObjectSP cmd_obj_sp = GetCommandSPExact("quit");
if (cmd_obj_sp) {
AddAlias("q", cmd_obj_sp);
AddAlias("exit", cmd_obj_sp);
}
- cmd_obj_sp = GetCommandSPExact("_regexp-attach", false);
+ cmd_obj_sp = GetCommandSPExact("_regexp-attach");
if (cmd_obj_sp)
AddAlias("attach", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
- cmd_obj_sp = GetCommandSPExact("process detach", false);
+ cmd_obj_sp = GetCommandSPExact("process detach");
if (cmd_obj_sp) {
AddAlias("detach", cmd_obj_sp);
}
- cmd_obj_sp = GetCommandSPExact("process continue", false);
+ cmd_obj_sp = GetCommandSPExact("process continue");
if (cmd_obj_sp) {
AddAlias("c", cmd_obj_sp);
AddAlias("continue", cmd_obj_sp);
}
- cmd_obj_sp = GetCommandSPExact("_regexp-break", false);
+ cmd_obj_sp = GetCommandSPExact("_regexp-break");
if (cmd_obj_sp)
AddAlias("b", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
- cmd_obj_sp = GetCommandSPExact("_regexp-tbreak", false);
+ cmd_obj_sp = GetCommandSPExact("_regexp-tbreak");
if (cmd_obj_sp)
AddAlias("tbreak", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
- cmd_obj_sp = GetCommandSPExact("thread step-inst", false);
+ cmd_obj_sp = GetCommandSPExact("thread step-inst");
if (cmd_obj_sp) {
AddAlias("stepi", cmd_obj_sp);
AddAlias("si", cmd_obj_sp);
}
- cmd_obj_sp = GetCommandSPExact("thread step-inst-over", false);
+ cmd_obj_sp = GetCommandSPExact("thread step-inst-over");
if (cmd_obj_sp) {
AddAlias("nexti", cmd_obj_sp);
AddAlias("ni", cmd_obj_sp);
}
- cmd_obj_sp = GetCommandSPExact("thread step-in", false);
+ cmd_obj_sp = GetCommandSPExact("thread step-in");
if (cmd_obj_sp) {
AddAlias("s", cmd_obj_sp);
AddAlias("step", cmd_obj_sp);
@@ -272,86 +289,86 @@ void CommandInterpreter::Initialize() {
}
}
- cmd_obj_sp = GetCommandSPExact("thread step-over", false);
+ cmd_obj_sp = GetCommandSPExact("thread step-over");
if (cmd_obj_sp) {
AddAlias("n", cmd_obj_sp);
AddAlias("next", cmd_obj_sp);
}
- cmd_obj_sp = GetCommandSPExact("thread step-out", false);
+ cmd_obj_sp = GetCommandSPExact("thread step-out");
if (cmd_obj_sp) {
AddAlias("finish", cmd_obj_sp);
}
- cmd_obj_sp = GetCommandSPExact("frame select", false);
+ cmd_obj_sp = GetCommandSPExact("frame select");
if (cmd_obj_sp) {
AddAlias("f", cmd_obj_sp);
}
- cmd_obj_sp = GetCommandSPExact("thread select", false);
+ cmd_obj_sp = GetCommandSPExact("thread select");
if (cmd_obj_sp) {
AddAlias("t", cmd_obj_sp);
}
- cmd_obj_sp = GetCommandSPExact("_regexp-jump", false);
+ cmd_obj_sp = GetCommandSPExact("_regexp-jump");
if (cmd_obj_sp) {
AddAlias("j", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
AddAlias("jump", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
}
- cmd_obj_sp = GetCommandSPExact("_regexp-list", false);
+ cmd_obj_sp = GetCommandSPExact("_regexp-list");
if (cmd_obj_sp) {
AddAlias("l", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
AddAlias("list", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
}
- cmd_obj_sp = GetCommandSPExact("_regexp-env", false);
+ cmd_obj_sp = GetCommandSPExact("_regexp-env");
if (cmd_obj_sp)
AddAlias("env", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
- cmd_obj_sp = GetCommandSPExact("memory read", false);
+ cmd_obj_sp = GetCommandSPExact("memory read");
if (cmd_obj_sp)
AddAlias("x", cmd_obj_sp);
- cmd_obj_sp = GetCommandSPExact("_regexp-up", false);
+ cmd_obj_sp = GetCommandSPExact("_regexp-up");
if (cmd_obj_sp)
AddAlias("up", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
- cmd_obj_sp = GetCommandSPExact("_regexp-down", false);
+ cmd_obj_sp = GetCommandSPExact("_regexp-down");
if (cmd_obj_sp)
AddAlias("down", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
- cmd_obj_sp = GetCommandSPExact("_regexp-display", false);
+ cmd_obj_sp = GetCommandSPExact("_regexp-display");
if (cmd_obj_sp)
AddAlias("display", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
- cmd_obj_sp = GetCommandSPExact("disassemble", false);
+ cmd_obj_sp = GetCommandSPExact("disassemble");
if (cmd_obj_sp)
AddAlias("dis", cmd_obj_sp);
- cmd_obj_sp = GetCommandSPExact("disassemble", false);
+ cmd_obj_sp = GetCommandSPExact("disassemble");
if (cmd_obj_sp)
AddAlias("di", cmd_obj_sp);
- cmd_obj_sp = GetCommandSPExact("_regexp-undisplay", false);
+ cmd_obj_sp = GetCommandSPExact("_regexp-undisplay");
if (cmd_obj_sp)
AddAlias("undisplay", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
- cmd_obj_sp = GetCommandSPExact("_regexp-bt", false);
+ cmd_obj_sp = GetCommandSPExact("_regexp-bt");
if (cmd_obj_sp)
AddAlias("bt", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
- cmd_obj_sp = GetCommandSPExact("target create", false);
+ cmd_obj_sp = GetCommandSPExact("target create");
if (cmd_obj_sp)
AddAlias("file", cmd_obj_sp);
- cmd_obj_sp = GetCommandSPExact("target modules", false);
+ cmd_obj_sp = GetCommandSPExact("target modules");
if (cmd_obj_sp)
AddAlias("image", cmd_obj_sp);
alias_arguments_vector_sp = std::make_shared<OptionArgVector>();
- cmd_obj_sp = GetCommandSPExact("expression", false);
+ cmd_obj_sp = GetCommandSPExact("expression");
if (cmd_obj_sp) {
AddAlias("p", cmd_obj_sp, "--")->SetHelpLong("");
AddAlias("print", cmd_obj_sp, "--")->SetHelpLong("");
@@ -381,7 +398,7 @@ void CommandInterpreter::Initialize() {
}
}
- cmd_obj_sp = GetCommandSPExact("platform shell", false);
+ cmd_obj_sp = GetCommandSPExact("platform shell");
if (cmd_obj_sp) {
CommandAlias *shell_alias = AddAlias("shell", cmd_obj_sp, " --host --");
if (shell_alias) {
@@ -391,12 +408,12 @@ void CommandInterpreter::Initialize() {
}
}
- cmd_obj_sp = GetCommandSPExact("process kill", false);
+ cmd_obj_sp = GetCommandSPExact("process kill");
if (cmd_obj_sp) {
AddAlias("kill", cmd_obj_sp);
}
- cmd_obj_sp = GetCommandSPExact("process launch", false);
+ cmd_obj_sp = GetCommandSPExact("process launch");
if (cmd_obj_sp) {
alias_arguments_vector_sp = std::make_shared<OptionArgVector>();
#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
@@ -420,27 +437,32 @@ void CommandInterpreter::Initialize() {
#endif
}
- cmd_obj_sp = GetCommandSPExact("target symbols add", false);
+ cmd_obj_sp = GetCommandSPExact("target symbols add");
if (cmd_obj_sp) {
AddAlias("add-dsym", cmd_obj_sp);
}
- cmd_obj_sp = GetCommandSPExact("breakpoint set", false);
+ cmd_obj_sp = GetCommandSPExact("breakpoint set");
if (cmd_obj_sp) {
AddAlias("rbreak", cmd_obj_sp, "--func-regex %1");
}
- cmd_obj_sp = GetCommandSPExact("frame variable", false);
+ cmd_obj_sp = GetCommandSPExact("frame variable");
if (cmd_obj_sp) {
AddAlias("v", cmd_obj_sp);
AddAlias("var", cmd_obj_sp);
AddAlias("vo", cmd_obj_sp, "--object-description");
}
- cmd_obj_sp = GetCommandSPExact("register", false);
+ cmd_obj_sp = GetCommandSPExact("register");
if (cmd_obj_sp) {
AddAlias("re", cmd_obj_sp);
}
+
+ cmd_obj_sp = GetCommandSPExact("session history");
+ if (cmd_obj_sp) {
+ AddAlias("history", cmd_obj_sp);
+ }
}
void CommandInterpreter::Clear() {
@@ -460,54 +482,40 @@ const char *CommandInterpreter::ProcessEmbeddedScriptCommands(const char *arg) {
return arg;
}
+#define REGISTER_COMMAND_OBJECT(NAME, CLASS) \
+ m_command_dict[NAME] = std::make_shared<CLASS>(*this);
+
void CommandInterpreter::LoadCommandDictionary() {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
-
- lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage();
-
- m_command_dict["apropos"] = CommandObjectSP(new CommandObjectApropos(*this));
- m_command_dict["breakpoint"] =
- CommandObjectSP(new CommandObjectMultiwordBreakpoint(*this));
- m_command_dict["command"] =
- CommandObjectSP(new CommandObjectMultiwordCommands(*this));
- m_command_dict["disassemble"] =
- CommandObjectSP(new CommandObjectDisassemble(*this));
- m_command_dict["expression"] =
- CommandObjectSP(new CommandObjectExpression(*this));
- m_command_dict["frame"] =
- CommandObjectSP(new CommandObjectMultiwordFrame(*this));
- m_command_dict["gui"] = CommandObjectSP(new CommandObjectGUI(*this));
- m_command_dict["help"] = CommandObjectSP(new CommandObjectHelp(*this));
- m_command_dict["log"] = CommandObjectSP(new CommandObjectLog(*this));
- m_command_dict["memory"] = CommandObjectSP(new CommandObjectMemory(*this));
- m_command_dict["platform"] =
- CommandObjectSP(new CommandObjectPlatform(*this));
- m_command_dict["plugin"] = CommandObjectSP(new CommandObjectPlugin(*this));
- m_command_dict["process"] =
- CommandObjectSP(new CommandObjectMultiwordProcess(*this));
- m_command_dict["quit"] = CommandObjectSP(new CommandObjectQuit(*this));
- m_command_dict["register"] =
- CommandObjectSP(new CommandObjectRegister(*this));
- m_command_dict["reproducer"] =
- CommandObjectSP(new CommandObjectReproducer(*this));
- m_command_dict["script"] =
- CommandObjectSP(new CommandObjectScript(*this, script_language));
- m_command_dict["settings"] =
- CommandObjectSP(new CommandObjectMultiwordSettings(*this));
- m_command_dict["source"] =
- CommandObjectSP(new CommandObjectMultiwordSource(*this));
- m_command_dict["statistics"] = CommandObjectSP(new CommandObjectStats(*this));
- m_command_dict["target"] =
- CommandObjectSP(new CommandObjectMultiwordTarget(*this));
- m_command_dict["thread"] =
- CommandObjectSP(new CommandObjectMultiwordThread(*this));
- m_command_dict["type"] = CommandObjectSP(new CommandObjectType(*this));
- m_command_dict["version"] = CommandObjectSP(new CommandObjectVersion(*this));
- m_command_dict["watchpoint"] =
- CommandObjectSP(new CommandObjectMultiwordWatchpoint(*this));
- m_command_dict["language"] =
- CommandObjectSP(new CommandObjectLanguage(*this));
+ LLDB_SCOPED_TIMER();
+
+ REGISTER_COMMAND_OBJECT("apropos", CommandObjectApropos);
+ REGISTER_COMMAND_OBJECT("breakpoint", CommandObjectMultiwordBreakpoint);
+ REGISTER_COMMAND_OBJECT("command", CommandObjectMultiwordCommands);
+ REGISTER_COMMAND_OBJECT("disassemble", CommandObjectDisassemble);
+ REGISTER_COMMAND_OBJECT("expression", CommandObjectExpression);
+ REGISTER_COMMAND_OBJECT("frame", CommandObjectMultiwordFrame);
+ REGISTER_COMMAND_OBJECT("gui", CommandObjectGUI);
+ REGISTER_COMMAND_OBJECT("help", CommandObjectHelp);
+ REGISTER_COMMAND_OBJECT("log", CommandObjectLog);
+ REGISTER_COMMAND_OBJECT("memory", CommandObjectMemory);
+ REGISTER_COMMAND_OBJECT("platform", CommandObjectPlatform);
+ REGISTER_COMMAND_OBJECT("plugin", CommandObjectPlugin);
+ REGISTER_COMMAND_OBJECT("process", CommandObjectMultiwordProcess);
+ REGISTER_COMMAND_OBJECT("quit", CommandObjectQuit);
+ REGISTER_COMMAND_OBJECT("register", CommandObjectRegister);
+ REGISTER_COMMAND_OBJECT("reproducer", CommandObjectReproducer);
+ REGISTER_COMMAND_OBJECT("script", CommandObjectScript);
+ REGISTER_COMMAND_OBJECT("settings", CommandObjectMultiwordSettings);
+ REGISTER_COMMAND_OBJECT("session", CommandObjectSession);
+ REGISTER_COMMAND_OBJECT("source", CommandObjectMultiwordSource);
+ REGISTER_COMMAND_OBJECT("statistics", CommandObjectStats);
+ REGISTER_COMMAND_OBJECT("target", CommandObjectMultiwordTarget);
+ REGISTER_COMMAND_OBJECT("thread", CommandObjectMultiwordThread);
+ REGISTER_COMMAND_OBJECT("trace", CommandObjectTrace);
+ REGISTER_COMMAND_OBJECT("type", CommandObjectType);
+ REGISTER_COMMAND_OBJECT("version", CommandObjectVersion);
+ REGISTER_COMMAND_OBJECT("watchpoint", CommandObjectMultiwordWatchpoint);
+ REGISTER_COMMAND_OBJECT("language", CommandObjectLanguage);
// clang-format off
const char *break_regexes[][2] = {
@@ -624,15 +632,10 @@ void CommandInterpreter::LoadCommandDictionary() {
if (tbreak_regex_cmd_up) {
bool success = true;
for (size_t i = 0; i < num_regexes; i++) {
- // If you add a resultant command string longer than 1024 characters be
- // sure to increase the size of this buffer.
- char buffer[1024];
- int num_printed =
- snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o 1");
- lldbassert(num_printed < 1024);
- UNUSED_IF_ASSERT_DISABLED(num_printed);
+ std::string command = break_regexes[i][1];
+ command += " -o 1";
success =
- tbreak_regex_cmd_up->AddRegexCommand(break_regexes[i][0], buffer);
+ tbreak_regex_cmd_up->AddRegexCommand(break_regexes[i][0], command);
if (!success)
break;
}
@@ -1034,47 +1037,46 @@ bool CommandInterpreter::AddUserCommand(llvm::StringRef name,
return false;
}
-CommandObjectSP CommandInterpreter::GetCommandSPExact(llvm::StringRef cmd_str,
- bool include_aliases) const {
- Args cmd_words(cmd_str); // Break up the command string into words, in case
- // it's a multi-word command.
- CommandObjectSP ret_val; // Possibly empty return value.
+CommandObjectSP
+CommandInterpreter::GetCommandSPExact(llvm::StringRef cmd_str,
+ bool include_aliases) const {
+ // Break up the command string into words, in case it's a multi-word command.
+ Args cmd_words(cmd_str);
if (cmd_str.empty())
- return ret_val;
+ return {};
if (cmd_words.GetArgumentCount() == 1)
- return GetCommandSP(cmd_str, include_aliases, true, nullptr);
- else {
- // We have a multi-word command (seemingly), so we need to do more work.
- // First, get the cmd_obj_sp for the first word in the command.
- CommandObjectSP cmd_obj_sp = GetCommandSP(llvm::StringRef(cmd_words.GetArgumentAtIndex(0)),
- include_aliases, true, nullptr);
- if (cmd_obj_sp.get() != nullptr) {
- // Loop through the rest of the words in the command (everything passed
- // in was supposed to be part of a command name), and find the
- // appropriate sub-command SP for each command word....
- size_t end = cmd_words.GetArgumentCount();
- for (size_t j = 1; j < end; ++j) {
- if (cmd_obj_sp->IsMultiwordObject()) {
- cmd_obj_sp =
- cmd_obj_sp->GetSubcommandSP(cmd_words.GetArgumentAtIndex(j));
- if (cmd_obj_sp.get() == nullptr)
- // The sub-command name was invalid. Fail and return the empty
- // 'ret_val'.
- return ret_val;
- } else
- // We have more words in the command name, but we don't have a
- // multiword object. Fail and return empty 'ret_val'.
- return ret_val;
- }
- // We successfully looped through all the command words and got valid
- // command objects for them. Assign the last object retrieved to
- // 'ret_val'.
- ret_val = cmd_obj_sp;
+ return GetCommandSP(cmd_str, include_aliases, true);
+
+ // We have a multi-word command (seemingly), so we need to do more work.
+ // First, get the cmd_obj_sp for the first word in the command.
+ CommandObjectSP cmd_obj_sp =
+ GetCommandSP(cmd_words.GetArgumentAtIndex(0), include_aliases, true);
+ if (!cmd_obj_sp)
+ return {};
+
+ // Loop through the rest of the words in the command (everything passed in
+ // was supposed to be part of a command name), and find the appropriate
+ // sub-command SP for each command word....
+ size_t end = cmd_words.GetArgumentCount();
+ for (size_t i = 1; i < end; ++i) {
+ if (!cmd_obj_sp->IsMultiwordObject()) {
+ // We have more words in the command name, but we don't have a
+ // multiword object. Fail and return.
+ return {};
+ }
+
+ cmd_obj_sp = cmd_obj_sp->GetSubcommandSP(cmd_words.GetArgumentAtIndex(i));
+ if (!cmd_obj_sp) {
+ // The sub-command name was invalid. Fail and return.
+ return {};
}
}
- return ret_val;
+
+ // We successfully looped through all the command words and got valid
+ // command objects for them.
+ return cmd_obj_sp;
}
CommandObject *
@@ -1518,16 +1520,12 @@ Status CommandInterpreter::PreprocessCommand(std::string &command) {
end_backtick - expr_content_start);
ExecutionContext exe_ctx(GetExecutionContext());
- Target *target = exe_ctx.GetTargetPtr();
// Get a dummy target to allow for calculator mode while processing
// backticks. This also helps break the infinite loop caused when target is
// null.
- if (!target)
- target = m_debugger.GetDummyTarget();
-
- if (!target)
- continue;
+ Target *exe_target = exe_ctx.GetTargetPtr();
+ Target &target = exe_target ? *exe_target : m_debugger.GetDummyTarget();
ValueObjectSP expr_result_valobj_sp;
@@ -1540,8 +1538,8 @@ Status CommandInterpreter::PreprocessCommand(std::string &command) {
options.SetTimeout(llvm::None);
ExpressionResults expr_result =
- target->EvaluateExpression(expr_str.c_str(), exe_ctx.GetFramePtr(),
- expr_result_valobj_sp, options);
+ target.EvaluateExpression(expr_str.c_str(), exe_ctx.GetFramePtr(),
+ expr_result_valobj_sp, options);
if (expr_result == eExpressionCompleted) {
Scalar scalar;
@@ -1648,9 +1646,7 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
command_line);
LLDB_LOGF(log, "Processing command: %s", command_line);
-
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat, "Handling command: %s.", command_line);
+ LLDB_SCOPED_TIMERF("Processing command: %s.", command_line);
if (!no_context_switching)
UpdateExecutionContext(override_context);
@@ -1667,6 +1663,8 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
else
add_to_history = (lazy_add_to_history == eLazyBoolYes);
+ m_transcript_stream << "(lldb) " << command_line << '\n';
+
bool empty_command = false;
bool comment_command = false;
if (command_string.empty())
@@ -1708,7 +1706,7 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
command_string = command_line;
original_command_string = command_line;
if (m_repeat_command.empty()) {
- result.AppendErrorWithFormat("No auto repeat.\n");
+ result.AppendError("No auto repeat.");
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1799,6 +1797,9 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
LLDB_LOGF(log, "HandleCommand, command %s",
(result.Succeeded() ? "succeeded" : "did not succeed"));
+ m_transcript_stream << result.GetOutputData();
+ m_transcript_stream << result.GetErrorData();
+
return result.Succeeded();
}
@@ -1871,6 +1872,19 @@ void CommandInterpreter::HandleCompletion(CompletionRequest &request) {
HandleCompletionMatches(request);
}
+llvm::Optional<std::string>
+CommandInterpreter::GetAutoSuggestionForCommand(llvm::StringRef line) {
+ if (line.empty())
+ return llvm::None;
+ const size_t s = m_command_history.GetSize();
+ for (int i = s - 1; i >= 0; --i) {
+ llvm::StringRef entry = m_command_history.GetStringAtIndex(i);
+ if (entry.consume_front(line))
+ return entry.str();
+ }
+ return llvm::None;
+}
+
CommandInterpreter::~CommandInterpreter() {}
void CommandInterpreter::UpdatePrompt(llvm::StringRef new_prompt) {
@@ -1975,10 +1989,7 @@ void CommandInterpreter::BuildAliasCommandArgs(CommandObject *alias_cmd_obj,
if (value_type != OptionParser::eOptionalArgument)
new_args.AppendArgument(value);
else {
- char buffer[255];
- ::snprintf(buffer, sizeof(buffer), "%s%s", option.c_str(),
- value.c_str());
- new_args.AppendArgument(llvm::StringRef(buffer));
+ new_args.AppendArgument(option + value);
}
} else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount()) {
@@ -2000,10 +2011,7 @@ void CommandInterpreter::BuildAliasCommandArgs(CommandObject *alias_cmd_obj,
if (value_type != OptionParser::eOptionalArgument)
new_args.AppendArgument(cmd_args.GetArgumentAtIndex(index));
else {
- char buffer[255];
- ::snprintf(buffer, sizeof(buffer), "%s%s", option.c_str(),
- cmd_args.GetArgumentAtIndex(index));
- new_args.AppendArgument(buffer);
+ new_args.AppendArgument(option + cmd_args.GetArgumentAtIndex(index));
}
used[index] = true;
}
@@ -2070,12 +2078,30 @@ static void GetHomeInitFile(llvm::SmallVectorImpl<char> &init_file,
init_file_name.append(suffix.str());
}
- llvm::sys::path::home_directory(init_file);
+ FileSystem::Instance().GetHomeDirectory(init_file);
llvm::sys::path::append(init_file, init_file_name);
FileSystem::Instance().Resolve(init_file);
}
+static void GetHomeREPLInitFile(llvm::SmallVectorImpl<char> &init_file) {
+ LanguageSet repl_languages = Language::GetLanguagesSupportingREPLs();
+ LanguageType language = eLanguageTypeUnknown;
+ if (auto main_repl_language = repl_languages.GetSingularLanguage())
+ language = *main_repl_language;
+ else
+ return;
+
+ std::string init_file_name =
+ (llvm::Twine(".lldbinit-") +
+ llvm::Twine(Language::GetNameForLanguageType(language)) +
+ llvm::Twine("-repl"))
+ .str();
+ FileSystem::Instance().GetHomeDirectory(init_file);
+ llvm::sys::path::append(init_file, init_file_name);
+ FileSystem::Instance().Resolve(init_file);
+}
+
static void GetCwdInitFile(llvm::SmallVectorImpl<char> &init_file) {
llvm::StringRef s = ".lldbinit";
init_file.assign(s.begin(), s.end());
@@ -2141,7 +2167,7 @@ void CommandInterpreter::SourceInitFileCwd(CommandReturnObject &result) {
llvm::sys::path::parent_path(home_init_file)) {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
} else {
- result.AppendErrorWithFormat(InitFileWarning);
+ result.AppendError(InitFileWarning);
result.SetStatus(eReturnStatusFailed);
}
}
@@ -2150,15 +2176,22 @@ void CommandInterpreter::SourceInitFileCwd(CommandReturnObject &result) {
/// We will first see if there is an application specific ".lldbinit" file
/// whose name is "~/.lldbinit" followed by a "-" and the name of the program.
-/// If this file doesn't exist, we fall back to just the "~/.lldbinit" file.
-void CommandInterpreter::SourceInitFileHome(CommandReturnObject &result) {
+/// If this file doesn't exist, we fall back to the REPL init file or the
+/// default home init file in "~/.lldbinit".
+void CommandInterpreter::SourceInitFileHome(CommandReturnObject &result,
+ bool is_repl) {
if (m_skip_lldbinit_files) {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return;
}
llvm::SmallString<128> init_file;
- GetHomeInitFile(init_file);
+
+ if (is_repl)
+ GetHomeREPLInitFile(init_file);
+
+ if (init_file.empty())
+ GetHomeInitFile(init_file);
if (!m_skip_app_init_files) {
llvm::StringRef program_name =
@@ -2265,6 +2298,8 @@ void CommandInterpreter::HandleCommands(const StringList &commands,
}
CommandReturnObject tmp_result(m_debugger.GetUseColor());
+ tmp_result.SetInteractive(result.GetInteractive());
+
// If override_context is not NULL, pass no_context_switching = true for
// HandleCommand() since we updated our context already.
@@ -2512,11 +2547,15 @@ void CommandInterpreter::HandleCommandsFromFile(
debugger.SetAsyncExecution(false);
m_command_source_depth++;
+ m_command_source_dirs.push_back(cmd_file.CopyByRemovingLastPathComponent());
debugger.RunIOHandlerSync(io_handler_sp);
if (!m_command_source_flags.empty())
m_command_source_flags.pop_back();
+
+ m_command_source_dirs.pop_back();
m_command_source_depth--;
+
result.SetStatus(eReturnStatusSuccessFinishNoResult);
debugger.SetAsyncExecution(old_async_execution);
}
@@ -2877,6 +2916,57 @@ bool CommandInterpreter::IOHandlerInterrupt(IOHandler &io_handler) {
return false;
}
+bool CommandInterpreter::SaveTranscript(
+ CommandReturnObject &result, llvm::Optional<std::string> output_file) {
+ if (output_file == llvm::None || output_file->empty()) {
+ std::string now = llvm::to_string(std::chrono::system_clock::now());
+ std::replace(now.begin(), now.end(), ' ', '_');
+ const std::string file_name = "lldb_session_" + now + ".log";
+ FileSpec tmp = HostInfo::GetGlobalTempDir();
+ tmp.AppendPathComponent(file_name);
+ output_file = tmp.GetPath();
+ }
+
+ auto error_out = [&](llvm::StringRef error_message, std::string description) {
+ LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMANDS), "{0} ({1}:{2})",
+ error_message, output_file, description);
+ result.AppendErrorWithFormatv(
+ "Failed to save session's transcripts to {0}!", *output_file);
+ return false;
+ };
+
+ File::OpenOptions flags = File::eOpenOptionWrite |
+ File::eOpenOptionCanCreate |
+ File::eOpenOptionTruncate;
+
+ auto opened_file = FileSystem::Instance().Open(FileSpec(*output_file), flags);
+
+ if (!opened_file)
+ return error_out("Unable to create file",
+ llvm::toString(opened_file.takeError()));
+
+ FileUP file = std::move(opened_file.get());
+
+ size_t byte_size = m_transcript_stream.GetSize();
+
+ Status error = file->Write(m_transcript_stream.GetData(), byte_size);
+
+ if (error.Fail() || byte_size != m_transcript_stream.GetSize())
+ return error_out("Unable to write to destination file",
+ "Bytes written do not match transcript size.");
+
+ result.AppendMessageWithFormat("Session's transcripts saved to %s\n",
+ output_file->c_str());
+
+ return true;
+}
+
+FileSpec CommandInterpreter::GetCurrentSourceDir() {
+ if (m_command_source_dirs.empty())
+ return {};
+ return m_command_source_dirs.back();
+}
+
void CommandInterpreter::GetLLDBCommandsFromIOHandler(
const char *prompt, IOHandlerDelegate &delegate, void *baton) {
Debugger &debugger = GetDebugger();