| #!/usr/bin/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 -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 >> result, "no variables here" |
| 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 >>result, ("Your frame has %d variables. Their total size " |
| "is %d bytes. The average size is %f bytes") % ( |
| variables_count, total_size, average_size) |
| # 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__) |