diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-09-02 21:17:18 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-12-08 17:34:50 +0000 |
commit | 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e (patch) | |
tree | 62f873df87c7c675557a179e0c4c83fe9f3087bc /contrib/llvm-project/lldb/source/Commands | |
parent | cf037972ea8863e2bab7461d77345367d2c1e054 (diff) | |
parent | 7fa27ce4a07f19b07799a767fc29416f3b625afb (diff) |
Diffstat (limited to 'contrib/llvm-project/lldb/source/Commands')
30 files changed, 1401 insertions, 867 deletions
diff --git a/contrib/llvm-project/lldb/source/Commands/CommandCompletions.cpp b/contrib/llvm-project/lldb/source/Commands/CommandCompletions.cpp index ae1ee1fdd30b..4d7e3d7f2497 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandCompletions.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandCompletions.cpp @@ -10,7 +10,6 @@ #include "llvm/ADT/StringSet.h" #include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Core/FileSpecList.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/DataFormatters/DataVisualization.h" @@ -27,6 +26,7 @@ #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/FileSpecList.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/TildeExpressionResolver.h" @@ -54,37 +54,41 @@ bool CommandCompletions::InvokeCommonCompletionCallbacks( bool handled = false; const CommonCompletionElement common_completions[] = { - {eSourceFileCompletion, CommandCompletions::SourceFiles}, - {eDiskFileCompletion, CommandCompletions::DiskFiles}, - {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories}, - {eSymbolCompletion, CommandCompletions::Symbols}, - {eModuleCompletion, CommandCompletions::Modules}, - {eModuleUUIDCompletion, CommandCompletions::ModuleUUIDs}, - {eSettingsNameCompletion, CommandCompletions::SettingsNames}, - {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames}, - {eArchitectureCompletion, CommandCompletions::ArchitectureNames}, - {eVariablePathCompletion, CommandCompletions::VariablePath}, - {eRegisterCompletion, CommandCompletions::Registers}, - {eBreakpointCompletion, CommandCompletions::Breakpoints}, - {eProcessPluginCompletion, CommandCompletions::ProcessPluginNames}, - {eDisassemblyFlavorCompletion, CommandCompletions::DisassemblyFlavors}, - {eTypeLanguageCompletion, CommandCompletions::TypeLanguages}, - {eFrameIndexCompletion, CommandCompletions::FrameIndexes}, - {eStopHookIDCompletion, CommandCompletions::StopHookIDs}, - {eThreadIndexCompletion, CommandCompletions::ThreadIndexes}, - {eWatchPointIDCompletion, CommandCompletions::WatchPointIDs}, - {eBreakpointNameCompletion, CommandCompletions::BreakpointNames}, - {eProcessIDCompletion, CommandCompletions::ProcessIDs}, - {eProcessNameCompletion, CommandCompletions::ProcessNames}, - {eRemoteDiskFileCompletion, CommandCompletions::RemoteDiskFiles}, - {eRemoteDiskDirectoryCompletion, + {lldb::eSourceFileCompletion, CommandCompletions::SourceFiles}, + {lldb::eDiskFileCompletion, CommandCompletions::DiskFiles}, + {lldb::eDiskDirectoryCompletion, CommandCompletions::DiskDirectories}, + {lldb::eSymbolCompletion, CommandCompletions::Symbols}, + {lldb::eModuleCompletion, CommandCompletions::Modules}, + {lldb::eModuleUUIDCompletion, CommandCompletions::ModuleUUIDs}, + {lldb::eSettingsNameCompletion, CommandCompletions::SettingsNames}, + {lldb::ePlatformPluginCompletion, + CommandCompletions::PlatformPluginNames}, + {lldb::eArchitectureCompletion, CommandCompletions::ArchitectureNames}, + {lldb::eVariablePathCompletion, CommandCompletions::VariablePath}, + {lldb::eRegisterCompletion, CommandCompletions::Registers}, + {lldb::eBreakpointCompletion, CommandCompletions::Breakpoints}, + {lldb::eProcessPluginCompletion, CommandCompletions::ProcessPluginNames}, + {lldb::eDisassemblyFlavorCompletion, + CommandCompletions::DisassemblyFlavors}, + {lldb::eTypeLanguageCompletion, CommandCompletions::TypeLanguages}, + {lldb::eFrameIndexCompletion, CommandCompletions::FrameIndexes}, + {lldb::eStopHookIDCompletion, CommandCompletions::StopHookIDs}, + {lldb::eThreadIndexCompletion, CommandCompletions::ThreadIndexes}, + {lldb::eWatchpointIDCompletion, CommandCompletions::WatchPointIDs}, + {lldb::eBreakpointNameCompletion, CommandCompletions::BreakpointNames}, + {lldb::eProcessIDCompletion, CommandCompletions::ProcessIDs}, + {lldb::eProcessNameCompletion, CommandCompletions::ProcessNames}, + {lldb::eRemoteDiskFileCompletion, CommandCompletions::RemoteDiskFiles}, + {lldb::eRemoteDiskDirectoryCompletion, CommandCompletions::RemoteDiskDirectories}, - {eTypeCategoryNameCompletion, CommandCompletions::TypeCategoryNames}, - {eNoCompletion, nullptr} // This one has to be last in the list. + {lldb::eTypeCategoryNameCompletion, + CommandCompletions::TypeCategoryNames}, + {lldb::CompletionType::eNoCompletion, + nullptr} // This one has to be last in the list. }; for (int i = 0;; i++) { - if (common_completions[i].type == eNoCompletion) + if (common_completions[i].type == lldb::eNoCompletion) break; else if ((common_completions[i].type & completion_mask) == common_completions[i].type && @@ -220,18 +224,15 @@ public: function_options.include_inlines = true; context.module_sp->FindFunctions(m_regex, function_options, sc_list); - SymbolContext sc; // Now add the functions & symbols to the list - only add if unique: - for (uint32_t i = 0; i < sc_list.GetSize(); i++) { - if (sc_list.GetContextAtIndex(i, sc)) { - ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled); - // Ensure that the function name matches the regex. This is more than - // a sanity check. It is possible that the demangled function name - // does not start with the prefix, for example when it's in an - // anonymous namespace. - if (!func_name.IsEmpty() && m_regex.Execute(func_name.GetStringRef())) - m_match_set.insert(func_name); - } + for (const SymbolContext &sc : sc_list) { + ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled); + // Ensure that the function name matches the regex. This is more than + // a sanity check. It is possible that the demangled function name + // does not start with the prefix, for example when it's in an + // anonymous namespace. + if (!func_name.IsEmpty() && m_regex.Execute(func_name.GetStringRef())) + m_match_set.insert(func_name); } } return Searcher::eCallbackReturnContinue; @@ -380,6 +381,8 @@ static void DiskFilesOrDirectories(const llvm::Twine &partial_name, Storage.append(RemainderDir); } SearchDir = Storage; + } else if (CompletionBuffer == path::root_directory(CompletionBuffer)) { + SearchDir = CompletionBuffer; } else { SearchDir = path::parent_path(CompletionBuffer); } @@ -389,9 +392,11 @@ static void DiskFilesOrDirectories(const llvm::Twine &partial_name, PartialItem = path::filename(CompletionBuffer); // path::filename() will return "." when the passed path ends with a - // directory separator. We have to filter those out, but only when the - // "." doesn't come from the completion request itself. - if (PartialItem == "." && path::is_separator(CompletionBuffer.back())) + // directory separator or the separator when passed the disk root directory. + // We have to filter those out, but only when the "." doesn't come from the + // completion request itself. + if ((PartialItem == "." || PartialItem == path::get_separator()) && + path::is_separator(CompletionBuffer.back())) PartialItem = llvm::StringRef(); if (SearchDir.empty()) { @@ -606,6 +611,9 @@ void CommandCompletions::Registers(CommandInterpreter &interpreter, RegisterContext *reg_ctx = interpreter.GetExecutionContext().GetRegisterContext(); + if (!reg_ctx) + return; + const size_t reg_num = reg_ctx->GetRegisterCount(); for (size_t reg_idx = 0; reg_idx < reg_num; ++reg_idx) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_idx); @@ -721,10 +729,14 @@ void CommandCompletions::FrameIndexes(CommandInterpreter &interpreter, return; lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP(); + Debugger &dbg = interpreter.GetDebugger(); const uint32_t frame_num = thread_sp->GetStackFrameCount(); for (uint32_t i = 0; i < frame_num; ++i) { lldb::StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(i); StreamString strm; + // Dumping frames can be slow, allow interruption. + if (INTERRUPT_REQUESTED(dbg, "Interrupted in frame completion")) + break; frame_sp->Dump(&strm, false, true); request.TryCompleteCurrentArg(std::to_string(i), strm.GetString()); } @@ -745,7 +757,7 @@ void CommandCompletions::StopHookIDs(CommandInterpreter &interpreter, // neater. strm.SetIndentLevel(11); const Target::StopHookSP stophook_sp = target_sp->GetStopHookAtIndex(idx); - stophook_sp->GetDescription(&strm, lldb::eDescriptionLevelInitial); + stophook_sp->GetDescription(strm, lldb::eDescriptionLevelInitial); request.TryCompleteCurrentArg(std::to_string(stophook_sp->GetID()), strm.GetString()); } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpoint.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpoint.cpp index 8c31630231b5..327dae4fd2af 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpoint.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpoint.cpp @@ -828,9 +828,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr); } Options *GetOptions() override { return &m_options; } @@ -902,9 +901,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr); } protected: @@ -1017,9 +1015,8 @@ the second re-enables the first location."); void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr); } protected: @@ -1394,9 +1391,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr); } Options *GetOptions() override { return &m_options; } @@ -1739,7 +1735,8 @@ protected: // check the error: BreakpointSP bp_sp; if (m_bp_id.m_breakpoint.OptionWasSet()) { - lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value(); + lldb::break_id_t bp_id = + m_bp_id.m_breakpoint.GetValueAs<uint64_t>().value_or(0); bp_sp = target.GetBreakpointByID(bp_id); if (!bp_sp) { result.AppendErrorWithFormatv("Could not find specified breakpoint {0}", @@ -1755,7 +1752,10 @@ protected: if (!bp_name) continue; if (m_bp_id.m_help_string.OptionWasSet()) - bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str()); + bp_name->SetHelp(m_bp_id.m_help_string.GetValueAs<llvm::StringRef>() + .value_or("") + .str() + .c_str()); if (bp_sp) target.ConfigureBreakpointName(*bp_name, bp_sp->GetOptions(), @@ -1799,9 +1799,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr); } Options *GetOptions() override { return &m_option_group; } @@ -1883,9 +1882,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr); } Options *GetOptions() override { return &m_option_group; } @@ -2199,9 +2197,8 @@ public: switch (GetDefinitions()[opt_defs_index].short_option) { case 'f': - CommandCompletions::InvokeCommonCompletionCallbacks( - interpreter, CommandCompletions::eDiskFileCompletion, request, - nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + interpreter, lldb::eDiskFileCompletion, request, nullptr); break; case 'N': @@ -2339,9 +2336,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr); } Options *GetOptions() override { return &m_options; } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectCommands.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectCommands.cpp index 7a5755d8d235..656ace223b5f 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectCommands.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectCommands.cpp @@ -66,9 +66,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); } Options *GetOptions() override { return &m_options; } @@ -880,7 +879,7 @@ protected: Status error; auto name = command[0].ref(); m_regex_cmd_up = std::make_unique<CommandObjectRegexCommand>( - m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0, + m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 0, true); if (argc == 1) { @@ -1080,9 +1079,10 @@ class CommandObjectPythonFunction : public CommandObjectRaw { public: CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name, std::string funct, std::string help, - ScriptedCommandSynchronicity synch) + ScriptedCommandSynchronicity synch, + CompletionType completion_type) : CommandObjectRaw(interpreter, name), m_function_name(funct), - m_synchro(synch) { + m_synchro(synch), m_completion_type(completion_type) { if (!help.empty()) SetHelp(help); else { @@ -1116,6 +1116,15 @@ public: return CommandObjectRaw::GetHelpLong(); } + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), m_completion_type, request, nullptr); + } + + bool WantsCompletion() override { return true; } + protected: bool DoExecute(llvm::StringRef raw_command_line, CommandReturnObject &result) override { @@ -1146,6 +1155,7 @@ private: std::string m_function_name; ScriptedCommandSynchronicity m_synchro; bool m_fetched_help_long = false; + CompletionType m_completion_type = eNoCompletion; }; class CommandObjectScriptingObject : public CommandObjectRaw { @@ -1153,10 +1163,11 @@ public: CommandObjectScriptingObject(CommandInterpreter &interpreter, std::string name, StructuredData::GenericSP cmd_obj_sp, - ScriptedCommandSynchronicity synch) + ScriptedCommandSynchronicity synch, + CompletionType completion_type) : CommandObjectRaw(interpreter, name), m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false), - m_fetched_help_long(false) { + m_fetched_help_long(false), m_completion_type(completion_type) { StreamString stream; stream.Printf("For more information run 'help %s'", name.c_str()); SetHelp(stream.GetString()); @@ -1166,6 +1177,15 @@ public: ~CommandObjectScriptingObject() override = default; + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), m_completion_type, request, nullptr); + } + + bool WantsCompletion() override { return true; } + bool IsRemovable() const override { return true; } ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } @@ -1232,6 +1252,7 @@ private: ScriptedCommandSynchronicity m_synchro; bool m_fetched_help_short : 1; bool m_fetched_help_long : 1; + CompletionType m_completion_type = eNoCompletion; }; // CommandObjectCommandsScriptImport @@ -1263,9 +1284,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); } Options *GetOptions() override { return &m_options; } @@ -1439,6 +1459,18 @@ protected: "unrecognized value for synchronicity '%s'", option_arg.str().c_str()); break; + case 'C': { + Status error; + OptionDefinition definition = GetDefinitions()[option_idx]; + lldb::CompletionType completion_type = + static_cast<lldb::CompletionType>(OptionArgParser::ToOptionEnum( + option_arg, definition.enum_values, eNoCompletion, error)); + if (!error.Success()) + error.SetErrorStringWithFormat( + "unrecognized value for command completion type '%s'", + option_arg.str().c_str()); + m_completion_type = completion_type; + } break; default: llvm_unreachable("Unimplemented option"); } @@ -1450,6 +1482,7 @@ protected: m_class_name.clear(); m_funct_name.clear(); m_short_help.clear(); + m_completion_type = eNoCompletion; m_overwrite_lazy = eLazyBoolCalculate; m_synchronicity = eScriptedCommandSynchronicitySynchronous; } @@ -1466,6 +1499,7 @@ protected: LazyBool m_overwrite_lazy = eLazyBoolCalculate; ScriptedCommandSynchronicity m_synchronicity = eScriptedCommandSynchronicitySynchronous; + CompletionType m_completion_type = eNoCompletion; }; void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { @@ -1496,7 +1530,7 @@ protected: CommandObjectSP command_obj_sp(new CommandObjectPythonFunction( m_interpreter, m_cmd_name, funct_name_str, m_short_help, - m_synchronicity)); + m_synchronicity, m_completion_type)); if (!m_container) { Status error = m_interpreter.AddUserCommand( m_cmd_name, command_obj_sp, m_overwrite); @@ -1577,6 +1611,7 @@ protected: m_short_help.assign(m_options.m_short_help); m_synchronicity = m_options.m_synchronicity; + m_completion_type = m_options.m_completion_type; // Handle the case where we prompt for the script code first: if (m_options.m_class_name.empty() && m_options.m_funct_name.empty()) { @@ -1589,7 +1624,7 @@ protected: if (m_options.m_class_name.empty()) { new_cmd_sp.reset(new CommandObjectPythonFunction( m_interpreter, m_cmd_name, m_options.m_funct_name, - m_options.m_short_help, m_synchronicity)); + m_options.m_short_help, m_synchronicity, m_completion_type)); } else { ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); if (!interpreter) { @@ -1600,12 +1635,14 @@ protected: auto cmd_obj_sp = interpreter->CreateScriptCommandObject( m_options.m_class_name.c_str()); if (!cmd_obj_sp) { - result.AppendError("cannot create helper object"); + result.AppendErrorWithFormatv("cannot create helper object for: " + "'{0}'", m_options.m_class_name); return false; } new_cmd_sp.reset(new CommandObjectScriptingObject( - m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity)); + m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity, + m_completion_type)); } // Assume we're going to succeed... @@ -1633,6 +1670,7 @@ protected: bool m_overwrite = false; ScriptedCommandSynchronicity m_synchronicity = eScriptedCommandSynchronicitySynchronous; + CompletionType m_completion_type = eNoCompletion; }; // CommandObjectCommandsScriptList @@ -1705,8 +1743,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request, - opt_element_vector); + lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs( + m_interpreter, request, opt_element_vector); } protected: @@ -1856,8 +1894,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request, - opt_element_vector); + lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs( + m_interpreter, request, opt_element_vector); } protected: @@ -1996,8 +2034,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request, - opt_element_vector); + lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs( + m_interpreter, request, opt_element_vector); } protected: diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.cpp index e15e723de588..b2b7f201a5ad 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.cpp @@ -9,13 +9,21 @@ #include "CommandObjectDWIMPrint.h" #include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/DumpValueObjectOptions.h" +#include "lldb/Expression/ExpressionVariable.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/OptionGroupFormat.h" +#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" #include "lldb/Target/StackFrame.h" #include "lldb/Utility/ConstString.h" +#include "lldb/lldb-defines.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-forward.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/FormatVariadic.h" using namespace llvm; using namespace lldb; @@ -26,12 +34,33 @@ CommandObjectDWIMPrint::CommandObjectDWIMPrint(CommandInterpreter &interpreter) "Print a variable or expression.", "dwim-print [<variable-name> | <expression>]", eCommandProcessMustBePaused | eCommandTryTargetAPILock) { + + CommandArgumentData var_name_arg(eArgTypeVarName, eArgRepeatPlain); + m_arguments.push_back({var_name_arg}); + + m_option_group.Append(&m_format_options, + OptionGroupFormat::OPTION_GROUP_FORMAT | + OptionGroupFormat::OPTION_GROUP_GDB_FMT, + LLDB_OPT_SET_1); + StringRef exclude_expr_options[] = {"debug", "top-level"}; + m_option_group.Append(&m_expr_options, exclude_expr_options); + m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Finalize(); +} + +Options *CommandObjectDWIMPrint::GetOptions() { return &m_option_group; } + +void CommandObjectDWIMPrint::HandleArgumentCompletion( + CompletionRequest &request, OptionElementVector &opt_element_vector) { + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eVariablePathCompletion, request, nullptr); } -bool CommandObjectDWIMPrint::DoExecute(StringRef expr, +bool CommandObjectDWIMPrint::DoExecute(StringRef command, CommandReturnObject &result) { - // Ignore leading and trailing whitespace. - expr = expr.trim(); + m_option_group.NotifyOptionParsingStarting(&m_exe_ctx); + OptionsWithRaw args{command}; + StringRef expr = args.GetRawPart(); if (expr.empty()) { result.AppendErrorWithFormatv("'{0}' takes a variable or expression", @@ -39,15 +68,53 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef expr, return false; } + if (args.HasArgs()) { + if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, + m_exe_ctx)) + return false; + } + + // If the user has not specified, default to disabling persistent results. + if (m_expr_options.suppress_persistent_result == eLazyBoolCalculate) + m_expr_options.suppress_persistent_result = eLazyBoolYes; + bool suppress_result = m_expr_options.ShouldSuppressResult(m_varobj_options); + auto verbosity = GetDebugger().GetDWIMPrintVerbosity(); + Target *target_ptr = m_exe_ctx.GetTargetPtr(); + // Fallback to the dummy target, which can allow for expression evaluation. + Target &target = target_ptr ? *target_ptr : GetDummyTarget(); + + EvaluateExpressionOptions eval_options = + m_expr_options.GetEvaluateExpressionOptions(target, m_varobj_options); + // This command manually removes the result variable, make sure expression + // evaluation doesn't do it first. + eval_options.SetSuppressPersistentResult(false); + + DumpValueObjectOptions dump_options = m_varobj_options.GetAsDumpOptions( + m_expr_options.m_verbosity, m_format_options.GetFormat()); + dump_options.SetHideRootName(suppress_result); + + StackFrame *frame = m_exe_ctx.GetFramePtr(); + // First, try `expr` as the name of a frame variable. - if (StackFrame *frame = m_exe_ctx.GetFramePtr()) { + if (frame) { auto valobj_sp = frame->FindVariable(ConstString(expr)); if (valobj_sp && valobj_sp->GetError().Success()) { - if (verbosity == eDWIMPrintVerbosityFull) - result.AppendMessageWithFormatv("note: ran `frame variable {0}`", expr); - valobj_sp->Dump(result.GetOutputStream()); + if (!suppress_result) { + if (auto persisted_valobj = valobj_sp->Persist()) + valobj_sp = persisted_valobj; + } + + if (verbosity == eDWIMPrintVerbosityFull) { + StringRef flags; + if (args.HasArgs()) + flags = args.GetArgString(); + result.AppendMessageWithFormatv("note: ran `frame variable {0}{1}`", + flags, expr); + } + + valobj_sp->Dump(result.GetOutputStream(), dump_options); result.SetStatus(eReturnStatusSuccessFinishResult); return true; } @@ -55,17 +122,31 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef expr, // Second, also lastly, try `expr` as a source expression to evaluate. { - Target *target_ptr = m_exe_ctx.GetTargetPtr(); - // Fallback to the dummy target, which can allow for expression evaluation. - Target &target = target_ptr ? *target_ptr : GetDummyTarget(); - auto *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); ValueObjectSP valobj_sp; - if (target.EvaluateExpression(expr, exe_scope, valobj_sp) == - eExpressionCompleted) { - if (verbosity != eDWIMPrintVerbosityNone) - result.AppendMessageWithFormatv("note: ran `expression -- {0}`", expr); - valobj_sp->Dump(result.GetOutputStream()); + ExpressionResults expr_result = + target.EvaluateExpression(expr, exe_scope, valobj_sp, eval_options); + if (expr_result == eExpressionCompleted) { + if (verbosity != eDWIMPrintVerbosityNone) { + StringRef flags; + if (args.HasArgs()) + flags = args.GetArgStringWithDelimiter(); + result.AppendMessageWithFormatv("note: ran `expression {0}{1}`", flags, + expr); + } + + if (valobj_sp->GetError().GetError() != UserExpression::kNoResult) + valobj_sp->Dump(result.GetOutputStream(), dump_options); + + if (suppress_result) + if (auto result_var_sp = + target.GetPersistentVariable(valobj_sp->GetName())) { + auto language = valobj_sp->GetPreferredDisplayLanguage(); + if (auto *persistent_state = + target.GetPersistentExpressionStateForLanguage(language)) + persistent_state->RemovePersistentVariable(result_var_sp); + } + result.SetStatus(eReturnStatusSuccessFinishResult); return true; } else { diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.h index 1284949aed3a..3fc6c01d4729 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.h +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.h @@ -9,7 +9,11 @@ #ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTDWIMPRINT_H #define LLDB_SOURCE_COMMANDS_COMMANDOBJECTDWIMPRINT_H +#include "CommandObjectExpression.h" #include "lldb/Interpreter/CommandObject.h" +#include "lldb/Interpreter/OptionGroupFormat.h" +#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" +#include "lldb/Interpreter/OptionValueFormat.h" namespace lldb_private { @@ -31,8 +35,21 @@ public: ~CommandObjectDWIMPrint() override = default; + Options *GetOptions() override; + + bool WantsCompletion() override { return true; } + + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override; + private: bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override; + + OptionGroupOptions m_option_group; + OptionGroupFormat m_format_options = lldb::eFormatDefault; + OptionGroupValueObjectDisplay m_varobj_options; + CommandObjectExpression::CommandOptions m_expr_options; }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.cpp index 9cce009f853e..e7e6e3820b99 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.cpp @@ -10,6 +10,7 @@ #include "CommandObjectExpression.h" #include "lldb/Core/Debugger.h" +#include "lldb/Expression/ExpressionVariable.h" #include "lldb/Expression/REPL.h" #include "lldb/Expression/UserExpression.h" #include "lldb/Host/OptionParser.h" @@ -21,6 +22,8 @@ #include "lldb/Target/Process.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-private-enumerations.h" using namespace lldb; using namespace lldb_private; @@ -145,6 +148,19 @@ Status CommandObjectExpression::CommandOptions::SetOptionValue( break; } + case '\x01': { + bool success; + bool persist_result = + OptionArgParser::ToBoolean(option_arg, true, &success); + if (success) + suppress_persistent_result = !persist_result ? eLazyBoolYes : eLazyBoolNo; + else + error.SetErrorStringWithFormat( + "could not convert \"%s\" to a boolean value.", + option_arg.str().c_str()); + break; + } + default: llvm_unreachable("Unimplemented option"); } @@ -173,6 +189,7 @@ void CommandObjectExpression::CommandOptions::OptionParsingStarting( auto_apply_fixits = eLazyBoolCalculate; top_level = false; allow_jit = true; + suppress_persistent_result = eLazyBoolCalculate; } llvm::ArrayRef<OptionDefinition> @@ -180,6 +197,57 @@ CommandObjectExpression::CommandOptions::GetDefinitions() { return llvm::ArrayRef(g_expression_options); } +EvaluateExpressionOptions +CommandObjectExpression::CommandOptions::GetEvaluateExpressionOptions( + const Target &target, const OptionGroupValueObjectDisplay &display_opts) { + EvaluateExpressionOptions options; + options.SetCoerceToId(display_opts.use_objc); + options.SetUnwindOnError(unwind_on_error); + options.SetIgnoreBreakpoints(ignore_breakpoints); + options.SetKeepInMemory(true); + options.SetUseDynamic(display_opts.use_dynamic); + options.SetTryAllThreads(try_all_threads); + options.SetDebug(debug); + options.SetLanguage(language); + options.SetExecutionPolicy( + allow_jit ? EvaluateExpressionOptions::default_execution_policy + : lldb_private::eExecutionPolicyNever); + + bool auto_apply_fixits; + if (this->auto_apply_fixits == eLazyBoolCalculate) + auto_apply_fixits = target.GetEnableAutoApplyFixIts(); + else + auto_apply_fixits = this->auto_apply_fixits == eLazyBoolYes; + + options.SetAutoApplyFixIts(auto_apply_fixits); + options.SetRetriesWithFixIts(target.GetNumberOfRetriesWithFixits()); + + if (top_level) + options.SetExecutionPolicy(eExecutionPolicyTopLevel); + + // If there is any chance we are going to stop and want to see what went + // wrong with our expression, we should generate debug info + if (!ignore_breakpoints || !unwind_on_error) + options.SetGenerateDebugInfo(true); + + if (timeout > 0) + options.SetTimeout(std::chrono::microseconds(timeout)); + else + options.SetTimeout(std::nullopt); + return options; +} + +bool CommandObjectExpression::CommandOptions::ShouldSuppressResult( + const OptionGroupValueObjectDisplay &display_opts) const { + // Explicitly disabling persistent results takes precedence over the + // m_verbosity/use_objc logic. + if (suppress_persistent_result != eLazyBoolCalculate) + return suppress_persistent_result == eLazyBoolYes; + + return display_opts.use_objc && + m_verbosity == eLanguageRuntimeDescriptionDisplayVerbosityCompact; +} + CommandObjectExpression::CommandObjectExpression( CommandInterpreter &interpreter) : CommandObjectRaw(interpreter, "expression", @@ -342,47 +410,6 @@ CanBeUsedForElementCountPrinting(ValueObject &valobj) { return Status(); } -EvaluateExpressionOptions -CommandObjectExpression::GetEvalOptions(const Target &target) { - EvaluateExpressionOptions options; - options.SetCoerceToId(m_varobj_options.use_objc); - options.SetUnwindOnError(m_command_options.unwind_on_error); - options.SetIgnoreBreakpoints(m_command_options.ignore_breakpoints); - options.SetKeepInMemory(true); - options.SetUseDynamic(m_varobj_options.use_dynamic); - options.SetTryAllThreads(m_command_options.try_all_threads); - options.SetDebug(m_command_options.debug); - options.SetLanguage(m_command_options.language); - options.SetExecutionPolicy( - m_command_options.allow_jit - ? EvaluateExpressionOptions::default_execution_policy - : lldb_private::eExecutionPolicyNever); - - bool auto_apply_fixits; - if (m_command_options.auto_apply_fixits == eLazyBoolCalculate) - auto_apply_fixits = target.GetEnableAutoApplyFixIts(); - else - auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes; - - options.SetAutoApplyFixIts(auto_apply_fixits); - options.SetRetriesWithFixIts(target.GetNumberOfRetriesWithFixits()); - - if (m_command_options.top_level) - options.SetExecutionPolicy(eExecutionPolicyTopLevel); - - // If there is any chance we are going to stop and want to see what went - // wrong with our expression, we should generate debug info - if (!m_command_options.ignore_breakpoints || - !m_command_options.unwind_on_error) - options.SetGenerateDebugInfo(true); - - if (m_command_options.timeout > 0) - options.SetTimeout(std::chrono::microseconds(m_command_options.timeout)); - else - options.SetTimeout(std::nullopt); - return options; -} - bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr, Stream &output_stream, Stream &error_stream, @@ -403,9 +430,14 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr, return false; } - const EvaluateExpressionOptions options = GetEvalOptions(target); + EvaluateExpressionOptions eval_options = + m_command_options.GetEvaluateExpressionOptions(target, m_varobj_options); + // This command manually removes the result variable, make sure expression + // evaluation doesn't do it first. + eval_options.SetSuppressPersistentResult(false); + ExpressionResults success = target.EvaluateExpression( - expr, frame, result_valobj_sp, options, &m_fixed_expression); + expr, frame, result_valobj_sp, eval_options, &m_fixed_expression); // We only tell you about the FixIt if we applied it. The compiler errors // will suggest the FixIt if it parsed. @@ -432,13 +464,25 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr, } } + bool suppress_result = + m_command_options.ShouldSuppressResult(m_varobj_options); + DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions( m_command_options.m_verbosity, format)); + options.SetHideRootName(suppress_result); options.SetVariableFormatDisplayLanguage( result_valobj_sp->GetPreferredDisplayLanguage()); result_valobj_sp->Dump(output_stream, options); + if (suppress_result) + if (auto result_var_sp = + target.GetPersistentVariable(result_valobj_sp->GetName())) { + auto language = result_valobj_sp->GetPreferredDisplayLanguage(); + if (auto *persistent_state = + target.GetPersistentExpressionStateForLanguage(language)) + persistent_state->RemovePersistentVariable(result_var_sp); + } result.SetStatus(eReturnStatusSuccessFinishResult); } } else { diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.h index 1e59cbc14528..b2b8fc73a1ee 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.h +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.h @@ -35,6 +35,15 @@ public: void OptionParsingStarting(ExecutionContext *execution_context) override; + /// Return the appropriate expression options used for evaluating the + /// expression in the given target. + EvaluateExpressionOptions GetEvaluateExpressionOptions( + const Target &target, + const OptionGroupValueObjectDisplay &display_opts); + + bool ShouldSuppressResult( + const OptionGroupValueObjectDisplay &display_opts) const; + bool top_level; bool unwind_on_error; bool ignore_breakpoints; @@ -47,6 +56,7 @@ public: lldb::LanguageType language; LanguageRuntimeDescriptionDisplayVerbosity m_verbosity; LazyBool auto_apply_fixits; + LazyBool suppress_persistent_result; }; CommandObjectExpression(CommandInterpreter &interpreter); @@ -67,10 +77,6 @@ protected: bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override; - /// Return the appropriate expression options used for evaluating the - /// expression in the given target. - EvaluateExpressionOptions GetEvalOptions(const Target &target); - /// Evaluates the given expression. /// \param output_stream The stream to which the evaluation result will be /// printed. diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectFrame.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectFrame.cpp index 4a0d75202797..1390fd8748df 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectFrame.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectFrame.cpp @@ -135,7 +135,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { Thread *thread = m_exe_ctx.GetThreadPtr(); - StackFrameSP frame_sp = thread->GetSelectedFrame(); + StackFrameSP frame_sp = thread->GetSelectedFrame(SelectMostRelevantFrame); ValueObjectSP valobj_sp; @@ -292,9 +292,8 @@ public: if (request.GetCursorIndex() != 0) return; - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eFrameIndexCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eFrameIndexCompletion, request, nullptr); } Options *GetOptions() override { return &m_options; } @@ -308,7 +307,7 @@ protected: uint32_t frame_idx = UINT32_MAX; if (m_options.relative_frame_offset) { // The one and only argument is a signed relative frame index - frame_idx = thread->GetSelectedFrameIndex(); + frame_idx = thread->GetSelectedFrameIndex(SelectMostRelevantFrame); if (frame_idx == UINT32_MAX) frame_idx = 0; @@ -327,21 +326,29 @@ protected: } } else if (*m_options.relative_frame_offset > 0) { // I don't want "up 20" where "20" takes you past the top of the stack - // to produce - // an error, but rather to just go to the top. So I have to count the - // stack here... - const uint32_t num_frames = thread->GetStackFrameCount(); - if (static_cast<int32_t>(num_frames - frame_idx) > - *m_options.relative_frame_offset) - frame_idx += *m_options.relative_frame_offset; + // to produce an error, but rather to just go to the top. OTOH, start + // by seeing if the requested frame exists, in which case we can avoid + // counting the stack here... + const uint32_t frame_requested = frame_idx + + *m_options.relative_frame_offset; + StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_requested); + if (frame_sp) + frame_idx = frame_requested; else { - if (frame_idx == num_frames - 1) { - // If we are already at the top of the stack, just warn and don't - // reset the frame. - result.AppendError("Already at the top of the stack."); - return false; - } else - frame_idx = num_frames - 1; + // The request went past the stack, so handle that case: + const uint32_t num_frames = thread->GetStackFrameCount(); + if (static_cast<int32_t>(num_frames - frame_idx) > + *m_options.relative_frame_offset) + frame_idx += *m_options.relative_frame_offset; + else { + if (frame_idx == num_frames - 1) { + // If we are already at the top of the stack, just warn and don't + // reset the frame. + result.AppendError("Already at the top of the stack."); + return false; + } else + frame_idx = num_frames - 1; + } } } } else { @@ -362,7 +369,7 @@ protected: return false; } } else if (command.GetArgumentCount() == 0) { - frame_idx = thread->GetSelectedFrameIndex(); + frame_idx = thread->GetSelectedFrameIndex(SelectMostRelevantFrame); if (frame_idx == UINT32_MAX) { frame_idx = 0; } @@ -372,7 +379,7 @@ protected: bool success = thread->SetSelectedFrameByIndexNoisily( frame_idx, result.GetOutputStream()); if (success) { - m_exe_ctx.SetFrameSP(thread->GetSelectedFrame()); + m_exe_ctx.SetFrameSP(thread->GetSelectedFrame(SelectMostRelevantFrame)); result.SetStatus(eReturnStatusSuccessFinishResult); } else { result.AppendErrorWithFormat("Frame index (%u) out of range.\n", @@ -445,9 +452,9 @@ may even involve JITing and running code in the target program.)"); HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { // Arguments are the standard source file completer. - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eVariablePathCompletion, request, + nullptr); } protected: @@ -473,6 +480,50 @@ protected: return llvm::StringRef(); } + /// Returns true if `scope` matches any of the options in `m_option_variable`. + bool ScopeRequested(lldb::ValueType scope) { + switch (scope) { + case eValueTypeVariableGlobal: + case eValueTypeVariableStatic: + return m_option_variable.show_globals; + case eValueTypeVariableArgument: + return m_option_variable.show_args; + case eValueTypeVariableLocal: + return m_option_variable.show_locals; + case eValueTypeInvalid: + case eValueTypeRegister: + case eValueTypeRegisterSet: + case eValueTypeConstResult: + case eValueTypeVariableThreadLocal: + return false; + } + } + + /// Finds all the variables in `all_variables` whose name matches `regex`, + /// inserting them into `matches`. Variables already contained in `matches` + /// are not inserted again. + /// Nullopt is returned in case of no matches. + /// A sub-range of `matches` with all newly inserted variables is returned. + /// This may be empty if all matches were already contained in `matches`. + std::optional<llvm::ArrayRef<VariableSP>> + findUniqueRegexMatches(RegularExpression ®ex, + VariableList &matches, + const VariableList &all_variables) { + bool any_matches = false; + const size_t previous_num_vars = matches.GetSize(); + + for (const VariableSP &var : all_variables) { + if (!var->NameMatches(regex) || !ScopeRequested(var->GetScope())) + continue; + any_matches = true; + matches.AddVariableIfUnique(var); + } + + if (any_matches) + return matches.toArrayRef().drop_front(previous_num_vars); + return std::nullopt; + } + bool DoExecute(Args &command, CommandReturnObject &result) override { // No need to check "frame" for validity as eCommandRequiresFrame ensures // it is valid @@ -480,6 +531,10 @@ protected: Stream &s = result.GetOutputStream(); + // Using a regex should behave like looking for an exact name match: it + // also finds globals. + m_option_variable.show_globals |= m_option_variable.use_regex; + // Be careful about the stack frame, if any summary formatter runs code, it // might clear the StackFrameList for the thread. So hold onto a shared // pointer to the frame so it stays alive. @@ -492,7 +547,6 @@ protected: result.AppendError(error.AsCString()); } - VariableSP var_sp; ValueObjectSP valobj_sp; TypeSummaryImplSP summary_format_sp; @@ -525,46 +579,38 @@ protected: // objects from them... for (auto &entry : command) { if (m_option_variable.use_regex) { - const size_t regex_start_index = regex_var_list.GetSize(); llvm::StringRef name_str = entry.ref(); RegularExpression regex(name_str); if (regex.IsValid()) { - size_t num_matches = 0; - const size_t num_new_regex_vars = - variable_list->AppendVariablesIfUnique(regex, regex_var_list, - num_matches); - if (num_new_regex_vars > 0) { - for (size_t regex_idx = regex_start_index, - end_index = regex_var_list.GetSize(); - regex_idx < end_index; ++regex_idx) { - var_sp = regex_var_list.GetVariableAtIndex(regex_idx); - if (var_sp) { - valobj_sp = frame->GetValueObjectForFrameVariable( - var_sp, m_varobj_options.use_dynamic); - if (valobj_sp) { - std::string scope_string; - if (m_option_variable.show_scope) - scope_string = GetScopeString(var_sp).str(); - - if (!scope_string.empty()) - s.PutCString(scope_string); - - if (m_option_variable.show_decl && - var_sp->GetDeclaration().GetFile()) { - bool show_fullpaths = false; - bool show_module = true; - if (var_sp->DumpDeclaration(&s, show_fullpaths, - show_module)) - s.PutCString(": "); - } - valobj_sp->Dump(result.GetOutputStream(), options); - } - } - } - } else if (num_matches == 0) { + std::optional<llvm::ArrayRef<VariableSP>> results = + findUniqueRegexMatches(regex, regex_var_list, *variable_list); + if (!results) { result.AppendErrorWithFormat( "no variables matched the regular expression '%s'.", entry.c_str()); + continue; + } + for (const VariableSP &var_sp : *results) { + valobj_sp = frame->GetValueObjectForFrameVariable( + var_sp, m_varobj_options.use_dynamic); + if (valobj_sp) { + std::string scope_string; + if (m_option_variable.show_scope) + scope_string = GetScopeString(var_sp).str(); + + if (!scope_string.empty()) + s.PutCString(scope_string); + + if (m_option_variable.show_decl && + var_sp->GetDeclaration().GetFile()) { + bool show_fullpaths = false; + bool show_module = true; + if (var_sp->DumpDeclaration(&s, show_fullpaths, + show_module)) + s.PutCString(": "); + } + valobj_sp->Dump(result.GetOutputStream(), options); + } } } else { if (llvm::Error err = regex.GetError()) @@ -622,28 +668,9 @@ protected: const size_t num_variables = variable_list->GetSize(); if (num_variables > 0) { for (size_t i = 0; i < num_variables; i++) { - var_sp = variable_list->GetVariableAtIndex(i); - switch (var_sp->GetScope()) { - case eValueTypeVariableGlobal: - if (!m_option_variable.show_globals) - continue; - break; - case eValueTypeVariableStatic: - if (!m_option_variable.show_globals) + VariableSP var_sp = variable_list->GetVariableAtIndex(i); + if (!ScopeRequested(var_sp->GetScope())) continue; - break; - case eValueTypeVariableArgument: - if (!m_option_variable.show_args) - continue; - break; - case eValueTypeVariableLocal: - if (!m_option_variable.show_locals) - continue; - break; - default: - continue; - break; - } std::string scope_string; if (m_option_variable.show_scope) scope_string = GetScopeString(var_sp).str(); diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectLog.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectLog.cpp index c63d8ce4f9e4..5dd6f8989837 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectLog.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectLog.cpp @@ -177,6 +177,20 @@ protected: return false; } + if ((m_options.handler != eLogHandlerCircular && + m_options.handler != eLogHandlerStream) && + m_options.buffer_size.GetCurrentValue() != 0) { + result.AppendError("a buffer size can only be specified for the circular " + "and stream buffer handler.\n"); + return false; + } + + if (m_options.handler != eLogHandlerStream && m_options.log_file) { + result.AppendError( + "a file name can only be specified for the stream handler.\n"); + return false; + } + // Store into a std::string since we're about to shift the channel off. const std::string channel = std::string(args[0].ref()); args.Shift(); // Shift off the channel @@ -490,7 +504,7 @@ public: protected: bool DoExecute(Args &args, CommandReturnObject &result) override { - Timer::DumpCategoryTimes(&result.GetOutputStream()); + Timer::DumpCategoryTimes(result.GetOutputStream()); Timer::SetDisplayDepth(0); result.SetStatus(eReturnStatusSuccessFinishResult); @@ -513,7 +527,7 @@ public: protected: bool DoExecute(Args &args, CommandReturnObject &result) override { - Timer::DumpCategoryTimes(&result.GetOutputStream()); + Timer::DumpCategoryTimes(result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); if (!result.Succeeded()) { diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp index 6606f4564dc8..ba5aad3d4ad5 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp @@ -594,18 +594,9 @@ protected: return false; } - ABISP abi; - if (Process *proc = m_exe_ctx.GetProcessPtr()) - abi = proc->GetABI(); - - if (abi) - addr = abi->FixDataAddress(addr); - if (argc == 2) { lldb::addr_t end_addr = OptionArgParser::ToAddress( &m_exe_ctx, command[1].ref(), LLDB_INVALID_ADDRESS, nullptr); - if (end_addr != LLDB_INVALID_ADDRESS && abi) - end_addr = abi->FixDataAddress(end_addr); if (end_addr == LLDB_INVALID_ADDRESS) { result.AppendError("invalid end address expression."); @@ -1045,12 +1036,6 @@ protected: return false; } - ABISP abi = m_exe_ctx.GetProcessPtr()->GetABI(); - if (abi) { - low_addr = abi->FixDataAddress(low_addr); - high_addr = abi->FixDataAddress(high_addr); - } - if (high_addr <= low_addr) { result.AppendError( "starting address must be smaller than ending address"); @@ -1062,7 +1047,8 @@ protected: DataBufferHeap buffer; if (m_memory_options.m_string.OptionWasSet()) { - llvm::StringRef str = m_memory_options.m_string.GetStringValue(); + llvm::StringRef str = + m_memory_options.m_string.GetValueAs<llvm::StringRef>().value_or(""); if (str.empty()) { result.AppendError("search string must have non-zero length."); return false; @@ -1073,7 +1059,9 @@ protected: ValueObjectSP result_sp; if ((eExpressionCompleted == process->GetTarget().EvaluateExpression( - m_memory_options.m_expr.GetStringValue(), frame, result_sp)) && + m_memory_options.m_expr.GetValueAs<llvm::StringRef>().value_or( + ""), + frame, result_sp)) && result_sp) { uint64_t value = result_sp->GetValueAsUnsigned(0); std::optional<uint64_t> size = @@ -1783,7 +1771,6 @@ protected: } auto load_addr_str = command[0].ref(); - // Non-address bits in this will be handled later by GetMemoryRegion load_addr = OptionArgParser::ToAddress(&m_exe_ctx, load_addr_str, LLDB_INVALID_ADDRESS, &error); if (error.Fail() || load_addr == LLDB_INVALID_ADDRESS) { diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectMemoryTag.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectMemoryTag.cpp index fd0fd2919c95..b436a185cd14 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectMemoryTag.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectMemoryTag.cpp @@ -51,7 +51,7 @@ protected: } Status error; - addr_t start_addr = OptionArgParser::ToAddress( + addr_t start_addr = OptionArgParser::ToRawAddress( &m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error); if (start_addr == LLDB_INVALID_ADDRESS) { result.AppendErrorWithFormatv("Invalid address expression, {0}", @@ -63,8 +63,8 @@ protected: addr_t end_addr = start_addr + 1; if (command.GetArgumentCount() > 1) { - end_addr = OptionArgParser::ToAddress(&m_exe_ctx, command[1].ref(), - LLDB_INVALID_ADDRESS, &error); + end_addr = OptionArgParser::ToRawAddress(&m_exe_ctx, command[1].ref(), + LLDB_INVALID_ADDRESS, &error); if (end_addr == LLDB_INVALID_ADDRESS) { result.AppendErrorWithFormatv("Invalid end address expression, {0}", error.AsCString()); @@ -155,8 +155,8 @@ public: switch (short_option) { case 'e': - m_end_addr = OptionArgParser::ToAddress(execution_context, option_value, - LLDB_INVALID_ADDRESS, &status); + m_end_addr = OptionArgParser::ToRawAddress( + execution_context, option_value, LLDB_INVALID_ADDRESS, &status); break; default: llvm_unreachable("Unimplemented option"); @@ -203,7 +203,7 @@ protected: } Status error; - addr_t start_addr = OptionArgParser::ToAddress( + addr_t start_addr = OptionArgParser::ToRawAddress( &m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error); if (start_addr == LLDB_INVALID_ADDRESS) { result.AppendErrorWithFormatv("Invalid address expression, {0}", diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectMultiword.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectMultiword.cpp index bae2717ffe68..7ef829afaab6 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectMultiword.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectMultiword.cpp @@ -274,10 +274,10 @@ void CommandObjectMultiword::HandleCompletion(CompletionRequest &request) { StringList new_matches; CommandObject *sub_command_object = GetSubcommandObject(arg0, &new_matches); - if (sub_command_object == nullptr) { - request.AddCompletions(new_matches); + + // The subcommand is ambiguous. The completion isn't meaningful. + if (!sub_command_object) return; - } // Remove the one match that we got from calling GetSubcommandObject. new_matches.DeleteStringAtIndex(0); diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectPlatform.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectPlatform.cpp index 1ab218fa6fb2..54115b51be78 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectPlatform.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectPlatform.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "CommandObjectPlatform.h" +#include "CommandOptionsProcessAttach.h" #include "CommandOptionsProcessLaunch.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" @@ -18,10 +19,13 @@ #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionGroupFile.h" #include "lldb/Interpreter/OptionGroupPlatform.h" +#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Utility/Args.h" +#include "lldb/Utility/ScriptedMetadata.h" +#include "lldb/Utility/State.h" #include "llvm/ADT/SmallString.h" @@ -158,8 +162,8 @@ public: ~CommandObjectPlatformSelect() override = default; void HandleCompletion(CompletionRequest &request) override { - CommandCompletions::PlatformPluginNames(GetCommandInterpreter(), request, - nullptr); + lldb_private::CommandCompletions::PlatformPluginNames( + GetCommandInterpreter(), request, nullptr); } Options *GetOptions() override { return &m_option_group; } @@ -382,8 +386,7 @@ public: "Set settings for the current target's platform.", "platform settings", 0), m_option_working_dir(LLDB_OPT_SET_1, false, "working-dir", 'w', - CommandCompletions::eRemoteDiskDirectoryCompletion, - eArgTypePath, + lldb::eRemoteDiskDirectoryCompletion, eArgTypePath, "The working directory for the platform.") { m_options.Append(&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); } @@ -481,9 +484,9 @@ public: HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { if (request.GetCursorIndex() == 0) - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), - CommandCompletions::eRemoteDiskFileCompletion, request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request, + nullptr); } bool DoExecute(Args &args, CommandReturnObject &result) override { @@ -828,13 +831,12 @@ public: HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { if (request.GetCursorIndex() == 0) - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), - CommandCompletions::eRemoteDiskFileCompletion, request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request, + nullptr); else if (request.GetCursorIndex() == 1) - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); } bool DoExecute(Args &args, CommandReturnObject &result) override { @@ -904,9 +906,9 @@ public: if (request.GetCursorIndex() != 0) return; - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eRemoteDiskFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request, + nullptr); } bool DoExecute(Args &args, CommandReturnObject &result) override { @@ -975,9 +977,9 @@ public: if (request.GetCursorIndex() != 0) return; - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eRemoteDiskFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request, + nullptr); } bool DoExecute(Args &args, CommandReturnObject &result) override { @@ -1045,9 +1047,9 @@ public: if (request.GetCursorIndex() != 0) return; - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eRemoteDiskFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request, + nullptr); } bool DoExecute(Args &args, CommandReturnObject &result) override { @@ -1104,13 +1106,12 @@ public: HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { if (request.GetCursorIndex() == 0) - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); else if (request.GetCursorIndex() == 1) - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), - CommandCompletions::eRemoteDiskFileCompletion, request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request, + nullptr); } bool DoExecute(Args &args, CommandReturnObject &result) override { @@ -1144,8 +1145,11 @@ public: : CommandObjectParsed(interpreter, "platform process launch", "Launch a new process on a remote platform.", "platform process launch program", - eCommandRequiresTarget | eCommandTryTargetAPILock) { + eCommandRequiresTarget | eCommandTryTargetAPILock), + m_class_options("scripted process", true, 'C', 'k', 'v', 0) { m_all_options.Append(&m_options); + m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2, + LLDB_OPT_SET_ALL); m_all_options.Finalize(); CommandArgumentData run_arg_arg{eArgTypeRunArgs, eArgRepeatStar}; m_arguments.push_back({run_arg_arg}); @@ -1180,6 +1184,14 @@ protected: m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture(); } + if (!m_class_options.GetName().empty()) { + m_options.launch_info.SetProcessPluginName("ScriptedProcess"); + ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>( + m_class_options.GetName(), m_class_options.GetStructuredData()); + m_options.launch_info.SetScriptedMetadata(metadata_sp); + target->SetProcessLaunchInfo(m_options.launch_info); + } + if (argc > 0) { if (m_options.launch_info.GetExecutableFile()) { // We already have an executable file, so we will use this and all @@ -1196,20 +1208,72 @@ protected: if (m_options.launch_info.GetExecutableFile()) { Debugger &debugger = GetDebugger(); - if (argc == 0) - target->GetRunArguments(m_options.launch_info.GetArguments()); + if (argc == 0) { + // If no arguments were given to the command, use target.run-args. + Args target_run_args; + target->GetRunArguments(target_run_args); + m_options.launch_info.GetArguments().AppendArguments(target_run_args); + } ProcessSP process_sp(platform_sp->DebugProcess( m_options.launch_info, debugger, *target, error)); + + if (!process_sp && error.Success()) { + result.AppendError("failed to launch or debug process"); + return false; + } else if (!error.Success()) { + result.AppendError(error.AsCString()); + return false; + } + + const bool synchronous_execution = + debugger.GetCommandInterpreter().GetSynchronous(); + auto launch_info = m_options.launch_info; + bool rebroadcast_first_stop = + !synchronous_execution && + launch_info.GetFlags().Test(eLaunchFlagStopAtEntry); + + EventSP first_stop_event_sp; + StateType state = process_sp->WaitForProcessToStop( + std::nullopt, &first_stop_event_sp, rebroadcast_first_stop, + launch_info.GetHijackListener()); + process_sp->RestoreProcessEvents(); + + if (rebroadcast_first_stop) { + assert(first_stop_event_sp); + process_sp->BroadcastEvent(first_stop_event_sp); + return true; + } + + switch (state) { + case eStateStopped: { + if (launch_info.GetFlags().Test(eLaunchFlagStopAtEntry)) + break; + if (synchronous_execution) { + // Now we have handled the stop-from-attach, and we are just + // switching to a synchronous resume. So we should switch to the + // SyncResume hijacker. + process_sp->ResumeSynchronous(&result.GetOutputStream()); + } else { + error = process_sp->Resume(); + if (!error.Success()) { + result.AppendErrorWithFormat( + "process resume at entry point failed: %s", + error.AsCString()); + } + } + } break; + default: + result.AppendErrorWithFormat( + "initial process state wasn't stopped: %s", + StateAsCString(state)); + break; + } + if (process_sp && process_sp->IsAlive()) { result.SetStatus(eReturnStatusSuccessFinishNoResult); return true; } - - if (error.Success()) - result.AppendError("process launch failed"); - else - result.AppendError(error.AsCString()); } else { result.AppendError("'platform process launch' uses the current target " "file and arguments, or the executable and its " @@ -1223,6 +1287,7 @@ protected: } CommandOptionsProcessLaunch m_options; + OptionGroupPythonClassWithDict m_class_options; OptionGroupOptions m_all_options; }; @@ -1508,9 +1573,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eProcessIDCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eProcessIDCompletion, request, nullptr); } protected: @@ -1572,71 +1636,16 @@ protected: class CommandObjectPlatformProcessAttach : public CommandObjectParsed { public: - class CommandOptions : public Options { - public: - CommandOptions() { - // Keep default values of all options in one place: OptionParsingStarting - // () - OptionParsingStarting(nullptr); - } - - ~CommandOptions() override = default; - - Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, - ExecutionContext *execution_context) override { - Status error; - char short_option = (char)m_getopt_table[option_idx].val; - switch (short_option) { - case 'p': { - lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; - if (option_arg.getAsInteger(0, pid)) { - error.SetErrorStringWithFormat("invalid process ID '%s'", - option_arg.str().c_str()); - } else { - attach_info.SetProcessID(pid); - } - } break; - - case 'P': - attach_info.SetProcessPluginName(option_arg); - break; - - case 'n': - attach_info.GetExecutableFile().SetFile(option_arg, - FileSpec::Style::native); - break; - - case 'w': - attach_info.SetWaitForLaunch(true); - break; - - default: - llvm_unreachable("Unimplemented option"); - } - return error; - } - - void OptionParsingStarting(ExecutionContext *execution_context) override { - attach_info.Clear(); - } - - llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::ArrayRef(g_platform_process_attach_options); - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - ProcessAttachInfo attach_info; - }; - CommandObjectPlatformProcessAttach(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "platform process attach", "Attach to a process.", - "platform process attach <cmd-options>") {} + "platform process attach <cmd-options>"), + m_class_options("scripted process", true, 'C', 'k', 'v', 0) { + m_all_options.Append(&m_options); + m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2, + LLDB_OPT_SET_ALL); + m_all_options.Finalize(); + } ~CommandObjectPlatformProcessAttach() override = default; @@ -1644,6 +1653,14 @@ public: PlatformSP platform_sp( GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) { + + if (!m_class_options.GetName().empty()) { + m_options.attach_info.SetProcessPluginName("ScriptedProcess"); + ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>( + m_class_options.GetName(), m_class_options.GetStructuredData()); + m_options.attach_info.SetScriptedMetadata(metadata_sp); + } + Status err; ProcessSP remote_process_sp = platform_sp->Attach( m_options.attach_info, GetDebugger(), nullptr, err); @@ -1659,10 +1676,12 @@ public: return result.Succeeded(); } - Options *GetOptions() override { return &m_options; } + Options *GetOptions() override { return &m_all_options; } protected: - CommandOptions m_options; + CommandOptionsProcessAttach m_options; + OptionGroupPythonClassWithDict m_class_options; + OptionGroupOptions m_all_options; }; class CommandObjectPlatformProcess : public CommandObjectMultiword { @@ -1864,9 +1883,8 @@ public: OptionElementVector &opt_element_vector) override { if (request.GetCursorIndex()) return; - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); } bool DoExecute(Args &args, CommandReturnObject &result) override { diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectPlugin.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectPlugin.cpp index 881415a49472..8661ebb5022b 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectPlugin.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectPlugin.cpp @@ -39,9 +39,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); } protected: diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp index a45371f824b1..ab047ee926c9 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp @@ -9,6 +9,7 @@ #include "CommandObjectProcess.h" #include "CommandObjectBreakpoint.h" #include "CommandObjectTrace.h" +#include "CommandOptionsProcessAttach.h" #include "CommandOptionsProcessLaunch.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointIDList.h" @@ -31,6 +32,7 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/Args.h" +#include "lldb/Utility/ScriptedMetadata.h" #include "lldb/Utility/State.h" #include "llvm/ADT/ScopeExit.h" @@ -145,9 +147,8 @@ public: HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); } Options *GetOptions() override { return &m_all_options; } @@ -199,10 +200,9 @@ protected: if (!m_class_options.GetName().empty()) { m_options.launch_info.SetProcessPluginName("ScriptedProcess"); - m_options.launch_info.SetScriptedProcessClassName( - m_class_options.GetName()); - m_options.launch_info.SetScriptedProcessDictionarySP( - m_class_options.GetStructuredData()); + ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>( + m_class_options.GetName(), m_class_options.GetStructuredData()); + m_options.launch_info.SetScriptedMetadata(metadata_sp); target->SetProcessLaunchInfo(m_options.launch_info); } @@ -304,77 +304,20 @@ protected: #pragma mark CommandObjectProcessAttach class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach { public: - class CommandOptions : public Options { - public: - CommandOptions() { - // Keep default values of all options in one place: OptionParsingStarting - // () - OptionParsingStarting(nullptr); - } - - ~CommandOptions() override = default; - - Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, - ExecutionContext *execution_context) override { - Status error; - const int short_option = m_getopt_table[option_idx].val; - switch (short_option) { - case 'c': - attach_info.SetContinueOnceAttached(true); - break; - - case 'p': { - lldb::pid_t pid; - if (option_arg.getAsInteger(0, pid)) { - error.SetErrorStringWithFormat("invalid process ID '%s'", - option_arg.str().c_str()); - } else { - attach_info.SetProcessID(pid); - } - } break; - - case 'P': - attach_info.SetProcessPluginName(option_arg); - break; - - case 'n': - attach_info.GetExecutableFile().SetFile(option_arg, - FileSpec::Style::native); - break; - - case 'w': - attach_info.SetWaitForLaunch(true); - break; - - case 'i': - attach_info.SetIgnoreExisting(false); - break; - - default: - llvm_unreachable("Unimplemented option"); - } - return error; - } - - void OptionParsingStarting(ExecutionContext *execution_context) override { - attach_info.Clear(); - } - - llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::ArrayRef(g_process_attach_options); - } - - ProcessAttachInfo attach_info; - }; - CommandObjectProcessAttach(CommandInterpreter &interpreter) : CommandObjectProcessLaunchOrAttach( interpreter, "process attach", "Attach to a process.", - "process attach <cmd-options>", 0, "attach") {} + "process attach <cmd-options>", 0, "attach"), + m_class_options("scripted process", true, 'C', 'k', 'v', 0) { + m_all_options.Append(&m_options); + m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2, + LLDB_OPT_SET_ALL); + m_all_options.Finalize(); + } ~CommandObjectProcessAttach() override = default; - Options *GetOptions() override { return &m_options; } + Options *GetOptions() override { return &m_all_options; } protected: bool DoExecute(Args &command, CommandReturnObject &result) override { @@ -409,6 +352,13 @@ protected: } } + if (!m_class_options.GetName().empty()) { + m_options.attach_info.SetProcessPluginName("ScriptedProcess"); + ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>( + m_class_options.GetName(), m_class_options.GetStructuredData()); + m_options.attach_info.SetScriptedMetadata(metadata_sp); + } + // Record the old executable module, we want to issue a warning if the // process of attaching changed the current executable (like somebody said // "file foo" then attached to a PID whose executable was bar.) @@ -483,7 +433,9 @@ protected: return result.Succeeded(); } - CommandOptions m_options; + CommandOptionsProcessAttach m_options; + OptionGroupPythonClassWithDict m_class_options; + OptionGroupOptions m_all_options; }; // CommandObjectProcessContinue @@ -1073,9 +1025,8 @@ public: if (!m_exe_ctx.HasProcessScope()) return; - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); } Options *GetOptions() override { return &m_options; } @@ -1355,6 +1306,13 @@ public: Options *GetOptions() override { return &m_options; } + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); + } + class CommandOptions : public Options { public: CommandOptions() = default; @@ -1403,6 +1361,7 @@ protected: if (process_sp) { if (command.GetArgumentCount() == 1) { FileSpec output_file(command.GetArgumentAtIndex(0)); + FileSystem::Instance().Resolve(output_file); SaveCoreStyle corefile_style = m_options.m_requested_save_core_style; Status error = PluginManager::SaveCore(process_sp, output_file, corefile_style, diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectRegexCommand.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectRegexCommand.cpp index 857193036e39..6ff1d281504a 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectRegexCommand.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectRegexCommand.cpp @@ -19,10 +19,9 @@ 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) + llvm::StringRef syntax, 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_completion_type_mask(completion_type_mask), m_is_removable(is_removable) {} // Destructor @@ -73,8 +72,9 @@ bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command, result.GetOutputStream().Printf("%s\n", new_command->c_str()); // We don't have to pass an override_context here, as the command that // called us should have set up the context appropriately. - return m_interpreter.HandleCommand(new_command->c_str(), - eLazyBoolNo, result); + bool force_repeat_command = true; + return m_interpreter.HandleCommand(new_command->c_str(), eLazyBoolNo, + result, force_repeat_command); } } result.SetStatus(eReturnStatusFailed); @@ -104,7 +104,7 @@ bool CommandObjectRegexCommand::AddRegexCommand(llvm::StringRef re_cstr, void CommandObjectRegexCommand::HandleCompletion(CompletionRequest &request) { if (m_completion_type_mask) { - CommandCompletions::InvokeCommonCompletionCallbacks( + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), m_completion_type_mask, request, nullptr); } } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectRegexCommand.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectRegexCommand.h index b2a375c63a76..47d493a8fdd7 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectRegexCommand.h +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectRegexCommand.h @@ -23,7 +23,7 @@ class CommandObjectRegexCommand : public CommandObjectRaw { public: CommandObjectRegexCommand(CommandInterpreter &interpreter, llvm::StringRef name, llvm::StringRef help, - llvm::StringRef syntax, uint32_t max_matches, + llvm::StringRef syntax, uint32_t completion_type_mask, bool is_removable); ~CommandObjectRegexCommand() override; @@ -50,7 +50,6 @@ protected: }; typedef std::list<Entry> EntryCollection; - const uint32_t m_max_matches; const uint32_t m_completion_type_mask; EntryCollection m_entries; bool m_is_removable; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectRegister.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectRegister.cpp index c61a1f6e865a..a0e88f6ab4ba 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectRegister.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectRegister.cpp @@ -8,8 +8,10 @@ #include "CommandObjectRegister.h" #include "lldb/Core/Debugger.h" +#include "lldb/Core/DumpRegisterInfo.h" #include "lldb/Core/DumpRegisterValue.h" #include "lldb/Host/OptionParser.h" +#include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionGroupFormat.h" @@ -44,7 +46,10 @@ public: nullptr, eCommandRequiresFrame | eCommandRequiresRegContext | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), - m_format_options(eFormatDefault) { + m_format_options(eFormatDefault, UINT64_MAX, UINT64_MAX, + {{CommandArgumentType::eArgTypeFormat, + "Specify a format to be used for display. If this " + "is set, register fields will not be displayed."}}) { CommandArgumentEntry arg; CommandArgumentData register_arg; @@ -76,48 +81,45 @@ public: if (!m_exe_ctx.HasProcessScope()) return; - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eRegisterCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eRegisterCompletion, request, nullptr); } Options *GetOptions() override { return &m_option_group; } bool DumpRegister(const ExecutionContext &exe_ctx, Stream &strm, - RegisterContext *reg_ctx, const RegisterInfo *reg_info) { - if (reg_info) { - RegisterValue reg_value; - - if (reg_ctx->ReadRegister(reg_info, reg_value)) { - strm.Indent(); - - bool prefix_with_altname = (bool)m_command_options.alternate_name; - bool prefix_with_name = !prefix_with_altname; - DumpRegisterValue(reg_value, &strm, reg_info, prefix_with_name, - prefix_with_altname, m_format_options.GetFormat(), 8, - exe_ctx.GetBestExecutionContextScope()); - if ((reg_info->encoding == eEncodingUint) || - (reg_info->encoding == eEncodingSint)) { - Process *process = exe_ctx.GetProcessPtr(); - if (process && reg_info->byte_size == process->GetAddressByteSize()) { - addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS); - if (reg_addr != LLDB_INVALID_ADDRESS) { - Address so_reg_addr; - if (exe_ctx.GetTargetRef() - .GetSectionLoadList() - .ResolveLoadAddress(reg_addr, so_reg_addr)) { - strm.PutCString(" "); - so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(), - Address::DumpStyleResolvedDescription); - } - } + RegisterContext ®_ctx, const RegisterInfo ®_info, + bool print_flags) { + RegisterValue reg_value; + if (!reg_ctx.ReadRegister(®_info, reg_value)) + return false; + + strm.Indent(); + + bool prefix_with_altname = (bool)m_command_options.alternate_name; + bool prefix_with_name = !prefix_with_altname; + DumpRegisterValue(reg_value, strm, reg_info, prefix_with_name, + prefix_with_altname, m_format_options.GetFormat(), 8, + exe_ctx.GetBestExecutionContextScope(), print_flags, + exe_ctx.GetTargetSP()); + if ((reg_info.encoding == eEncodingUint) || + (reg_info.encoding == eEncodingSint)) { + Process *process = exe_ctx.GetProcessPtr(); + if (process && reg_info.byte_size == process->GetAddressByteSize()) { + addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS); + if (reg_addr != LLDB_INVALID_ADDRESS) { + Address so_reg_addr; + if (exe_ctx.GetTargetRef().GetSectionLoadList().ResolveLoadAddress( + reg_addr, so_reg_addr)) { + strm.PutCString(" "); + so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(), + Address::DumpStyleResolvedDescription); } } - strm.EOL(); - return true; } } - return false; + strm.EOL(); + return true; } bool DumpRegisterSet(const ExecutionContext &exe_ctx, Stream &strm, @@ -142,7 +144,8 @@ public: if (primitive_only && reg_info && reg_info->value_regs) continue; - if (DumpRegister(exe_ctx, strm, reg_ctx, reg_info)) + if (reg_info && DumpRegister(exe_ctx, strm, *reg_ctx, *reg_info, + /*print_flags=*/false)) ++available_count; else ++unavailable_count; @@ -162,7 +165,6 @@ protected: Stream &strm = result.GetOutputStream(); RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); - const RegisterInfo *reg_info = nullptr; if (command.GetArgumentCount() == 0) { size_t set_idx; @@ -170,8 +172,9 @@ protected: const size_t set_array_size = m_command_options.set_indexes.GetSize(); if (set_array_size > 0) { for (size_t i = 0; i < set_array_size; ++i) { - set_idx = m_command_options.set_indexes[i]->GetUInt64Value(UINT32_MAX, - nullptr); + set_idx = + m_command_options.set_indexes[i]->GetValueAs<uint64_t>().value_or( + UINT32_MAX); if (set_idx < reg_ctx->GetRegisterSetCount()) { if (!DumpRegisterSet(m_exe_ctx, strm, reg_ctx, set_idx)) { if (errno) @@ -215,10 +218,14 @@ protected: auto arg_str = entry.ref(); arg_str.consume_front("$"); - reg_info = reg_ctx->GetRegisterInfoByName(arg_str); - - if (reg_info) { - if (!DumpRegister(m_exe_ctx, strm, reg_ctx, reg_info)) + if (const RegisterInfo *reg_info = + reg_ctx->GetRegisterInfoByName(arg_str)) { + // If they have asked for a specific format don't obscure that by + // printing flags afterwards. + bool print_flags = + !m_format_options.GetFormatValue().OptionWasSet(); + if (!DumpRegister(m_exe_ctx, strm, *reg_ctx, *reg_info, + print_flags)) strm.Printf("%-12s = error: unavailable\n", reg_info->name); } else { result.AppendErrorWithFormat("Invalid register name '%s'.\n", @@ -336,9 +343,8 @@ public: if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0) return; - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eRegisterCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eRegisterCompletion, request, nullptr); } protected: @@ -394,16 +400,86 @@ protected: } }; +// "register info" +class CommandObjectRegisterInfo : public CommandObjectParsed { +public: + CommandObjectRegisterInfo(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "register info", + "View information about a register.", nullptr, + eCommandRequiresRegContext | + eCommandProcessMustBeLaunched) { + SetHelpLong(R"( +Name The name lldb uses for the register, optionally with an alias. +Size The size of the register in bytes and again in bits. +Invalidates (*) The registers that would be changed if you wrote this + register. For example, writing to a narrower alias of a wider + register would change the value of the wider register. +Read from (*) The registers that the value of this register is constructed + from. For example, a narrower alias of a wider register will be + read from the wider register. +In sets (*) The register sets that contain this register. For example the + PC will be in the "General Purpose Register" set. +Fields (*) A table of the names and bit positions of the values contained + in this register. + +Fields marked with (*) may not always be present. Some information may be +different for the same register when connected to different debug servers.)"); + + CommandArgumentData register_arg; + register_arg.arg_type = eArgTypeRegisterName; + register_arg.arg_repetition = eArgRepeatPlain; + + CommandArgumentEntry arg1; + arg1.push_back(register_arg); + m_arguments.push_back(arg1); + } + + ~CommandObjectRegisterInfo() override = default; + + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0) + return; + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eRegisterCompletion, request, nullptr); + } + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + if (command.GetArgumentCount() != 1) { + result.AppendError("register info takes exactly 1 argument: <reg-name>"); + return result.Succeeded(); + } + + llvm::StringRef reg_name = command[0].ref(); + RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); + if (reg_info) { + DumpRegisterInfo( + result.GetOutputStream(), *reg_ctx, *reg_info, + GetCommandInterpreter().GetDebugger().GetTerminalWidth()); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else + result.AppendErrorWithFormat("No register found with name '%s'.\n", + reg_name.str().c_str()); + + return result.Succeeded(); + } +}; + // CommandObjectRegister constructor CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter) : CommandObjectMultiword(interpreter, "register", "Commands to access registers for the current " "thread and stack frame.", - "register [read|write] ...") { + "register [read|write|info] ...") { LoadSubCommand("read", CommandObjectSP(new CommandObjectRegisterRead(interpreter))); LoadSubCommand("write", CommandObjectSP(new CommandObjectRegisterWrite(interpreter))); + LoadSubCommand("info", + CommandObjectSP(new CommandObjectRegisterInfo(interpreter))); } CommandObjectRegister::~CommandObjectRegister() = default; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectSession.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectSession.cpp index 7c7236e9793b..6bf1ec99c888 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectSession.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectSession.cpp @@ -31,9 +31,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); } protected: diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectSettings.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectSettings.cpp index d658e137a4fd..7069cb1d8399 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectSettings.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectSettings.cpp @@ -143,9 +143,9 @@ insert-before or insert-after."); } if (request.GetCursorIndex() == setting_var_idx) { // Attempting to complete setting variable name - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eSettingsNameCompletion, request, + nullptr); return; } arg = request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()); @@ -161,8 +161,8 @@ insert-before or insert-after."); const char *setting_var_name = request.GetParsedLine().GetArgumentAtIndex(setting_var_idx); Status error; - lldb::OptionValueSP value_sp(GetDebugger().GetPropertyValue( - &m_exe_ctx, setting_var_name, false, error)); + lldb::OptionValueSP value_sp( + GetDebugger().GetPropertyValue(&m_exe_ctx, setting_var_name, error)); if (!value_sp) return; value_sp->AutoComplete(m_interpreter, request); @@ -267,9 +267,9 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eSettingsNameCompletion, request, + nullptr); } protected: @@ -511,16 +511,15 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eSettingsNameCompletion, request, + nullptr); } protected: bool DoExecute(Args &args, CommandReturnObject &result) override { result.SetStatus(eReturnStatusSuccessFinishResult); - const bool will_modify = false; const size_t argc = args.GetArgumentCount(); if (argc > 0) { const bool dump_qualified_name = true; @@ -530,7 +529,7 @@ protected: const Property *property = GetDebugger().GetValueProperties()->GetPropertyAtPath( - &m_exe_ctx, will_modify, property_path); + &m_exe_ctx, property_path); if (property) { property->DumpDescription(m_interpreter, result.GetOutputStream(), 0, @@ -596,9 +595,9 @@ public: HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { if (request.GetCursorIndex() < 2) - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eSettingsNameCompletion, request, + nullptr); } protected: @@ -704,9 +703,9 @@ public: OptionElementVector &opt_element_vector) override { // Attempting to complete variable name if (request.GetCursorIndex() < 2) - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eSettingsNameCompletion, request, + nullptr); } protected: @@ -796,9 +795,9 @@ public: OptionElementVector &opt_element_vector) override { // Attempting to complete variable name if (request.GetCursorIndex() < 2) - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eSettingsNameCompletion, request, + nullptr); } protected: @@ -892,9 +891,9 @@ public: OptionElementVector &opt_element_vector) override { // Attempting to complete variable name if (request.GetCursorIndex() < 2) - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eSettingsNameCompletion, request, + nullptr); } protected: @@ -977,9 +976,9 @@ public: OptionElementVector &opt_element_vector) override { // Attempting to complete variable name if (request.GetCursorIndex() < 2) - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eSettingsNameCompletion, request, + nullptr); } protected: @@ -1052,9 +1051,9 @@ public: OptionElementVector &opt_element_vector) override { // Attempting to complete variable name if (request.GetCursorIndex() < 2) - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eSettingsNameCompletion, request, + nullptr); } Options *GetOptions() override { return &m_options; } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectSource.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectSource.cpp index 44561cfd736e..16452c1784bd 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectSource.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectSource.cpp @@ -22,6 +22,7 @@ #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Target/Process.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/StackFrame.h" #include "lldb/Utility/FileSpec.h" @@ -146,10 +147,7 @@ protected: uint32_t num_matches = 0; // Dump all the line entries for the file in the list. ConstString last_module_file_name; - uint32_t num_scs = sc_list.GetSize(); - for (uint32_t i = 0; i < num_scs; ++i) { - SymbolContext sc; - sc_list.GetContextAtIndex(i, sc); + for (const SymbolContext &sc : sc_list) { if (sc.comp_unit) { Module *module = sc.module_sp.get(); CompileUnit *cu = sc.comp_unit; @@ -393,10 +391,7 @@ protected: SymbolContextList sc_list_symbols; module_list.FindFunctionSymbols(name, eFunctionNameTypeAuto, sc_list_symbols); - size_t num_symbol_matches = sc_list_symbols.GetSize(); - for (size_t i = 0; i < num_symbol_matches; i++) { - SymbolContext sc; - sc_list_symbols.GetContextAtIndex(i, sc); + for (const SymbolContext &sc : sc_list_symbols) { if (sc.symbol && sc.symbol->ValueIsAddress()) { const Address &base_address = sc.symbol->GetAddressRef(); Function *function = base_address.CalculateSymbolContextFunction(); @@ -412,9 +407,7 @@ protected: m_options.symbol_name.c_str()); return false; } - for (size_t i = 0; i < num_matches; i++) { - SymbolContext sc; - sc_list_funcs.GetContextAtIndex(i, sc); + for (const SymbolContext &sc : sc_list_funcs) { bool context_found_for_symbol = false; // Loop through all the ranges in the function. AddressRange range; @@ -926,69 +919,45 @@ protected: // Displaying the source for a symbol. Search for function named name. FindMatchingFunctions(target, name, sc_list); - size_t num_matches = sc_list.GetSize(); - if (!num_matches) { + if (sc_list.GetSize() == 0) { // If we didn't find any functions with that name, try searching for // symbols that line up exactly with function addresses. SymbolContextList sc_list_symbols; FindMatchingFunctionSymbols(target, name, sc_list_symbols); - size_t num_symbol_matches = sc_list_symbols.GetSize(); - - for (size_t i = 0; i < num_symbol_matches; i++) { - SymbolContext sc; - sc_list_symbols.GetContextAtIndex(i, sc); + for (const SymbolContext &sc : sc_list_symbols) { if (sc.symbol && sc.symbol->ValueIsAddress()) { const Address &base_address = sc.symbol->GetAddressRef(); Function *function = base_address.CalculateSymbolContextFunction(); if (function) { sc_list.Append(SymbolContext(function)); - num_matches++; break; } } } } - if (num_matches == 0) { + if (sc_list.GetSize() == 0) { result.AppendErrorWithFormat("Could not find function named: \"%s\".\n", m_options.symbol_name.c_str()); return false; } - if (num_matches > 1) { - std::set<SourceInfo> source_match_set; - - bool displayed_something = false; - for (size_t i = 0; i < num_matches; i++) { - SymbolContext sc; - sc_list.GetContextAtIndex(i, sc); - SourceInfo source_info(sc.GetFunctionName(), - sc.GetFunctionStartLineEntry()); - - if (source_info.IsValid()) { - if (source_match_set.find(source_info) == source_match_set.end()) { - source_match_set.insert(source_info); - if (DisplayFunctionSource(sc, source_info, result)) - displayed_something = true; - } - } - } - - if (displayed_something) - result.SetStatus(eReturnStatusSuccessFinishResult); - else - result.SetStatus(eReturnStatusFailed); - } else { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - SourceInfo source_info; - - if (DisplayFunctionSource(sc, source_info, result)) { - result.SetStatus(eReturnStatusSuccessFinishResult); - } else { - result.SetStatus(eReturnStatusFailed); + std::set<SourceInfo> source_match_set; + bool displayed_something = false; + for (const SymbolContext &sc : sc_list) { + SourceInfo source_info(sc.GetFunctionName(), + sc.GetFunctionStartLineEntry()); + if (source_info.IsValid() && + source_match_set.find(source_info) == source_match_set.end()) { + source_match_set.insert(source_info); + if (DisplayFunctionSource(sc, source_info, result)) + displayed_something = true; } } + if (displayed_something) + result.SetStatus(eReturnStatusSuccessFinishResult); + else + result.SetStatus(eReturnStatusFailed); return result.Succeeded(); } else if (m_options.address != LLDB_INVALID_ADDRESS) { Address so_addr; @@ -1052,10 +1021,7 @@ protected: return false; } } - uint32_t num_matches = sc_list.GetSize(); - for (uint32_t i = 0; i < num_matches; ++i) { - SymbolContext sc; - sc_list.GetContextAtIndex(i, sc); + for (const SymbolContext &sc : sc_list) { if (sc.comp_unit) { if (m_options.show_bp_locs) { m_breakpoint_locations.Clear(); @@ -1175,9 +1141,7 @@ protected: bool got_multiple = false; CompileUnit *test_cu = nullptr; - for (unsigned i = 0; i < num_matches; i++) { - SymbolContext sc; - sc_list.GetContextAtIndex(i, sc); + for (const SymbolContext &sc : sc_list) { if (sc.comp_unit) { if (test_cu) { if (test_cu != sc.comp_unit) @@ -1238,6 +1202,78 @@ protected: std::string m_reverse_name; }; +class CommandObjectSourceCacheDump : public CommandObjectParsed { +public: + CommandObjectSourceCacheDump(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "source cache dump", + "Dump the state of the source code cache. Intended " + "to be used for debugging LLDB itself.", + nullptr) {} + + ~CommandObjectSourceCacheDump() override = default; + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + // Dump the debugger source cache. + result.GetOutputStream() << "Debugger Source File Cache\n"; + SourceManager::SourceFileCache &cache = GetDebugger().GetSourceFileCache(); + cache.Dump(result.GetOutputStream()); + + // Dump the process source cache. + if (ProcessSP process_sp = m_exe_ctx.GetProcessSP()) { + result.GetOutputStream() << "\nProcess Source File Cache\n"; + SourceManager::SourceFileCache &cache = process_sp->GetSourceFileCache(); + cache.Dump(result.GetOutputStream()); + } + + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } +}; + +class CommandObjectSourceCacheClear : public CommandObjectParsed { +public: + CommandObjectSourceCacheClear(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "source cache clear", + "Clear the source code cache.\n", nullptr) {} + + ~CommandObjectSourceCacheClear() override = default; + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + // Clear the debugger cache. + SourceManager::SourceFileCache &cache = GetDebugger().GetSourceFileCache(); + cache.Clear(); + + // Clear the process cache. + if (ProcessSP process_sp = m_exe_ctx.GetProcessSP()) + process_sp->GetSourceFileCache().Clear(); + + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return result.Succeeded(); + } +}; + +class CommandObjectSourceCache : public CommandObjectMultiword { +public: + CommandObjectSourceCache(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "source cache", + "Commands for managing the source code cache.", + "source cache <sub-command>") { + LoadSubCommand( + "dump", CommandObjectSP(new CommandObjectSourceCacheDump(interpreter))); + LoadSubCommand("clear", CommandObjectSP(new CommandObjectSourceCacheClear( + interpreter))); + } + + ~CommandObjectSourceCache() override = default; + +private: + CommandObjectSourceCache(const CommandObjectSourceCache &) = delete; + const CommandObjectSourceCache & + operator=(const CommandObjectSourceCache &) = delete; +}; + #pragma mark CommandObjectMultiwordSource // CommandObjectMultiwordSource @@ -1253,6 +1289,8 @@ CommandObjectMultiwordSource::CommandObjectMultiwordSource( CommandObjectSP(new CommandObjectSourceInfo(interpreter))); LoadSubCommand("list", CommandObjectSP(new CommandObjectSourceList(interpreter))); + LoadSubCommand("cache", + CommandObjectSP(new CommandObjectSourceCache(interpreter))); } CommandObjectMultiwordSource::~CommandObjectMultiwordSource() = default; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp index 3d53de1d2d2b..3e024ff91b38 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp @@ -82,8 +82,14 @@ static void DumpTargetInfo(uint32_t target_idx, Target *target, if (!exe_valid) ::strcpy(exe_path, "<none>"); - strm.Printf("%starget #%u: %s", prefix_cstr ? prefix_cstr : "", target_idx, - exe_path); + std::string formatted_label = ""; + const std::string &label = target->GetLabel(); + if (!label.empty()) { + formatted_label = " (" + label + ")"; + } + + strm.Printf("%starget #%u%s: %s", prefix_cstr ? prefix_cstr : "", target_idx, + formatted_label.data(), exe_path); uint32_t properties = 0; if (target_arch.IsValid()) { @@ -209,6 +215,8 @@ public: m_platform_options(true), // Include the --platform option. m_core_file(LLDB_OPT_SET_1, false, "core", 'c', 0, eArgTypeFilename, "Fullpath to a core file to use for this target."), + m_label(LLDB_OPT_SET_1, false, "label", 'l', 0, eArgTypeName, + "Optional name for this target.", nullptr), m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0, eArgTypeFilename, "Fullpath to a stand alone debug " @@ -234,6 +242,7 @@ public: m_option_group.Append(&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1); m_option_group.Append(&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_label, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append(&m_remote_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append(&m_add_dependents, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); @@ -247,9 +256,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); } protected: @@ -303,6 +311,14 @@ protected: return false; } + const llvm::StringRef label = + m_label.GetOptionValue().GetCurrentValueAsRef(); + if (!label.empty()) { + if (auto E = target_sp->SetLabel(label)) + result.SetError(std::move(E)); + return false; + } + auto on_error = llvm::make_scope_exit( [&target_list = debugger.GetTargetList(), &target_sp]() { target_list.DeleteTarget(target_sp); @@ -455,6 +471,7 @@ private: OptionGroupArchitecture m_arch_option; OptionGroupPlatform m_platform_options; OptionGroupFile m_core_file; + OptionGroupString m_label; OptionGroupFile m_symbol_file; OptionGroupFile m_remote_file; OptionGroupDependents m_add_dependents; @@ -503,11 +520,11 @@ public: protected: bool DoExecute(Args &args, CommandReturnObject &result) override { if (args.GetArgumentCount() == 1) { - const char *target_idx_arg = args.GetArgumentAtIndex(0); - uint32_t target_idx; - if (llvm::to_integer(target_idx_arg, target_idx)) { - TargetList &target_list = GetDebugger().GetTargetList(); - const uint32_t num_targets = target_list.GetNumTargets(); + const char *target_identifier = args.GetArgumentAtIndex(0); + uint32_t target_idx = LLDB_INVALID_INDEX32; + TargetList &target_list = GetDebugger().GetTargetList(); + const uint32_t num_targets = target_list.GetNumTargets(); + if (llvm::to_integer(target_identifier, target_idx)) { if (target_idx < num_targets) { target_list.SetSelectedTarget(target_idx); Stream &strm = result.GetOutputStream(); @@ -526,8 +543,26 @@ protected: } } } else { - result.AppendErrorWithFormat("invalid index string value '%s'\n", - target_idx_arg); + for (size_t i = 0; i < num_targets; i++) { + if (TargetSP target_sp = target_list.GetTargetAtIndex(i)) { + const std::string &label = target_sp->GetLabel(); + if (!label.empty() && label == target_identifier) { + target_idx = i; + break; + } + } + } + + if (target_idx != LLDB_INVALID_INDEX32) { + target_list.SetSelectedTarget(target_idx); + Stream &strm = result.GetOutputStream(); + bool show_stopped_process_status = false; + DumpTargetList(target_list, show_stopped_process_status, strm); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("invalid index string value '%s'\n", + target_identifier); + } } } else { result.AppendError( @@ -576,7 +611,7 @@ protected: TargetSP target_sp; if (m_all_option.GetOptionValue()) { - for (int i = 0; i < target_list.GetNumTargets(); ++i) + for (size_t i = 0; i < target_list.GetNumTargets(); ++i) delete_target_list.push_back(target_list.GetTargetAtIndex(i)); } else if (argc > 0) { const uint32_t num_targets = target_list.GetNumTargets(); @@ -957,29 +992,21 @@ protected: compile_units.GetFileSpecAtIndex(cu_idx), sc_list); } - const uint32_t num_scs = sc_list.GetSize(); - if (num_scs > 0) { - SymbolContext sc; - for (uint32_t sc_idx = 0; sc_idx < num_scs; ++sc_idx) { - if (sc_list.GetContextAtIndex(sc_idx, sc)) { - if (sc.comp_unit) { - const bool can_create = true; - VariableListSP comp_unit_varlist_sp( - sc.comp_unit->GetVariableList(can_create)); - if (comp_unit_varlist_sp) - DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, - s); - } else if (sc.module_sp) { - // Get all global variables for this module - lldb_private::RegularExpression all_globals_regex( - llvm::StringRef( - ".")); // Any global with at least one character - VariableList variable_list; - sc.module_sp->FindGlobalVariables(all_globals_regex, UINT32_MAX, - variable_list); - DumpGlobalVariableList(m_exe_ctx, sc, variable_list, s); - } - } + for (const SymbolContext &sc : sc_list) { + if (sc.comp_unit) { + const bool can_create = true; + VariableListSP comp_unit_varlist_sp( + sc.comp_unit->GetVariableList(can_create)); + if (comp_unit_varlist_sp) + DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s); + } else if (sc.module_sp) { + // Get all global variables for this module + lldb_private::RegularExpression all_globals_regex( + llvm::StringRef(".")); // Any global with at least one character + VariableList variable_list; + sc.module_sp->FindGlobalVariables(all_globals_regex, UINT32_MAX, + variable_list); + DumpGlobalVariableList(m_exe_ctx, sc, variable_list, s); } } } @@ -1291,7 +1318,7 @@ static void DumpModuleArchitecture(Stream &strm, Module *module, static void DumpModuleUUID(Stream &strm, Module *module) { if (module && module->GetUUID().IsValid()) - module->GetUUID().Dump(&strm); + module->GetUUID().Dump(strm); else strm.PutCString(" "); } @@ -1306,22 +1333,22 @@ static uint32_t DumpCompileUnitLineTable(CommandInterpreter &interpreter, num_matches = module->ResolveSymbolContextsForFileSpec( file_spec, 0, false, eSymbolContextCompUnit, sc_list); - for (uint32_t i = 0; i < num_matches; ++i) { - SymbolContext sc; - if (sc_list.GetContextAtIndex(i, sc)) { - if (i > 0) - strm << "\n\n"; - - strm << "Line table for " << sc.comp_unit->GetPrimaryFile() << " in `" - << module->GetFileSpec().GetFilename() << "\n"; - LineTable *line_table = sc.comp_unit->GetLineTable(); - if (line_table) - line_table->GetDescription( - &strm, interpreter.GetExecutionContext().GetTargetPtr(), - desc_level); - else - strm << "No line table"; - } + bool first_module = true; + for (const SymbolContext &sc : sc_list) { + if (!first_module) + strm << "\n\n"; + + strm << "Line table for " << sc.comp_unit->GetPrimaryFile() << " in `" + << module->GetFileSpec().GetFilename() << "\n"; + LineTable *line_table = sc.comp_unit->GetLineTable(); + if (line_table) + line_table->GetDescription( + &strm, interpreter.GetExecutionContext().GetTargetPtr(), + desc_level); + else + strm << "No line table"; + + first_module = false; } } return num_matches; @@ -1480,28 +1507,6 @@ static bool LookupAddressInModule(CommandInterpreter &interpreter, Stream &strm, ExecutionContextScope *exe_scope = interpreter.GetExecutionContext().GetBestExecutionContextScope(); DumpAddress(exe_scope, so_addr, verbose, all_ranges, strm); - // strm.IndentMore(); - // strm.Indent (" Address: "); - // so_addr.Dump (&strm, exe_scope, - // Address::DumpStyleModuleWithFileAddress); - // strm.PutCString (" ("); - // so_addr.Dump (&strm, exe_scope, - // Address::DumpStyleSectionNameOffset); - // strm.PutCString (")\n"); - // strm.Indent (" Summary: "); - // const uint32_t save_indent = strm.GetIndentLevel (); - // strm.SetIndentLevel (save_indent + 13); - // so_addr.Dump (&strm, exe_scope, - // Address::DumpStyleResolvedDescription); - // strm.SetIndentLevel (save_indent); - // // Print out detailed address information when verbose is enabled - // if (verbose) - // { - // strm.EOL(); - // so_addr.Dump (&strm, exe_scope, - // Address::DumpStyleDetailedSymbolContext); - // } - // strm.IndentLess(); return true; } @@ -1568,21 +1573,21 @@ static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter, } static void DumpSymbolContextList(ExecutionContextScope *exe_scope, - Stream &strm, SymbolContextList &sc_list, + Stream &strm, + const SymbolContextList &sc_list, bool verbose, bool all_ranges) { strm.IndentMore(); + bool first_module = true; + for (const SymbolContext &sc : sc_list) { + if (!first_module) + strm.EOL(); - const uint32_t num_matches = sc_list.GetSize(); - - for (uint32_t i = 0; i < num_matches; ++i) { - SymbolContext sc; - if (sc_list.GetContextAtIndex(i, sc)) { - AddressRange range; + AddressRange range; - sc.GetAddressRange(eSymbolContextEverything, 0, true, range); + sc.GetAddressRange(eSymbolContextEverything, 0, true, range); - DumpAddress(exe_scope, range.GetBaseAddress(), verbose, all_ranges, strm); - } + DumpAddress(exe_scope, range.GetBaseAddress(), verbose, all_ranges, strm); + first_module = false; } strm.IndentLess(); } @@ -1818,9 +1823,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eModuleCompletion, request, - nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eModuleCompletion, request, nullptr); } }; @@ -1856,9 +1860,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eSourceFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eSourceFileCompletion, request, nullptr); } }; @@ -2002,8 +2005,11 @@ protected: result.GetOutputStream().EOL(); result.GetOutputStream().EOL(); } - if (m_interpreter.WasInterrupted()) + if (INTERRUPT_REQUESTED(GetDebugger(), + "Interrupted in dump all symtabs with {0} " + "of {1} dumped.", num_dumped, num_modules)) break; + num_dumped++; DumpModuleSymtab(m_interpreter, result.GetOutputStream(), module_sp.get(), m_options.m_sort_order, @@ -2029,8 +2035,11 @@ protected: result.GetOutputStream().EOL(); result.GetOutputStream().EOL(); } - if (m_interpreter.WasInterrupted()) + if (INTERRUPT_REQUESTED(GetDebugger(), + "Interrupted in dump symtab list with {0} of {1} dumped.", + num_dumped, num_matches)) break; + num_dumped++; DumpModuleSymtab(m_interpreter, result.GetOutputStream(), module_sp.get(), m_options.m_sort_order, @@ -2090,8 +2099,11 @@ protected: result.GetOutputStream().Format("Dumping sections for {0} modules.\n", num_modules); for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { - if (m_interpreter.WasInterrupted()) + if (INTERRUPT_REQUESTED(GetDebugger(), + "Interrupted in dump all sections with {0} of {1} dumped", + image_idx, num_modules)) break; + num_dumped++; DumpModuleSections( m_interpreter, result.GetOutputStream(), @@ -2108,8 +2120,11 @@ protected: FindModulesByName(target, arg_cstr, module_list, true); if (num_matches > 0) { for (size_t i = 0; i < num_matches; ++i) { - if (m_interpreter.WasInterrupted()) + if (INTERRUPT_REQUESTED(GetDebugger(), + "Interrupted in dump section list with {0} of {1} dumped.", + i, num_matches)) break; + Module *module = module_list.GetModulePointerAtIndex(i); if (module) { num_dumped++; @@ -2159,9 +2174,9 @@ protected: } const char *pcm_path = command.GetArgumentAtIndex(0); - FileSpec pcm_file{pcm_path}; + const FileSpec pcm_file{pcm_path}; - if (pcm_file.GetFileNameExtension().GetStringRef() != ".pcm") { + if (pcm_file.GetFileNameExtension() != ".pcm") { result.AppendError("file must have a .pcm extension"); return false; } @@ -2177,8 +2192,11 @@ protected: const char *clang_args[] = {"clang", pcm_path}; compiler.setInvocation(clang::createInvocation(clang_args)); - clang::DumpModuleInfoAction dump_module_info; - dump_module_info.OutputStream = &result.GetOutputStream().AsRawOstream(); + // Pass empty deleter to not attempt to free memory that was allocated + // outside of the current scope, possibly statically. + std::shared_ptr<llvm::raw_ostream> Out( + &result.GetOutputStream().AsRawOstream(), [](llvm::raw_ostream *) {}); + clang::DumpModuleInfoAction dump_module_info(Out); // DumpModuleInfoAction requires ObjectFilePCHContainerReader. compiler.getPCHContainerOperations()->registerReader( std::make_unique<clang::ObjectFilePCHContainerReader>()); @@ -2222,7 +2240,7 @@ protected: result.GetOutputStream().Format("Dumping clang ast for {0} modules.\n", num_modules); for (ModuleSP module_sp : module_list.ModulesNoLocking()) { - if (m_interpreter.WasInterrupted()) + if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted dumping clang ast")) break; if (SymbolFile *sf = module_sp->GetSymbolFile()) sf->DumpClangAST(result.GetOutputStream()); @@ -2247,8 +2265,11 @@ protected: } for (size_t i = 0; i < num_matches; ++i) { - if (m_interpreter.WasInterrupted()) + if (INTERRUPT_REQUESTED(GetDebugger(), + "Interrupted in dump clang ast list with {0} of {1} dumped.", + i, num_matches)) break; + Module *m = module_list.GetModulePointerAtIndex(i); if (SymbolFile *sf = m->GetSymbolFile()) sf->DumpClangAST(result.GetOutputStream()); @@ -2296,8 +2317,11 @@ protected: result.GetOutputStream().Format( "Dumping debug symbols for {0} modules.\n", num_modules); for (ModuleSP module_sp : target_modules.ModulesNoLocking()) { - if (m_interpreter.WasInterrupted()) + if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted in dumping all " + "debug symbols with {0} of {1} modules dumped", + num_dumped, num_modules)) break; + if (DumpModuleSymbolFile(result.GetOutputStream(), module_sp.get())) num_dumped++; } @@ -2312,7 +2336,9 @@ protected: FindModulesByName(target, arg_cstr, module_list, true); if (num_matches > 0) { for (size_t i = 0; i < num_matches; ++i) { - if (m_interpreter.WasInterrupted()) + if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted dumping {0} " + "of {1} requested modules", + i, num_matches)) break; Module *module = module_list.GetModulePointerAtIndex(i); if (module) { @@ -2376,11 +2402,16 @@ protected: const ModuleList &target_modules = target->GetImages(); std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); - if (target_modules.GetSize() > 0) { + size_t num_modules = target_modules.GetSize(); + if (num_modules > 0) { uint32_t num_dumped = 0; for (ModuleSP module_sp : target_modules.ModulesNoLocking()) { - if (m_interpreter.WasInterrupted()) + if (INTERRUPT_REQUESTED(GetDebugger(), + "Interrupted in dump all line tables with " + "{0} of {1} dumped", num_dumped, + num_modules)) break; + if (DumpCompileUnitLineTable( m_interpreter, result.GetOutputStream(), module_sp.get(), file_spec, @@ -2500,9 +2531,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); } protected: @@ -2533,7 +2563,7 @@ protected: return true; } else { StreamString strm; - module_spec.GetUUID().Dump(&strm); + module_spec.GetUUID().Dump(strm); if (module_spec.GetFileSpec()) { if (module_spec.GetSymbolFileSpec()) { result.AppendErrorWithFormat( @@ -2557,7 +2587,7 @@ protected: } } else { StreamString strm; - module_spec.GetUUID().Dump(&strm); + module_spec.GetUUID().Dump(strm); result.AppendErrorWithFormat( "Unable to locate the executable or symbol file with UUID %s", strm.GetData()); @@ -3363,16 +3393,13 @@ protected: return false; } - size_t num_matches = sc_list.GetSize(); - if (num_matches == 0) { + if (sc_list.GetSize() == 0) { result.AppendErrorWithFormat("no unwind data found that matches '%s'.", m_options.m_str.c_str()); return false; } - for (uint32_t idx = 0; idx < num_matches; idx++) { - SymbolContext sc; - sc_list.GetContextAtIndex(idx, sc); + for (const SymbolContext &sc : sc_list) { if (sc.symbol == nullptr && sc.function == nullptr) continue; if (!sc.module_sp || sc.module_sp->GetObjectFile() == nullptr) @@ -4034,8 +4061,8 @@ public: "target symbols add <cmd-options> [<symfile>]", eCommandRequiresTarget), m_file_option( - LLDB_OPT_SET_1, false, "shlib", 's', - CommandCompletions::eModuleCompletion, eArgTypeShlibName, + LLDB_OPT_SET_1, false, "shlib", 's', lldb::eModuleCompletion, + eArgTypeShlibName, "Locate the debug symbols for the shared library specified by " "name."), m_current_frame_option( @@ -4065,9 +4092,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); } Options *GetOptions() override { return &m_option_group; } @@ -4193,7 +4219,7 @@ protected: Status error; StreamString feedback_stream; module_sp->LoadScriptingResourceInTarget(target, error, - &feedback_stream); + feedback_stream); if (error.Fail() && error.AsCString()) result.AppendWarningWithFormat( "unable to load scripting data for module %s - error " @@ -4217,7 +4243,7 @@ protected: StreamString ss_symfile_uuid; if (module_spec.GetUUID().IsValid()) { ss_symfile_uuid << " ("; - module_spec.GetUUID().Dump(&ss_symfile_uuid); + module_spec.GetUUID().Dump(ss_symfile_uuid); ss_symfile_uuid << ')'; } result.AppendErrorWithFormat( @@ -4252,7 +4278,7 @@ protected: if (!DownloadObjectAndSymbolFile(module_spec, result, flush)) { StreamString error_strm; error_strm.PutCString("unable to find debug symbols for UUID "); - module_spec.GetUUID().Dump(&error_strm); + module_spec.GetUUID().Dump(error_strm); result.AppendError(error_strm.GetString()); return false; } @@ -4916,9 +4942,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eStopHookIDCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eStopHookIDCompletion, request, nullptr); } protected: @@ -4974,9 +4999,8 @@ public: OptionElementVector &opt_element_vector) override { if (request.GetCursorIndex()) return; - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eStopHookIDCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eStopHookIDCompletion, request, nullptr); } protected: @@ -5036,7 +5060,7 @@ protected: Target::StopHookSP this_hook = target.GetStopHookAtIndex(i); if (i > 0) result.GetOutputStream().PutCString("\n"); - this_hook->GetDescription(&(result.GetOutputStream()), + this_hook->GetDescription(result.GetOutputStream(), eDescriptionLevelFull); } } @@ -5084,8 +5108,8 @@ public: CommandObjectTargetDumpTypesystem(CommandInterpreter &interpreter) : CommandObjectParsed( interpreter, "target dump typesystem", - "Dump the state of the target's internal type system.\n" - "Intended to be used for debugging LLDB itself.", + "Dump the state of the target's internal type system. Intended to " + "be used for debugging LLDB itself.", nullptr, eCommandRequiresTarget) {} ~CommandObjectTargetDumpTypesystem() override = default; @@ -5102,6 +5126,29 @@ protected: } }; +#pragma mark CommandObjectTargetDumpSectionLoadList + +/// Dumps the SectionLoadList of the selected Target. +class CommandObjectTargetDumpSectionLoadList : public CommandObjectParsed { +public: + CommandObjectTargetDumpSectionLoadList(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "target dump section-load-list", + "Dump the state of the target's internal section load list. " + "Intended to be used for debugging LLDB itself.", + nullptr, eCommandRequiresTarget) {} + + ~CommandObjectTargetDumpSectionLoadList() override = default; + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + Target &target = GetSelectedTarget(); + target.GetSectionLoadList().Dump(result.GetOutputStream(), &target); + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } +}; + #pragma mark CommandObjectTargetDump /// Multi-word command for 'target dump'. @@ -5112,10 +5159,13 @@ public: : CommandObjectMultiword( interpreter, "target dump", "Commands for dumping information about the target.", - "target dump [typesystem]") { + "target dump [typesystem|section-load-list]") { LoadSubCommand( "typesystem", CommandObjectSP(new CommandObjectTargetDumpTypesystem(interpreter))); + LoadSubCommand("section-load-list", + CommandObjectSP(new CommandObjectTargetDumpSectionLoadList( + interpreter))); } ~CommandObjectTargetDump() override = default; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectThread.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectThread.cpp index 411f28d84a21..64f3edcad563 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectThread.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectThread.cpp @@ -228,8 +228,11 @@ protected: thread->GetIndexID()); return false; } - if (m_options.m_extended_backtrace) { - DoExtendedBacktrace(thread, result); + if (m_options.m_extended_backtrace) { + if (!INTERRUPT_REQUESTED(GetDebugger(), + "Interrupt skipped extended backtrace")) { + DoExtendedBacktrace(thread, result); + } } return true; @@ -401,9 +404,9 @@ public: if (request.GetCursorIndex()) return; - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eThreadIndexCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eThreadIndexCompletion, request, + nullptr); } Options *GetOptions() override { return &m_all_options; } @@ -556,8 +559,9 @@ protected: } else if (m_step_type == eStepTypeOut) { new_plan_sp = thread->QueueThreadPlanForStepOut( abort_other_plans, nullptr, false, bool_stop_other_threads, eVoteYes, - eVoteNoOpinion, thread->GetSelectedFrameIndex(), new_plan_status, - m_options.m_step_out_avoid_no_debug); + eVoteNoOpinion, + thread->GetSelectedFrameIndex(DoNoSelectMostRelevantFrame), + new_plan_status, m_options.m_step_out_avoid_no_debug); } else if (m_step_type == eStepTypeScripted) { new_plan_sp = thread->QueueThreadPlanForStepScripted( abort_other_plans, m_class_options.GetName().c_str(), @@ -663,9 +667,9 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eThreadIndexCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eThreadIndexCompletion, request, + nullptr); } bool DoExecute(Args &command, CommandReturnObject &result) override { @@ -1160,9 +1164,9 @@ public: if (request.GetCursorIndex()) return; - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eThreadIndexCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eThreadIndexCompletion, request, + nullptr); } protected: @@ -1294,9 +1298,9 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eThreadIndexCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eThreadIndexCompletion, request, + nullptr); } Options *GetOptions() override { return &m_options; } @@ -1344,9 +1348,9 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eThreadIndexCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eThreadIndexCompletion, request, + nullptr); } bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { @@ -1392,9 +1396,9 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eThreadIndexCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eThreadIndexCompletion, request, + nullptr); } bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { @@ -1527,7 +1531,8 @@ protected: bool success = thread->SetSelectedFrameByIndexNoisily(0, result.GetOutputStream()); if (success) { - m_exe_ctx.SetFrameSP(thread->GetSelectedFrame()); + m_exe_ctx.SetFrameSP( + thread->GetSelectedFrame(DoNoSelectMostRelevantFrame)); result.SetStatus(eReturnStatusSuccessFinishResult); } else { result.AppendErrorWithFormat( @@ -2418,7 +2423,7 @@ protected: } CommandOptions m_options; - // Last traversed id used to continue a repeat command. None means + // Last traversed id used to continue a repeat command. std::nullopt means // that all the trace has been consumed. std::optional<lldb::user_id_t> m_last_id; }; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectTrace.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectTrace.cpp index ba8289cb68d3..52fb56ffc1fb 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectTrace.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectTrace.cpp @@ -96,9 +96,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); } ~CommandObjectTraceSave() override = default; @@ -186,9 +185,8 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); } ~CommandObjectTraceLoad() override = default; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectType.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectType.cpp index 1120caa1da4c..e6dd63a6cb21 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectType.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectType.cpp @@ -39,9 +39,6 @@ #include <functional> #include <memory> -#define CHECK_FORMATTER_KIND_MASK(VAL) \ - ((m_formatter_kind_mask & (VAL)) == (VAL)) - using namespace lldb; using namespace lldb_private; @@ -100,6 +97,22 @@ static bool WarnOnPotentialUnquotedUnsignedType(Args &command, return false; } +const char *FormatCategoryToString(FormatCategoryItem item, bool long_name) { + switch (item) { + case eFormatCategoryItemSummary: + return "summary"; + case eFormatCategoryItemFilter: + return "filter"; + case eFormatCategoryItemSynth: + if (long_name) + return "synthetic child provider"; + return "synthetic"; + case eFormatCategoryItemFormat: + return "format"; + } + llvm_unreachable("Fully covered switch above!"); +} + #define LLDB_OPTIONS_type_summary_add #include "CommandOptions.inc" @@ -754,16 +767,25 @@ protected: }; CommandOptions m_options; - uint32_t m_formatter_kind_mask; + FormatCategoryItem m_formatter_kind; Options *GetOptions() override { return &m_options; } + static constexpr const char *g_short_help_template = + "Delete an existing %s for a type."; + + static constexpr const char *g_long_help_template = + "Delete an existing %s for a type. Unless you specify a " + "specific category or all categories, only the " + "'default' category is searched. The names must be exactly as " + "shown in the 'type %s list' output"; + public: CommandObjectTypeFormatterDelete(CommandInterpreter &interpreter, - uint32_t formatter_kind_mask, - const char *name, const char *help) - : CommandObjectParsed(interpreter, name, help, nullptr), - m_formatter_kind_mask(formatter_kind_mask) { + FormatCategoryItem formatter_kind) + : CommandObjectParsed(interpreter, + FormatCategoryToString(formatter_kind, false)), + m_formatter_kind(formatter_kind) { CommandArgumentEntry type_arg; CommandArgumentData type_style_arg; @@ -773,6 +795,19 @@ public: type_arg.push_back(type_style_arg); m_arguments.push_back(type_arg); + + const char *kind = FormatCategoryToString(formatter_kind, true); + const char *short_kind = FormatCategoryToString(formatter_kind, false); + + StreamString s; + s.Printf(g_short_help_template, kind); + SetHelp(s.GetData()); + s.Clear(); + s.Printf(g_long_help_template, kind, short_kind); + SetHelpLong(s.GetData()); + s.Clear(); + s.Printf("type %s delete", short_kind); + SetCommandName(s.GetData()); } ~CommandObjectTypeFormatterDelete() override = default; @@ -785,7 +820,7 @@ public: DataVisualization::Categories::ForEach( [this, &request](const lldb::TypeCategoryImplSP &category_sp) { - category_sp->AutoComplete(request, m_formatter_kind_mask); + category_sp->AutoComplete(request, m_formatter_kind); return true; }); } @@ -812,7 +847,7 @@ protected: if (m_options.m_delete_all) { DataVisualization::Categories::ForEach( [this, typeCS](const lldb::TypeCategoryImplSP &category_sp) -> bool { - category_sp->Delete(typeCS, m_formatter_kind_mask); + category_sp->Delete(typeCS, m_formatter_kind); return true; }); result.SetStatus(eReturnStatusSuccessFinishNoResult); @@ -827,14 +862,14 @@ protected: DataVisualization::Categories::GetCategory(m_options.m_language, category); if (category) - delete_category = category->Delete(typeCS, m_formatter_kind_mask); + delete_category = category->Delete(typeCS, m_formatter_kind); extra_deletion = FormatterSpecificDeletion(typeCS); } else { lldb::TypeCategoryImplSP category; DataVisualization::Categories::GetCategory( ConstString(m_options.m_category.c_str()), category); if (category) - delete_category = category->Delete(typeCS, m_formatter_kind_mask); + delete_category = category->Delete(typeCS, m_formatter_kind); extra_deletion = FormatterSpecificDeletion(typeCS); } @@ -888,16 +923,16 @@ private: }; CommandOptions m_options; - uint32_t m_formatter_kind_mask; + FormatCategoryItem m_formatter_kind; Options *GetOptions() override { return &m_options; } public: CommandObjectTypeFormatterClear(CommandInterpreter &interpreter, - uint32_t formatter_kind_mask, + FormatCategoryItem formatter_kind, const char *name, const char *help) : CommandObjectParsed(interpreter, name, help, nullptr), - m_formatter_kind_mask(formatter_kind_mask) { + m_formatter_kind(formatter_kind) { CommandArgumentData category_arg{eArgTypeName, eArgRepeatOptional}; m_arguments.push_back({category_arg}); } @@ -911,7 +946,7 @@ protected: if (m_options.m_delete_all) { DataVisualization::Categories::ForEach( [this](const TypeCategoryImplSP &category_sp) -> bool { - category_sp->Clear(m_formatter_kind_mask); + category_sp->Clear(m_formatter_kind); return true; }); } else { @@ -924,7 +959,7 @@ protected: DataVisualization::Categories::GetCategory(ConstString(nullptr), category); } - category->Clear(m_formatter_kind_mask); + category->Clear(m_formatter_kind); } FormatterSpecificDeletion(); @@ -940,8 +975,7 @@ class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete { public: CommandObjectTypeFormatDelete(CommandInterpreter &interpreter) : CommandObjectTypeFormatterDelete( - interpreter, eFormatCategoryItemFormat, "type format delete", - "Delete an existing formatting style for a type.") {} + interpreter, eFormatCategoryItemFormat) {} ~CommandObjectTypeFormatDelete() override = default; }; @@ -1609,8 +1643,7 @@ class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete { public: CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter) : CommandObjectTypeFormatterDelete( - interpreter, eFormatCategoryItemSummary, "type summary delete", - "Delete an existing summary for a type.") {} + interpreter, eFormatCategoryItemSummary) {} ~CommandObjectTypeSummaryDelete() override = default; @@ -1734,9 +1767,9 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), - CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion, request, + nullptr); } protected: @@ -1836,9 +1869,9 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), - CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion, request, + nullptr); } protected: @@ -1904,9 +1937,9 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), - CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion, request, + nullptr); } protected: @@ -2013,9 +2046,9 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), - CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion, request, + nullptr); } protected: @@ -2078,9 +2111,9 @@ public: OptionElementVector &opt_element_vector) override { if (request.GetCursorIndex()) return; - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), - CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion, request, + nullptr); } protected: @@ -2159,8 +2192,7 @@ class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete { public: CommandObjectTypeFilterDelete(CommandInterpreter &interpreter) : CommandObjectTypeFormatterDelete( - interpreter, eFormatCategoryItemFilter, "type filter delete", - "Delete an existing filter for a type.") {} + interpreter, eFormatCategoryItemFilter) {} ~CommandObjectTypeFilterDelete() override = default; }; @@ -2173,8 +2205,7 @@ class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete { public: CommandObjectTypeSynthDelete(CommandInterpreter &interpreter) : CommandObjectTypeFormatterDelete( - interpreter, eFormatCategoryItemSynth, "type synthetic delete", - "Delete an existing synthetic provider for a type.") {} + interpreter, eFormatCategoryItemSynth) {} ~CommandObjectTypeSynthDelete() override = default; }; @@ -2845,7 +2876,8 @@ protected: return false; } - StackFrameSP frame_sp = thread->GetSelectedFrame(); + StackFrameSP frame_sp = + thread->GetSelectedFrame(DoNoSelectMostRelevantFrame); ValueObjectSP result_valobj_sp; EvaluateExpressionOptions options; lldb::ExpressionResults expr_result = target_sp->EvaluateExpression( diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpoint.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpoint.cpp index 8df8aca04e4a..a4929ea0d515 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpoint.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpoint.cpp @@ -9,6 +9,7 @@ #include "CommandObjectWatchpoint.h" #include "CommandObjectWatchpointCommand.h" +#include <memory> #include <vector> #include "llvm/ADT/StringRef.h" @@ -20,6 +21,7 @@ #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Symbol/Function.h" #include "lldb/Symbol/Variable.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/StackFrame.h" @@ -29,12 +31,12 @@ using namespace lldb; using namespace lldb_private; -static void AddWatchpointDescription(Stream *s, Watchpoint *wp, +static void AddWatchpointDescription(Stream &s, Watchpoint &wp, lldb::DescriptionLevel level) { - s->IndentMore(); - wp->GetDescription(s, level); - s->IndentLess(); - s->EOL(); + s.IndentMore(); + wp.GetDescription(&s, level); + s.IndentLess(); + s.EOL(); } static bool CheckTargetForWatchpointOperations(Target *target, @@ -209,13 +211,13 @@ protected: Target *target = &GetSelectedTarget(); if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) { - uint32_t num_supported_hardware_watchpoints; - Status error = target->GetProcessSP()->GetWatchpointSupportInfo( - num_supported_hardware_watchpoints); - if (error.Success()) + std::optional<uint32_t> num_supported_hardware_watchpoints = + target->GetProcessSP()->GetWatchpointSlotCount(); + + if (num_supported_hardware_watchpoints) result.AppendMessageWithFormat( "Number of supported hardware watchpoints: %u\n", - num_supported_hardware_watchpoints); + *num_supported_hardware_watchpoints); } const WatchpointList &watchpoints = target->GetWatchpointList(); @@ -237,8 +239,8 @@ protected: // No watchpoint selected; show info about all currently set watchpoints. result.AppendMessage("Current watchpoints:"); for (size_t i = 0; i < num_watchpoints; ++i) { - Watchpoint *wp = watchpoints.GetByIndex(i).get(); - AddWatchpointDescription(&output_stream, wp, m_options.m_level); + WatchpointSP watch_sp = watchpoints.GetByIndex(i); + AddWatchpointDescription(output_stream, *watch_sp, m_options.m_level); } result.SetStatus(eReturnStatusSuccessFinishNoResult); } else { @@ -252,9 +254,9 @@ protected: const size_t size = wp_ids.size(); for (size_t i = 0; i < size; ++i) { - Watchpoint *wp = watchpoints.FindByID(wp_ids[i]).get(); - if (wp) - AddWatchpointDescription(&output_stream, wp, m_options.m_level); + WatchpointSP watch_sp = watchpoints.FindByID(wp_ids[i]); + if (watch_sp) + AddWatchpointDescription(output_stream, *watch_sp, m_options.m_level); result.SetStatus(eReturnStatusSuccessFinishNoResult); } } @@ -289,9 +291,9 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eWatchPointIDCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request, + nullptr); } protected: @@ -365,9 +367,9 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eWatchPointIDCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request, + nullptr); } protected: @@ -446,9 +448,9 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eWatchPointIDCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request, + nullptr); } Options *GetOptions() override { return &m_options; } @@ -569,9 +571,9 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eWatchPointIDCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request, + nullptr); } Options *GetOptions() override { return &m_options; } @@ -694,9 +696,9 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eWatchPointIDCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request, + nullptr); } Options *GetOptions() override { return &m_options; } @@ -758,8 +760,8 @@ protected: } if (command.GetArgumentCount() == 0) { - WatchpointSP wp_sp = target->GetLastCreatedWatchpoint(); - wp_sp->SetCondition(m_options.m_condition.c_str()); + WatchpointSP watch_sp = target->GetLastCreatedWatchpoint(); + watch_sp->SetCondition(m_options.m_condition.c_str()); result.SetStatus(eReturnStatusSuccessFinishNoResult); } else { // Particular watchpoints selected; set condition on them. @@ -773,9 +775,9 @@ protected: int count = 0; const size_t size = wp_ids.size(); for (size_t i = 0; i < size; ++i) { - WatchpointSP wp_sp = watchpoints.FindByID(wp_ids[i]); - if (wp_sp) { - wp_sp->SetCondition(m_options.m_condition.c_str()); + WatchpointSP watch_sp = watchpoints.FindByID(wp_ids[i]); + if (watch_sp) { + watch_sp->SetCondition(m_options.m_condition.c_str()); ++count; } } @@ -835,8 +837,7 @@ corresponding to the byte size of the data type."); m_arguments.push_back(arg); // Absorb the '-w' and '-s' options into our option group. - m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL, - LLDB_OPT_SET_1); + m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_1, LLDB_OPT_SET_1); m_option_group.Finalize(); } @@ -847,9 +848,9 @@ corresponding to the byte size of the data type."); OptionElementVector &opt_element_vector) override { if (request.GetCursorIndex() != 0) return; - CommandCompletions::InvokeCommonCompletionCallbacks( - GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion, - request, nullptr); + lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), lldb::eVariablePathCompletion, request, + nullptr); } Options *GetOptions() override { return &m_option_group; } @@ -949,30 +950,34 @@ protected: uint32_t watch_type = m_option_watchpoint.watch_type; error.Clear(); - Watchpoint *wp = - target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error) - .get(); - if (wp) { - wp->SetWatchSpec(command.GetArgumentAtIndex(0)); - wp->SetWatchVariable(true); - if (var_sp && var_sp->GetDeclaration().GetFile()) { + WatchpointSP watch_sp = + target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error); + if (!watch_sp) { + result.AppendErrorWithFormat( + "Watchpoint creation failed (addr=0x%" PRIx64 ", size=%" PRIu64 + ", variable expression='%s').\n", + addr, static_cast<uint64_t>(size), command.GetArgumentAtIndex(0)); + if (const char *error_message = error.AsCString(nullptr)) + result.AppendError(error_message); + return result.Succeeded(); + } + + watch_sp->SetWatchSpec(command.GetArgumentAtIndex(0)); + watch_sp->SetWatchVariable(true); + if (var_sp) { + if (var_sp->GetDeclaration().GetFile()) { StreamString ss; // True to show fullpath for declaration file. var_sp->GetDeclaration().DumpStopContext(&ss, true); - wp->SetDeclInfo(std::string(ss.GetString())); + watch_sp->SetDeclInfo(std::string(ss.GetString())); } - output_stream.Printf("Watchpoint created: "); - wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); - output_stream.EOL(); - result.SetStatus(eReturnStatusSuccessFinishResult); - } else { - result.AppendErrorWithFormat( - "Watchpoint creation failed (addr=0x%" PRIx64 ", size=%" PRIu64 - ", variable expression='%s').\n", - addr, (uint64_t)size, command.GetArgumentAtIndex(0)); - if (error.AsCString(nullptr)) - result.AppendError(error.AsCString()); + if (var_sp->GetScope() == eValueTypeVariableLocal) + watch_sp->SetupVariableWatchpointDisabler(m_exe_ctx.GetFrameSP()); } + output_stream.Printf("Watchpoint created: "); + watch_sp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); + output_stream.EOL(); + result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); } @@ -991,6 +996,7 @@ public: : CommandObjectRaw( interpreter, "watchpoint set expression", "Set a watchpoint on an address by supplying an expression. " + "Use the '-l' option to specify the language of the expression. " "Use the '-w' option to specify the type of watchpoint and " "the '-s' option to specify the byte size to watch for. " "If no '-w' option is specified, it defaults to write. " @@ -1084,6 +1090,8 @@ protected: options.SetKeepInMemory(false); options.SetTryAllThreads(true); options.SetTimeout(std::nullopt); + if (m_option_watchpoint.language_type != eLanguageTypeUnknown) + options.SetLanguage(m_option_watchpoint.language_type); ExpressionResults expr_result = target->EvaluateExpression(expr, frame, valobj_sp, options); @@ -1117,13 +1125,13 @@ protected: CompilerType compiler_type(valobj_sp->GetCompilerType()); Status error; - Watchpoint *wp = - target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error) - .get(); - if (wp) { + WatchpointSP watch_sp = + target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error); + if (watch_sp) { + watch_sp->SetWatchSpec(std::string(expr)); Stream &output_stream = result.GetOutputStream(); output_stream.Printf("Watchpoint created: "); - wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); + watch_sp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); output_stream.EOL(); result.SetStatus(eReturnStatusSuccessFinishResult); } else { diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpointCommand.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpointCommand.cpp index b33f403a6964..37052ddd62c8 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpointCommand.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpointCommand.cpp @@ -415,17 +415,18 @@ protected: // Special handling for one-liner specified inline. if (m_options.m_use_one_liner) { script_interp->SetWatchpointCommandCallback( - wp_options, m_options.m_one_liner.c_str()); + wp_options, m_options.m_one_liner.c_str(), + /*is_callback=*/false); } // Special handling for using a Python function by name instead of // extending the watchpoint callback data structures, we just // automatize what the user would do manually: make their watchpoint // command be a function call else if (!m_options.m_function_name.empty()) { - std::string oneliner(m_options.m_function_name); - oneliner += "(frame, wp, internal_dict)"; + std::string function_signature = m_options.m_function_name; + function_signature += "(frame, wp, internal_dict)"; script_interp->SetWatchpointCommandCallback( - wp_options, oneliner.c_str()); + wp_options, function_signature.c_str(), /*is_callback=*/true); } else { script_interp->CollectDataForWatchpointCommandCallback(wp_options, result); diff --git a/contrib/llvm-project/lldb/source/Commands/CommandOptionsProcessAttach.cpp b/contrib/llvm-project/lldb/source/Commands/CommandOptionsProcessAttach.cpp new file mode 100644 index 000000000000..d3d864dfe025 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Commands/CommandOptionsProcessAttach.cpp @@ -0,0 +1,76 @@ +//===-- CommandOptionsProcessAttach.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 "CommandOptionsProcessAttach.h" + +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Host/OptionParser.h" +#include "lldb/Interpreter/CommandCompletions.h" +#include "lldb/Interpreter/CommandObject.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" +#include "lldb/Interpreter/OptionArgParser.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Platform.h" +#include "lldb/Target/Target.h" + +#include "llvm/ADT/ArrayRef.h" + +using namespace llvm; +using namespace lldb; +using namespace lldb_private; + +#define LLDB_OPTIONS_process_attach +#include "CommandOptions.inc" + +Status CommandOptionsProcessAttach::SetOptionValue( + uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) { + Status error; + const int short_option = g_process_attach_options[option_idx].short_option; + switch (short_option) { + case 'c': + attach_info.SetContinueOnceAttached(true); + break; + + case 'p': { + lldb::pid_t pid; + if (option_arg.getAsInteger(0, pid)) { + error.SetErrorStringWithFormat("invalid process ID '%s'", + option_arg.str().c_str()); + } else { + attach_info.SetProcessID(pid); + } + } break; + + case 'P': + attach_info.SetProcessPluginName(option_arg); + break; + + case 'n': + attach_info.GetExecutableFile().SetFile(option_arg, + FileSpec::Style::native); + break; + + case 'w': + attach_info.SetWaitForLaunch(true); + break; + + case 'i': + attach_info.SetIgnoreExisting(false); + break; + + default: + llvm_unreachable("Unimplemented option"); + } + return error; +} + +llvm::ArrayRef<OptionDefinition> CommandOptionsProcessAttach::GetDefinitions() { + return llvm::ArrayRef(g_process_attach_options); +} diff --git a/contrib/llvm-project/lldb/source/Commands/CommandOptionsProcessAttach.h b/contrib/llvm-project/lldb/source/Commands/CommandOptionsProcessAttach.h new file mode 100644 index 000000000000..02daf1aa769a --- /dev/null +++ b/contrib/llvm-project/lldb/source/Commands/CommandOptionsProcessAttach.h @@ -0,0 +1,47 @@ +//===-- CommandOptionsProcessAttach.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_COMMANDS_COMMANDOPTIONSPROCESSATTACH_H +#define LLDB_SOURCE_COMMANDS_COMMANDOPTIONSPROCESSATTACH_H + +#include "lldb/Interpreter/Options.h" +#include "lldb/Target/Process.h" + +namespace lldb_private { + +// CommandOptionsProcessAttach + +class CommandOptionsProcessAttach : public lldb_private::OptionGroup { +public: + CommandOptionsProcessAttach() { + // Keep default values of all options in one place: OptionParsingStarting + // () + OptionParsingStarting(nullptr); + } + + ~CommandOptionsProcessAttach() override = default; + + lldb_private::Status + SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, + lldb_private::ExecutionContext *execution_context) override; + + void OptionParsingStarting( + lldb_private::ExecutionContext *execution_context) override { + attach_info.Clear(); + } + + llvm::ArrayRef<lldb_private::OptionDefinition> GetDefinitions() override; + + // Instance variables to hold the values for command options. + + lldb_private::ProcessAttachInfo attach_info; +}; // CommandOptionsProcessAttach + +} // namespace lldb_private + +#endif // LLDB_SOURCE_COMMANDS_COMMANDOPTIONSPROCESSATTACH_H diff --git a/contrib/llvm-project/lldb/source/Commands/Options.td b/contrib/llvm-project/lldb/source/Commands/Options.td index 6aee2ac22804..04830b8b990e 100644 --- a/contrib/llvm-project/lldb/source/Commands/Options.td +++ b/contrib/llvm-project/lldb/source/Commands/Options.td @@ -371,7 +371,7 @@ let Command = "expression" in { Arg<"Language">, Desc<"Specifies the Language to use when parsing the " "expression. If not set the target.language setting is used.">; def expression_options_apply_fixits : Option<"apply-fixits", "X">, - Groups<[1,2]>, Arg<"Language">, Desc<"If true, simple fix-it hints will be " + Groups<[1,2]>, Arg<"Boolean">, Desc<"If true, simple fix-it hints will be " "automatically applied to the expression.">; def expression_options_description_verbosity : Option<"description-verbosity", "v">, Group<1>, @@ -386,6 +386,11 @@ let Command = "expression" in { Arg<"Boolean">, Desc<"Controls whether the expression can fall back to being JITted if it's " "not supported by the interpreter (defaults to true).">; + def persistent_result : Option<"persistent-result", "\\x01">, Groups<[1,2]>, + Arg<"Boolean">, + Desc<"Persist expression result in a variable for subsequent use. " + "Expression results will be labeled with $-prefixed variables, e.g. $0, " + "$1, etc. Defaults to true.">; } let Command = "frame diag" in { @@ -799,6 +804,9 @@ let Command = "script add" in { EnumArg<"ScriptedCommandSynchronicity">, Desc<"Set the synchronicity of this command's executions with regard to " "LLDB event system.">; + def completion_type : Option<"completion-type", "C">, + EnumArg<"CompletionType">, + Desc<"Specify which completion type the command should use - if none is specified, the command won't use auto-completion.">; } let Command = "container add" in { |