GDB: format output for class entries and class constants (#15955)

For `zend_string` pointers in class entries, show the string contents (if not
`NULL`).

For class constants, the `ce` (class entry pointer) field is shown with the
name of the class, and the `doc_comment` field is shown with the string
contents if possible.
This commit is contained in:
DanielEScherzer 2024-10-09 04:10:48 -07:00 committed by GitHub
parent b675db4c56
commit e34eebb854
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 104 additions and 0 deletions

View file

@ -67,6 +67,12 @@ class ZendStringPrettyPrinter(gdb.printing.PrettyPrinter):
pp_set.add_printer('zend_string', '^_zend_string$', ZendStringPrettyPrinter)
def zendStringPointerPrinter(ptr):
"Given a pointer to a zend_string, show the contents (if non-NULL)"
if int(ptr) == 0:
return '0x0'
return ZendStringPrettyPrinter(ptr.dereference()).to_string()
class ZendTypePrettyPrinter(gdb.printing.PrettyPrinter):
"Print a zend_type"
@ -289,6 +295,52 @@ class ZvalPrettyPrinter(gdb.printing.PrettyPrinter):
pp_set.add_printer('zval', '^_zval_struct$', ZvalPrettyPrinter)
class ZendClassEntryPrettyPrinter(gdb.printing.PrettyPrinter):
"Print a zend_class_entry"
# String pointers, show the string contents if possible
STRING_FIELDS = [ 'name', 'doc_comment' ]
def __init__(self, val):
self.val = val
def to_string(self):
return zendStringPointerPrinter(self.val['name'])
def children(self):
for field in self.val.type.fields():
if field.name is not None:
if field.name in self.STRING_FIELDS:
yield (field.name, zendStringPointerPrinter(self.val[field.name]))
else:
yield (field.name, self.val[field.name])
else:
# Don't break on the union fields. Unfortunately, pretty
# printers done in python cannot match the default formatting of
# C anonymous fields, which omit the name entirely, see
# binutils-gdb/gdb/cp-valprint.c#248 (as of commit
# b6532accdd8e24329cc69bb58bc2883796008776)
yield ('<anonymous>', self.val[field])
pp_set.add_printer('zend_class_entry', '^_zend_class_entry$', ZendClassEntryPrettyPrinter)
class ZendClassConstantPrettyPrinter(gdb.printing.PrettyPrinter):
"Print a zend_class_constant"
def __init__(self, val):
self.val = val
def children(self):
for field in self.val.type.fields():
if field.name == 'doc_comment':
yield ('doc_comment', zendStringPointerPrinter(self.val['doc_comment']))
elif field.name == 'ce':
yield ('ce', zendStringPointerPrinter(self.val['ce']['name']))
else:
yield (field.name, self.val[field.name])
pp_set.add_printer('zend_class_constant', '^_zend_class_constant$', ZendClassConstantPrettyPrinter)
type_bit_to_name = None
type_name_to_bit = None