xref: /openbsd-src/gnu/llvm/lldb/examples/python/cmdtemplate.py (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1be691f3bSpatrick#!/usr/bin/env python
2061da546Spatrick
3061da546Spatrick# ---------------------------------------------------------------------
4061da546Spatrick# Be sure to add the python path that points to the LLDB shared library.
5061da546Spatrick#
6061da546Spatrick# # To use this in the embedded python interpreter using "lldb" just
7061da546Spatrick# import it with the full path using the "command script import"
8061da546Spatrick# command
9061da546Spatrick#   (lldb) command script import /path/to/cmdtemplate.py
10061da546Spatrick# ---------------------------------------------------------------------
11061da546Spatrick
12061da546Spatrickimport inspect
13061da546Spatrickimport lldb
14061da546Spatrickimport optparse
15061da546Spatrickimport shlex
16061da546Spatrickimport sys
17061da546Spatrick
18061da546Spatrick
19061da546Spatrickclass FrameStatCommand:
20061da546Spatrick    program = 'framestats'
21061da546Spatrick
22061da546Spatrick    @classmethod
23061da546Spatrick    def register_lldb_command(cls, debugger, module_name):
24061da546Spatrick        parser = cls.create_options()
25061da546Spatrick        cls.__doc__ = parser.format_help()
26061da546Spatrick        # Add any commands contained in this module to LLDB
27*f6aab3d8Srobert        command = 'command script add -o -c %s.%s %s' % (module_name,
28061da546Spatrick                                                      cls.__name__,
29061da546Spatrick                                                      cls.program)
30061da546Spatrick        debugger.HandleCommand(command)
31061da546Spatrick        print('The "{0}" command has been installed, type "help {0}" or "{0} '
32061da546Spatrick              '--help" for detailed help.'.format(cls.program))
33061da546Spatrick
34061da546Spatrick    @classmethod
35061da546Spatrick    def create_options(cls):
36061da546Spatrick
37061da546Spatrick        usage = "usage: %prog [options]"
38061da546Spatrick        description = ('This command is meant to be an example of how to make '
39061da546Spatrick                       'an LLDB command that does something useful, follows '
40061da546Spatrick                       'best practices, and exploits the SB API. '
41061da546Spatrick                       'Specifically, this command computes the aggregate '
42061da546Spatrick                       'and average size of the variables in the current '
43061da546Spatrick                       'frame and allows you to tweak exactly which variables '
44061da546Spatrick                       'are to be accounted in the computation.')
45061da546Spatrick
46061da546Spatrick        # Pass add_help_option = False, since this keeps the command in line
47061da546Spatrick        #  with lldb commands, and we wire up "help command" to work by
48061da546Spatrick        # providing the long & short help methods below.
49061da546Spatrick        parser = optparse.OptionParser(
50061da546Spatrick            description=description,
51061da546Spatrick            prog=cls.program,
52061da546Spatrick            usage=usage,
53061da546Spatrick            add_help_option=False)
54061da546Spatrick
55061da546Spatrick        parser.add_option(
56061da546Spatrick            '-i',
57061da546Spatrick            '--in-scope',
58061da546Spatrick            action='store_true',
59061da546Spatrick            dest='inscope',
60061da546Spatrick            help='in_scope_only = True',
61061da546Spatrick            default=True)
62061da546Spatrick
63061da546Spatrick        parser.add_option(
64061da546Spatrick            '-a',
65061da546Spatrick            '--arguments',
66061da546Spatrick            action='store_true',
67061da546Spatrick            dest='arguments',
68061da546Spatrick            help='arguments = True',
69061da546Spatrick            default=True)
70061da546Spatrick
71061da546Spatrick        parser.add_option(
72061da546Spatrick            '-l',
73061da546Spatrick            '--locals',
74061da546Spatrick            action='store_true',
75061da546Spatrick            dest='locals',
76061da546Spatrick            help='locals = True',
77061da546Spatrick            default=True)
78061da546Spatrick
79061da546Spatrick        parser.add_option(
80061da546Spatrick            '-s',
81061da546Spatrick            '--statics',
82061da546Spatrick            action='store_true',
83061da546Spatrick            dest='statics',
84061da546Spatrick            help='statics = True',
85061da546Spatrick            default=True)
86061da546Spatrick
87061da546Spatrick        return parser
88061da546Spatrick
89061da546Spatrick    def get_short_help(self):
90061da546Spatrick        return "Example command for use in debugging"
91061da546Spatrick
92061da546Spatrick    def get_long_help(self):
93061da546Spatrick        return self.help_string
94061da546Spatrick
95061da546Spatrick    def __init__(self, debugger, unused):
96061da546Spatrick        self.parser = self.create_options()
97061da546Spatrick        self.help_string = self.parser.format_help()
98061da546Spatrick
99061da546Spatrick    def __call__(self, debugger, command, exe_ctx, result):
100061da546Spatrick        # Use the Shell Lexer to properly parse up command options just like a
101061da546Spatrick        # shell would
102061da546Spatrick        command_args = shlex.split(command)
103061da546Spatrick
104061da546Spatrick        try:
105061da546Spatrick            (options, args) = self.parser.parse_args(command_args)
106061da546Spatrick        except:
107061da546Spatrick            # if you don't handle exceptions, passing an incorrect argument to
108061da546Spatrick            # the OptionParser will cause LLDB to exit (courtesy of OptParse
109061da546Spatrick            # dealing with argument errors by throwing SystemExit)
110061da546Spatrick            result.SetError("option parsing failed")
111061da546Spatrick            return
112061da546Spatrick
113061da546Spatrick        # Always get program state from the lldb.SBExecutionContext passed
114061da546Spatrick        # in as exe_ctx
115061da546Spatrick        frame = exe_ctx.GetFrame()
116061da546Spatrick        if not frame.IsValid():
117061da546Spatrick            result.SetError("invalid frame")
118061da546Spatrick            return
119061da546Spatrick
120061da546Spatrick        variables_list = frame.GetVariables(
121061da546Spatrick            options.arguments,
122061da546Spatrick            options.locals,
123061da546Spatrick            options.statics,
124061da546Spatrick            options.inscope)
125061da546Spatrick        variables_count = variables_list.GetSize()
126061da546Spatrick        if variables_count == 0:
127061da546Spatrick            print("no variables here", file=result)
128061da546Spatrick            return
129061da546Spatrick        total_size = 0
130061da546Spatrick        for i in range(0, variables_count):
131061da546Spatrick            variable = variables_list.GetValueAtIndex(i)
132061da546Spatrick            variable_type = variable.GetType()
133061da546Spatrick            total_size = total_size + variable_type.GetByteSize()
134061da546Spatrick            average_size = float(total_size) / variables_count
135061da546Spatrick            print("Your frame has %d variables. Their total size "
136061da546Spatrick                             "is %d bytes. The average size is %f bytes" % (
137061da546Spatrick                                    variables_count, total_size, average_size), file=result)
138061da546Spatrick        # not returning anything is akin to returning success
139061da546Spatrick
140061da546Spatrick
141061da546Spatrickdef __lldb_init_module(debugger, dict):
142061da546Spatrick    # Register all classes that have a register_lldb_command method
143061da546Spatrick    for _name, cls in inspect.getmembers(sys.modules[__name__]):
144061da546Spatrick        if inspect.isclass(cls) and callable(getattr(cls,
145061da546Spatrick                                                     "register_lldb_command",
146061da546Spatrick                                                     None)):
147061da546Spatrick            cls.register_lldb_command(debugger, __name__)
148