1d879a630SGreg Clayton#!/usr/bin/python
2d879a630SGreg Clayton
3d879a630SGreg 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
10d879a630SGreg Clayton#----------------------------------------------------------------------
11d879a630SGreg Clayton
12d879a630SGreg Claytonimport lldb
13d879a630SGreg Claytonimport commands
14d879a630SGreg Claytonimport optparse
15d879a630SGreg Claytonimport shlex
16d879a630SGreg Clayton
17083fcdb4SEnrico Granatadef create_framestats_options():
18083fcdb4SEnrico Granata    usage = "usage: %prog [options]"
19083fcdb4SEnrico Granata    description='''This command is meant to be an example of how to make an LLDB command that
20083fcdb4SEnrico Granatadoes something useful, follows best practices, and exploits the SB API.
21083fcdb4SEnrico GranataSpecifically, this command computes the aggregate and average size of the variables in the current frame
22083fcdb4SEnrico Granataand allows you to tweak exactly which variables are to be accounted in the computation.
23f453907aSGreg Clayton'''
24083fcdb4SEnrico Granata    parser = optparse.OptionParser(description=description, prog='framestats',usage=usage)
25083fcdb4SEnrico Granata    parser.add_option('-i', '--in-scope', action='store_true', dest='inscope', help='in_scope_only = True', default=False)
26083fcdb4SEnrico Granata    parser.add_option('-a', '--arguments', action='store_true', dest='arguments', help='arguments = True', default=False)
27083fcdb4SEnrico Granata    parser.add_option('-l', '--locals', action='store_true', dest='locals', help='locals = True', default=False)
28083fcdb4SEnrico Granata    parser.add_option('-s', '--statics', action='store_true', dest='statics', help='statics = True', default=False)
29f453907aSGreg Clayton    return parser
30f453907aSGreg Clayton
31083fcdb4SEnrico Granatadef the_framestats_command(debugger, command, result, dict):
32f453907aSGreg Clayton    # Use the Shell Lexer to properly parse up command options just like a
33f453907aSGreg Clayton    # shell would
34f453907aSGreg Clayton    command_args = shlex.split(command)
35083fcdb4SEnrico Granata    parser = create_framestats_options()
36d879a630SGreg Clayton    try:
37d879a630SGreg Clayton        (options, args) = parser.parse_args(command_args)
38d879a630SGreg Clayton    except:
396308f582SEnrico Granata        # if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit
406308f582SEnrico Granata        # (courtesy of OptParse dealing with argument errors by throwing SystemExit)
41*da504ff0SEnrico Granata        result.SetError ("option parsing failed")
42*da504ff0SEnrico Granata        return
43d879a630SGreg Clayton
44083fcdb4SEnrico Granata    # in a command - the lldb.* convenience variables are not to be used
45083fcdb4SEnrico Granata    # and their values (if any) are undefined
46083fcdb4SEnrico Granata    # this is the best practice to access those objects from within a command
47083fcdb4SEnrico Granata    target = debugger.GetSelectedTarget()
48083fcdb4SEnrico Granata    process = target.GetProcess()
49083fcdb4SEnrico Granata    thread = process.GetSelectedThread()
50083fcdb4SEnrico Granata    frame = thread.GetSelectedFrame()
51083fcdb4SEnrico Granata    if not frame.IsValid():
52083fcdb4SEnrico Granata        return "no frame here"
53083fcdb4SEnrico Granata    # from now on, replace lldb.<thing>.whatever with <thing>.whatever
54083fcdb4SEnrico Granata    variables_list = frame.GetVariables(options.arguments, options.locals, options.statics, options.inscope)
55083fcdb4SEnrico Granata    variables_count = variables_list.GetSize()
56083fcdb4SEnrico Granata    if variables_count == 0:
57*da504ff0SEnrico Granata        print >> result, "no variables here"
58083fcdb4SEnrico Granata        return
59083fcdb4SEnrico Granata    total_size = 0
60083fcdb4SEnrico Granata    for i in range(0,variables_count):
61083fcdb4SEnrico Granata        variable = variables_list.GetValueAtIndex(i)
62083fcdb4SEnrico Granata        variable_type = variable.GetType()
63083fcdb4SEnrico Granata        total_size = total_size + variable_type.GetByteSize()
64083fcdb4SEnrico Granata    average_size = float(total_size) / variables_count
65*da504ff0SEnrico Granata    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)
66*da504ff0SEnrico Granata    # not returning anything is akin to returning success
67d879a630SGreg Clayton
6887a59368SJim Inghamdef __lldb_init_module (debugger, dict):
6987a59368SJim Ingham    # This initializer is being run from LLDB in the embedded command interpreter
70f453907aSGreg Clayton    # Make the options so we can generate the help text for the new LLDB
71f453907aSGreg Clayton    # command line command prior to registering it with LLDB below
72083fcdb4SEnrico Granata    parser = create_framestats_options()
73083fcdb4SEnrico Granata    the_framestats_command.__doc__ = parser.format_help()
74d879a630SGreg Clayton    # Add any commands contained in this module to LLDB
75083fcdb4SEnrico Granata    debugger.HandleCommand('command script add -f cmdtemplate.the_framestats_command framestats')
76083fcdb4SEnrico Granata    print 'The "framestats" command has been installed, type "help framestats" or "framestats --help" for detailed help.'
77