| #!/usr/bin/env python |
| |
| # --------------------------------------------------------------------- |
| # Be sure to add the python path that points to the LLDB shared library. |
| # |
| # # To use this in the embedded python interpreter using "lldb" just |
| # import it with the full path using the "command script import" |
| # command |
| # (lldb) command script import /path/to/cmdtemplate.py |
| # --------------------------------------------------------------------- |
| |
| import inspect |
| import lldb |
| import optparse |
| import shlex |
| import sys |
| |
| |
| class FrameStatCommand: |
| program = "framestats" |
| |
| @classmethod |
| def register_lldb_command(cls, debugger, module_name): |
| parser = cls.create_options() |
| cls.__doc__ = parser.format_help() |
| # Add any commands contained in this module to LLDB |
| command = "command script add -o -c %s.%s %s" % ( |
| module_name, |
| cls.__name__, |
| cls.program, |
| ) |
| debugger.HandleCommand(command) |
| print( |
| 'The "{0}" command has been installed, type "help {0}" or "{0} ' |
| '--help" for detailed help.'.format(cls.program) |
| ) |
| |
| @classmethod |
| def create_options(cls): |
| usage = "usage: %prog [options]" |
| description = ( |
| "This command is meant to be an example of how to make " |
| "an LLDB command that does something useful, follows " |
| "best practices, and exploits the SB API. " |
| "Specifically, this command computes the aggregate " |
| "and average size of the variables in the current " |
| "frame and allows you to tweak exactly which variables " |
| "are to be accounted in the computation." |
| ) |
| |
| # Pass add_help_option = False, since this keeps the command in line |
| # with lldb commands, and we wire up "help command" to work by |
| # providing the long & short help methods below. |
| parser = optparse.OptionParser( |
| description=description, |
| prog=cls.program, |
| usage=usage, |
| add_help_option=False, |
| ) |
| |
| parser.add_option( |
| "-i", |
| "--in-scope", |
| action="store_true", |
| dest="inscope", |
| help="in_scope_only = True", |
| default=True, |
| ) |
| |
| parser.add_option( |
| "-a", |
| "--arguments", |
| action="store_true", |
| dest="arguments", |
| help="arguments = True", |
| default=True, |
| ) |
| |
| parser.add_option( |
| "-l", |
| "--locals", |
| action="store_true", |
| dest="locals", |
| help="locals = True", |
| default=True, |
| ) |
| |
| parser.add_option( |
| "-s", |
| "--statics", |
| action="store_true", |
| dest="statics", |
| help="statics = True", |
| default=True, |
| ) |
| |
| return parser |
| |
| def get_short_help(self): |
| return "Example command for use in debugging" |
| |
| def get_long_help(self): |
| return self.help_string |
| |
| def __init__(self, debugger, unused): |
| self.parser = self.create_options() |
| self.help_string = self.parser.format_help() |
| |
| def __call__(self, debugger, command, exe_ctx, result): |
| # Use the Shell Lexer to properly parse up command options just like a |
| # shell would |
| command_args = shlex.split(command) |
| |
| try: |
| (options, args) = self.parser.parse_args(command_args) |
| except: |
| # if you don't handle exceptions, passing an incorrect argument to |
| # the OptionParser will cause LLDB to exit (courtesy of OptParse |
| # dealing with argument errors by throwing SystemExit) |
| result.SetError("option parsing failed") |
| return |
| |
| # Always get program state from the lldb.SBExecutionContext passed |
| # in as exe_ctx |
| frame = exe_ctx.GetFrame() |
| if not frame.IsValid(): |
| result.SetError("invalid frame") |
| return |
| |
| variables_list = frame.GetVariables( |
| options.arguments, options.locals, options.statics, options.inscope |
| ) |
| variables_count = variables_list.GetSize() |
| if variables_count == 0: |
| print("no variables here", file=result) |
| return |
| total_size = 0 |
| for i in range(0, variables_count): |
| variable = variables_list.GetValueAtIndex(i) |
| variable_type = variable.GetType() |
| total_size = total_size + variable_type.GetByteSize() |
| average_size = float(total_size) / variables_count |
| print( |
| "Your frame has %d variables. Their total size " |
| "is %d bytes. The average size is %f bytes" |
| % (variables_count, total_size, average_size), |
| file=result, |
| ) |
| # not returning anything is akin to returning success |
| |
| |
| def __lldb_init_module(debugger, dict): |
| # Register all classes that have a register_lldb_command method |
| for _name, cls in inspect.getmembers(sys.modules[__name__]): |
| if inspect.isclass(cls) and callable( |
| getattr(cls, "register_lldb_command", None) |
| ): |
| cls.register_lldb_command(debugger, __name__) |