aboutsummaryrefslogtreecommitdiff
path: root/libs/kstd/gdb
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-08-30 17:30:35 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-08-30 17:30:35 +0200
commit58fe72ab83ab6490b9a09e71f5762f2a12bd2c5a (patch)
tree87527422732ec9dc022fcd4f0e21b4b36d3f4470 /libs/kstd/gdb
parent3e87bb1da9e4980286d0d44b29f22a5dc8bb33d5 (diff)
downloadkernel-58fe72ab83ab6490b9a09e71f5762f2a12bd2c5a.tar.xz
kernel-58fe72ab83ab6490b9a09e71f5762f2a12bd2c5a.zip
kstd/gdb: add error_code and result printers
Diffstat (limited to 'libs/kstd/gdb')
-rw-r--r--libs/kstd/gdb/__init__.py10
-rw-r--r--libs/kstd/gdb/error_code.py66
-rw-r--r--libs/kstd/gdb/result.py51
3 files changed, 124 insertions, 3 deletions
diff --git a/libs/kstd/gdb/__init__.py b/libs/kstd/gdb/__init__.py
index 0cdafffd..018b31f2 100644
--- a/libs/kstd/gdb/__init__.py
+++ b/libs/kstd/gdb/__init__.py
@@ -1,15 +1,17 @@
import gdb.printing
-from .units import KstdBytesPrinter
-from .vector import KstdVectorPrinter
-from .string import KstdStringPrinter
+from .error_code import KstdErrorCodePrinter
+from .result import KstdResultPrinter
from .smart_pointers import (
KstdUniquePtrPrinter,
KstdSharedPtrPrinter,
KstdObserverPtrPrinter,
KstdWeakPtrPrinter,
)
+from .string import KstdStringPrinter
+from .units import KstdBytesPrinter
+from .vector import KstdVectorPrinter
def build_pretty_printers():
@@ -22,6 +24,8 @@ def build_pretty_printers():
pp.add_printer("observer_ptr", "^kstd::observer_ptr<.*>$", KstdObserverPtrPrinter)
pp.add_printer("bytes", "^kstd::basic_unit<.*, kstd::bytes_tag, .*>$", KstdBytesPrinter)
pp.add_printer("offset", "^kstd::basic_unit<.*, kstd::byte_offset_tag, .*>$", KstdBytesPrinter)
+ pp.add_printer("error_code", "^kstd::error_code$", KstdErrorCodePrinter)
+ pp.add_printer("result", "^std::expected<.*, kstd::error_code>$", KstdResultPrinter)
return pp
diff --git a/libs/kstd/gdb/error_code.py b/libs/kstd/gdb/error_code.py
new file mode 100644
index 00000000..1569f59a
--- /dev/null
+++ b/libs/kstd/gdb/error_code.py
@@ -0,0 +1,66 @@
+import gdb
+
+
+class KstdErrorCodePrinter(gdb.ValuePrinter):
+ def __init__(self, val):
+ self.__val = val
+
+ def _error_value(self):
+ return int(self.__val["m_value"])
+
+ def _category_name(self):
+ try:
+ category_pointer = self.__val["m_category"]
+ if int(category_pointer) == 0:
+ return "<null category>"
+ category = category_pointer.dereference()
+ try:
+ dynamic = category.dynamic_type
+ name = str(dynamic)
+ except gdb.error:
+ name = str(category.type)
+ name = name.replace("(anonymous namespace)::", "")
+ if name.endswith("_t"):
+ name = name[:-2]
+ return name
+ except (gdb.error, AttributeError):
+ return "?"
+
+ def _message(self):
+ try:
+ category_pointer = self.__val["m_category"]
+ if int(category_pointer) == 0:
+ return None
+ value = self._error_value()
+ address = int(category_pointer)
+ result = gdb.parse_and_eval(
+ f"((kstd::error_category const *){address:#x})->message({value})"
+ )
+ try:
+ ptr = result["_M_str"]
+ length = int(result["_M_len"])
+ if int(ptr) != 0 and length > 0:
+ return ptr.string(length=length)
+ except (gdb.error, AttributeError, KeyError):
+ pass
+ return str(result)
+ except (gdb.error, RuntimeError):
+ return None
+
+ def to_string(self):
+ value = self._error_value()
+ category = self._category_name()
+ msg = self._message()
+ if msg is not None:
+ return f"{category}:{value} ({msg})"
+ return f"{category}:{value}"
+
+ def children(self):
+ yield ("value", self.__val["m_value"])
+ category_pointer = self.__val["m_category"]
+ if int(category_pointer) != 0:
+ yield ("category", category_pointer.dereference())
+
+ def display_hint(self):
+ return None
+
diff --git a/libs/kstd/gdb/result.py b/libs/kstd/gdb/result.py
new file mode 100644
index 00000000..8cef0fed
--- /dev/null
+++ b/libs/kstd/gdb/result.py
@@ -0,0 +1,51 @@
+import gdb
+
+from .error_code import KstdErrorCodePrinter
+
+
+class KstdResultPrinter(gdb.ValuePrinter):
+ def __init__(self, val):
+ self.__val = val
+ self.__has_value = bool(val["_M_has_value"])
+ try:
+ t = val.type.template_argument(0)
+ self.__is_void = t.code == gdb.TYPE_CODE_VOID
+ except (gdb.error, AttributeError):
+ self.__is_void = False
+
+ @property
+ def _error_code(self):
+ return self.__val["_M_unex"]
+
+ @property
+ def _value(self):
+ return self.__val["_M_val"]
+
+ def _format_value(self, gdb_value):
+ printer = gdb.default_visualizer(gdb_value)
+ if printer is not None:
+ return printer.to_string()
+ s = str(gdb_value)
+ if s.startswith("{"):
+ return str(gdb_value.type.strip_typedefs())
+ return s
+
+ def _format_error(self, error_code_val):
+ printer = KstdErrorCodePrinter(error_code_val)
+ return printer.to_string()
+
+ def to_string(self):
+ if not self.__has_value:
+ return f"failure: {self._format_error(self._error_code)}"
+ if self.__is_void:
+ return "success"
+ return f"success: {self._format_value(self._value)}"
+
+ def children(self):
+ if not self.__has_value:
+ yield ("error", self._error_code)
+ elif not self.__is_void:
+ yield ("value", self._value)
+
+ def display_hint(self):
+ return None