[Lldb-commits] [lldb] [lldb/docs] Breakdown python reference into multiple files (PR #158331)

Med Ismail Bennani via lldb-commits lldb-commits at lists.llvm.org
Fri Sep 12 11:20:22 PDT 2025


================
@@ -0,0 +1,420 @@
+# Writing Custom Commands
+
+### Create a new command using a Python function
+
+Python functions can be used to create new LLDB command interpreter commands,
+which will work like all the natively defined lldb commands. This provides a
+very flexible and easy way to extend LLDB to meet your debugging requirements.
+
+To write a python function that implements a new LLDB command define the
+function to take five arguments as follows:
+
+```python3
+def command_function(debugger, command, exe_ctx, result, internal_dict):
+    # Your code goes here
+```
+
+The meaning of the arguments is given in the table below.
+
+If you provide a Python docstring in your command function LLDB will use it
+when providing "long help" for your command, as in:
+
+```python3
+def command_function(debugger, command, result, internal_dict):
+    """This command takes a lot of options and does many fancy things"""
+    # Your code goes here
+```
+
+though providing help can also be done programmatically (see below).
+
+Prior to lldb 3.5.2 (April 2015), LLDB Python command definitions didn't take the SBExecutionContext
+argument. So you may still see commands where the command definition is:
+
+```python3
+def command_function(debugger, command, result, internal_dict):
+    # Your code goes here
+```
+
+Using this form is strongly discouraged because it can only operate on the "currently selected"
+target, process, thread, frame.  The command will behave as expected when run
+directly on the command line.  But if the command is used in a stop-hook, breakpoint
+callback, etc. where the response to the callback determines whether we will select
+this or that particular process/frame/thread, the global "currently selected"
+entity is not necessarily the one the callback is meant to handle.  In that case, this
+command definition form can't do the right thing.
+
+| Argument | Type | Description |
+|----------|------|-------------|
+| `debugger` | `lldb.SBDebugger` | The current debugger object. |
+| `command` | `python string` | A python string containing all arguments for your command. If you need to chop up the arguments try using the `shlex` module's `shlex.split(command)` to properly extract the arguments. |
+| `exe_ctx` | `lldb.SBExecutionContext` | An execution context object carrying around information on the inferior process' context in which the command is expected to act *Optional since lldb 3.5.2, unavailable before* |
+| `result` | `lldb.SBCommandReturnObject` | A return object which encapsulates success/failure information for the command and output text that needs to be printed as a result of the command. The plain Python "print" command also works but text won't go in the result by default (it is useful as a temporary logging facility). |
+| `internal_dict` | `python dict object` | The dictionary for the current embedded script session which contains all variables and functions. |
+
+### Create a new command using a Python class
+
+Since lldb 3.7, Python commands can also be implemented by means of a class
+which should implement the following interface:
+
+```python3
+class CommandObjectType:
+    def __init__(self, debugger, internal_dict):
+        # this call should initialize the command with respect to the command interpreter for the passed-in debugger
+
+    def __call__(self, debugger, command, exe_ctx, result):
+        # this is the actual bulk of the command, akin to Python command functions
+
+    def get_short_help(self):
+        # this call should return the short help text for this command[1]
+
+    def get_long_help(self):
+        # this call should return the long help text for this command[1]
+
+    def get_flags(self):
+        # this will be called when the command is added to the command interpreter,
+        # and should return a flag field made from or-ing together the appropriate
+        # elements of the lldb.CommandFlags enum to specify the requirements of this command.
+        # The CommandInterpreter will make sure all these requirements are met, and will
+        # return the standard lldb error if they are not.[1]
+
+    def get_repeat_command(self, command):
+        # The auto-repeat command is what will get executed when the user types just
+        # a return at the next prompt after this command is run.  Even if your command
+        # was run because it was specified as a repeat command, that invocation will still
+        # get asked for IT'S repeat command, so you can chain a series of repeats, for instance
+        # to implement a pager.
+
+        # The command argument is the command that is about to be executed.
+
+        # If this call returns None, then the ordinary repeat mechanism will be used
+        # If this call returns an empty string, then auto-repeat is disabled
+        # If this call returns any other string, that will be the repeat command [1]
+```
+
+[1] This method is optional.
+
+As a convenience, you can treat the result object as a Python file object, and
+say
+
+```python3
+print("my command does lots of cool stuff", file=result)
+```
+
+`SBCommandReturnObject` and `SBStream` both support this file-like behavior by
+providing `write()` and `flush()` calls at the Python layer.
+
+### Parsed Commands
+
+The commands that are added using this class definition are what lldb calls
+"raw" commands.  The command interpreter doesn't attempt to parse the command,
+doesn't handle option values, neither generating help for them, or their
+completion.  Raw commands are useful when the arguments passed to the command
+are unstructured, and having to protect them against lldb command parsing would
+be onerous.  For instance, "expr" is a raw command.
+
+You can also add scripted commands that implement the "parsed command", where
+the options and their types are specified, as well as the argument and argument
+types.  These commands look and act like the majority of lldb commands, and you
+can also add custom completions for the options and/or the arguments if you have
+special needs.
+
+The easiest way to do this is to derive your new command from the lldb.ParsedCommand
+class.  That responds in the same way to the help & repeat command interfaces, and
+provides some convenience methods, and most importantly an LLDBOptionValueParser,
+accessed through lldb.ParsedCommand.get_parser().  The parser is used to set
+your command definitions, and to retrieve option values in the `__call__` method.
+
+To set up the command definition, implement the ParsedCommand abstract method:
+
+```python3
+def setup_command_definition(self):
+```
+
+This is called when your command is added to lldb.  In this method you add the
+options and their types, the option help strings, etc. to the command using the API:
+
+```python3
+def add_option(self, short_option, long_option, help, default,
+               dest = None, required=False, groups = None,
+               value_type=lldb.eArgTypeNone, completion_type=None,
+               enum_values=None):
+    """
+    short_option: one character, must be unique, not required
+    long_option:  no spaces, must be unique, required
+    help:         a usage string for this option, will print in the command help
+    default:      the initial value for this option (if it has a value)
+    dest:         the name of the property that gives you access to the value for
+                  this value.  Defaults to the long option if not provided.
+    required: if true, this option must be provided or the command will error out
+    groups: Which "option groups" does this option belong to.  This can either be
+            a simple list (e.g. [1, 3, 4, 5]) or you can specify ranges by sublists:
+            so [1, [3,5]] is the same as [1, 3, 4, 5].
+    value_type: one of the lldb.eArgType enum values.  Some of the common arg
+                types also have default completers, which will be applied automatically.
+    completion_type: currently these are values form the lldb.CompletionType enum.	If
+                     you need custom completions, implement	handle_option_argument_completion.
+    enum_values: An array of duples: ["element_name", "element_help"].  If provided,
+                 only one of the enum elements is allowed.  The value will be the
+                 element_name for the chosen enum element as a string.
+    """
+```
+
+Similarly, you can add argument types to the command:
+
+```python3
+def make_argument_element(self, arg_type, repeat = "optional", groups = None):
+    """
+  	arg_type: The argument type, one of the	lldb.eArgType enum values.
+  	repeat:	Choose from the	following options:
+  	      	"plain"	- one value
+  	      	"optional" - zero or more values
+  	      	"plus" - one or	more values
+  	groups:	As with	add_option.
+    """
+```
+
+Then implement the body of the command by defining:
+
+```python3
+def __call__(self, debugger, args_array, exe_ctx, result):
+    """This is the command callback.  The option values are
+    provided by the 'dest' properties on the parser.
+
+    args_array: This is the list of arguments provided.
+    exe_ctx: Gives the SBExecutionContext on which the
+             command should operate.
+    result:  Any results of the command should be
+             written into this SBCommandReturnObject.
+    """
+```
+
+This differs from the "raw" command's `__call__` in that the arguments are already
+parsed into the args_array, and the option values are set in the parser, and
+can be accessed using their property name.  The LLDBOptionValueParser class has
+a couple of other handy methods:
+
+```python3
+def was_set(self, long_option_name):
+```
+
+returns `True` if the option was specified on the command line.
+
+```python
+def dest_for_option(self, long_option_name):
+"""
+This will return the value of the dest variable you defined for opt_name.
+Mostly useful for handle_completion where you get passed the long option.
+"""
+```
+
+### Completion
+
+lldb will handle completing your option names, and all your enum values
+automatically.  If your option or argument types have associated built-in completers,
+then lldb will also handle that completion for you.  But if you have a need for
+custom completions, either in your arguments or option values, you can handle
+completion by hand as well.  To handle completion of option value arguments,
+your lldb.ParsedCommand subclass should implement:
+
+```python3
+def handle_option_argument_completion(self, long_option, cursor_pos):
+"""
+long_option: The long option name of the option whose value you are
+             asked to complete.
+cursor_pos: The cursor position in the value for that option - which
+you can get from the option parser.
+"""
+```
+
+And to handle the completion of arguments:
+
+```python3
+def handle_argument_completion(self, args, arg_pos, cursor_pos):
+"""
+args: A list of the arguments to the command
+arg_pos: An index into the args list of the argument with the cursor
+cursor_pos: The cursor position in the arg specified by arg_pos
+"""
+```
+
+When either of these API's is called, the command line will have been parsed up to
+the word containing the cursor, and any option values set in that part of the command
+string are available from the option value parser.  That's useful for instance
+if you have a --shared-library option that would constrain the completions for,
+say, a symbol name option or argument.
+
+The return value specifies what the completion options are.  You have four
+choices:
+
+- `True`: the completion was handled with no completions.
+
+- `False`: the completion was not handled, forward it to the regular
+completion machinery.
+
+- A dictionary with the key: "completion": there is one candidate,
+whose value is the value of the "completion" key.  Optionally you can pass a
+"mode" key whose value is either "partial" or "complete".  Return partial if
+the "completion" string is a prefix for all the completed value.
+
+For instance, if the string you are completing is "Test" and the available completions are:
+"Test1", "Test11" and "Test111", you should return the dictionary:
+
+```python3
+return {"completion": "Test1", "mode" : "partial"}
+```
+
+and then lldb will add the "1" at the cursor and advance it after the added string,
+waiting for more completions.  But if "Test1" is the only completion, return:
+
+```python3
+{"completion": "Test1", "mode": "complete"}
+```
+
+and lldb will add "1 " at the cursor, indicating the command string is complete.
+
+The default is "complete", you don't need to specify a "mode" in that case.
+
+- A dictionary with the key: "values" whose value is a list of candidate completion
+strings.  The command interpreter will present those strings as the available choices.
+You can optionally include a "descriptions" key, whose value is a parallel array
+of description strings, and the completion will show the description next to
+each completion.
+
+## Loading Commands
+
+One other handy convenience when defining lldb command-line commands is the
+command "command script import" which will import a module specified by file
+path, so you don't have to change your PYTHONPATH for temporary scripts. It
+also has another convenience that if your new script module has a function of
+the form:
+
+```python
+def __lldb_init_module(debugger, internal_dict):
+    # Command Initialization code goes here
+```
+
+where debugger and internal_dict are as above, that function will get run when
+the module is loaded allowing you to add whatever commands you want into the
+current debugger. Note that this function will only be run when using the LLDB
+command `command script import`, it will not get run if anyone imports your
+module from another module.
+
+## Examples
+
+Now we can create a module called ls.py in the file ~/ls.py that will implement
+a function that can be used by LLDB's python command code:
+
+```python
+#!/usr/bin/env python
+
+import lldb
+import commands
+import optparse
----------------
medismailben wrote:

Great point!

https://github.com/llvm/llvm-project/pull/158331


More information about the lldb-commits mailing list