Try to improve linux pretty printers as much as possible

* These are not as good as natvis but better than nothing... maybe
This commit is contained in:
baldurk
2025-07-10 17:43:06 +01:00
parent b5d3cf07a3
commit 095556663d
+184 -23
View File
@@ -1,42 +1,56 @@
import re
class _childplusextras_iterator():
def __init__(self, extras, elems, usedCount):
self.extras = extras
self.elems = elems
self.usedCount = usedCount
self.i = 0
def __iter__(self):
return self
def __next__(self):
if len(self.extras) > 0:
return self.extras.pop(0)
if self.i >= self.usedCount:
raise StopIteration
ret = ('[{}]'.format(self.i), self.elems[self.i])
self.i = self.i + 1
return ret
class rdcstrPrinter(object):
def __init__(self, val):
self.val = val
def to_string(self):
if self.val['d']['fixed']['flags'] & 0xC000000000000000:
if self.val['d']['fixed']['flags'] & int(self.val['FIXED_STATE']):
return self.val['d']['fixed']['str']
if self.val['d']['fixed']['flags'] & int(self.val['ALLOC_STATE']):
return self.val['d']['alloc']['str']
return self.val['d']['arr']['str'].cast(gdb.lookup_type("char").pointer())
def display_hint(self):
return 'string'
class rdcarrayPrinter(object):
class _iterator():
def __init__(self, value_type, elems, usedCount):
self.value_type = value_type
self.elems = elems
self.usedCount = usedCount
self.i = 0
def __iter__(self):
return self
def __next__(self):
if self.i >= self.usedCount:
raise StopIteration
ret = ('[{}]'.format(self.i), self.elems[self.i])
self.i = self.i + 1
return ret
class rdcinflexiblestrPrinter(object):
def __init__(self, val):
self.val = val
self.value_type = self.val.type.template_argument(0)
def to_string(self):
return self.val['pointer'].cast(gdb.lookup_type("char").pointer())
def display_hint(self):
return 'string'
class rdcarrayPrinter(object):
def __init__(self, val):
self.val = val
def children(self):
return self._iterator(self.value_type, self.val['elems'], self.val['usedCount'])
return _childplusextras_iterator([], self.val['elems'], self.val['usedCount'])
def to_string(self):
return None
@@ -44,6 +58,142 @@ class rdcarrayPrinter(object):
def display_hint(self):
return 'array'
class rdcpairPrinter(object):
def __init__(self, val):
self.val = val
def children(self):
return [('first', self.val['first']), ('second', self.val['second'])]
def to_string(self):
return ('{{ {}, {} }}'.format(self.val['first'], self.val['second']))
class rdcbytetrieNodePrinter(object):
def __init__(self, val):
self.val = val
self.nodeSize = self.val['v']['_trie'] & int(0xC000)
self.trietype = self.val.type.name.replace('::NodeOrLeaf', '')
def children(self):
ret = []
prefixLen = self.val['v']['_trie'] & int(0x1FFF)
prefixName = '{} byte prefix'.format(prefixLen)
thisPtr = int(self.val.address)
prefixValue = thisPtr + self.val.type.sizeof
prefixValue = gdb.Value(prefixValue).cast(gdb.lookup_type("byte").pointer())
ret.append((prefixName, prefixValue))
if self.val['v']['_trie'] & int(0x2000):
ret.append(('value', self.val['v']))
if self.nodeSize == 0xC000:
ret.append(('children', gdb.Value(thisPtr).cast(gdb.lookup_type(self.trietype + "::FatNode").pointer()).dereference()['children']))
elif self.nodeSize == 0x8000:
ret.append(('children', gdb.Value(thisPtr).cast(gdb.lookup_type(self.trietype + "::SmallNode<(unsigned char)'\\b'>").pointer()).dereference()['children']))
ret.append(('childBytes', gdb.Value(thisPtr).cast(gdb.lookup_type(self.trietype + "::SmallNode<(unsigned char)'\\b'>").pointer()).dereference()['childBytes']))
elif self.nodeSize == 0x4000:
ret.append(('children', gdb.Value(thisPtr).cast(gdb.lookup_type(self.trietype + "::SmallNode<(unsigned char)'\\x02'>").pointer()).dereference()['children']))
ret.append(('childBytes', gdb.Value(thisPtr).cast(gdb.lookup_type(self.trietype + "::SmallNode<(unsigned char)'\\x02'>").pointer()).dereference()['childBytes']))
return ret
def to_string(self):
if self.val['v']['_trie'] & int(0x2000):
if self.nodeSize == 0xC000:
return 'FatNode = {}'.format(self.val['v'])
elif self.nodeSize == 0x8000:
return 'Node8 = {}'.format(self.val['v'])
elif self.nodeSize == 0x4000:
return 'Node2 = {}'.format(self.val['v'])
else:
if self.nodeSize == 0xC000:
return 'FatNode without value'
elif self.nodeSize == 0x8000:
return 'Node8 without value'
elif self.nodeSize == 0x4000:
return 'Node2 without value'
return 'Leaf = {}'.format(self.val['v'])
class sdtypePrinter(object):
def __init__(self, val):
self.val = val
def children(self):
return [
('name', self.val['name']),
('basetype', self.val['basetype']),
('byteSize', self.val['byteSize']),
('flags', self.val['flags']),
]
def to_string(self):
return str(self.val['name'])
class sdobjectPrinter(object):
def __init__(self, val):
self.val = val
def children(self):
if (self.val['type']['basetype'] == int(gdb.lookup_type('SDBasic')['SDBasic::Array'].enumval) or \
self.val['type']['basetype'] == int(gdb.lookup_type('SDBasic')['SDBasic::Struct'].enumval)):
return _childplusextras_iterator([], self.val['data']['children']['elems'], self.val['data']['children']['usedCount'])
else:
return [
('type', self.val['type']),
('name', self.val['name']),
('data', self.val['data']),
]
def to_string(self):
if self.val['type']['flags'] & int(gdb.lookup_type('SDTypeFlags')['SDTypeFlags::HasCustomString'].enumval):
return '{} = {}'.format(self.val['name'], self.val['data']['str'])
if self.val['type']['basetype'] == int(gdb.lookup_type('SDBasic')['SDBasic::String'].enumval):
return '{} = {}'.format(self.val['name'], self.val['data']['str'])
if self.val['type']['basetype'] == int(gdb.lookup_type('SDBasic')['SDBasic::UnsignedInteger'].enumval):
return '{} = {}'.format(self.val['name'], self.val['data']['u'])
if self.val['type']['basetype'] == int(gdb.lookup_type('SDBasic')['SDBasic::SignedInteger'].enumval):
return '{} = {}'.format(self.val['name'], self.val['data']['i'])
if self.val['type']['basetype'] == int(gdb.lookup_type('SDBasic')['SDBasic::Float'].enumval):
return '{} = {}'.format(self.val['name'], self.val['data']['d'])
if self.val['type']['basetype'] == int(gdb.lookup_type('SDBasic')['SDBasic::Boolean'].enumval):
return '{} = {}'.format(self.val['name'], self.val['data']['b'])
if self.val['type']['basetype'] == int(gdb.lookup_type('SDBasic')['SDBasic::Character'].enumval):
return '{} = {}'.format(self.val['name'], self.val['data']['c'])
if self.val['type']['basetype'] == int(gdb.lookup_type('SDBasic')['SDBasic::Resource'].enumval):
return '{} = {}'.format(self.val['name'], self.val['data']['id'])
if self.val['type']['basetype'] == int(gdb.lookup_type('SDBasic')['SDBasic::Array'].enumval):
return '{} = {}[]'.format(self.val['name'], self.val['type']['name'])
return 'SDObject: {} {}'.format(self.val['type']['name'], self.val['name'])
class sdchunkPrinter(object):
def __init__(self, val):
self.val = val
def children(self):
return _childplusextras_iterator([('metadata', self.val['metadata'])], self.val['data']['children']['elems'], self.val['data']['children']['usedCount'])
def to_string(self):
return ('SDChunk: {} ({})'.format(self.val['name'], self.val['metadata']['chunkID']))
class sdchunkPtrPrinter(sdchunkPrinter):
def __init__(self, val):
self.val = val.dereference()
class sdobjectPtrPrinter(sdobjectPrinter):
def __init__(self, val):
self.val = val.dereference()
class rdcbytetrieNodePtrPrinter(rdcbytetrieNodePrinter):
def __init__(self, val):
self.val = val.dereference()
self.nodeSize = self.val['v']['_trie'] & int(0xC000)
self.trietype = self.val.type.name.replace('::NodeOrLeaf', '')
import gdb.printing
def register(objfile):
@@ -52,7 +202,18 @@ def register(objfile):
printer = gdb.printing.RegexpCollectionPrettyPrinter('renderdoc')
printer.add_printer('rdcstr', r'^rdcstr$', rdcstrPrinter)
printer.add_printer('rdcinflexiblestr', r'^rdcinflexiblestr$', rdcinflexiblestrPrinter)
printer.add_printer('rdcarray', r'^rdcarray<.*>$', rdcarrayPrinter)
printer.add_printer('rdcpair', r'^rdcpair<.*>$', rdcpairPrinter)
printer.add_printer('rdcbytetrie', r'^rdcbytetrie<.*>::NodeOrLeaf$', rdcbytetrieNodePrinter)
printer.add_printer('SDType', r'^SDType$', sdtypePrinter)
printer.add_printer('SDObject', r'^SDObject$', sdobjectPrinter)
printer.add_printer('SDChunk', r'^SDChunk$', sdchunkPrinter)
printer.add_printer('SDObjectPtr', r'^SDObject *\*&?$', sdobjectPtrPrinter)
printer.add_printer('SDChunkPtr', r'^SDChunk *\*&?$', sdchunkPtrPrinter)
printer.add_printer('rdcbytetriePtr', r'^rdcbytetrie<.*>::NodeOrLeaf *\*&?$', rdcbytetrieNodePtrPrinter)
if objfile == None:
objfile = gdb