diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2021-06-13 19:31:46 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2021-06-13 19:37:19 +0000 |
commit | e8d8bef961a50d4dc22501cde4fb9fb0be1b2532 (patch) | |
tree | 94f04805f47bb7c59ae29690d8952b6074fff602 /contrib/llvm-project/lldb/source/Interpreter | |
parent | bb130ff39747b94592cb26d71b7cb097b9a4ea6b (diff) | |
parent | b60736ec1405bb0a8dd40989f67ef4c93da068ab (diff) | |
download | src-e8d8bef961a50d4dc22501cde4fb9fb0be1b2532.tar.gz src-e8d8bef961a50d4dc22501cde4fb9fb0be1b2532.zip |
Merge llvm-project main llvmorg-12-init-17869-g8e464dd76bef
This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvmorg-12-init-17869-g8e464dd76bef, the last commit before the
upstream release/12.x branch was created.
PR: 255570
MFC after: 6 weeks
Diffstat (limited to 'contrib/llvm-project/lldb/source/Interpreter')
17 files changed, 444 insertions, 416 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(); diff --git a/contrib/llvm-project/lldb/source/Interpreter/CommandObject.cpp b/contrib/llvm-project/lldb/source/Interpreter/CommandObject.cpp index 538f7a1ba693..71adf8c39f1b 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/CommandObject.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/CommandObject.cpp @@ -258,6 +258,15 @@ bool CommandObject::CheckRequirements(CommandReturnObject &result) { } } } + + if (GetFlags().Test(eCommandProcessMustBeTraced)) { + Target *target = m_exe_ctx.GetTargetPtr(); + if (target && !target->GetTrace()) { + result.SetError("Process is not being traced."); + return false; + } + } + return true; } @@ -930,11 +939,11 @@ const char *CommandObject::GetArgumentDescriptionAsCString( } Target &CommandObject::GetDummyTarget() { - return *m_interpreter.GetDebugger().GetDummyTarget(); + return m_interpreter.GetDebugger().GetDummyTarget(); } Target &CommandObject::GetSelectedOrDummyTarget(bool prefer_dummy) { - return *m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy); + return m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy); } Target &CommandObject::GetSelectedTarget() { @@ -1041,13 +1050,13 @@ CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = { { eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, { nullptr, false }, "A Boolean value: 'true' or 'false'" }, { eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, { BreakpointIDHelpTextCallback, false }, nullptr }, { eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, { BreakpointIDRangeHelpTextCallback, false }, nullptr }, - { eArgTypeBreakpointName, "breakpoint-name", CommandCompletions::eNoCompletion, { BreakpointNameHelpTextCallback, false }, nullptr }, + { eArgTypeBreakpointName, "breakpoint-name", CommandCompletions::eBreakpointNameCompletion, { BreakpointNameHelpTextCallback, false }, nullptr }, { eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, { nullptr, false }, "Number of bytes to use." }, { eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, { nullptr, false }, "Then name of a class from the debug information in the program." }, { eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { nullptr, false }, "A debugger command (may be multiple words), without any options or arguments." }, { eArgTypeCount, "count", CommandCompletions::eNoCompletion, { nullptr, false }, "An unsigned integer." }, { eArgTypeDirectoryName, "directory", CommandCompletions::eDiskDirectoryCompletion, { nullptr, false }, "A directory name." }, - { eArgTypeDisassemblyFlavor, "disassembly-flavor", CommandCompletions::eNoCompletion, { nullptr, false }, "A disassembly flavor recognized by your disassembly plugin. Currently the only valid options are \"att\" and \"intel\" for Intel targets" }, + { eArgTypeDisassemblyFlavor, "disassembly-flavor", CommandCompletions::eDisassemblyFlavorCompletion, { nullptr, false }, "A disassembly flavor recognized by your disassembly plugin. Currently the only valid options are \"att\" and \"intel\" for Intel targets" }, { eArgTypeDescriptionVerbosity, "description-verbosity", CommandCompletions::eNoCompletion, { nullptr, false }, "How verbose the output of 'po' should be." }, { eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." }, { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." }, @@ -1055,19 +1064,20 @@ CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = { { eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, { nullptr, false }, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" }, { eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, { nullptr, false }, "The name of a file (can include path)." }, { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, { FormatHelpTextCallback, true }, nullptr }, - { eArgTypeFrameIndex, "frame-index", CommandCompletions::eNoCompletion, { nullptr, false }, "Index into a thread's list of frames." }, + { eArgTypeFrameIndex, "frame-index", CommandCompletions::eFrameIndexCompletion, { nullptr, false }, "Index into a thread's list of frames." }, { eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." }, { eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a function." }, { eArgTypeFunctionOrSymbol, "function-or-symbol", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a function or symbol." }, { eArgTypeGDBFormat, "gdb-format", CommandCompletions::eNoCompletion, { GDBFormatHelpTextCallback, true }, nullptr }, { eArgTypeHelpText, "help-text", CommandCompletions::eNoCompletion, { nullptr, false }, "Text to be used as help for some other entity in LLDB" }, { eArgTypeIndex, "index", CommandCompletions::eNoCompletion, { nullptr, false }, "An index into a list." }, - { eArgTypeLanguage, "source-language", CommandCompletions::eNoCompletion, { LanguageTypeHelpTextCallback, true }, nullptr }, + { eArgTypeLanguage, "source-language", CommandCompletions::eTypeLanguageCompletion, { LanguageTypeHelpTextCallback, true }, nullptr }, { eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, { nullptr, false }, "Line number in a source file." }, + { eArgTypeFileLineColumn, "linespec", CommandCompletions::eNoCompletion, { nullptr, false }, "A source specifier in the form file:line[:column]" }, { eArgTypeLogCategory, "log-category", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a category within a log channel, e.g. all (try \"log list\" to see a list of all channels and their categories." }, { eArgTypeLogChannel, "log-channel", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a log channel, e.g. process.gdb-remote (try \"log list\" to see a list of all channels and their categories)." }, { eArgTypeMethod, "method", CommandCompletions::eNoCompletion, { nullptr, false }, "A C++ method name." }, - { eArgTypeName, "name", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." }, + { eArgTypeName, "name", CommandCompletions::eTypeCategoryNameCompletion, { nullptr, false }, "Help text goes here." }, { eArgTypeNewPathPrefix, "new-path-prefix", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." }, { eArgTypeNumLines, "num-lines", CommandCompletions::eNoCompletion, { nullptr, false }, "The number of lines to use." }, { eArgTypeNumberPerLine, "number-per-line", CommandCompletions::eNoCompletion, { nullptr, false }, "The number of items per line to display." }, @@ -1077,9 +1087,9 @@ CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = { { eArgTypePath, "path", CommandCompletions::eDiskFileCompletion, { nullptr, false }, "Path." }, { eArgTypePermissionsNumber, "perms-numeric", CommandCompletions::eNoCompletion, { nullptr, false }, "Permissions given as an octal number (e.g. 755)." }, { eArgTypePermissionsString, "perms=string", CommandCompletions::eNoCompletion, { nullptr, false }, "Permissions given as a string value (e.g. rw-r-xr--)." }, - { eArgTypePid, "pid", CommandCompletions::eNoCompletion, { nullptr, false }, "The process ID number." }, + { eArgTypePid, "pid", CommandCompletions::eProcessIDCompletion, { nullptr, false }, "The process ID number." }, { eArgTypePlugin, "plugin", CommandCompletions::eProcessPluginCompletion, { nullptr, false }, "Help text goes here." }, - { eArgTypeProcessName, "process-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of the process." }, + { eArgTypeProcessName, "process-name", CommandCompletions::eProcessNameCompletion, { nullptr, false }, "The name of the process." }, { eArgTypePythonClass, "python-class", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a Python class." }, { eArgTypePythonFunction, "python-function", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a Python function." }, { eArgTypePythonScript, "python-script", CommandCompletions::eNoCompletion, { nullptr, false }, "Source code written in Python." }, @@ -1118,7 +1128,8 @@ CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = { { eArgTypeWatchType, "watch-type", CommandCompletions::eNoCompletion, { nullptr, false }, "Specify the type for a watchpoint." }, { eArgRawInput, "raw-input", CommandCompletions::eNoCompletion, { nullptr, false }, "Free-form text passed to a command without prior interpretation, allowing spaces without requiring quotes. To pass arguments and free form text put two dashes ' -- ' between the last argument and any raw input." }, { eArgTypeCommand, "command", CommandCompletions::eNoCompletion, { nullptr, false }, "An LLDB Command line command." }, - { eArgTypeColumnNum, "column", CommandCompletions::eNoCompletion, { nullptr, false }, "Column number in a source file." } + { eArgTypeColumnNum, "column", CommandCompletions::eNoCompletion, { nullptr, false }, "Column number in a source file." }, + { eArgTypeModuleUUID, "module-uuid", CommandCompletions::eModuleUUIDCompletion, { nullptr, false }, "A module UUID value." } // clang-format on }; diff --git a/contrib/llvm-project/lldb/source/Interpreter/CommandObjectRegexCommand.cpp b/contrib/llvm-project/lldb/source/Interpreter/CommandObjectRegexCommand.cpp deleted file mode 100644 index 5a0265e58c5c..000000000000 --- a/contrib/llvm-project/lldb/source/Interpreter/CommandObjectRegexCommand.cpp +++ /dev/null @@ -1,92 +0,0 @@ -//===-- CommandObjectRegexCommand.cpp -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Interpreter/CommandObjectRegexCommand.h" - -#include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Interpreter/CommandReturnObject.h" - -using namespace lldb; -using namespace lldb_private; - -// CommandObjectRegexCommand constructor -CommandObjectRegexCommand::CommandObjectRegexCommand( - CommandInterpreter &interpreter, llvm::StringRef name, llvm::StringRef help, - llvm::StringRef syntax, uint32_t max_matches, uint32_t completion_type_mask, - bool is_removable) - : CommandObjectRaw(interpreter, name, help, syntax), - m_max_matches(max_matches), m_completion_type_mask(completion_type_mask), - m_entries(), m_is_removable(is_removable) {} - -// Destructor -CommandObjectRegexCommand::~CommandObjectRegexCommand() {} - -bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command, - CommandReturnObject &result) { - EntryCollection::const_iterator pos, end = m_entries.end(); - for (pos = m_entries.begin(); pos != end; ++pos) { - llvm::SmallVector<llvm::StringRef, 4> matches; - if (pos->regex.Execute(command, &matches)) { - std::string new_command(pos->command); - char percent_var[8]; - size_t idx, percent_var_idx; - for (uint32_t match_idx = 1; match_idx <= m_max_matches; ++match_idx) { - if (match_idx < matches.size()) { - const std::string match_str = matches[match_idx].str(); - const int percent_var_len = - ::snprintf(percent_var, sizeof(percent_var), "%%%u", match_idx); - for (idx = 0; (percent_var_idx = new_command.find( - percent_var, idx)) != std::string::npos;) { - new_command.erase(percent_var_idx, percent_var_len); - new_command.insert(percent_var_idx, match_str); - idx += percent_var_idx + match_str.size(); - } - } - } - // Interpret the new command and return this as the result! - if (m_interpreter.GetExpandRegexAliases()) - result.GetOutputStream().Printf("%s\n", new_command.c_str()); - // Pass in true for "no context switching". The command that called us - // should have set up the context appropriately, we shouldn't have to - // redo that. - return m_interpreter.HandleCommand( - new_command.c_str(), eLazyBoolCalculate, result, nullptr, true, true); - } - } - result.SetStatus(eReturnStatusFailed); - if (!GetSyntax().empty()) - result.AppendError(GetSyntax()); - else - result.GetOutputStream() << "Command contents '" << command - << "' failed to match any " - "regular expression in the '" - << m_cmd_name << "' regex "; - return false; -} - -bool CommandObjectRegexCommand::AddRegexCommand(const char *re_cstr, - const char *command_cstr) { - m_entries.resize(m_entries.size() + 1); - // Only add the regular expression if it compiles - m_entries.back().regex = - RegularExpression(llvm::StringRef::withNullAsEmpty(re_cstr)); - if (m_entries.back().regex.IsValid()) { - m_entries.back().command.assign(command_cstr); - return true; - } - // The regex didn't compile... - m_entries.pop_back(); - return false; -} - -void CommandObjectRegexCommand::HandleCompletion(CompletionRequest &request) { - if (m_completion_type_mask) { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), m_completion_type_mask, request, nullptr); - } -} diff --git a/contrib/llvm-project/lldb/source/Interpreter/CommandObjectScript.cpp b/contrib/llvm-project/lldb/source/Interpreter/CommandObjectScript.cpp deleted file mode 100644 index 5e98c658ebdb..000000000000 --- a/contrib/llvm-project/lldb/source/Interpreter/CommandObjectScript.cpp +++ /dev/null @@ -1,68 +0,0 @@ -//===-- CommandObjectScript.cpp -------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "CommandObjectScript.h" -#include "lldb/Core/Debugger.h" -#include "lldb/DataFormatters/DataVisualization.h" -#include "lldb/Host/Config.h" -#include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/ScriptInterpreter.h" -#include "lldb/Utility/Args.h" - -using namespace lldb; -using namespace lldb_private; - -// CommandObjectScript - -CommandObjectScript::CommandObjectScript(CommandInterpreter &interpreter, - ScriptLanguage script_lang) - : CommandObjectRaw( - interpreter, "script", - "Invoke the script interpreter with provided code and display any " - "results. Start the interactive interpreter if no code is supplied.", - "script [<script-code>]") {} - -CommandObjectScript::~CommandObjectScript() {} - -bool CommandObjectScript::DoExecute(llvm::StringRef command, - CommandReturnObject &result) { - if (m_interpreter.GetDebugger().GetScriptLanguage() == - lldb::eScriptLanguageNone) { - result.AppendError( - "the script-lang setting is set to none - scripting not available"); - result.SetStatus(eReturnStatusFailed); - return false; - } - - ScriptInterpreter *script_interpreter = GetDebugger().GetScriptInterpreter(); - - if (script_interpreter == nullptr) { - result.AppendError("no script interpreter"); - result.SetStatus(eReturnStatusFailed); - return false; - } - - // Script might change Python code we use for formatting. Make sure we keep - // up to date with it. - DataVisualization::ForceUpdate(); - - if (command.empty()) { - script_interpreter->ExecuteInterpreterLoop(); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); - } - - // We can do better when reporting the status of one-liner script execution. - if (script_interpreter->ExecuteOneLine(command, &result)) - result.SetStatus(eReturnStatusSuccessFinishNoResult); - else - result.SetStatus(eReturnStatusFailed); - - return result.Succeeded(); -} diff --git a/contrib/llvm-project/lldb/source/Interpreter/CommandObjectScript.h b/contrib/llvm-project/lldb/source/Interpreter/CommandObjectScript.h deleted file mode 100644 index a5f659995de3..000000000000 --- a/contrib/llvm-project/lldb/source/Interpreter/CommandObjectScript.h +++ /dev/null @@ -1,31 +0,0 @@ -//===-- CommandObjectScript.h -----------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_SOURCE_INTERPRETER_COMMANDOBJECTSCRIPT_H -#define LLDB_SOURCE_INTERPRETER_COMMANDOBJECTSCRIPT_H - -#include "lldb/Interpreter/CommandObject.h" - -namespace lldb_private { - -// CommandObjectScript - -class CommandObjectScript : public CommandObjectRaw { -public: - CommandObjectScript(CommandInterpreter &interpreter, - lldb::ScriptLanguage script_lang); - - ~CommandObjectScript() override; - -protected: - bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override; -}; - -} // namespace lldb_private - -#endif // LLDB_SOURCE_INTERPRETER_COMMANDOBJECTSCRIPT_H diff --git a/contrib/llvm-project/lldb/source/Interpreter/InterpreterProperties.td b/contrib/llvm-project/lldb/source/Interpreter/InterpreterProperties.td index 600c1e3edb9b..e5346d14a6e1 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/InterpreterProperties.td +++ b/contrib/llvm-project/lldb/source/Interpreter/InterpreterProperties.td @@ -9,6 +9,10 @@ let Definition = "interpreter" in { Global, DefaultTrue, Desc<"If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case.">; + def SaveSessionOnQuit: Property<"save-session-on-quit", "Boolean">, + Global, + DefaultFalse, + Desc<"If true, LLDB will save the session's transcripts before quitting.">; def StopCmdSourceOnError: Property<"stop-command-source-on-error", "Boolean">, Global, DefaultTrue, diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupUUID.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupUUID.cpp index 46f2ff75225a..dc6f4139896f 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupUUID.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupUUID.cpp @@ -19,7 +19,7 @@ OptionGroupUUID::~OptionGroupUUID() {} static constexpr OptionDefinition g_option_table[] = { {LLDB_OPT_SET_1, false, "uuid", 'u', OptionParser::eRequiredArgument, - nullptr, {}, 0, eArgTypeNone, "A module UUID value."}, + nullptr, {}, 0, eArgTypeModuleUUID, "A module UUID value."}, }; llvm::ArrayRef<OptionDefinition> OptionGroupUUID::GetDefinitions() { diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionValue.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionValue.cpp index 198be85a7b47..0bd9a591af67 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionValue.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionValue.cpp @@ -39,7 +39,7 @@ Status OptionValue::SetSubValue(const ExecutionContext *exe_ctx, VarSetOperationType op, llvm::StringRef name, llvm::StringRef value) { Status error; - error.SetErrorStringWithFormat("SetSubValue is not supported"); + error.SetErrorString("SetSubValue is not supported"); return error; } @@ -471,6 +471,8 @@ const char *OptionValue::GetBuiltinTypeAsCString(Type t) { return "dictionary"; case eTypeEnum: return "enum"; + case eTypeFileLineColumn: + return "file:line:column specifier"; case eTypeFileSpec: return "file"; case eTypeFileSpecList: diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionValueArray.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionValueArray.cpp index 9be11e32e2db..0b293ccfc248 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionValueArray.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionValueArray.cpp @@ -52,6 +52,7 @@ void OptionValueArray::DumpValue(const ExecutionContext *exe_ctx, Stream &strm, case eTypeChar: case eTypeEnum: case eTypeFileSpec: + case eTypeFileLineColumn: case eTypeFormat: case eTypeSInt64: case eTypeString: diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionValueDictionary.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionValueDictionary.cpp index caadccd04232..79323f502d17 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionValueDictionary.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionValueDictionary.cpp @@ -62,6 +62,7 @@ void OptionValueDictionary::DumpValue(const ExecutionContext *exe_ctx, case eTypeBoolean: case eTypeChar: case eTypeEnum: + case eTypeFileLineColumn: case eTypeFileSpec: case eTypeFormat: case eTypeSInt64: diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionValueFileColonLine.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionValueFileColonLine.cpp new file mode 100644 index 000000000000..dac557c4248a --- /dev/null +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionValueFileColonLine.cpp @@ -0,0 +1,145 @@ +//===-- OptionValueFileColonLine.cpp---------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Interpreter/OptionValueFileColonLine.h" + +#include "lldb/DataFormatters/FormatManager.h" +#include "lldb/Interpreter/CommandCompletions.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Utility/Args.h" +#include "lldb/Utility/State.h" + +using namespace lldb; +using namespace lldb_private; + +// This is an OptionValue for parsing file:line:column specifications. +// I set the completer to "source file" which isn't quite right, but we can +// only usefully complete in the file name part of it so it should be good +// enough. +OptionValueFileColonLine::OptionValueFileColonLine() + : OptionValue(), m_file_spec(), m_line_number(LLDB_INVALID_LINE_NUMBER), + m_column_number(LLDB_INVALID_COLUMN_NUMBER), + m_completion_mask(CommandCompletions::eSourceFileCompletion) {} + +OptionValueFileColonLine::OptionValueFileColonLine(llvm::StringRef input) + : OptionValue(), m_file_spec(), m_line_number(LLDB_INVALID_LINE_NUMBER), + m_column_number(LLDB_INVALID_COLUMN_NUMBER), + m_completion_mask(CommandCompletions::eSourceFileCompletion) { + SetValueFromString(input, eVarSetOperationAssign); +} + +void OptionValueFileColonLine::DumpValue(const ExecutionContext *exe_ctx, + Stream &strm, uint32_t dump_mask) { + if (dump_mask & eDumpOptionType) + strm.Printf("(%s)", GetTypeAsCString()); + if (dump_mask & eDumpOptionValue) { + if (dump_mask & eDumpOptionType) + strm.PutCString(" = "); + + if (m_file_spec) + strm << '"' << m_file_spec.GetPath().c_str() << '"'; + if (m_line_number != LLDB_INVALID_LINE_NUMBER) + strm.Printf(":%d", m_line_number); + if (m_column_number != LLDB_INVALID_COLUMN_NUMBER) + strm.Printf(":%d", m_column_number); + } +} + +Status OptionValueFileColonLine::SetValueFromString(llvm::StringRef value, + VarSetOperationType op) { + Status error; + switch (op) { + case eVarSetOperationClear: + Clear(); + NotifyValueChanged(); + break; + + case eVarSetOperationReplace: + case eVarSetOperationAssign: + if (value.size() > 0) { + // This is in the form filename:linenumber:column. + // I wish we could use filename:linenumber.column, that would make the + // parsing unambiguous and so much easier... + // But clang & gcc both print the output with two : so we're stuck with + // the two colons. Practically, the only actual ambiguity this introduces + // is with files like "foo:10", which doesn't seem terribly likely. + + // Providing the column is optional, so the input value might have one or + // two colons. First pick off the last colon separated piece. + // It has to be there, since the line number is required: + llvm::StringRef last_piece; + llvm::StringRef left_of_last_piece; + + std::tie(left_of_last_piece, last_piece) = value.rsplit(':'); + if (last_piece.empty()) { + error.SetErrorStringWithFormat("Line specifier must include file and " + "line: '%s'", + value.str().c_str()); + return error; + } + + // Now see if there's another colon and if so pull out the middle piece: + // Then check whether the middle piece is an integer. If it is, then it + // was the line number, and if it isn't we're going to assume that there + // was a colon in the filename (see note at the beginning of the function) + // and ignore it. + llvm::StringRef file_name; + llvm::StringRef middle_piece; + + std::tie(file_name, middle_piece) = left_of_last_piece.rsplit(':'); + if (middle_piece.empty() || !llvm::to_integer(middle_piece, + m_line_number)) { + // The middle piece was empty or not an integer, so there were only two + // legit pieces; our original division was right. Reassign the file + // name and pull out the line number: + file_name = left_of_last_piece; + if (!llvm::to_integer(last_piece, m_line_number)) { + error.SetErrorStringWithFormat("Bad line number value '%s' in: '%s'", + last_piece.str().c_str(), + value.str().c_str()); + return error; + } + } else { + // There were three pieces, and we've got the line number. So now + // we just need to check the column number which was the last peice. + if (!llvm::to_integer(last_piece, m_column_number)) { + error.SetErrorStringWithFormat("Bad column value '%s' in: '%s'", + last_piece.str().c_str(), + value.str().c_str()); + return error; + } + } + + m_value_was_set = true; + m_file_spec.SetFile(file_name, FileSpec::Style::native); + NotifyValueChanged(); + } else { + error.SetErrorString("invalid value string"); + } + break; + + case eVarSetOperationInsertBefore: + case eVarSetOperationInsertAfter: + case eVarSetOperationRemove: + case eVarSetOperationAppend: + case eVarSetOperationInvalid: + error = OptionValue::SetValueFromString(value, op); + break; + } + return error; +} + +lldb::OptionValueSP OptionValueFileColonLine::DeepCopy() const { + return OptionValueSP(new OptionValueFileColonLine(*this)); +} + +void OptionValueFileColonLine::AutoComplete(CommandInterpreter &interpreter, + CompletionRequest &request) { + CommandCompletions::InvokeCommonCompletionCallbacks( + interpreter, m_completion_mask, request, nullptr); +} diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionValueFileSpec.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionValueFileSpec.cpp index 15acb7e5e5b0..a03fd55d0385 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionValueFileSpec.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionValueFileSpec.cpp @@ -64,13 +64,6 @@ Status OptionValueFileSpec::SetValueFromString(llvm::StringRef value, case eVarSetOperationReplace: case eVarSetOperationAssign: if (value.size() > 0) { - // The setting value may have whitespace, double-quotes, or single-quotes - // around the file path to indicate that internal spaces are not word - // breaks. Strip off any ws & quotes from the start and end of the file - // path - we aren't doing any word // breaking here so the quoting is - // unnecessary. NB this will cause a problem if someone tries to specify - // a file path that legitimately begins or ends with a " or ' character, - // or whitespace. value = value.trim("\"' \t"); m_value_was_set = true; m_current_value.SetFile(value.str(), FileSpec::Style::native); diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionValueFormatEntity.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionValueFormatEntity.cpp index 6b36bd575186..509a21752e48 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionValueFormatEntity.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionValueFormatEntity.cpp @@ -29,11 +29,10 @@ OptionValueFormatEntity::OptionValueFormatEntity(const char *default_format) } } -bool OptionValueFormatEntity::Clear() { +void OptionValueFormatEntity::Clear() { m_current_entry = m_default_entry; m_current_format = m_default_format; m_value_was_set = false; - return true; } static void EscapeBackticks(llvm::StringRef str, std::string &dst) { @@ -85,7 +84,7 @@ Status OptionValueFormatEntity::SetValueFromString(llvm::StringRef value_str, if (first_char == '"' || first_char == '\'') { const size_t trimmed_len = trimmed_value_str.size(); if (trimmed_len == 1 || value_str[trimmed_len - 1] != first_char) { - error.SetErrorStringWithFormat("mismatched quotes"); + error.SetErrorString("mismatched quotes"); return error; } value_str = trimmed_value_str.substr(1, trimmed_len - 2); diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionValueProperties.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionValueProperties.cpp index 24cda056977e..6c4e77f614f9 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionValueProperties.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionValueProperties.cpp @@ -147,38 +147,6 @@ OptionValueProperties::GetSubValue(const ExecutionContext *exe_ctx, } return return_val_sp; } - case '{': - // Predicate matching for predicates like - // "<setting-name>{<predicate>}" - // strings are parsed by the current OptionValueProperties subclass to mean - // whatever they want to. For instance a subclass of OptionValueProperties - // for a lldb_private::Target might implement: "target.run- - // args{arch==i386}" -- only set run args if the arch is i386 "target - // .run-args{path=/tmp/a/b/c/a.out}" -- only set run args if the path - // matches "target.run-args{basename==test&&arch==x86_64}" -- only set run - // args if executable basename is "test" and arch is "x86_64" - if (sub_name[1]) { - llvm::StringRef predicate_start = sub_name.drop_front(); - size_t pos = predicate_start.find('}'); - if (pos != llvm::StringRef::npos) { - auto predicate = predicate_start.take_front(pos); - auto rest = predicate_start.drop_front(pos); - if (PredicateMatches(exe_ctx, predicate)) { - if (!rest.empty()) { - // Still more subvalue string to evaluate - return value_sp->GetSubValue(exe_ctx, rest, - will_modify, error); - } else { - // We have a match! - break; - } - } - } - } - // Predicate didn't match or wasn't correctly formed - value_sp.reset(); - break; - case '[': // Array or dictionary access for subvalues like: "[12]" -- access // 12th array element "['hello']" -- dictionary access of key named hello @@ -517,11 +485,10 @@ bool OptionValueProperties::SetPropertyAtIndexAsUInt64( return false; } -bool OptionValueProperties::Clear() { +void OptionValueProperties::Clear() { const size_t num_properties = m_properties.size(); for (size_t i = 0; i < num_properties; ++i) m_properties[i].GetValue()->Clear(); - return true; } Status OptionValueProperties::SetValueFromString(llvm::StringRef value, diff --git a/contrib/llvm-project/lldb/source/Interpreter/Options.cpp b/contrib/llvm-project/lldb/source/Interpreter/Options.cpp index c14b6b6ce66a..9ecc9e229e0e 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/Options.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/Options.cpp @@ -223,7 +223,7 @@ Option *Options::GetLongOptions() { std::map<int, uint32_t>::const_iterator pos = option_seen.find(short_opt); StreamString strm; - if (isprint8(short_opt)) + if (defs[i].HasShortOption()) Host::SystemLog(Host::eSystemLogError, "option[%u] --%s has a short option -%c that " "conflicts with option[%u] --%s, short option won't " @@ -355,9 +355,7 @@ enum OptionDisplayType { static bool PrintOption(const OptionDefinition &opt_def, OptionDisplayType display_type, const char *header, const char *footer, bool show_optional, Stream &strm) { - const bool has_short_option = isprint8(opt_def.short_option) != 0; - - if (display_type == eDisplayShortOption && !has_short_option) + if (display_type == eDisplayShortOption && !opt_def.HasShortOption()) return false; if (header && header[0]) @@ -366,7 +364,7 @@ static bool PrintOption(const OptionDefinition &opt_def, if (show_optional && !opt_def.required) strm.PutChar('['); const bool show_short_option = - has_short_option && display_type != eDisplayLongOption; + opt_def.HasShortOption() && display_type != eDisplayLongOption; if (show_short_option) strm.Printf("-%c", opt_def.short_option); else @@ -445,7 +443,7 @@ void Options::GenerateOptionUsage(Stream &strm, CommandObject *cmd, std::set<int> options; std::set<int>::const_iterator options_pos, options_end; for (auto &def : opt_defs) { - if (def.usage_mask & opt_set_mask && isprint8(def.short_option)) { + if (def.usage_mask & opt_set_mask && def.HasShortOption()) { // Add current option to the end of out_stream. if (def.required && def.option_has_arg == OptionParser::eNoArgument) { @@ -470,7 +468,7 @@ void Options::GenerateOptionUsage(Stream &strm, CommandObject *cmd, options.clear(); for (auto &def : opt_defs) { - if (def.usage_mask & opt_set_mask && isprint8(def.short_option)) { + if (def.usage_mask & opt_set_mask && def.HasShortOption()) { // Add current option to the end of out_stream. if (!def.required && @@ -498,7 +496,7 @@ void Options::GenerateOptionUsage(Stream &strm, CommandObject *cmd, // First go through and print the required options (list them up front). for (auto &def : opt_defs) { - if (def.usage_mask & opt_set_mask && isprint8(def.short_option)) { + if (def.usage_mask & opt_set_mask && def.HasShortOption()) { if (def.required && def.option_has_arg != OptionParser::eNoArgument) PrintOption(def, eDisplayBestOption, " ", nullptr, true, strm); } @@ -579,7 +577,7 @@ void Options::GenerateOptionUsage(Stream &strm, CommandObject *cmd, arg_name_str.Printf("<%s>", CommandObject::GetArgumentName(arg_type)); strm.Indent(); - if (opt_defs[i].short_option && isprint8(opt_defs[i].short_option)) { + if (opt_defs[i].short_option && opt_defs[i].HasShortOption()) { PrintOption(opt_defs[i], eDisplayShortOption, nullptr, nullptr, false, strm); PrintOption(opt_defs[i], eDisplayLongOption, " ( ", " )", false, strm); @@ -1308,7 +1306,7 @@ llvm::Expected<Args> Options::Parse(const Args &args, &long_options_index); if (val == ':') { - error.SetErrorStringWithFormat("last option requires an argument"); + error.SetErrorString("last option requires an argument"); break; } @@ -1317,7 +1315,7 @@ llvm::Expected<Args> Options::Parse(const Args &args, // Did we get an error? if (val == '?') { - error.SetErrorStringWithFormat("unknown or ambiguous option"); + error.SetErrorString("unknown or ambiguous option"); break; } // The option auto-set itself diff --git a/contrib/llvm-project/lldb/source/Interpreter/Property.cpp b/contrib/llvm-project/lldb/source/Interpreter/Property.cpp index 923811249853..a02497662ff5 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/Property.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/Property.cpp @@ -99,6 +99,12 @@ Property::Property(const PropertyDefinition &definition) } break; + case OptionValue::eTypeFileLineColumn: + // "definition.default_uint_value" is not used for a + // OptionValue::eTypeFileSpecList + m_value_sp = std::make_shared<OptionValueFileColonLine>(); + break; + case OptionValue::eTypeFileSpec: { // "definition.default_uint_value" represents if the // "definition.default_cstr_value" should be resolved or not diff --git a/contrib/llvm-project/lldb/source/Interpreter/ScriptInterpreter.cpp b/contrib/llvm-project/lldb/source/Interpreter/ScriptInterpreter.cpp index 86620449f2f4..013ed6aecb80 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/ScriptInterpreter.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/ScriptInterpreter.cpp @@ -47,9 +47,11 @@ void ScriptInterpreter::CollectDataForWatchpointCommandCallback( "This script interpreter does not support watchpoint callbacks."); } -bool ScriptInterpreter::LoadScriptingModule( - const char *filename, bool init_session, lldb_private::Status &error, - StructuredData::ObjectSP *module_sp) { +bool ScriptInterpreter::LoadScriptingModule(const char *filename, + bool init_session, + lldb_private::Status &error, + StructuredData::ObjectSP *module_sp, + FileSpec extra_search_dir) { error.SetErrorString( "This script interpreter does not support importing modules."); return false; |