[Lldb-commits] [lldb] [lldb/Commands] Add `scripting template list` command with auto discovery (PR #97273)
via lldb-commits
lldb-commits at lists.llvm.org
Mon Jul 1 02:58:29 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Med Ismail Bennani (medismailben)
<details>
<summary>Changes</summary>
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 <ismail@<!-- -->bennani.ma>
---
Patch is 36.11 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/97273.diff
17 Files Affected:
- (modified) lldb/include/lldb/Core/PluginManager.h (+25)
- (modified) lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h (+7)
- (modified) lldb/include/lldb/lldb-private-interfaces.h (+4)
- (modified) lldb/source/Commands/CMakeLists.txt (+1-1)
- (removed) lldb/source/Commands/CommandObjectScript.cpp (-113)
- (removed) lldb/source/Commands/CommandObjectScript.h (-42)
- (added) lldb/source/Commands/CommandObjectScripting.cpp (+290)
- (added) lldb/source/Commands/CommandObjectScripting.h (+80)
- (modified) lldb/source/Commands/Options.td (+8-2)
- (modified) lldb/source/Core/PluginManager.cpp (+83)
- (modified) lldb/source/Interpreter/CommandInterpreter.cpp (+7-2)
- (modified) lldb/source/Plugins/CMakeLists.txt (+3)
- (modified) lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt (+5)
- (modified) lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp (+23)
- (modified) lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h (+12-1)
- (modified) lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp (+18)
- (modified) lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h (+12-1)
``````````diff
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/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/CommandObjectScript.cpp
deleted file mode 100644
index 25f25b8e65947..0000000000000
--- a/lldb/source/Commands/CommandObjectScript.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-//===-- CommandObjectScript.cpp -------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "CommandObjectScript.h"
-#include "lldb/Core/Debugger.h"
-#include "lldb/DataFormatters/DataVisualization.h"
-#include "lldb/Host/Config.h"
-#include "lldb/Host/OptionParser.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
-#include "lldb/Interpreter/CommandOptionArgumentTable.h"
-#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Interpreter/OptionArgParser.h"
-#include "lldb/Interpreter/ScriptInterpreter.h"
-#include "lldb/Utility/Args.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-#define LLDB_OPTIONS_script
-#include "CommandOptions.inc"
-
-Status CommandObjectScript::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 CommandObjectScript::CommandOptions::OptionParsingStarting(
- ExecutionContext *execution_context) {
- language = lldb::eScriptLanguageNone;
-}
-
-llvm::ArrayRef<OptionDefinition>
-CommandObjectScript::CommandOptions::GetDefinitions() {
- return llvm::ArrayRef(g_script_options);
-}
-
-CommandObjectScript::CommandObjectScript(CommandInterpreter &interpreter)
- : CommandObjectRaw(
- interpreter, "script",
- "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>]") {}
-
-CommandObjectScript::~CommandObjectScript() = default;
-
-void CommandObjectScript::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);
- if (raw_args.HasArgs()) {
- if (!ParseOptions(raw_args.GetArgs(), result))
- return;
- command = raw_args.GetRawPart();
- }
-
- 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;
- }
-
- // Script might change Python code we use for formatting. Make sure we keep
- // up to date with it.
- DataVisualization::ForceUpdate();
-
- if (command.empty()) {
- script_interpreter->ExecuteInterpreterLoop();
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- return;
- }
-
- // We can do better when reporting the status of one-liner script execution.
- if (script_interpreter->ExecuteOneLine(command, &result))
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- else
- result.SetStatus(eReturnStatusFailed);
-}
diff --git a/lldb/source/Commands/CommandObjectScript.h b/lldb/source/Commands/CommandObjectScript.h
deleted file mode 100644
index 3a8c4a890404a..0000000000000
--- a/lldb/source/Commands/CommandObjectScript.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//===-- CommandObjectScript.h -----------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDB_SOURCE_INTERPRETER_COMMANDOBJECTSCRIPT_H
-#define LLDB_SOURCE_INTERPRETER_COMMANDOBJECTSCRIPT_H
-
-#include "lldb/Interpreter/CommandObject.h"
-
-namespace lldb_private {
-
-class CommandObjectScript : public CommandObjectRaw {
-public:
- CommandObjectScript(CommandInterpreter &interpreter);
- ~CommandObjectScript() 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(llvm::StringRef command, CommandReturnObject &result) override;
-
-private:
- CommandOptions m_options;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_SOURCE_INTERPRETER_COMMANDOBJECTSCRIPT_H
diff --git a/lldb/source/Commands/CommandObjectScripting.cpp b/lldb/source/Commands/CommandObjectScripting.cpp
new file mode 100644
index 0000000000000..f03c93ed1ef9d
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectScripting.cpp
@@ -0,0 +1,290 @@
+//===-- 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.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandOptionArgumentTable.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Utility/Args.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#pragma mark CommandObjectScriptingExecute
+
+#define LLDB_OPTIONS_scripting_execute
+#include "CommandOptions.inc"
+
+Status CommandObjectScriptingExecute::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 CommandObjectScriptingExecute::CommandOptions::OptionParsingStarting(
+ ExecutionContext *execution_context) {
+ language = lldb::eScriptLanguageNone;
+}
+
+llvm::ArrayRef<OptionDefinition>
+CommandObjectScriptingExecute::CommandOptions::GetDefinitions() {
+ return llvm::ArrayRef(g_scripting_execute_options);
+}
+
+CommandObjectScriptingExecute::CommandObjectScriptingExecute(
+ CommandInterpreter &interpreter)
+ : CommandObjectRaw(
+ interpreter, "scripting execute",
+ "Invoke the script interpreter with provided code and display any "
+ "results. Start the interactive interpreter if no code is supplied.",
+ "scripting execute [--language <scripting-language> --] "
+ "[<script-code>]") {}
+
+CommandObjectScriptingExecute::~CommandObjectScriptingExecute() = default;
+
+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);
+ if (raw_args.HasArgs()) {
+ if (!ParseOptions(raw_args.GetArgs(), result))
+ return;
+ command = raw_args.GetRawPart();
+ }
+
+ 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;
+ }
+
+ // Script might change Python code we use for formatting. Make sure we keep
+ // up to date with it.
+ DataVisualization::ForceUpdate();
+
+ if (command.empty()) {
+ script_interpreter->ExecuteInterpreterLoop();
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ return;
+ }
+
+ // We can do better when reporting the status of one-liner script execution.
+ if (script_interpreter->ExecuteOneLine(command, &result))
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
+}
+
+#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
+
+CommandObjectMultiwordScripting::CommandObjectMultiwordScripting(
+ CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "scripting",
+ "Commands for operating on the scripting functionnalities.",
+ "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
new file mode 100644
index 0000000000000..a9af6ee62e298
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectScripting.h
@@ -0,0 +1,80 @@
+//===-- 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.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_INTERPRETER_COMMANDOBJECTSCRIPT_H
+#define LLDB_SOURCE_INTE...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/97273
More information about the lldb-commits
mailing list