Files
gnat-gdb-scripts/gnatdbg/debug.py
Pierre-Marie de Rodat 430a77d4ec gnatdbg: add type hints
Change-Id: Ib0f0cafe4927fc3c581f58d2e90a502b5b3a1544
TN: V707-013
2022-07-07 11:37:40 +00:00

78 lines
2.4 KiB
Python

"""
Helpers to ease the discovery/debugging of GDB's Python API.
"""
from __future__ import annotations
import itertools
from typing import Dict, Tuple
import gdb
from gnatdbg.utils import gdb_code_names
def print_type_tree(typeobj: gdb.Type) -> None:
"""
Print a GDB type as a tree on the standard output.
:param gdb.Type typeobj: Root type for the tree to print.
"""
counter = iter(itertools.count(0))
visited: Dict[Tuple[int, str, str], int] = {}
def helper(t: gdb.Type, indent: int = 1) -> str:
indent_str = " " * indent
code_name = gdb_code_names[t.code]
# To avoid too verbose outputs, try to avoid describing types more than
# once. As we can't rely on identity of gdb.Type instances, we use
# instead the following tuple.
key = (code_name, str(t), t.name)
try:
no = visited[key]
except KeyError:
no = next(counter)
visited[key] = no
else:
return "%{} ({} : {})".format(no, t.name, code_name)
result = "%{} ({} : {})".format(no, t.name, code_name)
if t.code in (gdb.TYPE_CODE_PTR, gdb.TYPE_CODE_TYPEDEF):
result += ":\n{}{}".format(
indent_str, helper(t.target(), indent + 1)
)
elif t.code == gdb.TYPE_CODE_INT:
result += " ({} bytes)".format(t.sizeof)
elif t.code == gdb.TYPE_CODE_ARRAY:
first, last = t.range()
result += "[{} .. {}]:\n{}{}".format(
first, last, indent_str, helper(t.target(), indent + 1)
)
elif t.code in (gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION):
result += ":"
for field in t.fields():
result += "\n{}{}: {}".format(
indent_str, field.name, helper(field.type, indent + 1)
)
return result
print(helper(typeobj))
class PrintGDBTypeTreeCommand(gdb.Command):
"""
Prints a GDB type as a tree.
This command is intended to help pretty-printers development. It prints the
GDB view of user types, i.e. trees of gdb.Type instances.
"""
def __init__(self) -> None:
super().__init__("dbgtype", gdb.COMMAND_NONE, gdb.COMPLETE_SYMBOL)
def invoke(self, arg: str, from_tty: bool) -> None:
argv = gdb.string_to_argv(arg)
typeobj = gdb.parse_and_eval(argv[0]).type
print_type_tree(typeobj)