xref: /llvm-project/lldb/examples/python/cmdtemplate.py (revision 04b443e77845cd20ab5acc4356cee509316135dd)
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 sys
15from lldb.plugins.parsed_cmd import ParsedCommand
16
17class FrameStatCommand(ParsedCommand):
18    program = "framestats"
19
20    @classmethod
21    def register_lldb_command(cls, debugger, module_name):
22        ParsedCommand.do_register_cmd(cls, debugger, module_name)
23        print(
24            'The "{0}" command has been installed, type "help {0}" or "{0} '
25            '--help" for detailed help.'.format(cls.program)
26        )
27
28    def get_flags(self):
29        return lldb.eCommandRequiresFrame | lldb.eCommandProcessMustBePaused
30
31    def setup_command_definition(self):
32        ov_parser = self.get_parser()
33        ov_parser.add_option(
34            "i",
35            "in-scope",
36            help = "in_scope_only = True",
37            value_type = lldb.eArgTypeBoolean,
38            dest = "bool_arg",
39            default = True,
40        )
41
42        ov_parser.add_option(
43            "i",
44            "in-scope",
45            help = "in_scope_only = True",
46            value_type = lldb.eArgTypeBoolean,
47            dest = "inscope",
48            default=True,
49        )
50
51        ov_parser.add_option(
52            "a",
53            "arguments",
54            help = "arguments = True",
55            value_type = lldb.eArgTypeBoolean,
56            dest = "arguments",
57            default = True,
58        )
59
60        ov_parser.add_option(
61            "l",
62            "locals",
63            help = "locals = True",
64            value_type = lldb.eArgTypeBoolean,
65            dest = "locals",
66            default = True,
67        )
68
69        ov_parser.add_option(
70            "s",
71            "statics",
72            help = "statics = True",
73            value_type = lldb.eArgTypeBoolean,
74            dest = "statics",
75            default = True,
76        )
77
78    def get_repeat_command(self, args):
79        """As an example, make the command not auto-repeat:"""
80        return ""
81
82    def get_short_help(self):
83        return "Example command for use in debugging"
84
85    def get_long_help(self):
86        return ("This command is meant to be an example of how to make "
87            "an LLDB command that does something useful, follows "
88            "best practices, and exploits the SB API. "
89            "Specifically, this command computes the aggregate "
90            "and average size of the variables in the current "
91            "frame and allows you to tweak exactly which variables "
92            "are to be accounted in the computation.")
93
94
95    def __init__(self, debugger, unused):
96        super().__init__(debugger, unused)
97
98    def __call__(self, debugger, command, exe_ctx, result):
99        # Always get program state from the lldb.SBExecutionContext passed
100        # in as exe_ctx
101        frame = exe_ctx.GetFrame()
102        if not frame.IsValid():
103            result.SetError("invalid frame")
104            return
105
106        ov_parser = self.get_parser()
107        variables_list = frame.GetVariables(
108            ov_parser.arguments, ov_parser.locals, ov_parser.statics, ov_parser.inscope
109        )
110        variables_count = variables_list.GetSize()
111        if variables_count == 0:
112            print("no variables here", file=result)
113            return
114        total_size = 0
115        for i in range(0, variables_count):
116            variable = variables_list.GetValueAtIndex(i)
117            variable_type = variable.GetType()
118            total_size = total_size + variable_type.GetByteSize()
119            average_size = float(total_size) / variables_count
120            print(
121                "Your frame has %d variables. Their total size "
122                "is %d bytes. The average size is %f bytes"
123                % (variables_count, total_size, average_size),
124                file=result,
125            )
126        # not returning anything is akin to returning success
127
128
129def __lldb_init_module(debugger, dict):
130    # Register all classes that have a register_lldb_command method
131    for _name, cls in inspect.getmembers(sys.modules[__name__]):
132        if inspect.isclass(cls) and callable(
133            getattr(cls, "register_lldb_command", None)
134        ):
135            cls.register_lldb_command(debugger, __name__)
136