1#!/usr/bin/env python 2 3# --------------------------------------------------------------------- 4# Be sure to add the python path that points to the LLDB shared library. 5# 6# # To use this in the embedded python interpreter using "lldb" just 7# import it with the full path using the "command script import" 8# command 9# (lldb) command script import /path/to/cmdtemplate.py 10# --------------------------------------------------------------------- 11 12import inspect 13import lldb 14import optparse 15import shlex 16import sys 17 18 19class FrameStatCommand: 20 program = 'framestats' 21 22 @classmethod 23 def register_lldb_command(cls, debugger, module_name): 24 parser = cls.create_options() 25 cls.__doc__ = parser.format_help() 26 # Add any commands contained in this module to LLDB 27 command = 'command script add -o -c %s.%s %s' % (module_name, 28 cls.__name__, 29 cls.program) 30 debugger.HandleCommand(command) 31 print('The "{0}" command has been installed, type "help {0}" or "{0} ' 32 '--help" for detailed help.'.format(cls.program)) 33 34 @classmethod 35 def create_options(cls): 36 37 usage = "usage: %prog [options]" 38 description = ('This command is meant to be an example of how to make ' 39 'an LLDB command that does something useful, follows ' 40 'best practices, and exploits the SB API. ' 41 'Specifically, this command computes the aggregate ' 42 'and average size of the variables in the current ' 43 'frame and allows you to tweak exactly which variables ' 44 'are to be accounted in the computation.') 45 46 # Pass add_help_option = False, since this keeps the command in line 47 # with lldb commands, and we wire up "help command" to work by 48 # providing the long & short help methods below. 49 parser = optparse.OptionParser( 50 description=description, 51 prog=cls.program, 52 usage=usage, 53 add_help_option=False) 54 55 parser.add_option( 56 '-i', 57 '--in-scope', 58 action='store_true', 59 dest='inscope', 60 help='in_scope_only = True', 61 default=True) 62 63 parser.add_option( 64 '-a', 65 '--arguments', 66 action='store_true', 67 dest='arguments', 68 help='arguments = True', 69 default=True) 70 71 parser.add_option( 72 '-l', 73 '--locals', 74 action='store_true', 75 dest='locals', 76 help='locals = True', 77 default=True) 78 79 parser.add_option( 80 '-s', 81 '--statics', 82 action='store_true', 83 dest='statics', 84 help='statics = True', 85 default=True) 86 87 return parser 88 89 def get_short_help(self): 90 return "Example command for use in debugging" 91 92 def get_long_help(self): 93 return self.help_string 94 95 def __init__(self, debugger, unused): 96 self.parser = self.create_options() 97 self.help_string = self.parser.format_help() 98 99 def __call__(self, debugger, command, exe_ctx, result): 100 # Use the Shell Lexer to properly parse up command options just like a 101 # shell would 102 command_args = shlex.split(command) 103 104 try: 105 (options, args) = self.parser.parse_args(command_args) 106 except: 107 # if you don't handle exceptions, passing an incorrect argument to 108 # the OptionParser will cause LLDB to exit (courtesy of OptParse 109 # dealing with argument errors by throwing SystemExit) 110 result.SetError("option parsing failed") 111 return 112 113 # Always get program state from the lldb.SBExecutionContext passed 114 # in as exe_ctx 115 frame = exe_ctx.GetFrame() 116 if not frame.IsValid(): 117 result.SetError("invalid frame") 118 return 119 120 variables_list = frame.GetVariables( 121 options.arguments, 122 options.locals, 123 options.statics, 124 options.inscope) 125 variables_count = variables_list.GetSize() 126 if variables_count == 0: 127 print("no variables here", file=result) 128 return 129 total_size = 0 130 for i in range(0, variables_count): 131 variable = variables_list.GetValueAtIndex(i) 132 variable_type = variable.GetType() 133 total_size = total_size + variable_type.GetByteSize() 134 average_size = float(total_size) / variables_count 135 print("Your frame has %d variables. Their total size " 136 "is %d bytes. The average size is %f bytes" % ( 137 variables_count, total_size, average_size), file=result) 138 # not returning anything is akin to returning success 139 140 141def __lldb_init_module(debugger, dict): 142 # Register all classes that have a register_lldb_command method 143 for _name, cls in inspect.getmembers(sys.modules[__name__]): 144 if inspect.isclass(cls) and callable(getattr(cls, 145 "register_lldb_command", 146 None)): 147 cls.register_lldb_command(debugger, __name__) 148