2025-08-08 22:29:54 +02:00
|
|
|
import sys
|
|
|
|
|
sys.path.insert(0, '/usr/share/gdb/python/')
|
|
|
|
|
import gdb.printing
|
|
|
|
|
|
2026-04-12 20:49:02 +02:00
|
|
|
|
|
|
|
|
def _base_cast(val):
|
|
|
|
|
for field in val.type.strip_typedefs().fields():
|
|
|
|
|
if getattr(field, 'is_base_class', False):
|
|
|
|
|
return val.cast(field.type)
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _member(val, name):
|
|
|
|
|
"""Find a member by name on a value, searching base classes if needed."""
|
|
|
|
|
current = val
|
|
|
|
|
while current is not None:
|
|
|
|
|
t = current.type.strip_typedefs()
|
|
|
|
|
for field in t.fields():
|
|
|
|
|
if field.name == name:
|
|
|
|
|
return current[name]
|
|
|
|
|
current = _base_cast(current)
|
|
|
|
|
raise gdb.error(f"Member '{name}' not found on {val.type}")
|
|
|
|
|
|
2025-08-08 22:29:54 +02:00
|
|
|
class ArrayPrinter:
|
|
|
|
|
def __init__(self, val):
|
|
|
|
|
self.val = val
|
2025-08-10 12:28:50 +02:00
|
|
|
|
2025-08-08 22:29:54 +02:00
|
|
|
def to_string(self):
|
|
|
|
|
return f"Array(size={int(self.val['arraySize'])})"
|
|
|
|
|
|
|
|
|
|
def children(self):
|
|
|
|
|
data = self.val['_data']
|
|
|
|
|
size = int(self.val['arraySize'])
|
|
|
|
|
allocated = int(self.val['allocated'])
|
2026-04-12 20:49:02 +02:00
|
|
|
yield f"[size]", size
|
|
|
|
|
yield f"[allocated]", allocated
|
2025-08-08 22:29:54 +02:00
|
|
|
for i in range(size):
|
|
|
|
|
elem_val = (data + i).dereference()
|
|
|
|
|
yield f"[{i}]", elem_val
|
|
|
|
|
|
|
|
|
|
def display_hint(self):
|
|
|
|
|
return "array"
|
|
|
|
|
|
2026-04-12 20:49:02 +02:00
|
|
|
|
|
|
|
|
class ListPrinter:
|
|
|
|
|
def __init__(self, val):
|
|
|
|
|
self.val = val
|
|
|
|
|
|
|
|
|
|
def to_string(self):
|
|
|
|
|
size = int(_member(self.val, '_size'))
|
|
|
|
|
return f"List(size={size})"
|
|
|
|
|
|
|
|
|
|
def children(self):
|
|
|
|
|
size = int(_member(self.val, '_size'))
|
|
|
|
|
root = _member(self.val, 'root')
|
|
|
|
|
tail = _member(self.val, 'tail')
|
|
|
|
|
yield "[size]", size
|
|
|
|
|
|
|
|
|
|
node = root
|
|
|
|
|
idx = 0
|
|
|
|
|
# Bound traversal by logical size to avoid walking corrupted links forever.
|
|
|
|
|
while idx < size and node != tail:
|
|
|
|
|
yield f"[{idx}]", node['data']
|
|
|
|
|
node = node['next']
|
|
|
|
|
idx += 1
|
|
|
|
|
|
|
|
|
|
def display_hint(self):
|
|
|
|
|
return "array"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MapPrinter:
|
|
|
|
|
def __init__(self, val):
|
|
|
|
|
self.val = val
|
|
|
|
|
|
|
|
|
|
def to_string(self):
|
|
|
|
|
size = int(_member(self.val, '_size'))
|
|
|
|
|
return f"Map(size={size})"
|
|
|
|
|
|
|
|
|
|
def children(self):
|
|
|
|
|
size = int(_member(self.val, '_size'))
|
|
|
|
|
root = _member(self.val, 'root')
|
|
|
|
|
|
|
|
|
|
stack = []
|
|
|
|
|
node = root
|
|
|
|
|
idx = 0
|
|
|
|
|
|
|
|
|
|
# In-order traversal of Tree nodes yields map entries sorted by key.
|
|
|
|
|
while (node or stack) and idx < size:
|
|
|
|
|
while node:
|
|
|
|
|
stack.append(node)
|
|
|
|
|
node = node['leftChild']
|
|
|
|
|
|
|
|
|
|
node = stack.pop()
|
|
|
|
|
pair = node['data']
|
|
|
|
|
yield f"[{idx}].key", pair['key']
|
|
|
|
|
yield f"[{idx}].value", pair['value']
|
|
|
|
|
idx += 1
|
|
|
|
|
node = node['rightChild']
|
|
|
|
|
|
|
|
|
|
def display_hint(self):
|
|
|
|
|
return "map"
|
|
|
|
|
|
|
|
|
|
|
2025-08-10 12:28:50 +02:00
|
|
|
class VectorPrinter:
|
|
|
|
|
def __init__(self, val):
|
|
|
|
|
self.val = val
|
|
|
|
|
t = val.type.strip_typedefs()
|
|
|
|
|
self.length = int(t.template_argument(0))
|
|
|
|
|
self.value_type = t.template_argument(1)
|
|
|
|
|
|
|
|
|
|
def to_string(self):
|
|
|
|
|
comps = [float(self.val['x']), float(self.val['y'])]
|
|
|
|
|
if self.length >= 3:
|
|
|
|
|
comps.append(float(self.val['z']))
|
|
|
|
|
if self.length == 4:
|
|
|
|
|
comps.append(float(self.val['w']))
|
|
|
|
|
return "(" + ", ".join(map(str, comps)) + ")"
|
|
|
|
|
|
|
|
|
|
def display_hint(self):
|
|
|
|
|
return "string"
|
|
|
|
|
|
|
|
|
|
def _children(self):
|
|
|
|
|
comps = {'x': self.val['x'], 'y': self.val['y']}
|
|
|
|
|
if self.length >= 3:
|
|
|
|
|
comps['z'] = self.val['z']
|
|
|
|
|
if self.length == 4:
|
|
|
|
|
comps['w'] = self.val['w']
|
|
|
|
|
for key, value in comps.items():
|
|
|
|
|
yield key, value
|
|
|
|
|
|
|
|
|
|
|
2025-08-08 22:29:54 +02:00
|
|
|
def build_pretty_printer():
|
|
|
|
|
pp = gdb.printing.RegexpCollectionPrettyPrinter("Seele")
|
|
|
|
|
pp.add_printer("Array", r'^Seele::Array<.*>$', ArrayPrinter)
|
2026-04-12 20:49:02 +02:00
|
|
|
pp.add_printer("List", r'^Seele::List<.*>$', ListPrinter)
|
|
|
|
|
pp.add_printer("Map", r'^Seele::Map<.*>$', MapPrinter)
|
2025-08-10 12:28:50 +02:00
|
|
|
pp.add_printer("Vector", r"^glm::(detail::)?t?vec(\d)?<[^<>]*>$", VectorPrinter)
|
2025-08-08 22:29:54 +02:00
|
|
|
return pp
|
|
|
|
|
|
2025-08-10 12:28:50 +02:00
|
|
|
|
2025-08-08 22:29:54 +02:00
|
|
|
gdb.printing.register_pretty_printer(gdb.current_objfile(), build_pretty_printer())
|