From 78e42a1b6e0a857865be1e60f82871ac13c91bb1 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 4 May 2026 12:01:01 +0200 Subject: debug: improve pretty printer implementations --- kapi/gdb/__init__.py | 4 ++++ kapi/gdb/address.py | 25 +++++++++++------------- kapi/gdb/device.py | 9 +++++++++ libs/kstd/gdb/smart_pointers.py | 43 +++++++++++++++++++++-------------------- libs/kstd/gdb/std_types.py | 8 +++----- libs/kstd/gdb/string.py | 4 ++-- libs/kstd/gdb/vector.py | 19 +++++++++--------- scripts/gdb/pretty_printers.py | 6 +++++- scripts/gdb/teachos/__init__.py | 30 ++++++++++++++++++++++++++++ 9 files changed, 96 insertions(+), 52 deletions(-) create mode 100644 kapi/gdb/device.py create mode 100644 scripts/gdb/teachos/__init__.py diff --git a/kapi/gdb/__init__.py b/kapi/gdb/__init__.py index c37c7b7..ce95628 100644 --- a/kapi/gdb/__init__.py +++ b/kapi/gdb/__init__.py @@ -1,6 +1,7 @@ import gdb.printing from .address import KapiMemoryAddressPrinter +from .device import KapiDevicesDevicePrinter def build_pretty_printers(): @@ -8,6 +9,9 @@ def build_pretty_printers(): pp.add_printer( "kapi_memory_address", "^kapi::memory::address<.*>$", KapiMemoryAddressPrinter ) + pp.add_printer( + "kapi_devices_device", "^kapi::devices::device$", KapiDevicesDevicePrinter + ) return pp diff --git a/kapi/gdb/address.py b/kapi/gdb/address.py index 677c9aa..24fe681 100644 --- a/kapi/gdb/address.py +++ b/kapi/gdb/address.py @@ -1,17 +1,16 @@ import gdb +from teachos import TeachOSBasePrinter -class KapiMemoryAddressPrinter: - """Print kapi::MemoryAddress.""" - +class KapiMemoryAddressPrinter(TeachOSBasePrinter): def __init__(self, val): - self.val = val - self.address_type = val.type.template_argument(0) + super().__init__(val) + self.__type = val.type.template_argument(0) def to_string(self): try: - raw_address = int(self.val["m_value"]) - type_string = str(self.address_type) + raw_address = int(self.value["m_value"]) + type_string = str(self.__type) if "linear" in type_string: suffix = "%lin" @@ -22,12 +21,10 @@ class KapiMemoryAddressPrinter: return f"{raw_address:#018x}{suffix}" except Exception as e: - return f"{self.val}: {e}" + return f"{self.value}: {e}" def children(self): - if "linear" in str(self.address_type): - yield ( - "std::byte *", - self.val["m_value"].cast(gdb.lookup_type("std::byte").pointer()), - ) - yield ("m_value", self.val["m_value"]) + if "linear" in str(self.__type): + pointer_type = gdb.lookup_type("std::byte").pointer() + yield ("[bytes]", self.value["m_value"].cast(pointer_type)) + yield from super().children() diff --git a/kapi/gdb/device.py b/kapi/gdb/device.py new file mode 100644 index 0000000..b655972 --- /dev/null +++ b/kapi/gdb/device.py @@ -0,0 +1,9 @@ +import gdb +from teachos import TeachOSBasePrinter + + +class KapiDevicesDevicePrinter(TeachOSBasePrinter): + def to_string(self): + return ( + f"{self.value['m_name']} @ {self.value['m_major']}:{self.value['m_minor']}" + ) diff --git a/libs/kstd/gdb/smart_pointers.py b/libs/kstd/gdb/smart_pointers.py index 6e4a4f9..3e5da02 100644 --- a/libs/kstd/gdb/smart_pointers.py +++ b/libs/kstd/gdb/smart_pointers.py @@ -1,50 +1,51 @@ import gdb +from teachos import TeachOSBasePrinter -class KstdUniquePtrPrinter: - +class KstdUniquePtrPrinter(TeachOSBasePrinter): def __init__(self, val): - self.val = val - self.type = val.type.template_argument(0) + super().__init__(val) + self.__type = val.type.template_argument(0) def to_string(self): - pointer = self.val["pointer"] + pointer = self.value["pointer"] if int(pointer) == 0: - return f"kstd::unique_ptr<{self.type}> (empty)" - return f"kstd::unique_ptr<{self.type}>" + return f"kstd::unique_ptr<{self.__type}> (empty)" + return f"kstd::unique_ptr<{self.__type}>" def children(self): - pointer = self.val["pointer"] + pointer = self.value["pointer"] if int(pointer) != 0: - yield ("get()", pointer) - yield ("*get()", pointer.dereference()) + yield ("[object]", pointer.dereference()) + yield from super().children() -class KstdSharedPtrPrinter: +class KstdSharedPtrPrinter(TeachOSBasePrinter): def __init__(self, val): - self.val = val - self.type = val.type.template_argument(0) + super().__init__(val) + self.__type = val.type.template_argument(0) def to_string(self): - pointer = self.val["pointer"] - control_block = self.val["control"] + pointer = self.value["pointer"] + control_block = self.value["control"] if int(pointer) == 0 or int(control_block) == 0: - return f"kstd::shared_ptr<{self.type}> (empty)" + return f"kstd::shared_ptr<{self.__type}> (empty)" strong_refs = int(control_block["shared_count"]["_M_i"]) weak_refs = int(control_block["weak_count"]["_M_i"]) - return f"kstd::shared_ptr<{self.type}> (use_count={strong_refs}, weak_count={weak_refs})" + return f"kstd::shared_ptr<{self.__type}> (use_count={strong_refs}, weak_count={weak_refs})" def children(self): - pointer = self.val["pointer"] - control_block = self.val["control"] + pointer = self.value["pointer"] + control_block = self.value["control"] if int(pointer) != 0: - yield ("get()", pointer) - yield ("*get()", pointer.dereference()) + yield ("[object]", pointer.dereference()) if int(control_block) != 0: yield ("[control_block]", control_block.dereference()) + + yield from super().children() diff --git a/libs/kstd/gdb/std_types.py b/libs/kstd/gdb/std_types.py index 78d094c..deb5c58 100644 --- a/libs/kstd/gdb/std_types.py +++ b/libs/kstd/gdb/std_types.py @@ -1,15 +1,13 @@ import gdb +from teachos import TeachOSBasePrinter -class StdBytePrinter: - - def __init__(self, val): - self.val = val +class StdBytePrinter(TeachOSBasePrinter): def to_string(self): try: uint8_type = gdb.lookup_type("unsigned char") - numeric_value = int(self.val.cast(uint8_type)) + numeric_value = int(self.value.cast(uint8_type)) return f"{numeric_value:#04x}" except gdb.error: return f"" diff --git a/libs/kstd/gdb/string.py b/libs/kstd/gdb/string.py index 8230b21..2688061 100644 --- a/libs/kstd/gdb/string.py +++ b/libs/kstd/gdb/string.py @@ -4,10 +4,10 @@ import gdb class KstdStringPrinter: def __init__(self, val): - self.val = val + self.__val = val def to_string(self): - storage = self.val["m_storage"] + storage = self.__val["m_storage"] storage_size = int(storage["m_size"]) if storage_size <= 0: diff --git a/libs/kstd/gdb/vector.py b/libs/kstd/gdb/vector.py index 597ffdc..4340ef4 100644 --- a/libs/kstd/gdb/vector.py +++ b/libs/kstd/gdb/vector.py @@ -1,20 +1,21 @@ import gdb +from teachos import TeachOSBasePrinter -class KstdVectorPrinter: - +class KstdVectorPrinter(TeachOSBasePrinter): def __init__(self, val): - self.val = val - self.type = val.type.template_argument(0) + super().__init__(val) + self.__type = val.type.template_argument(0) def to_string(self): - size = int(self.val["m_size"]) - capacity = int(self.val["m_capacity"]) - return f"kstd::vector of length {size}, capacity {capacity}" + size = int(self.value["m_size"]) + capacity = int(self.value["m_capacity"]) + return f"kstd::vector<{self.__type}> (size={size}, capacity={capacity})" def children(self): - size = int(self.val["m_size"]) - data_pointer = self.val["m_data"] + yield from super().children() + size = int(self.value["m_size"]) + data_pointer = self.value["m_data"] for i in range(size): yield (f"[{i}]", (data_pointer + i).dereference()) diff --git a/scripts/gdb/pretty_printers.py b/scripts/gdb/pretty_printers.py index 83db491..c209328 100644 --- a/scripts/gdb/pretty_printers.py +++ b/scripts/gdb/pretty_printers.py @@ -4,7 +4,11 @@ import gdb import importlib.util script_path = os.path.abspath(__file__) -repo_root = os.path.dirname(os.path.dirname(os.path.dirname(script_path))) +script_root = os.path.dirname(script_path) +repo_root = os.path.dirname(os.path.dirname(script_root)) + +if script_root not in sys.path: + sys.path.insert(0, script_root) components = { "kstd": "libs/kstd/gdb", diff --git a/scripts/gdb/teachos/__init__.py b/scripts/gdb/teachos/__init__.py new file mode 100644 index 0000000..d90d6ad --- /dev/null +++ b/scripts/gdb/teachos/__init__.py @@ -0,0 +1,30 @@ +import gdb + + +class TeachOSBasePrinter: + def __init__(self, val): + self.__val = val + + @property + def value(self): + return self.__val + + def children(self): + real_type = self.value.type.strip_typedefs() + + if real_type.code not in (gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION): + return + + for field in real_type.fields(): + if field.artificial: + continue + + try: + if field.is_base_class: + yield (field.name, self.value.cast(field.type)) + elif field.name is not None: + yield (field.name, self.value[field.name]) + else: + yield ("", self.value[field]) + except gdb.error: + yield (str(field.name), "") -- cgit v1.2.3