Debugger: Fix enum dumper

Make the hex display work with LLDB, fix GDB and LLDB test.

Change-Id: I529b5cdc908dbcba7270bc4574fa59a012fcacad
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
hjk
2018-03-21 17:10:24 +01:00
parent f88dc5fd58
commit a8a23110bf
6 changed files with 30 additions and 42 deletions

View File

@@ -181,8 +181,8 @@ class Dumper(DumperBase):
tdata.lalignment = lambda : \ tdata.lalignment = lambda : \
self.nativeStructAlignment(nativeType) self.nativeStructAlignment(nativeType)
if code == TypeCodeEnum: if code == TypeCodeEnum:
tdata.enumDisplay = lambda intval, addr : \ tdata.enumDisplay = lambda intval, addr, form : \
self.nativeTypeEnumDisplay(nativeType, addr) self.nativeTypeEnumDisplay(nativeType, addr, form)
tdata.templateArguments = self.listTemplateParameters(nativeType.name()) tdata.templateArguments = self.listTemplateParameters(nativeType.name())
self.registerType(typeId, tdata) # Fix up fields and template args self.registerType(typeId, tdata) # Fix up fields and template args
return self.Type(self, typeId) return self.Type(self, typeId)
@@ -208,7 +208,7 @@ class Dumper(DumperBase):
align = handleItem(f.type(), align) align = handleItem(f.type(), align)
return align return align
def nativeTypeEnumDisplay(self, nativeType, addr): def nativeTypeEnumDisplay(self, nativeType, addr, form):
value = cdbext.createValue(addr, nativeType) value = cdbext.createValue(addr, nativeType)
if value is None: if value is None:
return '' return ''

View File

@@ -2742,13 +2742,8 @@ class DumperBase:
if typeobj.code == TypeCodeBitfield: if typeobj.code == TypeCodeBitfield:
#warn('BITFIELD VALUE: %s %d %s' % (value.name, value.lvalue, typeName)) #warn('BITFIELD VALUE: %s %d %s' % (value.name, value.lvalue, typeName))
self.putNumChild(0) self.putNumChild(0)
if typeobj.ltarget and typeobj.ltarget.code == TypeCodeEnum: dd = typeobj.ltarget.typeData().enumDisplay
if hasattr(typeobj.ltarget.typeData(), 'enumHexDisplay'): self.putValue(str(value.lvalue) if dd is None else dd(value.lvalue, value.laddress, '%d'))
self.putValue(typeobj.ltarget.typeData().enumHexDisplay(value.lvalue, value.laddress))
else:
self.putValue(typeobj.ltarget.typeData().enumDisplay(value.lvalue, value.laddress))
else:
self.putValue(value.lvalue)
self.putType(typeName) self.putType(typeName)
return return
@@ -2911,12 +2906,14 @@ class DumperBase:
% (self.name, self.type.name, self.lbitsize, self.lbitpos, % (self.name, self.type.name, self.lbitsize, self.lbitpos,
self.dumper.hexencode(self.ldata), addr) self.dumper.hexencode(self.ldata), addr)
def display(self, useHex = 1): def displayEnum(self, form='%d'):
if self.type.code == TypeCodeEnum:
intval = self.integer() intval = self.integer()
if useHex and hasattr(self.type.typeData(), 'enumHexDisplay'): dd = self.type.typeData().enumDisplay
return self.type.typeData().enumHexDisplay(intval, self.laddress) if dd is None:
return self.type.typeData().enumDisplay(intval, self.laddress) return str(intval)
return dd(intval, self.laddress, form)
def display(self):
simple = self.value() simple = self.value()
if simple is not None: if simple is not None:
return str(simple) return str(simple)
@@ -3375,7 +3372,7 @@ class DumperBase:
self.code = None self.code = None
self.name = None self.name = None
self.typeId = None self.typeId = None
self.enumDisplay = str self.enumDisplay = None
self.moduleName = None self.moduleName = None
def copy(self): def copy(self):

View File

@@ -354,10 +354,8 @@ class Dumper(DumperBase):
gdb.TYPE_CODE_STRING : TypeCodeFortranString, gdb.TYPE_CODE_STRING : TypeCodeFortranString,
}[code] }[code]
if tdata.code == TypeCodeEnum: if tdata.code == TypeCodeEnum:
tdata.enumDisplay = lambda intval, addr : \ tdata.enumDisplay = lambda intval, addr, form : \
self.nativeTypeEnumDisplay(nativeType, intval, 0) self.nativeTypeEnumDisplay(nativeType, intval, form)
tdata.enumHexDisplay = lambda intval, addr : \
self.nativeTypeEnumDisplay(nativeType, intval, 1)
if tdata.code == TypeCodeStruct: if tdata.code == TypeCodeStruct:
tdata.lalignment = lambda : \ tdata.lalignment = lambda : \
self.nativeStructAlignment(nativeType) self.nativeStructAlignment(nativeType)
@@ -388,17 +386,13 @@ class Dumper(DumperBase):
targs2 = self.listTemplateParametersManually(str(nativeType)) targs2 = self.listTemplateParametersManually(str(nativeType))
return targs if len(targs) >= len(targs2) else targs2 return targs if len(targs) >= len(targs2) else targs2
def nativeTypeEnumDisplay(self, nativeType, intval, useHex): def nativeTypeEnumDisplay(self, nativeType, intval, form):
if useHex:
format = lambda text, intval: '%s (0x%04x)' % (text, intval)
else:
format = lambda text, intval: '%s (%d)' % (text, intval)
try: try:
enumerators = [] enumerators = []
for field in nativeType.fields(): for field in nativeType.fields():
# If we found an exact match, return it immediately # If we found an exact match, return it immediately
if field.enumval == intval: if field.enumval == intval:
return format(field.name, intval) return field.name + ' (' + (form % intval) + ')'
enumerators.append((field.name, field.enumval)) enumerators.append((field.name, field.enumval))
# No match was found, try to return as flags # No match was found, try to return as flags
@@ -414,12 +408,10 @@ class Dumper(DumperBase):
if not found or v != 0: if not found or v != 0:
# Leftover value # Leftover value
flags.append('unknown:%d' % v) flags.append('unknown:%d' % v)
return format(" | ".join(flags), intval) return " | ".join(flags) + ' (' + (form % intval) + ')'
except: except:
pass pass
if useHex: return form % intval
return '0x%04x' % intval;
return '%d' % intval
def nativeTypeId(self, nativeType): def nativeTypeId(self, nativeType):
if nativeType and (nativeType.code == gdb.TYPE_CODE_TYPEDEF): if nativeType and (nativeType.code == gdb.TYPE_CODE_TYPEDEF):

View File

@@ -445,8 +445,8 @@ class Dumper(DumperBase):
warn('UNKNOWN TYPE KEY: %s: %s' % (typeName, code)) warn('UNKNOWN TYPE KEY: %s: %s' % (typeName, code))
elif code == lldb.eTypeClassEnumeration: elif code == lldb.eTypeClassEnumeration:
tdata.code = TypeCodeEnum tdata.code = TypeCodeEnum
tdata.enumDisplay = lambda intval, addr : \ tdata.enumDisplay = lambda intval, addr, form : \
self.nativeTypeEnumDisplay(nativeType, intval) self.nativeTypeEnumDisplay(nativeType, intval, form)
elif code in (lldb.eTypeClassComplexInteger, lldb.eTypeClassComplexFloat): elif code in (lldb.eTypeClassComplexInteger, lldb.eTypeClassComplexFloat):
tdata.code = TypeCodeComplex tdata.code = TypeCodeComplex
elif code in (lldb.eTypeClassClass, lldb.eTypeClassStruct, lldb.eTypeClassUnion): elif code in (lldb.eTypeClassClass, lldb.eTypeClassStruct, lldb.eTypeClassUnion):
@@ -534,7 +534,7 @@ class Dumper(DumperBase):
#warn('NATIVE TYPE ID FOR %s IS %s' % (name, typeId)) #warn('NATIVE TYPE ID FOR %s IS %s' % (name, typeId))
return typeId return typeId
def nativeTypeEnumDisplay(self, nativeType, intval): def nativeTypeEnumDisplay(self, nativeType, intval, form):
if hasattr(nativeType, 'get_enum_members_array'): if hasattr(nativeType, 'get_enum_members_array'):
for enumMember in nativeType.get_enum_members_array(): for enumMember in nativeType.get_enum_members_array():
# Even when asking for signed we get unsigned with LLDB 3.8. # Even when asking for signed we get unsigned with LLDB 3.8.
@@ -543,8 +543,8 @@ class Dumper(DumperBase):
if diff & mask == 0: if diff & mask == 0:
path = nativeType.GetName().split('::') path = nativeType.GetName().split('::')
path[-1] = enumMember.GetName() path[-1] = enumMember.GetName()
return '%s (%d)' % ('::'.join(path), intval) return '::'.join(path) + ' (' + (form % intval) + ')'
return '%d' % intval return form % intval
def nativeDynamicTypeName(self, address, baseType): def nativeDynamicTypeName(self, address, baseType):
return None # FIXME: Seems sufficient, no idea why. return None # FIXME: Seems sufficient, no idea why.

View File

@@ -644,10 +644,8 @@ def qdump__QFiniteStack(d, value):
def qdump__QFlags(d, value): def qdump__QFlags(d, value):
i = value.split('{int}')[0] i = value.split('{int}')[0]
enumType = value.type[0] enumType = value.type[0]
if d.isGdb: v = i.cast(enumType.name)
d.putValue(i.cast('enum ' + enumType.name).display(useHex = 1)) d.putValue(v.displayEnum('0x%04x'))
else:
d.putValue(i.cast(enumType.name).display())
d.putNumChild(0) d.putNumChild(0)

View File

@@ -1944,8 +1944,9 @@ void tst_Dumpers::dumper_data()
"FooFlags f1(a);\n" "FooFlags f1(a);\n"
"FooFlags f2(a | b);\n") "FooFlags f2(a | b);\n")
+ CoreProfile() + CoreProfile()
+ Check("f1", "a (1)", TypeDef("QFlags<enum Foo>", "FooFlags")) + Check("f1", "a (1)", TypeDef("QFlags<enum Foo>", "FooFlags")) % CdbEngine
+ Check("f2", "(a | b) (3)", "FooFlags") % GdbEngine; + Check("f1", "a (0x0001)", "FooFlags") % NoCdbEngine
+ Check("f2", "a | b (0x0003)", "FooFlags") % GdbEngine;
QTest::newRow("QDateTime") QTest::newRow("QDateTime")
<< Data("#include <QDateTime>\n", << Data("#include <QDateTime>\n",