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