From 1246e00478fb5ab2a357de17066fd8738395d9f1 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 4 May 2026 08:20:42 +0200 Subject: debug: split gdb modules --- .vscode/launch.json | 2 +- .vscode/settings.json | 2 +- kapi/gdb/__init__.py | 15 ++++++++++++ kapi/gdb/address.py | 33 +++++++++++++++++++++++++ libs/kstd/gdb/__init__.py | 20 +++++++++++++++ libs/kstd/gdb/smart_pointers.py | 50 ++++++++++++++++++++++++++++++++++++++ libs/kstd/gdb/std_types.py | 15 ++++++++++++ libs/kstd/gdb/string.py | 27 ++++++++++++++++++++ libs/kstd/gdb/vector.py | 22 +++++++++++++++++ scripts/gdb/kapi/__init__.py | 15 ------------ scripts/gdb/kapi/address.py | 33 ------------------------- scripts/gdb/kstd/__init__.py | 20 --------------- scripts/gdb/kstd/smart_pointers.py | 50 -------------------------------------- scripts/gdb/kstd/std_types.py | 15 ------------ scripts/gdb/kstd/string.py | 27 -------------------- scripts/gdb/kstd/vector.py | 22 ----------------- scripts/gdb/load.py | 16 ------------ scripts/gdb/pretty_printers.py | 37 ++++++++++++++++++++++++++++ 18 files changed, 221 insertions(+), 200 deletions(-) create mode 100644 kapi/gdb/__init__.py create mode 100644 kapi/gdb/address.py create mode 100644 libs/kstd/gdb/__init__.py create mode 100644 libs/kstd/gdb/smart_pointers.py create mode 100644 libs/kstd/gdb/std_types.py create mode 100644 libs/kstd/gdb/string.py create mode 100644 libs/kstd/gdb/vector.py delete mode 100644 scripts/gdb/kapi/__init__.py delete mode 100644 scripts/gdb/kapi/address.py delete mode 100644 scripts/gdb/kstd/__init__.py delete mode 100644 scripts/gdb/kstd/smart_pointers.py delete mode 100644 scripts/gdb/kstd/std_types.py delete mode 100644 scripts/gdb/kstd/string.py delete mode 100644 scripts/gdb/kstd/vector.py delete mode 100644 scripts/gdb/load.py create mode 100644 scripts/gdb/pretty_printers.py diff --git a/.vscode/launch.json b/.vscode/launch.json index d5b2401..15f5d3a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -28,7 +28,7 @@ }, { "description": "Load custom Python helpers", - "text": "-interpreter-exec console \"source ${workspaceFolder}/scripts/gdb/load.py\"" + "text": "-interpreter-exec console \"source ${workspaceFolder}/scripts/gdb/pretty_printers.py\"" } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index c8f9013..efe3bc7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -90,7 +90,7 @@ }, { "description": "Load custom Python helpers", - "text": "-interpreter-exec console \"source ${workspaceFolder}/scripts/gdb/load.py\"" + "text": "-interpreter-exec console \"source ${workspaceFolder}/scripts/gdb/pretty_printers.py\"" } ], }, diff --git a/kapi/gdb/__init__.py b/kapi/gdb/__init__.py new file mode 100644 index 0000000..c37c7b7 --- /dev/null +++ b/kapi/gdb/__init__.py @@ -0,0 +1,15 @@ +import gdb.printing + +from .address import KapiMemoryAddressPrinter + + +def build_pretty_printers(): + pp = gdb.printing.RegexpCollectionPrettyPrinter("kapi") + pp.add_printer( + "kapi_memory_address", "^kapi::memory::address<.*>$", KapiMemoryAddressPrinter + ) + return pp + + +def register_printers(objfile): + gdb.printing.register_pretty_printer(objfile, build_pretty_printers(), replace=True) diff --git a/kapi/gdb/address.py b/kapi/gdb/address.py new file mode 100644 index 0000000..677c9aa --- /dev/null +++ b/kapi/gdb/address.py @@ -0,0 +1,33 @@ +import gdb + + +class KapiMemoryAddressPrinter: + """Print kapi::MemoryAddress.""" + + def __init__(self, val): + self.val = val + self.address_type = val.type.template_argument(0) + + def to_string(self): + try: + raw_address = int(self.val["m_value"]) + type_string = str(self.address_type) + + if "linear" in type_string: + suffix = "%lin" + elif "physical" in type_string: + suffix = "%phy" + else: + suffix = "%???" + + return f"{raw_address:#018x}{suffix}" + except Exception as e: + return f"{self.val}: {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"]) diff --git a/libs/kstd/gdb/__init__.py b/libs/kstd/gdb/__init__.py new file mode 100644 index 0000000..fc5e8fb --- /dev/null +++ b/libs/kstd/gdb/__init__.py @@ -0,0 +1,20 @@ +import gdb.printing + +from .vector import KstdVectorPrinter +from .string import KstdStringPrinter +from .std_types import StdBytePrinter +from .smart_pointers import KstdUniquePtrPrinter, KstdSharedPtrPrinter + + +def build_pretty_printers(): + pp = gdb.printing.RegexpCollectionPrettyPrinter("kstd") + pp.add_printer("vector", "^kstd::vector<.*>$", KstdVectorPrinter) + pp.add_printer("string", "^kstd::string$", KstdStringPrinter) + pp.add_printer("std_byte", "^std::byte$", StdBytePrinter) + pp.add_printer("unique_ptr", "^kstd::unique_ptr<.*>$", KstdUniquePtrPrinter) + pp.add_printer("shared_ptr", "^kstd::shared_ptr<.*>$", KstdSharedPtrPrinter) + return pp + + +def register_printers(objfile): + gdb.printing.register_pretty_printer(objfile, build_pretty_printers(), replace=True) diff --git a/libs/kstd/gdb/smart_pointers.py b/libs/kstd/gdb/smart_pointers.py new file mode 100644 index 0000000..6e4a4f9 --- /dev/null +++ b/libs/kstd/gdb/smart_pointers.py @@ -0,0 +1,50 @@ +import gdb + + +class KstdUniquePtrPrinter: + + def __init__(self, val): + self.val = val + self.type = val.type.template_argument(0) + + def to_string(self): + pointer = self.val["pointer"] + if int(pointer) == 0: + return f"kstd::unique_ptr<{self.type}> (empty)" + return f"kstd::unique_ptr<{self.type}>" + + def children(self): + pointer = self.val["pointer"] + if int(pointer) != 0: + yield ("get()", pointer) + yield ("*get()", pointer.dereference()) + + +class KstdSharedPtrPrinter: + + def __init__(self, val): + self.val = val + self.type = val.type.template_argument(0) + + def to_string(self): + pointer = self.val["pointer"] + control_block = self.val["control"] + + if int(pointer) == 0 or int(control_block) == 0: + 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})" + + def children(self): + pointer = self.val["pointer"] + control_block = self.val["control"] + + if int(pointer) != 0: + yield ("get()", pointer) + yield ("*get()", pointer.dereference()) + + if int(control_block) != 0: + yield ("[control_block]", control_block.dereference()) diff --git a/libs/kstd/gdb/std_types.py b/libs/kstd/gdb/std_types.py new file mode 100644 index 0000000..78d094c --- /dev/null +++ b/libs/kstd/gdb/std_types.py @@ -0,0 +1,15 @@ +import gdb + + +class StdBytePrinter: + + def __init__(self, val): + self.val = val + + def to_string(self): + try: + uint8_type = gdb.lookup_type("unsigned char") + numeric_value = int(self.val.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 new file mode 100644 index 0000000..8230b21 --- /dev/null +++ b/libs/kstd/gdb/string.py @@ -0,0 +1,27 @@ +import gdb + + +class KstdStringPrinter: + + def __init__(self, val): + self.val = val + + def to_string(self): + storage = self.val["m_storage"] + storage_size = int(storage["m_size"]) + + if storage_size <= 0: + return '""' + + data_pointer = storage["m_data"] + string_length = storage_size - 1 + + try: + if hasattr(data_pointer, "lazy_string"): + return data_pointer.lazy_string(encoding="utf-8", length=string_length) + return data_pointer.string(encoding="utf-8", length=string_length) + except gdb.error: + return "" + + def display_hint(self): + return "string" diff --git a/libs/kstd/gdb/vector.py b/libs/kstd/gdb/vector.py new file mode 100644 index 0000000..597ffdc --- /dev/null +++ b/libs/kstd/gdb/vector.py @@ -0,0 +1,22 @@ +import gdb + + +class KstdVectorPrinter: + + def __init__(self, val): + self.val = 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}" + + def children(self): + size = int(self.val["m_size"]) + data_pointer = self.val["m_data"] + for i in range(size): + yield (f"[{i}]", (data_pointer + i).dereference()) + + def display_hint(self): + return "array" diff --git a/scripts/gdb/kapi/__init__.py b/scripts/gdb/kapi/__init__.py deleted file mode 100644 index c37c7b7..0000000 --- a/scripts/gdb/kapi/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -import gdb.printing - -from .address import KapiMemoryAddressPrinter - - -def build_pretty_printers(): - pp = gdb.printing.RegexpCollectionPrettyPrinter("kapi") - pp.add_printer( - "kapi_memory_address", "^kapi::memory::address<.*>$", KapiMemoryAddressPrinter - ) - return pp - - -def register_printers(objfile): - gdb.printing.register_pretty_printer(objfile, build_pretty_printers(), replace=True) diff --git a/scripts/gdb/kapi/address.py b/scripts/gdb/kapi/address.py deleted file mode 100644 index 677c9aa..0000000 --- a/scripts/gdb/kapi/address.py +++ /dev/null @@ -1,33 +0,0 @@ -import gdb - - -class KapiMemoryAddressPrinter: - """Print kapi::MemoryAddress.""" - - def __init__(self, val): - self.val = val - self.address_type = val.type.template_argument(0) - - def to_string(self): - try: - raw_address = int(self.val["m_value"]) - type_string = str(self.address_type) - - if "linear" in type_string: - suffix = "%lin" - elif "physical" in type_string: - suffix = "%phy" - else: - suffix = "%???" - - return f"{raw_address:#018x}{suffix}" - except Exception as e: - return f"{self.val}: {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"]) diff --git a/scripts/gdb/kstd/__init__.py b/scripts/gdb/kstd/__init__.py deleted file mode 100644 index fc5e8fb..0000000 --- a/scripts/gdb/kstd/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -import gdb.printing - -from .vector import KstdVectorPrinter -from .string import KstdStringPrinter -from .std_types import StdBytePrinter -from .smart_pointers import KstdUniquePtrPrinter, KstdSharedPtrPrinter - - -def build_pretty_printers(): - pp = gdb.printing.RegexpCollectionPrettyPrinter("kstd") - pp.add_printer("vector", "^kstd::vector<.*>$", KstdVectorPrinter) - pp.add_printer("string", "^kstd::string$", KstdStringPrinter) - pp.add_printer("std_byte", "^std::byte$", StdBytePrinter) - pp.add_printer("unique_ptr", "^kstd::unique_ptr<.*>$", KstdUniquePtrPrinter) - pp.add_printer("shared_ptr", "^kstd::shared_ptr<.*>$", KstdSharedPtrPrinter) - return pp - - -def register_printers(objfile): - gdb.printing.register_pretty_printer(objfile, build_pretty_printers(), replace=True) diff --git a/scripts/gdb/kstd/smart_pointers.py b/scripts/gdb/kstd/smart_pointers.py deleted file mode 100644 index 6e4a4f9..0000000 --- a/scripts/gdb/kstd/smart_pointers.py +++ /dev/null @@ -1,50 +0,0 @@ -import gdb - - -class KstdUniquePtrPrinter: - - def __init__(self, val): - self.val = val - self.type = val.type.template_argument(0) - - def to_string(self): - pointer = self.val["pointer"] - if int(pointer) == 0: - return f"kstd::unique_ptr<{self.type}> (empty)" - return f"kstd::unique_ptr<{self.type}>" - - def children(self): - pointer = self.val["pointer"] - if int(pointer) != 0: - yield ("get()", pointer) - yield ("*get()", pointer.dereference()) - - -class KstdSharedPtrPrinter: - - def __init__(self, val): - self.val = val - self.type = val.type.template_argument(0) - - def to_string(self): - pointer = self.val["pointer"] - control_block = self.val["control"] - - if int(pointer) == 0 or int(control_block) == 0: - 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})" - - def children(self): - pointer = self.val["pointer"] - control_block = self.val["control"] - - if int(pointer) != 0: - yield ("get()", pointer) - yield ("*get()", pointer.dereference()) - - if int(control_block) != 0: - yield ("[control_block]", control_block.dereference()) diff --git a/scripts/gdb/kstd/std_types.py b/scripts/gdb/kstd/std_types.py deleted file mode 100644 index 78d094c..0000000 --- a/scripts/gdb/kstd/std_types.py +++ /dev/null @@ -1,15 +0,0 @@ -import gdb - - -class StdBytePrinter: - - def __init__(self, val): - self.val = val - - def to_string(self): - try: - uint8_type = gdb.lookup_type("unsigned char") - numeric_value = int(self.val.cast(uint8_type)) - return f"{numeric_value:#04x}" - except gdb.error: - return f"" diff --git a/scripts/gdb/kstd/string.py b/scripts/gdb/kstd/string.py deleted file mode 100644 index 8230b21..0000000 --- a/scripts/gdb/kstd/string.py +++ /dev/null @@ -1,27 +0,0 @@ -import gdb - - -class KstdStringPrinter: - - def __init__(self, val): - self.val = val - - def to_string(self): - storage = self.val["m_storage"] - storage_size = int(storage["m_size"]) - - if storage_size <= 0: - return '""' - - data_pointer = storage["m_data"] - string_length = storage_size - 1 - - try: - if hasattr(data_pointer, "lazy_string"): - return data_pointer.lazy_string(encoding="utf-8", length=string_length) - return data_pointer.string(encoding="utf-8", length=string_length) - except gdb.error: - return "" - - def display_hint(self): - return "string" diff --git a/scripts/gdb/kstd/vector.py b/scripts/gdb/kstd/vector.py deleted file mode 100644 index 597ffdc..0000000 --- a/scripts/gdb/kstd/vector.py +++ /dev/null @@ -1,22 +0,0 @@ -import gdb - - -class KstdVectorPrinter: - - def __init__(self, val): - self.val = 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}" - - def children(self): - size = int(self.val["m_size"]) - data_pointer = self.val["m_data"] - for i in range(size): - yield (f"[{i}]", (data_pointer + i).dereference()) - - def display_hint(self): - return "array" diff --git a/scripts/gdb/load.py b/scripts/gdb/load.py deleted file mode 100644 index ec512b7..0000000 --- a/scripts/gdb/load.py +++ /dev/null @@ -1,16 +0,0 @@ -import sys -import os -import gdb - -script_dir = os.path.dirname(os.path.abspath(__file__)) - -if script_dir not in sys.path: - sys.path.insert(0, script_dir) - -import kstd -import kapi - -kstd.register_printers(gdb.current_objfile()) -kapi.register_printers(gdb.current_objfile()) - -gdb.write("Loaded TeachOS pretty printers.\n") diff --git a/scripts/gdb/pretty_printers.py b/scripts/gdb/pretty_printers.py new file mode 100644 index 0000000..83db491 --- /dev/null +++ b/scripts/gdb/pretty_printers.py @@ -0,0 +1,37 @@ +import sys +import os +import gdb +import importlib.util + +script_path = os.path.abspath(__file__) +repo_root = os.path.dirname(os.path.dirname(os.path.dirname(script_path))) + +components = { + "kstd": "libs/kstd/gdb", + "kapi": "kapi/gdb", +} + +for component, path in components.items(): + full_path = os.path.join(repo_root, *path.split("/")) + init_file = os.path.join(full_path, "__init__.py") + + if os.path.isfile(init_file): + try: + spec = importlib.util.spec_from_file_location(component, init_file) + module = importlib.util.module_from_spec(spec) + sys.modules[component] = module + spec.loader.exec_module(module) + + if hasattr(module, "register_printers"): + module.register_printers(gdb.current_objfile()) + gdb.write(f"Info: Registered pretty printers for '{component}'.\n") + else: + gdb.write( + f"Warning: '{component}' does not have 'register_printers' function\n" + ) + except Exception as e: + gdb.write(f"Warning: Failed to load '{component}' pretty printers: {e}\n") + else: + gdb.write(f"Warning: GDB extension init not found: '{init_file}'\n") + +gdb.write("Info: Loaded TeachOS pretty printers.\n") -- cgit v1.2.3