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