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