xref: /aosp_15_r20/external/pytorch/tools/gdb/pytorch-gdb.py (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1*da0073e9SAndroid Build Coastguard Workerimport textwrap
2*da0073e9SAndroid Build Coastguard Workerfrom typing import Any
3*da0073e9SAndroid Build Coastguard Worker
4*da0073e9SAndroid Build Coastguard Workerimport gdb  # type: ignore[import]
5*da0073e9SAndroid Build Coastguard Worker
6*da0073e9SAndroid Build Coastguard Worker
7*da0073e9SAndroid Build Coastguard Workerclass DisableBreakpoints:
8*da0073e9SAndroid Build Coastguard Worker    """
9*da0073e9SAndroid Build Coastguard Worker    Context-manager to temporarily disable all gdb breakpoints, useful if
10*da0073e9SAndroid Build Coastguard Worker    there is a risk to hit one during the evaluation of one of our custom
11*da0073e9SAndroid Build Coastguard Worker    commands
12*da0073e9SAndroid Build Coastguard Worker    """
13*da0073e9SAndroid Build Coastguard Worker
14*da0073e9SAndroid Build Coastguard Worker    def __enter__(self) -> None:
15*da0073e9SAndroid Build Coastguard Worker        self.disabled_breakpoints = []
16*da0073e9SAndroid Build Coastguard Worker        for b in gdb.breakpoints():
17*da0073e9SAndroid Build Coastguard Worker            if b.enabled:
18*da0073e9SAndroid Build Coastguard Worker                b.enabled = False
19*da0073e9SAndroid Build Coastguard Worker                self.disabled_breakpoints.append(b)
20*da0073e9SAndroid Build Coastguard Worker
21*da0073e9SAndroid Build Coastguard Worker    def __exit__(self, etype: Any, evalue: Any, tb: Any) -> None:
22*da0073e9SAndroid Build Coastguard Worker        for b in self.disabled_breakpoints:
23*da0073e9SAndroid Build Coastguard Worker            b.enabled = True
24*da0073e9SAndroid Build Coastguard Worker
25*da0073e9SAndroid Build Coastguard Worker
26*da0073e9SAndroid Build Coastguard Workerclass TensorRepr(gdb.Command):  # type: ignore[misc, no-any-unimported]
27*da0073e9SAndroid Build Coastguard Worker    """
28*da0073e9SAndroid Build Coastguard Worker    Print a human readable representation of the given at::Tensor.
29*da0073e9SAndroid Build Coastguard Worker    Usage: torch-tensor-repr EXP
30*da0073e9SAndroid Build Coastguard Worker
31*da0073e9SAndroid Build Coastguard Worker    at::Tensor instances do not have a C++ implementation of a repr method: in
32*da0073e9SAndroid Build Coastguard Worker    pytorch, this is done by pure-Python code. As such, torch-tensor-repr
33*da0073e9SAndroid Build Coastguard Worker    internally creates a Python wrapper for the given tensor and call repr()
34*da0073e9SAndroid Build Coastguard Worker    on it.
35*da0073e9SAndroid Build Coastguard Worker    """
36*da0073e9SAndroid Build Coastguard Worker
37*da0073e9SAndroid Build Coastguard Worker    __doc__ = textwrap.dedent(__doc__).strip()
38*da0073e9SAndroid Build Coastguard Worker
39*da0073e9SAndroid Build Coastguard Worker    def __init__(self) -> None:
40*da0073e9SAndroid Build Coastguard Worker        gdb.Command.__init__(
41*da0073e9SAndroid Build Coastguard Worker            self, "torch-tensor-repr", gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION
42*da0073e9SAndroid Build Coastguard Worker        )
43*da0073e9SAndroid Build Coastguard Worker
44*da0073e9SAndroid Build Coastguard Worker    def invoke(self, args: str, from_tty: bool) -> None:
45*da0073e9SAndroid Build Coastguard Worker        args = gdb.string_to_argv(args)
46*da0073e9SAndroid Build Coastguard Worker        if len(args) != 1:
47*da0073e9SAndroid Build Coastguard Worker            print("Usage: torch-tensor-repr EXP")
48*da0073e9SAndroid Build Coastguard Worker            return
49*da0073e9SAndroid Build Coastguard Worker        name = args[0]
50*da0073e9SAndroid Build Coastguard Worker        with DisableBreakpoints():
51*da0073e9SAndroid Build Coastguard Worker            res = gdb.parse_and_eval(f"torch::gdb::tensor_repr({name})")
52*da0073e9SAndroid Build Coastguard Worker            print(f"Python-level repr of {name}:")
53*da0073e9SAndroid Build Coastguard Worker            print(res.string())
54*da0073e9SAndroid Build Coastguard Worker            # torch::gdb::tensor_repr returns a malloc()ed buffer, let's free it
55*da0073e9SAndroid Build Coastguard Worker            gdb.parse_and_eval(f"(void)free({int(res)})")
56*da0073e9SAndroid Build Coastguard Worker
57*da0073e9SAndroid Build Coastguard Worker
58*da0073e9SAndroid Build Coastguard WorkerTensorRepr()
59