1be691f3bSpatrick#!/usr/bin/env python 2061da546Spatrick 3061da546Spatrick# --------------------------------------------------------------------- 4061da546Spatrick# Be sure to add the python path that points to the LLDB shared library. 5061da546Spatrick# 6061da546Spatrick# # To use this in the embedded python interpreter using "lldb" just 7061da546Spatrick# import it with the full path using the "command script import" 8061da546Spatrick# command 9061da546Spatrick# (lldb) command script import /path/to/cmdtemplate.py 10061da546Spatrick# --------------------------------------------------------------------- 11061da546Spatrick 12061da546Spatrickimport inspect 13061da546Spatrickimport lldb 14061da546Spatrickimport optparse 15061da546Spatrickimport shlex 16061da546Spatrickimport sys 17061da546Spatrick 18061da546Spatrick 19061da546Spatrickclass FrameStatCommand: 20061da546Spatrick program = 'framestats' 21061da546Spatrick 22061da546Spatrick @classmethod 23061da546Spatrick def register_lldb_command(cls, debugger, module_name): 24061da546Spatrick parser = cls.create_options() 25061da546Spatrick cls.__doc__ = parser.format_help() 26061da546Spatrick # Add any commands contained in this module to LLDB 27*f6aab3d8Srobert command = 'command script add -o -c %s.%s %s' % (module_name, 28061da546Spatrick cls.__name__, 29061da546Spatrick cls.program) 30061da546Spatrick debugger.HandleCommand(command) 31061da546Spatrick print('The "{0}" command has been installed, type "help {0}" or "{0} ' 32061da546Spatrick '--help" for detailed help.'.format(cls.program)) 33061da546Spatrick 34061da546Spatrick @classmethod 35061da546Spatrick def create_options(cls): 36061da546Spatrick 37061da546Spatrick usage = "usage: %prog [options]" 38061da546Spatrick description = ('This command is meant to be an example of how to make ' 39061da546Spatrick 'an LLDB command that does something useful, follows ' 40061da546Spatrick 'best practices, and exploits the SB API. ' 41061da546Spatrick 'Specifically, this command computes the aggregate ' 42061da546Spatrick 'and average size of the variables in the current ' 43061da546Spatrick 'frame and allows you to tweak exactly which variables ' 44061da546Spatrick 'are to be accounted in the computation.') 45061da546Spatrick 46061da546Spatrick # Pass add_help_option = False, since this keeps the command in line 47061da546Spatrick # with lldb commands, and we wire up "help command" to work by 48061da546Spatrick # providing the long & short help methods below. 49061da546Spatrick parser = optparse.OptionParser( 50061da546Spatrick description=description, 51061da546Spatrick prog=cls.program, 52061da546Spatrick usage=usage, 53061da546Spatrick add_help_option=False) 54061da546Spatrick 55061da546Spatrick parser.add_option( 56061da546Spatrick '-i', 57061da546Spatrick '--in-scope', 58061da546Spatrick action='store_true', 59061da546Spatrick dest='inscope', 60061da546Spatrick help='in_scope_only = True', 61061da546Spatrick default=True) 62061da546Spatrick 63061da546Spatrick parser.add_option( 64061da546Spatrick '-a', 65061da546Spatrick '--arguments', 66061da546Spatrick action='store_true', 67061da546Spatrick dest='arguments', 68061da546Spatrick help='arguments = True', 69061da546Spatrick default=True) 70061da546Spatrick 71061da546Spatrick parser.add_option( 72061da546Spatrick '-l', 73061da546Spatrick '--locals', 74061da546Spatrick action='store_true', 75061da546Spatrick dest='locals', 76061da546Spatrick help='locals = True', 77061da546Spatrick default=True) 78061da546Spatrick 79061da546Spatrick parser.add_option( 80061da546Spatrick '-s', 81061da546Spatrick '--statics', 82061da546Spatrick action='store_true', 83061da546Spatrick dest='statics', 84061da546Spatrick help='statics = True', 85061da546Spatrick default=True) 86061da546Spatrick 87061da546Spatrick return parser 88061da546Spatrick 89061da546Spatrick def get_short_help(self): 90061da546Spatrick return "Example command for use in debugging" 91061da546Spatrick 92061da546Spatrick def get_long_help(self): 93061da546Spatrick return self.help_string 94061da546Spatrick 95061da546Spatrick def __init__(self, debugger, unused): 96061da546Spatrick self.parser = self.create_options() 97061da546Spatrick self.help_string = self.parser.format_help() 98061da546Spatrick 99061da546Spatrick def __call__(self, debugger, command, exe_ctx, result): 100061da546Spatrick # Use the Shell Lexer to properly parse up command options just like a 101061da546Spatrick # shell would 102061da546Spatrick command_args = shlex.split(command) 103061da546Spatrick 104061da546Spatrick try: 105061da546Spatrick (options, args) = self.parser.parse_args(command_args) 106061da546Spatrick except: 107061da546Spatrick # if you don't handle exceptions, passing an incorrect argument to 108061da546Spatrick # the OptionParser will cause LLDB to exit (courtesy of OptParse 109061da546Spatrick # dealing with argument errors by throwing SystemExit) 110061da546Spatrick result.SetError("option parsing failed") 111061da546Spatrick return 112061da546Spatrick 113061da546Spatrick # Always get program state from the lldb.SBExecutionContext passed 114061da546Spatrick # in as exe_ctx 115061da546Spatrick frame = exe_ctx.GetFrame() 116061da546Spatrick if not frame.IsValid(): 117061da546Spatrick result.SetError("invalid frame") 118061da546Spatrick return 119061da546Spatrick 120061da546Spatrick variables_list = frame.GetVariables( 121061da546Spatrick options.arguments, 122061da546Spatrick options.locals, 123061da546Spatrick options.statics, 124061da546Spatrick options.inscope) 125061da546Spatrick variables_count = variables_list.GetSize() 126061da546Spatrick if variables_count == 0: 127061da546Spatrick print("no variables here", file=result) 128061da546Spatrick return 129061da546Spatrick total_size = 0 130061da546Spatrick for i in range(0, variables_count): 131061da546Spatrick variable = variables_list.GetValueAtIndex(i) 132061da546Spatrick variable_type = variable.GetType() 133061da546Spatrick total_size = total_size + variable_type.GetByteSize() 134061da546Spatrick average_size = float(total_size) / variables_count 135061da546Spatrick print("Your frame has %d variables. Their total size " 136061da546Spatrick "is %d bytes. The average size is %f bytes" % ( 137061da546Spatrick variables_count, total_size, average_size), file=result) 138061da546Spatrick # not returning anything is akin to returning success 139061da546Spatrick 140061da546Spatrick 141061da546Spatrickdef __lldb_init_module(debugger, dict): 142061da546Spatrick # Register all classes that have a register_lldb_command method 143061da546Spatrick for _name, cls in inspect.getmembers(sys.modules[__name__]): 144061da546Spatrick if inspect.isclass(cls) and callable(getattr(cls, 145061da546Spatrick "register_lldb_command", 146061da546Spatrick None)): 147061da546Spatrick cls.register_lldb_command(debugger, __name__) 148