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