Greg Clayton | d879a63 | 2012-01-22 02:55:08 +0000 | [diff] [blame] | 1 | #!/usr/bin/python |
| 2 | |
| 3 | #---------------------------------------------------------------------- |
| 4 | # Be sure to add the python path that points to the LLDB shared library. |
| 5 | # |
Greg Clayton | e284163 | 2012-01-26 02:56:24 +0000 | [diff] [blame] | 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 |
Greg Clayton | d879a63 | 2012-01-22 02:55:08 +0000 | [diff] [blame] | 10 | #---------------------------------------------------------------------- |
| 11 | |
| 12 | import lldb |
| 13 | import commands |
| 14 | import optparse |
| 15 | import shlex |
| 16 | |
Enrico Granata | 083fcdb | 2013-05-09 01:32:24 +0000 | [diff] [blame] | 17 | def create_framestats_options(): |
| 18 | usage = "usage: %prog [options]" |
| 19 | description='''This command is meant to be an example of how to make an LLDB command that |
| 20 | does something useful, follows best practices, and exploits the SB API. |
| 21 | Specifically, this command computes the aggregate and average size of the variables in the current frame |
| 22 | and allows you to tweak exactly which variables are to be accounted in the computation. |
Greg Clayton | f453907 | 2012-09-13 05:35:34 +0000 | [diff] [blame] | 23 | ''' |
Enrico Granata | 083fcdb | 2013-05-09 01:32:24 +0000 | [diff] [blame] | 24 | parser = optparse.OptionParser(description=description, prog='framestats',usage=usage) |
| 25 | parser.add_option('-i', '--in-scope', action='store_true', dest='inscope', help='in_scope_only = True', default=False) |
| 26 | parser.add_option('-a', '--arguments', action='store_true', dest='arguments', help='arguments = True', default=False) |
| 27 | parser.add_option('-l', '--locals', action='store_true', dest='locals', help='locals = True', default=False) |
| 28 | parser.add_option('-s', '--statics', action='store_true', dest='statics', help='statics = True', default=False) |
Greg Clayton | f453907 | 2012-09-13 05:35:34 +0000 | [diff] [blame] | 29 | return parser |
| 30 | |
Enrico Granata | 083fcdb | 2013-05-09 01:32:24 +0000 | [diff] [blame] | 31 | def the_framestats_command(debugger, command, result, dict): |
Greg Clayton | f453907 | 2012-09-13 05:35:34 +0000 | [diff] [blame] | 32 | # Use the Shell Lexer to properly parse up command options just like a |
| 33 | # shell would |
| 34 | command_args = shlex.split(command) |
Enrico Granata | 083fcdb | 2013-05-09 01:32:24 +0000 | [diff] [blame] | 35 | parser = create_framestats_options() |
Greg Clayton | d879a63 | 2012-01-22 02:55:08 +0000 | [diff] [blame] | 36 | try: |
| 37 | (options, args) = parser.parse_args(command_args) |
| 38 | except: |
Enrico Granata | 6308f58 | 2013-02-25 23:01:08 +0000 | [diff] [blame] | 39 | # if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit |
| 40 | # (courtesy of OptParse dealing with argument errors by throwing SystemExit) |
Enrico Granata | da504ff | 2013-07-11 21:49:38 +0000 | [diff] [blame] | 41 | result.SetError ("option parsing failed") |
| 42 | return |
Greg Clayton | d879a63 | 2012-01-22 02:55:08 +0000 | [diff] [blame] | 43 | |
Enrico Granata | 083fcdb | 2013-05-09 01:32:24 +0000 | [diff] [blame] | 44 | # in a command - the lldb.* convenience variables are not to be used |
| 45 | # and their values (if any) are undefined |
| 46 | # this is the best practice to access those objects from within a command |
| 47 | target = debugger.GetSelectedTarget() |
| 48 | process = target.GetProcess() |
| 49 | thread = process.GetSelectedThread() |
| 50 | frame = thread.GetSelectedFrame() |
| 51 | if not frame.IsValid(): |
| 52 | return "no frame here" |
| 53 | # from now on, replace lldb.<thing>.whatever with <thing>.whatever |
| 54 | variables_list = frame.GetVariables(options.arguments, options.locals, options.statics, options.inscope) |
| 55 | variables_count = variables_list.GetSize() |
| 56 | if variables_count == 0: |
Enrico Granata | da504ff | 2013-07-11 21:49:38 +0000 | [diff] [blame] | 57 | print >> result, "no variables here" |
Enrico Granata | 083fcdb | 2013-05-09 01:32:24 +0000 | [diff] [blame] | 58 | return |
| 59 | total_size = 0 |
| 60 | for i in range(0,variables_count): |
| 61 | variable = variables_list.GetValueAtIndex(i) |
| 62 | variable_type = variable.GetType() |
| 63 | total_size = total_size + variable_type.GetByteSize() |
| 64 | average_size = float(total_size) / variables_count |
Enrico Granata | da504ff | 2013-07-11 21:49:38 +0000 | [diff] [blame] | 65 | 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 | # not returning anything is akin to returning success |
Greg Clayton | d879a63 | 2012-01-22 02:55:08 +0000 | [diff] [blame] | 67 | |
Jim Ingham | 87a5936 | 2012-01-24 02:40:42 +0000 | [diff] [blame] | 68 | def __lldb_init_module (debugger, dict): |
Greg Clayton | f453907 | 2012-09-13 05:35:34 +0000 | [diff] [blame] | 69 | # This initializer is being run from LLDB in the embedded command interpreter |
| 70 | # Make the options so we can generate the help text for the new LLDB |
| 71 | # command line command prior to registering it with LLDB below |
Enrico Granata | 083fcdb | 2013-05-09 01:32:24 +0000 | [diff] [blame] | 72 | parser = create_framestats_options() |
| 73 | the_framestats_command.__doc__ = parser.format_help() |
Greg Clayton | d879a63 | 2012-01-22 02:55:08 +0000 | [diff] [blame] | 74 | # Add any commands contained in this module to LLDB |
Enrico Granata | 083fcdb | 2013-05-09 01:32:24 +0000 | [diff] [blame] | 75 | debugger.HandleCommand('command script add -f cmdtemplate.the_framestats_command framestats') |
| 76 | print 'The "framestats" command has been installed, type "help framestats" or "framestats --help" for detailed help.' |