https://github.com/medismailben updated https://github.com/llvm/llvm-project/pull/97273
>From 8e016c7aa66c4d5f7a90b5dc05b05c1838919177 Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani <ism...@bennani.ma> Date: Mon, 1 Jul 2024 12:00:04 -0700 Subject: [PATCH 1/2] [lldb/Commands] Alias `script` command to `scripting execute` This patch introduces a new top-level `scripting` command with an `execute` sub-command, that basically replaces the `script` raw command. To avoid breaking the `script` command usages, this patch also adds an `script` alias to the `scripting execute` sub-command. The reason behind this change is to have a top-level command that will cover scripting related subcommands. Signed-off-by: Med Ismail Bennani <ism...@bennani.ma> --- lldb/source/Commands/CMakeLists.txt | 2 +- ...tScript.cpp => CommandObjectScripting.cpp} | 44 +++++++++++++------ ...bjectScript.h => CommandObjectScripting.h} | 17 ++++--- lldb/source/Commands/Options.td | 2 +- .../source/Interpreter/CommandInterpreter.cpp | 13 +++++- .../abbreviation/TestAbbreviations.py | 4 +- 6 files changed, 59 insertions(+), 23 deletions(-) rename lldb/source/Commands/{CommandObjectScript.cpp => CommandObjectScripting.cpp} (68%) rename lldb/source/Commands/{CommandObjectScript.h => CommandObjectScripting.h} (71%) diff --git a/lldb/source/Commands/CMakeLists.txt b/lldb/source/Commands/CMakeLists.txt index 6a36c5376d5c5..76397227d535d 100644 --- a/lldb/source/Commands/CMakeLists.txt +++ b/lldb/source/Commands/CMakeLists.txt @@ -26,7 +26,7 @@ add_lldb_library(lldbCommands NO_PLUGIN_DEPENDENCIES CommandObjectQuit.cpp CommandObjectRegexCommand.cpp CommandObjectRegister.cpp - CommandObjectScript.cpp + CommandObjectScripting.cpp CommandObjectSession.cpp CommandObjectSettings.cpp CommandObjectSource.cpp diff --git a/lldb/source/Commands/CommandObjectScript.cpp b/lldb/source/Commands/CommandObjectScripting.cpp similarity index 68% rename from lldb/source/Commands/CommandObjectScript.cpp rename to lldb/source/Commands/CommandObjectScripting.cpp index 25f25b8e65947..72f653690e532 100644 --- a/lldb/source/Commands/CommandObjectScript.cpp +++ b/lldb/source/Commands/CommandObjectScripting.cpp @@ -1,4 +1,4 @@ -//===-- CommandObjectScript.cpp -------------------------------------------===// +//===-- CommandObjectScripting.cpp ----------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "CommandObjectScript.h" +#include "CommandObjectScripting.h" #include "lldb/Core/Debugger.h" #include "lldb/DataFormatters/DataVisualization.h" #include "lldb/Host/Config.h" @@ -21,10 +21,10 @@ using namespace lldb; using namespace lldb_private; -#define LLDB_OPTIONS_script +#define LLDB_OPTIONS_scripting_execute #include "CommandOptions.inc" -Status CommandObjectScript::CommandOptions::SetOptionValue( +Status CommandObjectScriptingExecute::CommandOptions::SetOptionValue( uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) { Status error; @@ -46,27 +46,29 @@ Status CommandObjectScript::CommandOptions::SetOptionValue( return error; } -void CommandObjectScript::CommandOptions::OptionParsingStarting( +void CommandObjectScriptingExecute::CommandOptions::OptionParsingStarting( ExecutionContext *execution_context) { language = lldb::eScriptLanguageNone; } llvm::ArrayRef<OptionDefinition> -CommandObjectScript::CommandOptions::GetDefinitions() { - return llvm::ArrayRef(g_script_options); +CommandObjectScriptingExecute::CommandOptions::GetDefinitions() { + return llvm::ArrayRef(g_scripting_execute_options); } -CommandObjectScript::CommandObjectScript(CommandInterpreter &interpreter) +CommandObjectScriptingExecute::CommandObjectScriptingExecute( + CommandInterpreter &interpreter) : CommandObjectRaw( - interpreter, "script", + interpreter, "scripting execute", "Invoke the script interpreter with provided code and display any " "results. Start the interactive interpreter if no code is supplied.", - "script [--language <scripting-language> --] [<script-code>]") {} + "scripting execute [--language <scripting-language> --] " + "[<script-code>]") {} -CommandObjectScript::~CommandObjectScript() = default; +CommandObjectScriptingExecute::~CommandObjectScriptingExecute() = default; -void CommandObjectScript::DoExecute(llvm::StringRef command, - CommandReturnObject &result) { +void CommandObjectScriptingExecute::DoExecute(llvm::StringRef command, + CommandReturnObject &result) { // Try parsing the language option but when the command contains a raw part // separated by the -- delimiter. OptionsWithRaw raw_args(command); @@ -111,3 +113,19 @@ void CommandObjectScript::DoExecute(llvm::StringRef command, else result.SetStatus(eReturnStatusFailed); } + +#pragma mark CommandObjectMultiwordScripting + +// CommandObjectMultiwordScripting + +CommandObjectMultiwordScripting::CommandObjectMultiwordScripting( + CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "scripting", + "Commands for operating on the scripting functionnalities.", + "scripting <subcommand> [<subcommand-options>]") { + LoadSubCommand("execute", CommandObjectSP(new CommandObjectScriptingExecute( + interpreter))); +} + +CommandObjectMultiwordScripting::~CommandObjectMultiwordScripting() = default; diff --git a/lldb/source/Commands/CommandObjectScript.h b/lldb/source/Commands/CommandObjectScripting.h similarity index 71% rename from lldb/source/Commands/CommandObjectScript.h rename to lldb/source/Commands/CommandObjectScripting.h index 3a8c4a890404a..b4a8a32cb644a 100644 --- a/lldb/source/Commands/CommandObjectScript.h +++ b/lldb/source/Commands/CommandObjectScripting.h @@ -1,4 +1,4 @@ -//===-- CommandObjectScript.h -----------------------------------*- C++ -*-===// +//===-- CommandObjectScripting.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. @@ -9,14 +9,21 @@ #ifndef LLDB_SOURCE_INTERPRETER_COMMANDOBJECTSCRIPT_H #define LLDB_SOURCE_INTERPRETER_COMMANDOBJECTSCRIPT_H -#include "lldb/Interpreter/CommandObject.h" +#include "lldb/Interpreter/CommandObjectMultiword.h" namespace lldb_private { -class CommandObjectScript : public CommandObjectRaw { +class CommandObjectMultiwordScripting : public CommandObjectMultiword { public: - CommandObjectScript(CommandInterpreter &interpreter); - ~CommandObjectScript() override; + CommandObjectMultiwordScripting(CommandInterpreter &interpreter); + + ~CommandObjectMultiwordScripting() override; +}; + +class CommandObjectScriptingExecute : public CommandObjectRaw { +public: + CommandObjectScriptingExecute(CommandInterpreter &interpreter); + ~CommandObjectScriptingExecute() override; Options *GetOptions() override { return &m_options; } class CommandOptions : public Options { diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index fa8af7cb3d762..752121ee6edb2 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -835,7 +835,7 @@ let Command = "container add" in { Desc<"Overwrite an existing command at this node.">; } -let Command = "script" in { +let Command = "scripting execute" in { def script_language : Option<"language", "l">, EnumArg<"ScriptLang">, Desc<"Specify the scripting " " language. If none is specific the default scripting language is used.">; diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index 40c915b2c94fc..6b701591d0326 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -33,7 +33,7 @@ #include "Commands/CommandObjectQuit.h" #include "Commands/CommandObjectRegexCommand.h" #include "Commands/CommandObjectRegister.h" -#include "Commands/CommandObjectScript.h" +#include "Commands/CommandObjectScripting.h" #include "Commands/CommandObjectSession.h" #include "Commands/CommandObjectSettings.h" #include "Commands/CommandObjectSource.h" @@ -518,6 +518,15 @@ void CommandInterpreter::Initialize() { AddAlias("re", cmd_obj_sp); } + cmd_obj_sp = GetCommandSPExact("scripting execute"); + if (cmd_obj_sp) { + AddAlias("sc", cmd_obj_sp); + AddAlias("scr", cmd_obj_sp); + AddAlias("scri", cmd_obj_sp); + AddAlias("scrip", cmd_obj_sp); + AddAlias("script", cmd_obj_sp); + } + cmd_obj_sp = GetCommandSPExact("session history"); if (cmd_obj_sp) { AddAlias("history", cmd_obj_sp); @@ -569,7 +578,7 @@ void CommandInterpreter::LoadCommandDictionary() { REGISTER_COMMAND_OBJECT("process", CommandObjectMultiwordProcess); REGISTER_COMMAND_OBJECT("quit", CommandObjectQuit); REGISTER_COMMAND_OBJECT("register", CommandObjectRegister); - REGISTER_COMMAND_OBJECT("script", CommandObjectScript); + REGISTER_COMMAND_OBJECT("scripting", CommandObjectMultiwordScripting); REGISTER_COMMAND_OBJECT("settings", CommandObjectMultiwordSettings); REGISTER_COMMAND_OBJECT("session", CommandObjectSession); REGISTER_COMMAND_OBJECT("source", CommandObjectMultiwordSource); diff --git a/lldb/test/API/functionalities/abbreviation/TestAbbreviations.py b/lldb/test/API/functionalities/abbreviation/TestAbbreviations.py index 10431e41dc81a..cd9b6c69a8ee3 100644 --- a/lldb/test/API/functionalities/abbreviation/TestAbbreviations.py +++ b/lldb/test/API/functionalities/abbreviation/TestAbbreviations.py @@ -80,7 +80,9 @@ def test_command_abbreviations_and_aliases(self): # Check a command that wants the raw input. command_interpreter.ResolveCommand(r"""sc print("\n\n\tHello!\n")""", result) self.assertTrue(result.Succeeded()) - self.assertEqual(r"""script print("\n\n\tHello!\n")""", result.GetOutput()) + self.assertEqual( + r"""scripting execute print("\n\n\tHello!\n")""", result.GetOutput() + ) # Prompt changing stuff should be tested, but this doesn't seem like the # right test to do it in. It has nothing to do with aliases or abbreviations. >From 55e53e4a33db36d9f207d230112aed907a2dd9cf Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani <ism...@bennani.ma> Date: Mon, 1 Jul 2024 02:54:33 -0700 Subject: [PATCH 2/2] [lldb/Commands] Add `scripting template list` command with auto discovery This patch introduces a new `template` multiword sub-command to the `scripting` top-level command. As the name suggests, this sub-command operates on scripting templates, and currently has the ability to automatically discover the various scripting extensions that lldb supports. Signed-off-by: Med Ismail Bennani <ism...@bennani.ma> --- lldb/include/lldb/Core/PluginManager.h | 25 +++ .../Interfaces/ScriptedInterface.h | 7 + lldb/include/lldb/lldb-private-interfaces.h | 4 + .../Commands/CommandObjectScripting.cpp | 159 ++++++++++++++++++ lldb/source/Commands/CommandObjectScripting.h | 31 ++++ lldb/source/Commands/Options.td | 8 +- lldb/source/Core/PluginManager.cpp | 83 +++++++++ lldb/source/Plugins/CMakeLists.txt | 3 + .../Python/Interfaces/CMakeLists.txt | 5 + .../ScriptedProcessPythonInterface.cpp | 23 +++ .../ScriptedProcessPythonInterface.h | 13 +- .../ScriptedThreadPlanPythonInterface.cpp | 18 ++ .../ScriptedThreadPlanPythonInterface.h | 13 +- 13 files changed, 389 insertions(+), 3 deletions(-) diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h index f2296e2920238..df20109e791a5 100644 --- a/lldb/include/lldb/Core/PluginManager.h +++ b/lldb/include/lldb/Core/PluginManager.h @@ -487,6 +487,31 @@ class PluginManager { static LanguageSet GetAllTypeSystemSupportedLanguagesForExpressions(); + // Scripted Interface + static bool + RegisterPlugin(llvm::StringRef name, llvm::StringRef description, + ScriptedInterfaceCreateInstance create_callback, + lldb::ScriptLanguage language, + std::vector<llvm::StringRef> command_interpreter_usages, + std::vector<llvm::StringRef> api_usages); + + static bool UnregisterPlugin(ScriptedInterfaceCreateInstance create_callback); + + static ScriptedInterfaceCreateInstance + GetScriptedInterfaceCreateCallbackAtIndex(uint32_t idx); + + static llvm::StringRef GetScriptedInterfaceNameAtIndex(uint32_t idx); + + static llvm::StringRef GetScriptedInterfaceDescriptionAtIndex(uint32_t idx); + + static lldb::ScriptLanguage GetScriptedInterfaceLanguageAtIndex(uint32_t idx); + + static std::vector<llvm::StringRef> + GetScriptedInterfaceCommandInterpreterUsagesAtIndex(uint32_t idx); + + static std::vector<llvm::StringRef> + GetScriptedInterfaceAPIUsagesAtIndex(uint32_t idx); + // REPL static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, REPLCreateInstance create_callback, diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h index 69504dbcda5dc..23658b90bb90a 100644 --- a/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h +++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h @@ -68,6 +68,13 @@ class ScriptedInterface { return true; } + static bool + CreateInstance(lldb::ScriptLanguage language, + std::vector<llvm::StringRef> command_interpreter_usages, + std::vector<llvm::StringRef> api_usages) { + return false; + } + protected: StructuredData::GenericSP m_object_instance_sp; }; diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h index cdd9b51d9329c..2404e28158690 100644 --- a/lldb/include/lldb/lldb-private-interfaces.h +++ b/lldb/include/lldb/lldb-private-interfaces.h @@ -124,6 +124,10 @@ typedef lldb::REPLSP (*REPLCreateInstance)(Status &error, lldb::LanguageType language, Debugger *debugger, Target *target, const char *repl_options); +typedef bool (*ScriptedInterfaceCreateInstance)( + lldb::ScriptLanguage language, + std::vector<llvm::StringRef> command_interpreter_usages, + std::vector<llvm::StringRef> api_usages); typedef int (*ComparisonFunction)(const void *, const void *); typedef void (*DebuggerInitializeCallback)(Debugger &debugger); /// Trace diff --git a/lldb/source/Commands/CommandObjectScripting.cpp b/lldb/source/Commands/CommandObjectScripting.cpp index 72f653690e532..f03c93ed1ef9d 100644 --- a/lldb/source/Commands/CommandObjectScripting.cpp +++ b/lldb/source/Commands/CommandObjectScripting.cpp @@ -8,6 +8,7 @@ #include "CommandObjectScripting.h" #include "lldb/Core/Debugger.h" +#include "lldb/Core/PluginManager.h" #include "lldb/DataFormatters/DataVisualization.h" #include "lldb/Host/Config.h" #include "lldb/Host/OptionParser.h" @@ -21,6 +22,8 @@ using namespace lldb; using namespace lldb_private; +#pragma mark CommandObjectScriptingExecute + #define LLDB_OPTIONS_scripting_execute #include "CommandOptions.inc" @@ -114,6 +117,159 @@ void CommandObjectScriptingExecute::DoExecute(llvm::StringRef command, result.SetStatus(eReturnStatusFailed); } +#pragma mark CommandObjectScriptingTemplateList + +#define LLDB_OPTIONS_scripting_template_list +#include "CommandOptions.inc" + +Status CommandObjectScriptingTemplateList::CommandOptions::SetOptionValue( + uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) { + Status error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'l': + language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum( + option_arg, GetDefinitions()[option_idx].enum_values, + eScriptLanguageNone, error); + if (!error.Success()) + error.SetErrorStringWithFormat("unrecognized value for language '%s'", + option_arg.str().c_str()); + break; + default: + llvm_unreachable("Unimplemented option"); + } + + return error; +} + +void CommandObjectScriptingTemplateList::CommandOptions::OptionParsingStarting( + ExecutionContext *execution_context) { + language = lldb::eScriptLanguageNone; +} + +llvm::ArrayRef<OptionDefinition> +CommandObjectScriptingTemplateList::CommandOptions::GetDefinitions() { + return llvm::ArrayRef(g_scripting_execute_options); +} + +CommandObjectScriptingTemplateList::CommandObjectScriptingTemplateList( + CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "scripting template list", + "List all the available scripting affordances templates. ", + "scripting template list [--language <scripting-language> --]") {} + +CommandObjectScriptingTemplateList::~CommandObjectScriptingTemplateList() = + default; + +void CommandObjectScriptingTemplateList::DoExecute( + Args &command, CommandReturnObject &result) { + lldb::ScriptLanguage language = + (m_options.language == lldb::eScriptLanguageNone) + ? m_interpreter.GetDebugger().GetScriptLanguage() + : m_options.language; + + if (language == lldb::eScriptLanguageNone) { + result.AppendError( + "the script-lang setting is set to none - scripting not available"); + return; + } + + ScriptInterpreter *script_interpreter = + GetDebugger().GetScriptInterpreter(true, language); + + if (script_interpreter == nullptr) { + result.AppendError("no script interpreter"); + return; + } + + Stream &s = result.GetOutputStream(); + s.Printf("Available scripted affordances:\n"); + + auto print_field = [&s](llvm::StringRef key, llvm::StringRef value, + bool check_validy = false) { + if (!check_validy || !value.empty()) { + s.IndentMore(); + s.Indent(); + s << key << ": " << value << '\n'; + s.IndentLess(); + } + }; + auto print_usages = [&s](llvm::StringRef usage_kind, + std::vector<llvm::StringRef> &usages) { + s.IndentMore(); + s.Indent(); + s << usage_kind << " Usages:"; + if (usages.empty()) + s << " No usages.\n"; + else if (usages.size() == 1) + s << " " << usages.front() << '\n'; + else { + s << '\n'; + for (llvm::StringRef usage : usages) { + s.IndentMore(); + s.Indent(); + s << usage << '\n'; + s.IndentLess(); + } + } + s.IndentLess(); + }; + + size_t i = 0; + for (llvm::StringRef plugin_name = + PluginManager::GetScriptedInterfaceNameAtIndex(i); + !plugin_name.empty();) { + + llvm::StringRef desc = + PluginManager::GetScriptedInterfaceDescriptionAtIndex(i); + lldb::ScriptLanguage lang = + PluginManager::GetScriptedInterfaceLanguageAtIndex(i); + std::vector<llvm::StringRef> ci_usages = + PluginManager::GetScriptedInterfaceCommandInterpreterUsagesAtIndex(i); + std::vector<llvm::StringRef> api_usages = + PluginManager::GetScriptedInterfaceAPIUsagesAtIndex(i); + + print_field("Name", plugin_name); + switch (lang) { + case eScriptLanguagePython: + print_field("Language", "Python"); + break; + case eScriptLanguageLua: + print_field("Language", "Lua"); + break; + default: + break; + } + print_field("Description", desc); + print_usages("Command Interpreter", ci_usages); + print_usages("API", api_usages); + + plugin_name = PluginManager::GetScriptedInterfaceNameAtIndex(++i); + if (!plugin_name.empty()) + s.EOL(); + } +} + +#pragma mark CommandObjectMultiwordScriptingTemplate + +// CommandObjectMultiwordScriptingTemplate + +CommandObjectMultiwordScriptingTemplate:: + CommandObjectMultiwordScriptingTemplate(CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "scripting template", + "Commands for operating on the scripting templates.", + "scripting template [<subcommand-options>]") { + LoadSubCommand("list", CommandObjectSP(new CommandObjectScriptingTemplateList( + interpreter))); +} + +CommandObjectMultiwordScriptingTemplate:: + ~CommandObjectMultiwordScriptingTemplate() = default; + #pragma mark CommandObjectMultiwordScripting // CommandObjectMultiwordScripting @@ -126,6 +282,9 @@ CommandObjectMultiwordScripting::CommandObjectMultiwordScripting( "scripting <subcommand> [<subcommand-options>]") { LoadSubCommand("execute", CommandObjectSP(new CommandObjectScriptingExecute( interpreter))); + LoadSubCommand("template", + CommandObjectSP( + new CommandObjectMultiwordScriptingTemplate(interpreter))); } CommandObjectMultiwordScripting::~CommandObjectMultiwordScripting() = default; diff --git a/lldb/source/Commands/CommandObjectScripting.h b/lldb/source/Commands/CommandObjectScripting.h index b4a8a32cb644a..a9af6ee62e298 100644 --- a/lldb/source/Commands/CommandObjectScripting.h +++ b/lldb/source/Commands/CommandObjectScripting.h @@ -44,6 +44,37 @@ class CommandObjectScriptingExecute : public CommandObjectRaw { CommandOptions m_options; }; +class CommandObjectMultiwordScriptingTemplate : public CommandObjectMultiword { +public: + CommandObjectMultiwordScriptingTemplate(CommandInterpreter &interpreter); + + ~CommandObjectMultiwordScriptingTemplate() override; +}; + +class CommandObjectScriptingTemplateList : public CommandObjectParsed { +public: + CommandObjectScriptingTemplateList(CommandInterpreter &interpreter); + ~CommandObjectScriptingTemplateList() override; + Options *GetOptions() override { return &m_options; } + + class CommandOptions : public Options { + public: + CommandOptions() = default; + ~CommandOptions() override = default; + Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) override; + void OptionParsingStarting(ExecutionContext *execution_context) override; + llvm::ArrayRef<OptionDefinition> GetDefinitions() override; + lldb::ScriptLanguage language = lldb::eScriptLanguageNone; + }; + +protected: + void DoExecute(Args &command, CommandReturnObject &result) override; + +private: + CommandOptions m_options; +}; + } // namespace lldb_private #endif // LLDB_SOURCE_INTERPRETER_COMMANDOBJECTSCRIPT_H diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index 752121ee6edb2..8eb17295e6df8 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -836,7 +836,13 @@ let Command = "container add" in { } let Command = "scripting execute" in { - def script_language : Option<"language", "l">, + def scripting_execute_language : Option<"language", "l">, + EnumArg<"ScriptLang">, Desc<"Specify the scripting " + " language. If none is specific the default scripting language is used.">; +} + +let Command = "scripting template list" in { + def scripting_template_list_language : Option<"language", "l">, EnumArg<"ScriptLang">, Desc<"Specify the scripting " " language. If none is specific the default scripting language is used.">; } diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp index b428370d7f333..2387d2ab6426b 100644 --- a/lldb/source/Core/PluginManager.cpp +++ b/lldb/source/Core/PluginManager.cpp @@ -1479,6 +1479,88 @@ LanguageSet PluginManager::GetAllTypeSystemSupportedLanguagesForExpressions() { return all; } +#pragma mark ScriptedInterfaces + +struct ScriptedInterfaceInstance + : public PluginInstance<ScriptedInterfaceCreateInstance> { + ScriptedInterfaceInstance( + llvm::StringRef name, llvm::StringRef description, + ScriptedInterfaceCreateInstance create_callback, + lldb::ScriptLanguage language, + std::vector<llvm::StringRef> command_interpreter_usages, + std::vector<llvm::StringRef> api_usages) + : PluginInstance<ScriptedInterfaceCreateInstance>(name, description, + create_callback), + language(language), + command_interpreter_usages(command_interpreter_usages), + api_usages(api_usages) {} + + lldb::ScriptLanguage language; + std::vector<llvm::StringRef> command_interpreter_usages; + std::vector<llvm::StringRef> api_usages; +}; + +typedef PluginInstances<ScriptedInterfaceInstance> ScriptedInterfaceInstances; + +static ScriptedInterfaceInstances &GetScriptedInterfaceInstances() { + static ScriptedInterfaceInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin( + llvm::StringRef name, llvm::StringRef description, + ScriptedInterfaceCreateInstance create_callback, + lldb::ScriptLanguage language, + std::vector<llvm::StringRef> command_interpreter_usages, + std::vector<llvm::StringRef> api_usages) { + return GetScriptedInterfaceInstances().RegisterPlugin( + name, description, create_callback, language, command_interpreter_usages, + api_usages); +} + +bool PluginManager::UnregisterPlugin( + ScriptedInterfaceCreateInstance create_callback) { + return GetScriptedInterfaceInstances().UnregisterPlugin(create_callback); +} + +ScriptedInterfaceCreateInstance +PluginManager::GetScriptedInterfaceCreateCallbackAtIndex(uint32_t idx) { + return GetScriptedInterfaceInstances().GetCallbackAtIndex(idx); +} + +llvm::StringRef PluginManager::GetScriptedInterfaceNameAtIndex(uint32_t index) { + return GetScriptedInterfaceInstances().GetNameAtIndex(index); +} + +llvm::StringRef +PluginManager::GetScriptedInterfaceDescriptionAtIndex(uint32_t index) { + return GetScriptedInterfaceInstances().GetDescriptionAtIndex(index); +} + +lldb::ScriptLanguage +PluginManager::GetScriptedInterfaceLanguageAtIndex(uint32_t idx) { + const auto &instances = GetScriptedInterfaceInstances().GetInstances(); + return idx < instances.size() ? instances[idx].language + : ScriptLanguage::eScriptLanguageNone; +} + +std::vector<llvm::StringRef> +PluginManager::GetScriptedInterfaceCommandInterpreterUsagesAtIndex( + uint32_t idx) { + const auto &instances = GetScriptedInterfaceInstances().GetInstances(); + if (idx >= instances.size()) + return {}; + return instances[idx].command_interpreter_usages; +} + +std::vector<llvm::StringRef> +PluginManager::GetScriptedInterfaceAPIUsagesAtIndex(uint32_t idx) { + const auto &instances = GetScriptedInterfaceInstances().GetInstances(); + if (idx >= instances.size()) + return {}; + return instances[idx].api_usages; +} + #pragma mark REPL struct REPLInstance : public PluginInstance<REPLCreateInstance> { @@ -1539,6 +1621,7 @@ void PluginManager::DebuggerInitialize(Debugger &debugger) { GetOperatingSystemInstances().PerformDebuggerCallback(debugger); GetStructuredDataPluginInstances().PerformDebuggerCallback(debugger); GetTracePluginInstances().PerformDebuggerCallback(debugger); + GetScriptedInterfaceInstances().PerformDebuggerCallback(debugger); } // This is the preferred new way to register plugin specific settings. e.g. diff --git a/lldb/source/Plugins/CMakeLists.txt b/lldb/source/Plugins/CMakeLists.txt index 854f589f45ae0..34dd8c1eb22f6 100644 --- a/lldb/source/Plugins/CMakeLists.txt +++ b/lldb/source/Plugins/CMakeLists.txt @@ -29,6 +29,9 @@ add_subdirectory(UnwindAssembly) set(LLDB_STRIPPED_PLUGINS) get_property(LLDB_ALL_PLUGINS GLOBAL PROPERTY LLDB_PLUGINS) +get_property(LLDB_EXTRA_PLUGINS GLOBAL PROPERTY LLDB_EXTRA_SCRIPT_PLUGINS) +list(APPEND LLDB_ALL_PLUGINS ${LLDB_EXTRA_PLUGINS}) + set(LLDB_ENUM_PLUGINS "") diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt index c60e4bb503a37..c0ee9c8d0654d 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt @@ -19,6 +19,11 @@ if (LLDB_ENABLE_LIBEDIT) list(APPEND LLDB_LIBEDIT_LIBS LibEdit::LibEdit) endif() +set_property(GLOBAL PROPERTY LLDB_EXTRA_SCRIPT_PLUGINS + lldbPluginScriptedProcessPythonInterface + lldbPluginScriptedThreadPlanPythonInterface +) + add_lldb_library(lldbPluginScriptInterpreterPythonInterfaces OperatingSystemPythonInterface.cpp ScriptedPythonInterface.cpp diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp index 313c597ce48f3..1464467fb3797 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp @@ -11,6 +11,7 @@ // LLDB Python header must be included first #include "../lldb-python.h" #endif +#include "lldb/Core/PluginManager.h" #include "lldb/Target/Process.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" @@ -29,6 +30,8 @@ using namespace lldb_private; using namespace lldb_private::python; using Locker = ScriptInterpreterPythonImpl::Locker; +LLDB_PLUGIN_DEFINE(ScriptedProcessPythonInterface) + ScriptedProcessPythonInterface::ScriptedProcessPythonInterface( ScriptInterpreterPythonImpl &interpreter) : ScriptedProcessInterface(), ScriptedPythonInterface(interpreter) {} @@ -208,4 +211,24 @@ StructuredData::DictionarySP ScriptedProcessPythonInterface::GetMetadata() { return dict; } +void ScriptedProcessPythonInterface::Initialize() { + const std::vector<llvm::StringRef> ci_usages = { + "process attach -C <script-name> [-k key -v value ...]", + "process launch -C <script-name> [-k key -v value ...]"}; + const std::vector<llvm::StringRef> api_usages = { + "SBAttachInfo.SetScriptedProcessClassName", + "SBAttachInfo.SetScriptedProcessDictionary", + "SBTarget.Attach", + "SBLaunchInfo.SetScriptedProcessClassName", + "SBLaunchInfo.SetScriptedProcessDictionary", + "SBTarget.Launch"}; + PluginManager::RegisterPlugin( + GetPluginNameStatic(), llvm::StringRef("Mock process state"), + CreateInstance, eScriptLanguagePython, ci_usages, api_usages); +} + +void ScriptedProcessPythonInterface::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + #endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h index c75caa9340f25..8bfc3f2c0757c 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h @@ -19,7 +19,8 @@ namespace lldb_private { class ScriptedProcessPythonInterface : public ScriptedProcessInterface, - public ScriptedPythonInterface { + public ScriptedPythonInterface, + public PluginInterface { public: ScriptedProcessPythonInterface(ScriptInterpreterPythonImpl &interpreter); @@ -67,6 +68,16 @@ class ScriptedProcessPythonInterface : public ScriptedProcessInterface, StructuredData::DictionarySP GetMetadata() override; + static void Initialize(); + + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { + return "ScriptedProcessPythonInterface"; + } + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + private: lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override; }; diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp index f23858c01277c..05b7fbaa37af3 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp @@ -18,11 +18,14 @@ #include "../SWIGPythonBridge.h" #include "../ScriptInterpreterPythonImpl.h" #include "ScriptedThreadPlanPythonInterface.h" +#include "lldb/Core/PluginManager.h" using namespace lldb; using namespace lldb_private; using namespace lldb_private::python; +LLDB_PLUGIN_DEFINE(ScriptedThreadPlanPythonInterface) + ScriptedThreadPlanPythonInterface::ScriptedThreadPlanPythonInterface( ScriptInterpreterPythonImpl &interpreter) : ScriptedThreadPlanInterface(), ScriptedPythonInterface(interpreter) {} @@ -102,4 +105,19 @@ ScriptedThreadPlanPythonInterface::GetStopDescription(lldb::StreamSP &stream) { return llvm::Error::success(); } +void ScriptedThreadPlanPythonInterface::Initialize() { + const std::vector<llvm::StringRef> ci_usages = { + "thread step-scripted -C <script-name> [-k key -v value ...]"}; + const std::vector<llvm::StringRef> api_usages = { + "SBThread.StepUsingScriptedThreadPlan"}; + PluginManager::RegisterPlugin( + GetPluginNameStatic(), + llvm::StringRef("Alter thread stepping logic and stop reason"), + CreateInstance, eScriptLanguagePython, ci_usages, api_usages); +} + +void ScriptedThreadPlanPythonInterface::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + #endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h index 6ec89b9f59253..4dc4607fb9c9d 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h @@ -19,7 +19,8 @@ namespace lldb_private { class ScriptedThreadPlanPythonInterface : public ScriptedThreadPlanInterface, - public ScriptedPythonInterface { + public ScriptedPythonInterface, + public PluginInterface { public: ScriptedThreadPlanPythonInterface(ScriptInterpreterPythonImpl &interpreter); @@ -41,6 +42,16 @@ class ScriptedThreadPlanPythonInterface : public ScriptedThreadPlanInterface, lldb::StateType GetRunState() override; llvm::Error GetStopDescription(lldb::StreamSP &stream) override; + + static void Initialize(); + + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { + return "ScriptedThreadPlanPythonInterface"; + } + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } }; } // namespace lldb_private _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits