Skip to content

Commit

Permalink
[lldb] Use __lldb_init_module instead of "if lldb.debugger" idiom
Browse files Browse the repository at this point in the history
Update examples and docs to demonstrate using `__lldb_init_module` instead of
the idiom that checks for `lldb.debugger` at the top-level.

```
if __name__ == '__main__':
    ...
elif lldb.debugger:
    ...
```

Is replaced with:

```
if __name__ == '__main__':
    ...

def __lldb_init_module(debugger, internal_dict):
    ...
```

This change is for two reasons. First, it's generally encouraged not to only
use the convenience singletons (`lldb.{debugger,process,target,etc}`)
interactively from the `script` command. Second, there's a bug where
registering a python class as a command (using `command script add -c ...`),
result in the command not being runnable. Note that registering function-backed
commands does not have this bug.

Differential Revision: https://reviews.llvm.org/D117237
  • Loading branch information
kastiglione committed Jan 14, 2022
1 parent bc56097 commit 1441ffe
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 70 deletions.
33 changes: 20 additions & 13 deletions lldb/docs/use/python-reference.rst
Expand Up @@ -584,26 +584,33 @@ the form:
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. If you want to always run code when your module is
loaded from LLDB or when loaded via an import statement in python code you can
test the lldb.debugger object, since you imported the module at the top of the
python ls.py module. This test must be in code that isn't contained inside of
any function or class, just like the standard test for __main__ like all python
modules usually do. Sample code would look like:
command ``command script import``, it will not get run if anyone imports your
module from another module.

The standard test for ``__main__``, like many python modules do, is useful for
creating scripts that can be run from the command line. However, for command
line scripts, the debugger instance must be created manually. Sample code would
look like:

::

if __name__ == '__main__':
# Initialize the debugger before making any API calls.
lldb.SBDebugger.Initialize()
# Create a new debugger instance in your module if your module
# can be run from the command line. When we run a script from
# the command line, we won't have any debugger object in
# lldb.debugger, so we can just create it if it will be needed
lldb.debugger = lldb.SBDebugger.Create()
elif lldb.debugger:
# Module is being run inside the LLDB interpreter
lldb.debugger.HandleCommand('command script add -f ls.ls ls')
print 'The "ls" python command has been installed and is ready for use.'
debugger = lldb.SBDebugger.Create()

# Next, do whatever work this module should do when run as a command.
# ...

# Finally, dispose of the debugger you just made.
lldb.SBDebugger.Destroy(debugger)
# Terminate the debug sesssion
lldb.SBDebugger.Terminate()


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:
Expand Down Expand Up @@ -673,7 +680,7 @@ that goal:
Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
>>> def pofoo_funct(debugger, command, result, internal_dict):
... cmd = "po [ModifyString(" + command + ") capitalizedString]"
... lldb.debugger.HandleCommand(cmd)
... debugger.HandleCommand(cmd)
...
>>> ^D
(lldb) command script add pofoo -f pofoo_funct
Expand Down
53 changes: 26 additions & 27 deletions lldb/examples/darwin/heap_find/heap.py
Expand Up @@ -1494,30 +1494,29 @@ def objc_refs(debugger, command, result, dict):
if __name__ == '__main__':
lldb.debugger = lldb.SBDebugger.Create()

# Make the options so we can generate the help text for the new LLDB
# command line command prior to registering it with LLDB below. This way
# if clients in LLDB type "help malloc_info", they will see the exact same
# output as typing "malloc_info --help".
ptr_refs.__doc__ = get_ptr_refs_options().format_help()
cstr_refs.__doc__ = get_cstr_refs_options().format_help()
malloc_info.__doc__ = get_malloc_info_options().format_help()
objc_refs.__doc__ = get_objc_refs_options().format_help()
lldb.debugger.HandleCommand(
'command script add -f %s.ptr_refs ptr_refs' %
__name__)
lldb.debugger.HandleCommand(
'command script add -f %s.cstr_refs cstr_refs' %
__name__)
lldb.debugger.HandleCommand(
'command script add -f %s.malloc_info malloc_info' %
__name__)
lldb.debugger.HandleCommand(
'command script add -f %s.find_variable find_variable' %
__name__)
# lldb.debugger.HandleCommand('command script add -f %s.heap heap' % package_name)
# lldb.debugger.HandleCommand('command script add -f %s.section_ptr_refs section_ptr_refs' % package_name)
# lldb.debugger.HandleCommand('command script add -f %s.stack_ptr_refs stack_ptr_refs' % package_name)
lldb.debugger.HandleCommand(
'command script add -f %s.objc_refs objc_refs' %
__name__)
print('"malloc_info", "ptr_refs", "cstr_refs", "find_variable", and "objc_refs" commands have been installed, use the "--help" options on these commands for detailed help.')
def __lldb_init_module(debugger, internal_dict):
# Make the options so we can generate the help text for the new LLDB
# command line command prior to registering it with LLDB below. This way
# if clients in LLDB type "help malloc_info", they will see the exact same
# output as typing "malloc_info --help".
ptr_refs.__doc__ = get_ptr_refs_options().format_help()
cstr_refs.__doc__ = get_cstr_refs_options().format_help()
malloc_info.__doc__ = get_malloc_info_options().format_help()
objc_refs.__doc__ = get_objc_refs_options().format_help()
debugger.HandleCommand(
'command script add -f %s.ptr_refs ptr_refs' %
__name__)
debugger.HandleCommand(
'command script add -f %s.cstr_refs cstr_refs' %
__name__)
debugger.HandleCommand(
'command script add -f %s.malloc_info malloc_info' %
__name__)
debugger.HandleCommand(
'command script add -f %s.find_variable find_variable' %
__name__)
# debugger.HandleCommand('command script add -f %s.section_ptr_refs section_ptr_refs' % package_name)
debugger.HandleCommand(
'command script add -f %s.objc_refs objc_refs' %
__name__)
print('"malloc_info", "ptr_refs", "cstr_refs", "find_variable", and "objc_refs" commands have been installed, use the "--help" options on these commands for detailed help.')
7 changes: 3 additions & 4 deletions lldb/examples/python/delta.py
Expand Up @@ -125,11 +125,10 @@ def parse_log_file(file, options):
import sys
parse_time_log_args(sys.argv[1:])

else:
import lldb
if lldb.debugger:

def __lldb_init_module(debugger, internal_dict):
# This initializer is being run from LLDB in the embedded command interpreter
# Add any commands contained in this module to LLDB
lldb.debugger.HandleCommand(
debugger.HandleCommand(
'command script add -f delta.parse_time_log parse_time_log')
print('The "parse_time_log" command is now installed and ready for use, type "parse_time_log --help" for more information')
9 changes: 5 additions & 4 deletions lldb/examples/python/diagnose_unwind.py
Expand Up @@ -308,7 +308,8 @@ def create_diagnose_unwind_options():
usage=usage)
return parser

lldb.debugger.HandleCommand(
'command script add -f %s.diagnose_unwind diagnose-unwind' %
__name__)
print('The "diagnose-unwind" command has been installed, type "help diagnose-unwind" for detailed help.')
def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand(
'command script add -f %s.diagnose_unwind diagnose-unwind' %
__name__)
print('The "diagnose-unwind" command has been installed, type "help diagnose-unwind" for detailed help.')
7 changes: 4 additions & 3 deletions lldb/examples/python/gdb_disassemble.py
Expand Up @@ -21,6 +21,7 @@ def disassemble(debugger, command, result, dict):
print("<%s + %-4u> 0x%x %8s %s" % (name, inst_offset, inst_addr, inst.mnemonic, inst.operands))

# Install the command when the module gets imported
lldb.debugger.HandleCommand(
'command script add -f gdb_disassemble.disassemble gdb-disassemble')
print('Installed "gdb-disassemble" command for disassembly')
def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand(
'command script add -f gdb_disassemble.disassemble gdb-disassemble')
print('Installed "gdb-disassemble" command for disassembly')
18 changes: 8 additions & 10 deletions lldb/examples/python/gdbremote.py
Expand Up @@ -1619,13 +1619,11 @@ def parse_gdb_log(file, options):
else:
parse_gdb_log(sys.stdin, options)

else:
import lldb
if lldb.debugger:
# This initializer is being run from LLDB in the embedded command interpreter
# Add any commands contained in this module to LLDB
lldb.debugger.HandleCommand(
'command script add -f gdbremote.start_gdb_log start_gdb_log')
lldb.debugger.HandleCommand(
'command script add -f gdbremote.stop_gdb_log stop_gdb_log')
print('The "start_gdb_log" and "stop_gdb_log" commands are now installed and ready for use, type "start_gdb_log --help" or "stop_gdb_log --help" for more information')
def __lldb_init_module(debugger, internal_dict):
# This initializer is being run from LLDB in the embedded command interpreter
# Add any commands contained in this module to LLDB
debugger.HandleCommand(
'command script add -f gdbremote.start_gdb_log start_gdb_log')
debugger.HandleCommand(
'command script add -f gdbremote.stop_gdb_log stop_gdb_log')
print('The "start_gdb_log" and "stop_gdb_log" commands are now installed and ready for use, type "start_gdb_log --help" or "stop_gdb_log --help" for more information')
4 changes: 2 additions & 2 deletions lldb/examples/python/jump.py
Expand Up @@ -191,8 +191,8 @@ def jump(debugger, command, result, internal_dict):

frame.SetPC(desired_address.GetLoadAddress(target))

if lldb.debugger:
def __lldb_init_module(debugger, internal_dict):
# Module is being run inside the LLDB interpreter
jump.__doc__ = usage_string()
lldb.debugger.HandleCommand('command script add -f jump.jump jump')
debugger.HandleCommand('command script add -f jump.jump jump')
print('The "jump" command has been installed, type "help jump" or "jump <ENTER>" for detailed help.')
5 changes: 3 additions & 2 deletions lldb/examples/python/memory.py
Expand Up @@ -270,8 +270,9 @@ def memfind(target, options, args, result):

if __name__ == '__main__':
print('error: this script is designed to be used within the embedded script interpreter in LLDB')
elif getattr(lldb, 'debugger', None):

def __lldb_init_module(debugger, internal_dict):
memfind_command.__doc__ = create_memfind_options().format_help()
lldb.debugger.HandleCommand(
debugger.HandleCommand(
'command script add -f memory.memfind_command memfind')
print('"memfind" command installed, use the "--help" option for detailed help')
7 changes: 4 additions & 3 deletions lldb/examples/python/stacks.py
Expand Up @@ -63,6 +63,7 @@ def stack_frames(debugger, command, result, dict):
print(frame_info)


lldb.debugger.HandleCommand(
"command script add -f stacks.stack_frames stack_frames")
print("A new command called 'stack_frames' was added, type 'stack_frames --help' for more information.")
def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand(
"command script add -f stacks.stack_frames stack_frames")
print("A new command called 'stack_frames' was added, type 'stack_frames --help' for more information.")
4 changes: 2 additions & 2 deletions lldb/examples/python/types.py
Expand Up @@ -351,7 +351,7 @@ def verify_types(target, options):
continue
verify_types(target, options)

elif getattr(lldb, 'debugger', None):
lldb.debugger.HandleCommand(
def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand(
'command script add -f types.check_padding_command check_padding')
print('"check_padding" command installed, use the "--help" option for detailed help')

0 comments on commit 1441ffe

Please sign in to comment.