From 3bf3c748eec38c776dd3c54cbb30be1d44ffb5c3 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 7 Apr 2026 14:01:18 +0200 Subject: ide: simplify overall configuration --- scripts/qemu-wrapper.sh | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/qemu-wrapper.sh b/scripts/qemu-wrapper.sh index fa89ac5..49c01ec 100755 --- a/scripts/qemu-wrapper.sh +++ b/scripts/qemu-wrapper.sh @@ -1,4 +1,30 @@ #!/bin/bash +# scripts/qemu-wrapper.sh -echo "QEMU WRAPPER" -qemu-system-x86_64 $@ +WORKSPACE_DIR=${1:-.} +BUILD_TYPE=${2:-Debug} +ISO_PATH=$3 +IS_DEBUG=${4:-0} + +if [ -z "$ISO_PATH" ]; then + echo "Usage: $0 [is_debug]" + exit 1 +fi + +ARGS=( + "-m" "32M" + "-machine" "q35" + "-smp" "4,sockets=1,cores=4,threads=1" + "-display" "curses" + "-debugcon" "file:${WORKSPACE_DIR}/qemu-debugcon-${BUILD_TYPE}.log" + "-cdrom" "${ISO_PATH}" +) + +if [ "$IS_DEBUG" == "1" ]; then + ARGS=( "-s" "-no-reboot" "-d" "int,cpu_reset" "${ARGS[@]}" ) +fi + +echo "QEMU WRAPPER: Executing TeachOS" +echo "Arguments: ${ARGS[@]}" + +qemu-system-x86_64 "${ARGS[@]}" 2> "${WORKSPACE_DIR}/qemu-stderr-${BUILD_TYPE}.log" -- cgit v1.2.3 From 9c0fb15aa67a4dda6beed3cbdfc4cc510674313f Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Wed, 8 Apr 2026 14:13:19 +0200 Subject: add test with multiple correct formatted ext2 file systems increase QEMU memory --- scripts/qemu-wrapper.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/qemu-wrapper.sh b/scripts/qemu-wrapper.sh index 49c01ec..dd0200d 100755 --- a/scripts/qemu-wrapper.sh +++ b/scripts/qemu-wrapper.sh @@ -12,7 +12,7 @@ if [ -z "$ISO_PATH" ]; then fi ARGS=( - "-m" "32M" + "-m" "64M" "-machine" "q35" "-smp" "4,sockets=1,cores=4,threads=1" "-display" "curses" -- cgit v1.2.3 From 61949538ad6d114c1c2a788928a0b9706b4efc76 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 1 May 2026 20:46:21 +0200 Subject: debug: add support for kstd pretty printing --- scripts/gdb/kstd/__init__.py | 17 +++++++++++++++++ scripts/gdb/kstd/std_types.py | 15 +++++++++++++++ scripts/gdb/kstd/string.py | 26 ++++++++++++++++++++++++++ scripts/gdb/kstd/vector.py | 22 ++++++++++++++++++++++ scripts/gdb/load_kstd.py | 14 ++++++++++++++ 5 files changed, 94 insertions(+) create mode 100644 scripts/gdb/kstd/__init__.py create mode 100644 scripts/gdb/kstd/std_types.py create mode 100644 scripts/gdb/kstd/string.py create mode 100644 scripts/gdb/kstd/vector.py create mode 100644 scripts/gdb/load_kstd.py (limited to 'scripts') diff --git a/scripts/gdb/kstd/__init__.py b/scripts/gdb/kstd/__init__.py new file mode 100644 index 0000000..7dc1596 --- /dev/null +++ b/scripts/gdb/kstd/__init__.py @@ -0,0 +1,17 @@ +import gdb.printing + +from .vector import KstdVectorPrinter +from .string import KstdStringPrinter +from .std_types import StdBytePrinter + + +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) + return pp + + +def register_printers(objfile): + gdb.printing.register_pretty_printer(objfile, build_pretty_printers(), replace=True) diff --git a/scripts/gdb/kstd/std_types.py b/scripts/gdb/kstd/std_types.py new file mode 100644 index 0000000..78d094c --- /dev/null +++ b/scripts/gdb/kstd/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/scripts/gdb/kstd/string.py b/scripts/gdb/kstd/string.py new file mode 100644 index 0000000..6fa9996 --- /dev/null +++ b/scripts/gdb/kstd/string.py @@ -0,0 +1,26 @@ +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: + string_data = data_pointer.string(encoding="utf-8", length=string_length) + return f"{string_data}" + except gdb.error: + return "" + + def display_hint(self): + return "string" diff --git a/scripts/gdb/kstd/vector.py b/scripts/gdb/kstd/vector.py new file mode 100644 index 0000000..b42aeae --- /dev/null +++ b/scripts/gdb/kstd/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<{self.type}> 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_kstd.py b/scripts/gdb/load_kstd.py new file mode 100644 index 0000000..f3adce1 --- /dev/null +++ b/scripts/gdb/load_kstd.py @@ -0,0 +1,14 @@ +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 + +kstd.register_printers(gdb.current_objfile()) + +gdb.write("Loaded kstd pretty printers.\n") -- cgit v1.2.3 From 128e4a2adca6721254e8ffd290b670cc58b7a898 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 1 May 2026 21:00:39 +0200 Subject: debug: add support for smart pointer pretty printing --- scripts/gdb/kstd/__init__.py | 3 +++ scripts/gdb/kstd/smart_pointers.py | 50 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 scripts/gdb/kstd/smart_pointers.py (limited to 'scripts') diff --git a/scripts/gdb/kstd/__init__.py b/scripts/gdb/kstd/__init__.py index 7dc1596..fc5e8fb 100644 --- a/scripts/gdb/kstd/__init__.py +++ b/scripts/gdb/kstd/__init__.py @@ -3,6 +3,7 @@ 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(): @@ -10,6 +11,8 @@ def build_pretty_printers(): 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 diff --git a/scripts/gdb/kstd/smart_pointers.py b/scripts/gdb/kstd/smart_pointers.py new file mode 100644 index 0000000..9af16fd --- /dev/null +++ b/scripts/gdb/kstd/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["m_ptr"] + 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"] + cb = self.val["control_block"] + + if int(pointer) == 0 or int(cb) == 0: + return f"kstd::shared_ptr<{self.type}> (empty)" + + strong_refs = int(cb["m_strong_refs"]) + weak_refs = int(cb["m_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"] + + if int(pointer) != 0: + yield ("get()", pointer) + yield ("*get()", pointer.dereference()) + + if int(control_block) != 0: + yield ("[control_block]", control_block.dereference()) -- cgit v1.2.3 From d55ebee48dbf06ed59759f6c78c75c264bf6b8c5 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Sat, 2 May 2026 13:29:38 +0200 Subject: debug: fix smart pointer pretty printers --- scripts/gdb/kstd/smart_pointers.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/gdb/kstd/smart_pointers.py b/scripts/gdb/kstd/smart_pointers.py index 9af16fd..6e4a4f9 100644 --- a/scripts/gdb/kstd/smart_pointers.py +++ b/scripts/gdb/kstd/smart_pointers.py @@ -14,7 +14,7 @@ class KstdUniquePtrPrinter: return f"kstd::unique_ptr<{self.type}>" def children(self): - pointer = self.val["m_ptr"] + pointer = self.val["pointer"] if int(pointer) != 0: yield ("get()", pointer) yield ("*get()", pointer.dereference()) @@ -28,13 +28,13 @@ class KstdSharedPtrPrinter: def to_string(self): pointer = self.val["pointer"] - cb = self.val["control_block"] + control_block = self.val["control"] - if int(pointer) == 0 or int(cb) == 0: + if int(pointer) == 0 or int(control_block) == 0: return f"kstd::shared_ptr<{self.type}> (empty)" - strong_refs = int(cb["m_strong_refs"]) - weak_refs = int(cb["m_weak_refs"]) + 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})" -- cgit v1.2.3 From 596550c8002c2a1fa375ff7f39b6b9707b9f042d Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Sat, 2 May 2026 14:49:28 +0200 Subject: debug: add kapi formatter support --- scripts/gdb/kapi/__init__.py | 15 +++++++++++++++ scripts/gdb/kapi/address.py | 33 +++++++++++++++++++++++++++++++++ scripts/gdb/load.py | 16 ++++++++++++++++ scripts/gdb/load_kstd.py | 14 -------------- 4 files changed, 64 insertions(+), 14 deletions(-) create mode 100644 scripts/gdb/kapi/__init__.py create mode 100644 scripts/gdb/kapi/address.py create mode 100644 scripts/gdb/load.py delete mode 100644 scripts/gdb/load_kstd.py (limited to 'scripts') diff --git a/scripts/gdb/kapi/__init__.py b/scripts/gdb/kapi/__init__.py new file mode 100644 index 0000000..c37c7b7 --- /dev/null +++ b/scripts/gdb/kapi/__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/scripts/gdb/kapi/address.py b/scripts/gdb/kapi/address.py new file mode 100644 index 0000000..677c9aa --- /dev/null +++ b/scripts/gdb/kapi/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/scripts/gdb/load.py b/scripts/gdb/load.py new file mode 100644 index 0000000..ec512b7 --- /dev/null +++ b/scripts/gdb/load.py @@ -0,0 +1,16 @@ +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/load_kstd.py b/scripts/gdb/load_kstd.py deleted file mode 100644 index f3adce1..0000000 --- a/scripts/gdb/load_kstd.py +++ /dev/null @@ -1,14 +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 - -kstd.register_printers(gdb.current_objfile()) - -gdb.write("Loaded kstd pretty printers.\n") -- cgit v1.2.3 From ff5d5458df2e69c7fca43d78f02ad1c5837a4a22 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Sat, 2 May 2026 15:17:01 +0200 Subject: debug: fix vector pretty printer --- scripts/gdb/kstd/vector.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/gdb/kstd/vector.py b/scripts/gdb/kstd/vector.py index b42aeae..597ffdc 100644 --- a/scripts/gdb/kstd/vector.py +++ b/scripts/gdb/kstd/vector.py @@ -8,9 +8,9 @@ class KstdVectorPrinter: 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<{self.type}> of length {size}, capacity {capacity}" + 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"]) -- cgit v1.2.3 From 44961491f7c3097d1182d68f9c34929275d8655c Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Sat, 2 May 2026 15:17:21 +0200 Subject: debug: optimize string pretty printer --- scripts/gdb/kstd/string.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/gdb/kstd/string.py b/scripts/gdb/kstd/string.py index 6fa9996..8230b21 100644 --- a/scripts/gdb/kstd/string.py +++ b/scripts/gdb/kstd/string.py @@ -17,8 +17,9 @@ class KstdStringPrinter: string_length = storage_size - 1 try: - string_data = data_pointer.string(encoding="utf-8", length=string_length) - return f"{string_data}" + 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 "" -- cgit v1.2.3 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 --- 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 ++++++++++++++++++++++++++++ 9 files changed, 37 insertions(+), 198 deletions(-) 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 (limited to 'scripts') 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 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 --- scripts/gdb/pretty_printers.py | 6 +++++- scripts/gdb/teachos/__init__.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 scripts/gdb/teachos/__init__.py (limited to 'scripts') 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 From d8670d8eeb55bc0ea347cfe4a9a27640fe4e4e7e Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 4 May 2026 19:40:01 +0200 Subject: debug: add multiboot2 information dump tool This patch introduces a new GDB tool `dump_mb2i` that dump the multiboot2 information provided by the bootloader. This tool can be invoked in the GDB console. For example in vscode: -exec dump_mb2i ((kapi::boot::information)bootstrap_information).mbi The tool expects the address of the loader provided MB2 information as its only argument. --- scripts/gdb/load.py | 47 +++++++++++++ scripts/gdb/pretty_printers.py | 41 ----------- scripts/gdb/teachos/dump_mb2i.py | 147 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+), 41 deletions(-) create mode 100644 scripts/gdb/load.py delete mode 100644 scripts/gdb/pretty_printers.py create mode 100644 scripts/gdb/teachos/dump_mb2i.py (limited to 'scripts') diff --git a/scripts/gdb/load.py b/scripts/gdb/load.py new file mode 100644 index 0000000..355f6b9 --- /dev/null +++ b/scripts/gdb/load.py @@ -0,0 +1,47 @@ +import sys +import os +import gdb +import importlib.util + +script_path = os.path.abspath(__file__) +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) + +from teachos.dump_mb2i import DumpMB2I + +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") + +DumpMB2I() + +gdb.write("Info: Loaded TeachOS tools.\n") \ No newline at end of file diff --git a/scripts/gdb/pretty_printers.py b/scripts/gdb/pretty_printers.py deleted file mode 100644 index c209328..0000000 --- a/scripts/gdb/pretty_printers.py +++ /dev/null @@ -1,41 +0,0 @@ -import sys -import os -import gdb -import importlib.util - -script_path = os.path.abspath(__file__) -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", - "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") diff --git a/scripts/gdb/teachos/dump_mb2i.py b/scripts/gdb/teachos/dump_mb2i.py new file mode 100644 index 0000000..ff15fde --- /dev/null +++ b/scripts/gdb/teachos/dump_mb2i.py @@ -0,0 +1,147 @@ +import gdb +import struct + + +TAG_NAMES = { + 0: "End of Tags", + 1: "Boot Command Line", + 2: "Boot Loader Name", + 3: "Boot Module", + 4: "Basic Memory Information", + 5: "BIOS Boot Device", + 6: "Memory Map", + 7: "VBE Info", + 8: "Framebuffer Info", + 9: "ELF Symbols", + 10: "APM Table", + 14: "ACPI old RSDP (1.0)", + 15: "ACPI new RSDP (2.0+)", + 21: "Image Load Base Physical Address", +} + +MEMORY_TYPES = { + 1: "Available", + 2: "Reserved", + 3: "ACPI Reclaim", + 4: "Non-volatile storage", + 5: "Bad Memory", +} + +INDENT = f"{' '*11}" + + +class DumpMB2I(gdb.Command): + """ + Dump the information provided by the Multiboot2 loader. + Usage: dump_mb2i + Example: dump_mb2i $rbx + dump_mb2i 0x8000 + """ + + def __init__(self): + super(DumpMB2I, self).__init__("dump_mb2i", gdb.COMMAND_USER) + + def invoke(self, arg, from_tty): + if not arg: + gdb.write( + "Error: please provide the address of the Multiboot2 information structure.\n" + ) + return + + try: + address = int(gdb.parse_and_eval(arg)) + except gdb.error as e: + gdb.write(f"Error: Invalid address expression: {e}\n") + return + + inferior = gdb.selected_inferior() + + try: + header_data = inferior.read_memory(address, 8).tobytes() + total_size, reserved = struct.unpack(" 1024 * 1024: + gdb.write("Warning: suspicious total size ({total_size} bytes). Aborting.") + return + + gdb.write(f"+{'-'*70}+\n") + gdb.write(f"| Multiboot2 Boot Information Payload{' ':>34}|\n") + gdb.write(f"+{'-'*70}+\n") + gdb.write(f"Base Address: {address:#018x}\nTotal Size: {total_size} Bytes\n\n") + + offset = 8 + + while offset < total_size: + tag_address = address + offset + + try: + tag_header = inferior.read_memory(tag_address, 8).tobytes() + tag_type, tag_size = struct.unpack("\n") -- cgit v1.2.3 From 1e9daa3ccda0a39a8b260649ddc3c75f95a88bdf Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 6 May 2026 05:20:48 +0000 Subject: dump_mb2i: add support for bios boot device tag --- scripts/gdb/teachos/dump_mb2i.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'scripts') diff --git a/scripts/gdb/teachos/dump_mb2i.py b/scripts/gdb/teachos/dump_mb2i.py index ff15fde..41a2932 100644 --- a/scripts/gdb/teachos/dump_mb2i.py +++ b/scripts/gdb/teachos/dump_mb2i.py @@ -123,6 +123,12 @@ class DumpMB2I(gdb.Command): ) if string: gdb.write(f'{INDENT}string: "{string}"\n') + elif tag_type == 5: + data = inferior.read_memory(tag_address + 8, tag_size - 8).tobytes() + device, partition, sub_partition = struct.unpack_from(" Date: Wed, 6 May 2026 06:34:29 +0000 Subject: debug: refactor dump_mb2i tool --- scripts/gdb/teachos/dump_mb2i.py | 199 ++++++++++++++++++++++++++------------- 1 file changed, 135 insertions(+), 64 deletions(-) (limited to 'scripts') diff --git a/scripts/gdb/teachos/dump_mb2i.py b/scripts/gdb/teachos/dump_mb2i.py index 41a2932..06f4531 100644 --- a/scripts/gdb/teachos/dump_mb2i.py +++ b/scripts/gdb/teachos/dump_mb2i.py @@ -1,30 +1,72 @@ import gdb import struct +from enum import IntEnum + + +class TagType(IntEnum): + END = 0 + CMDLINE = 1 + BOOT_LOADER_NAME = 2 + MODULE = 3 + BASIC_MEMINFO = 4 + BOOTDEV = 5 + MMAP = 6 + VBE = 7 + FRAMEBUFFER = 8 + ELF_SECTIONS = 9 + APM = 10 + EFI32_SYSTEM_TABLE_POINTER = 11 + EFI64_SYSTEM_TABLE_POINTER = 12 + SMBIOS_TABLES = 13 + ACPI_OLD = 14 + ACPI_NEW = 15 + NETWORKING = 16 + EFI_MEMORY_MAP = 17 + EFI_BOOT_SERVICES_NOT_TERMINATED = 18 + EFI32_IMAGE_HANDLE_POINTER = 19 + EFI64_IMAGE_HANDLE_POINTER = 20 + LOAD_BASE_ADDR = 21 + + +class MemoryType(IntEnum): + AVAILABLE = 1 + RESERVED = 2 + ACPI_RECLAIM = 3 + NVS = 4 + BAD = 5 TAG_NAMES = { - 0: "End of Tags", - 1: "Boot Command Line", - 2: "Boot Loader Name", - 3: "Boot Module", - 4: "Basic Memory Information", - 5: "BIOS Boot Device", - 6: "Memory Map", - 7: "VBE Info", - 8: "Framebuffer Info", - 9: "ELF Symbols", - 10: "APM Table", - 14: "ACPI old RSDP (1.0)", - 15: "ACPI new RSDP (2.0+)", - 21: "Image Load Base Physical Address", + TagType.END: "End of Tags", + TagType.CMDLINE: "Boot Command Line", + TagType.BOOT_LOADER_NAME: "Boot Loader Name", + TagType.MODULE: "Boot Module", + TagType.BASIC_MEMINFO: "Basic Memory Information", + TagType.BOOTDEV: "BIOS Boot Device", + TagType.MMAP: "Memory Map", + TagType.VBE: "VBE Info", + TagType.FRAMEBUFFER: "Framebuffer Info", + TagType.ELF_SECTIONS: "ELF Symbols", + TagType.APM: "APM Table", + TagType.EFI32_SYSTEM_TABLE_POINTER: "EFI 32-bit System Table Pointer", + TagType.EFI64_SYSTEM_TABLE_POINTER: "EFI 64-bit System Table Pointer", + TagType.SMBIOS_TABLES: "SMBIOS Tables", + TagType.ACPI_OLD: "ACPI old RSDP (1.0)", + TagType.ACPI_NEW: "ACPI new RSDP (2.0+)", + TagType.NETWORKING: "Networking Information", + TagType.EFI_MEMORY_MAP: "EFI Memory Map", + TagType.EFI_BOOT_SERVICES_NOT_TERMINATED: "EFI Boot Services Not Terminated", + TagType.EFI32_IMAGE_HANDLE_POINTER: "EFI 32-bit Image Handle Pointer", + TagType.EFI64_IMAGE_HANDLE_POINTER: "EFI 64-bit Image Handle Pointer", + TagType.LOAD_BASE_ADDR: "Image Load Base Physical Address", } MEMORY_TYPES = { - 1: "Available", - 2: "Reserved", - 3: "ACPI Reclaim", - 4: "Non-volatile storage", - 5: "Bad Memory", + MemoryType.AVAILABLE: "Available", + MemoryType.RESERVED: "Reserved", + MemoryType.ACPI_RECLAIM: "ACPI Reclaim", + MemoryType.NVS: "Non-volatile storage", + MemoryType.BAD: "Bad Memory", } INDENT = f"{' '*11}" @@ -64,7 +106,9 @@ class DumpMB2I(gdb.Command): return if total_size < 8 or total_size > 1024 * 1024: - gdb.write("Warning: suspicious total size ({total_size} bytes). Aborting.") + gdb.write( + f"Warning: suspicious total size ({total_size} bytes). Aborting.\n" + ) return gdb.write(f"+{'-'*70}+\n") @@ -86,11 +130,11 @@ class DumpMB2I(gdb.Command): ) break - self._print_tag(inferior, tag_address, tag_type, tag_size) - - if tag_type == 0 and tag_size == 0: + if tag_type == TagType.END and tag_size == 8: break + self._print_tag(inferior, tag_address, tag_type, tag_size) + offset += (tag_size + 7) & ~7 def _format_size(self, size): @@ -104,50 +148,77 @@ class DumpMB2I(gdb.Command): def _print_tag(self, inferior, tag_address, tag_type, tag_size): name = TAG_NAMES.get(tag_type, f"Unknown Tag") - gdb.write(f"[Tag {tag_type:#04x}] {name} (size: {self._format_size(tag_size)})\n") + gdb.write( + f"[Tag {tag_type:#04x}] {name} (size: {self._format_size(tag_size)})\n" + ) - if tag_size <= 8 and tag_type != 0: + if tag_size <= 8 and tag_type != TagType.END: return try: - if tag_type in (1, 2): - data = inferior.read_memory(tag_address + 8, tag_size - 8).tobytes() - text = data.split(b"\x00")[0].decode("ascii", "replace") - gdb.write(f'{INDENT}"{text}"\n') - elif tag_type == 3: - data = inferior.read_memory(tag_address + 8, tag_size - 8).tobytes() - start, end = struct.unpack_from("\n") + gdb.write( + f"{INDENT}\n" + ) + + def _write_string_tag(self, data): + text = data.split(b"\x00")[0].decode("ascii", "replace") + gdb.write(f'{INDENT}"{text}"\n') + + def _write_module_tag(self, data): + start, end = struct.unpack_from(" Date: Wed, 6 May 2026 06:49:02 +0000 Subject: dump_mb2i: add support for framebuffer tag --- scripts/gdb/teachos/dump_mb2i.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/gdb/teachos/dump_mb2i.py b/scripts/gdb/teachos/dump_mb2i.py index 06f4531..ca0c378 100644 --- a/scripts/gdb/teachos/dump_mb2i.py +++ b/scripts/gdb/teachos/dump_mb2i.py @@ -36,6 +36,12 @@ class MemoryType(IntEnum): BAD = 5 +class FramebufferType(IntEnum): + INDEXED = 0 + RGB = 1 + TEXT = 2 + + TAG_NAMES = { TagType.END: "End of Tags", TagType.CMDLINE: "Boot Command Line", @@ -69,6 +75,13 @@ MEMORY_TYPES = { MemoryType.BAD: "Bad Memory", } +FRAMEBUFFER_TYPES = { + FramebufferType.INDEXED: "Indexed Color", + FramebufferType.RGB: "RGB", + FramebufferType.TEXT: "Text Mode", +} + + INDENT = f"{' '*11}" @@ -221,4 +234,11 @@ class DumpMB2I(gdb.Command): gdb.write(f"{INDENT}address: {base:#010x}\n") def _write_framebuffer_info_tag(self, data): - pass + address, pitch, width, height, bpp, type = struct.unpack_from(" Date: Wed, 6 May 2026 06:56:47 +0000 Subject: dump_mb2i: dump unsupported tags as hex --- scripts/gdb/teachos/dump_mb2i.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/gdb/teachos/dump_mb2i.py b/scripts/gdb/teachos/dump_mb2i.py index ca0c378..3a9ee4a 100644 --- a/scripts/gdb/teachos/dump_mb2i.py +++ b/scripts/gdb/teachos/dump_mb2i.py @@ -161,9 +161,9 @@ class DumpMB2I(gdb.Command): def _print_tag(self, inferior, tag_address, tag_type, tag_size): name = TAG_NAMES.get(tag_type, f"Unknown Tag") - gdb.write( - f"[Tag {tag_type:#04x}] {name} (size: {self._format_size(tag_size)})\n" - ) + size = self._format_size(tag_size) + payload = self._format_size(tag_size - 8) + gdb.write(f"[Tag {tag_type:#04x}] {name} (size: {size} | payload: {payload})\n") if tag_size <= 8 and tag_type != TagType.END: return @@ -182,9 +182,8 @@ class DumpMB2I(gdb.Command): TagType.FRAMEBUFFER: self._write_framebuffer_info_tag, } - handler = handlers.get(tag_type) - if handler: - handler(data) + handler = handlers.get(tag_type, self._write_unknown_tag) + handler(data) except Exception as e: gdb.write( @@ -242,3 +241,9 @@ class DumpMB2I(gdb.Command): gdb.write(f"{INDENT}width: {width} chars | height: {height} chars\n") else: gdb.write(f"{INDENT}width: {width} px | height: {height} px\n") + + def _write_unknown_tag(self, data): + for i in range(0, len(data), 16): + chunk = data[i : i + 16] + hex_chunk = " ".join([f"{b:02x}" for b in chunk]) + gdb.write(f"{INDENT}{i:#010x}: {hex_chunk}\n") -- cgit v1.2.3 From 0ea43527332b7e5f1cfec6007506aa54e8f628cb Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 7 May 2026 09:12:05 +0000 Subject: debug: enable libstdc++ helpers --- scripts/gdb/load.py | 47 ----------------------------------------------- scripts/gdb/teachos.py | 47 +++++++++++++++++++++++++++++++++++++++++++++++ scripts/gdb/toolchain.py | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 47 deletions(-) delete mode 100644 scripts/gdb/load.py create mode 100644 scripts/gdb/teachos.py create mode 100644 scripts/gdb/toolchain.py (limited to 'scripts') diff --git a/scripts/gdb/load.py b/scripts/gdb/load.py deleted file mode 100644 index 355f6b9..0000000 --- a/scripts/gdb/load.py +++ /dev/null @@ -1,47 +0,0 @@ -import sys -import os -import gdb -import importlib.util - -script_path = os.path.abspath(__file__) -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) - -from teachos.dump_mb2i import DumpMB2I - -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") - -DumpMB2I() - -gdb.write("Info: Loaded TeachOS tools.\n") \ No newline at end of file diff --git a/scripts/gdb/teachos.py b/scripts/gdb/teachos.py new file mode 100644 index 0000000..355f6b9 --- /dev/null +++ b/scripts/gdb/teachos.py @@ -0,0 +1,47 @@ +import sys +import os +import gdb +import importlib.util + +script_path = os.path.abspath(__file__) +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) + +from teachos.dump_mb2i import DumpMB2I + +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") + +DumpMB2I() + +gdb.write("Info: Loaded TeachOS tools.\n") \ No newline at end of file diff --git a/scripts/gdb/toolchain.py b/scripts/gdb/toolchain.py new file mode 100644 index 0000000..bbb7810 --- /dev/null +++ b/scripts/gdb/toolchain.py @@ -0,0 +1,35 @@ +import os +import subprocess +import sys + + +def setup_toolchain_debugging(): + try: + gcc_path = ( + subprocess.check_output(["which", "x86_64-pc-elf-g++"]) + .decode("utf-8") + .strip() + ) + python_dir = None + + share_path = os.path.join(os.path.dirname(os.path.dirname(gcc_path)), "share") + for root, dirs, _ in os.walk(share_path): + if "libstdcxx" in dirs: + python_dir = root + break + + if python_dir: + sys.path.insert(0, python_dir) + + from libstdcxx.v6.printers import register_libstdcxx_printers + from libstdcxx.v6.xmethods import register_libstdcxx_xmethods + + register_libstdcxx_printers(None) + register_libstdcxx_xmethods(None) + + print(f"Loaded Printers & Xmethods from: {python_dir}") + except Exception as e: + print(f"Debug setup failed: {e}") + + +setup_toolchain_debugging() -- cgit v1.2.3 From 6ac1537d07dffa3482bbccf710a77a7316191c2e Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 7 May 2026 12:09:27 +0200 Subject: debug: use gdb.ValuePrinter base class --- scripts/gdb/teachos/__init__.py | 30 ------------------------------ 1 file changed, 30 deletions(-) (limited to 'scripts') diff --git a/scripts/gdb/teachos/__init__.py b/scripts/gdb/teachos/__init__.py index d90d6ad..e69de29 100644 --- a/scripts/gdb/teachos/__init__.py +++ b/scripts/gdb/teachos/__init__.py @@ -1,30 +0,0 @@ -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 From 07fb219869099c719b0fbfeae81b95512487639e Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 8 May 2026 17:12:24 +0200 Subject: debug: add page and frame formatters --- scripts/gdb/teachos/__init__.py | 8 ++++++++ scripts/gdb/teachos/dump_mb2i.py | 22 +++++++--------------- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'scripts') diff --git a/scripts/gdb/teachos/__init__.py b/scripts/gdb/teachos/__init__.py index e69de29..a5eca92 100644 --- a/scripts/gdb/teachos/__init__.py +++ b/scripts/gdb/teachos/__init__.py @@ -0,0 +1,8 @@ +def format_size(size): + for unit in ["Bytes", "KiB", "MiB", "GiB", "TiB", "PiB"]: + if size < 1024.0: + if unit == "Bytes": + return f"{int(size)} {unit}" + return f"{size:.2f} {unit}" + size /= 1024.0 + return f"{size:.2f} PiB" diff --git a/scripts/gdb/teachos/dump_mb2i.py b/scripts/gdb/teachos/dump_mb2i.py index 3a9ee4a..0657ebd 100644 --- a/scripts/gdb/teachos/dump_mb2i.py +++ b/scripts/gdb/teachos/dump_mb2i.py @@ -1,6 +1,7 @@ import gdb import struct from enum import IntEnum +from teachos import format_size class TagType(IntEnum): @@ -150,19 +151,10 @@ class DumpMB2I(gdb.Command): offset += (tag_size + 7) & ~7 - def _format_size(self, size): - for unit in ["Bytes", "KiB", "MiB", "GiB", "TiB", "PiB"]: - if size < 1024.0: - if unit == "Bytes": - return f"{int(size)} {unit}" - return f"{size:.2f} {unit}" - size /= 1024.0 - return f"{size:.2f} PiB" - def _print_tag(self, inferior, tag_address, tag_type, tag_size): name = TAG_NAMES.get(tag_type, f"Unknown Tag") - size = self._format_size(tag_size) - payload = self._format_size(tag_size - 8) + size = format_size(tag_size) + payload = format_size(tag_size - 8) gdb.write(f"[Tag {tag_type:#04x}] {name} (size: {size} | payload: {payload})\n") if tag_size <= 8 and tag_type != TagType.END: @@ -198,7 +190,7 @@ class DumpMB2I(gdb.Command): start, end = struct.unpack_from(" Date: Mon, 18 May 2026 13:50:49 +0200 Subject: ci: enable code quality reporting --- scripts/ci/parse_clang_tidy.py | 47 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 scripts/ci/parse_clang_tidy.py (limited to 'scripts') diff --git a/scripts/ci/parse_clang_tidy.py b/scripts/ci/parse_clang_tidy.py new file mode 100644 index 0000000..48596de --- /dev/null +++ b/scripts/ci/parse_clang_tidy.py @@ -0,0 +1,47 @@ +import hashlib +import json +import re +import sys + + +def parse_clang_tidy(log_file_path: str) -> list[dict]: + issues = [] + pattern = re.compile( + r"^(.*?):(\d+):(\d+):\s+(warning|error|note):\s+(.*?)\s+\[(.*?)\]$" + ) + + with open(log_file_path, "r") as f: + for line in f: + match = pattern.match(line) + if not match: + continue + + path, line, column, severity, message, name = match.groups() + severity = "minor" if severity == "warning" else "major" + + fingerprint_data = f"{path}:{line}:{name}" + fingerprint = hashlib.sha256(fingerprint_data.encode()).hexdigest() + + issues.append( + { + "description": f"{message} ({name})", + "fingerprint": fingerprint, + "severity": severity, + "location": { + "path": path, + "lines": { + "begin": int(line), + }, + }, + } + ) + + return issues + + +if __name__ == "__main__": + if len(sys.argv) < 2: + sys.exit("Usage: python3 parse_clang_tidy.py ") + + issues = parse_clang_tidy(sys.argv[1]) + print(json.dumps(issues, indent=2)) -- cgit v1.2.3 From de8efd2af75a8d8d5dd4b0b5c125d006bf7f1ba9 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 18 May 2026 14:26:52 +0200 Subject: ci: fix code quality file paths --- scripts/ci/parse_clang_tidy.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/ci/parse_clang_tidy.py b/scripts/ci/parse_clang_tidy.py index 48596de..6167c99 100644 --- a/scripts/ci/parse_clang_tidy.py +++ b/scripts/ci/parse_clang_tidy.py @@ -1,5 +1,6 @@ import hashlib import json +import os import re import sys @@ -9,6 +10,7 @@ def parse_clang_tidy(log_file_path: str) -> list[dict]: pattern = re.compile( r"^(.*?):(\d+):(\d+):\s+(warning|error|note):\s+(.*?)\s+\[(.*?)\]$" ) + repo_root = os.environ.get("CI_PROJECT_DIR", os.getcwd()) with open(log_file_path, "r") as f: for line in f: @@ -19,7 +21,12 @@ def parse_clang_tidy(log_file_path: str) -> list[dict]: path, line, column, severity, message, name = match.groups() severity = "minor" if severity == "warning" else "major" - fingerprint_data = f"{path}:{line}:{name}" + try: + path = os.path.relpath(path, repo_root) + except ValueError: + pass + + fingerprint_data = f"{path}:{line}:{name}:{message}" fingerprint = hashlib.sha256(fingerprint_data.encode()).hexdigest() issues.append( -- cgit v1.2.3 From a7ba17a11c17c9975e7dc2233264913aa2e79538 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 18 May 2026 14:31:17 +0200 Subject: ci: improve code quality fingerprints --- scripts/ci/parse_clang_tidy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/ci/parse_clang_tidy.py b/scripts/ci/parse_clang_tidy.py index 6167c99..ec51d77 100644 --- a/scripts/ci/parse_clang_tidy.py +++ b/scripts/ci/parse_clang_tidy.py @@ -26,7 +26,7 @@ def parse_clang_tidy(log_file_path: str) -> list[dict]: except ValueError: pass - fingerprint_data = f"{path}:{line}:{name}:{message}" + fingerprint_data = f"{path}:{line}:{column}:{message}:{name}" fingerprint = hashlib.sha256(fingerprint_data.encode()).hexdigest() issues.append( -- cgit v1.2.3