aboutsummaryrefslogtreecommitdiff
path: root/lldb/source
diff options
context:
space:
mode:
authorjimingham <jingham@apple.com>2024-07-03 10:39:34 -0700
committerGitHub <noreply@github.com>2024-07-03 10:39:34 -0700
commit77d131eddb6ca9060c844fae9cb78779fa70c8f0 (patch)
treef540d78500a8a832a701db3e25b8a53dc91d0fac /lldb/source
parent94471e6d238acab291b5b652fc18f17c4815cc7d (diff)
downloadllvm-77d131eddb6ca9060c844fae9cb78779fa70c8f0.zip
llvm-77d131eddb6ca9060c844fae9cb78779fa70c8f0.tar.gz
llvm-77d131eddb6ca9060c844fae9cb78779fa70c8f0.tar.bz2
Add the ability for Script based commands to specify their "repeat command" (#94823)
Among other things, returning an empty string as the repeat command disables auto-repeat, which can be useful for state-changing commands. There's one remaining refinement to this setup, which is that for parsed script commands, it should be possible to change an option value, or add a new option value that wasn't originally specified, then ask lldb "make this back into a command string". That would make doing fancy things with repeat commands easier. That capability isn't present in the lldb_private side either, however. So that's for a next iteration. I haven't added this to the docs on adding commands yet. I wanted to make sure this was an acceptable approach before I spend the time to do that.
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/Commands/CommandObjectCommands.cpp31
-rw-r--r--lldb/source/Commands/CommandObjectThread.cpp2
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h4
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp27
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h9
5 files changed, 66 insertions, 7 deletions
diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp
index f4903e3..c63445b 100644
--- a/lldb/source/Commands/CommandObjectCommands.cpp
+++ b/lldb/source/Commands/CommandObjectCommands.cpp
@@ -1142,6 +1142,15 @@ public:
ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
+ std::optional<std::string> GetRepeatCommand(Args &args,
+ uint32_t index) override {
+ ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
+ if (!scripter)
+ return std::nullopt;
+
+ return scripter->GetRepeatCommandForScriptedCommand(m_cmd_obj_sp, args);
+ }
+
llvm::StringRef GetHelp() override {
if (m_fetched_help_short)
return CommandObjectRaw::GetHelp();
@@ -1588,7 +1597,9 @@ private:
options.ForEach(add_element);
return error;
}
-
+
+ size_t GetNumOptions() { return m_num_options; }
+
private:
struct EnumValueStorage {
EnumValueStorage() {
@@ -1827,6 +1838,15 @@ public:
ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
+ std::optional<std::string> GetRepeatCommand(Args &args,
+ uint32_t index) override {
+ ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
+ if (!scripter)
+ return std::nullopt;
+
+ return scripter->GetRepeatCommandForScriptedCommand(m_cmd_obj_sp, args);
+ }
+
llvm::StringRef GetHelp() override {
if (m_fetched_help_short)
return CommandObjectParsed::GetHelp();
@@ -1857,9 +1877,14 @@ public:
SetHelpLong(docstring);
return CommandObjectParsed::GetHelpLong();
}
-
- Options *GetOptions() override { return &m_options; }
+ Options *GetOptions() override {
+ // CommandObjectParsed requires that a command with no options return
+ // nullptr.
+ if (m_options.GetNumOptions() == 0)
+ return nullptr;
+ return &m_options;
+ }
protected:
void DoExecute(Args &args,
diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp
index 5e64dd2..4398cf3 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -132,7 +132,7 @@ public:
Options *GetOptions() override { return &m_options; }
std::optional<std::string> GetRepeatCommand(Args &current_args,
- uint32_t idx) override {
+ uint32_t index) override {
llvm::StringRef count_opt("--count");
llvm::StringRef start_opt("--start");
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
index 95eb5a7..3026b61 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
@@ -206,6 +206,10 @@ public:
lldb_private::CommandReturnObject &cmd_retobj,
lldb::ExecutionContextRefSP exe_ctx_ref_sp);
+ static std::optional<std::string>
+ LLDBSwigPythonGetRepeatCommandForScriptedCommand(PyObject *implementor,
+ std::string &command);
+
static bool LLDBSwigPythonCallModuleInit(const char *python_module_name,
const char *session_dictionary_name,
lldb::DebuggerSP debugger);
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 70c9f94..70fa6d8 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -2708,6 +2708,33 @@ bool ScriptInterpreterPythonImpl::RunScriptBasedParsedCommand(
return ret_val;
}
+std::optional<std::string>
+ScriptInterpreterPythonImpl::GetRepeatCommandForScriptedCommand(
+ StructuredData::GenericSP impl_obj_sp, Args &args) {
+ if (!impl_obj_sp || !impl_obj_sp->IsValid())
+ return std::nullopt;
+
+ lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();
+
+ if (!debugger_sp.get())
+ return std::nullopt;
+
+ std::optional<std::string> ret_val;
+
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+
+ StructuredData::ArraySP args_arr_sp(new StructuredData::Array());
+
+ // For scripting commands, we send the command string:
+ std::string command;
+ args.GetQuotedCommandString(command);
+ ret_val = SWIGBridge::LLDBSwigPythonGetRepeatCommandForScriptedCommand(
+ static_cast<PyObject *>(impl_obj_sp->GetValue()), command);
+ }
+ return ret_val;
+}
/// In Python, a special attribute __doc__ contains the docstring for an object
/// (function, method, class, ...) if any is defined Otherwise, the attribute's
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
index fa23540..c2024ef 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -160,13 +160,16 @@ public:
lldb_private::CommandReturnObject &cmd_retobj, Status &error,
const lldb_private::ExecutionContext &exe_ctx) override;
- virtual bool RunScriptBasedParsedCommand(
- StructuredData::GenericSP impl_obj_sp, Args& args,
+ bool RunScriptBasedParsedCommand(
+ StructuredData::GenericSP impl_obj_sp, Args &args,
ScriptedCommandSynchronicity synchronicity,
lldb_private::CommandReturnObject &cmd_retobj, Status &error,
const lldb_private::ExecutionContext &exe_ctx) override;
-
+ std::optional<std::string>
+ GetRepeatCommandForScriptedCommand(StructuredData::GenericSP impl_obj_sp,
+ Args &args) override;
+
Status GenerateFunction(const char *signature, const StringList &input,
bool is_callback) override;