diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp')
-rw-r--r-- | contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp | 400 |
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(); |