Debugger: Prepare delayed type creation for DumperBase.Values

Change-Id: I283bcdec178e0a860bef71753cd29cc283a58391
Reviewed-by: David Schulz <david.schulz@qt.io>
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
hjk
2021-01-19 16:02:48 +01:00
parent 6cbdae8070
commit c2e3e0419d
4 changed files with 43 additions and 34 deletions

View File

@@ -106,10 +106,10 @@ class Dumper(DumperBase):
self.check(isinstance(nativeValue, cdbext.Value)) self.check(isinstance(nativeValue, cdbext.Value))
val = self.Value(self) val = self.Value(self)
val.name = nativeValue.name() val.name = nativeValue.name()
val.type = self.fromNativeType(nativeValue.type()) val._type = self.fromNativeType(nativeValue.type())
# There is no cdb api for the size of bitfields. # There is no cdb api for the size of bitfields.
# Workaround this issue by parsing the native debugger text for integral types. # Workaround this issue by parsing the native debugger text for integral types.
if val.type.code == TypeCode.Integral: if val._type.code == TypeCode.Integral:
try: try:
integerString = nativeValue.nativeDebuggerValue() integerString = nativeValue.nativeDebuggerValue()
except UnicodeDecodeError: except UnicodeDecodeError:
@@ -128,16 +128,16 @@ class Dumper(DumperBase):
base = 16 base = 16
else: else:
base = 10 base = 10
signed = not val.type.name.startswith('unsigned') signed = not val._type.name.startswith('unsigned')
try: try:
val.ldata = int(integerString, base).to_bytes(val.type.size(), val.ldata = int(integerString, base).to_bytes(val._type.size(),
byteorder='little', signed=signed) byteorder='little', signed=signed)
except: except:
# read raw memory in case the integerString can not be interpreted # read raw memory in case the integerString can not be interpreted
pass pass
if val.type.code == TypeCode.Enum: if val._type.code == TypeCode.Enum:
val.ldisplay = self.enumValue(nativeValue) val.ldisplay = self.enumValue(nativeValue)
val.isBaseClass = val.name == val.type.name val.isBaseClass = val.name == val._type.name
val.nativeValue = nativeValue val.nativeValue = nativeValue
val.laddress = nativeValue.address() val.laddress = nativeValue.address()
return val return val
@@ -408,10 +408,10 @@ class Dumper(DumperBase):
nativeType = self.lookupNativeType(typeName, module) nativeType = self.lookupNativeType(typeName, module)
if nativeType is None: if nativeType is None:
return None return None
type = self.fromNativeType(nativeType) _type = self.fromNativeType(nativeType)
if type.name != typeName: if _type.name != typeName:
self.registerType(typeName, type.typeData()) self.registerType(typeName, _type.typeData())
return type return _type
return self.Type(self, typeName) return self.Type(self, typeName)
def lookupNativeType(self, name, module=0): def lookupNativeType(self, name, module=0):
@@ -509,7 +509,7 @@ class Dumper(DumperBase):
else: else:
val = self.Value(self) val = self.Value(self)
val.laddress = value.pointer() val.laddress = value.pointer()
val.type = value.type.dereference() val._type = value.type.dereference()
return val return val

View File

@@ -752,7 +752,7 @@ class DumperBase():
buf = bytearray(struct.pack('i', ival)) buf = bytearray(struct.pack('i', ival))
val = self.Value(self) val = self.Value(self)
val.ldata = bytes(buf) val.ldata = bytes(buf)
val.type = self.createType(typish) val._type = self.createType(typish)
with SubItem(self, name): with SubItem(self, name):
self.putItem(val) self.putItem(val)
@@ -2907,7 +2907,7 @@ class DumperBase():
def __init__(self, dumper): def __init__(self, dumper):
self.dumper = dumper self.dumper = dumper
self.name = None self.name = None
self.type = None self._type = None
self.ldata = None # Target address in case of references and pointers. self.ldata = None # Target address in case of references and pointers.
self.laddress = None # Own address. self.laddress = None # Own address.
self.lvalue = None self.lvalue = None
@@ -2924,7 +2924,7 @@ class DumperBase():
val = self.dumper.Value(self.dumper) val = self.dumper.Value(self.dumper)
val.dumper = self.dumper val.dumper = self.dumper
val.name = self.name val.name = self.name
val.type = self.type val._type = self._type
val.ldata = self.ldata val.ldata = self.ldata
val.laddress = self.laddress val.laddress = self.laddress
val.lIsInScope = self.lIsInScope val.lIsInScope = self.lIsInScope
@@ -2936,6 +2936,12 @@ class DumperBase():
val.nativeValue = self.nativeValue val.nativeValue = self.nativeValue
return val return val
@property
def type(self):
if self._type is None and self.nativeValue is not None:
self._type = self.dumper.nativeValueType(self.nativeValue)
return self._type
def check(self): def check(self):
if self.laddress is not None and not self.dumper.isInt(self.laddress): if self.laddress is not None and not self.dumper.isInt(self.laddress):
raise RuntimeError('INCONSISTENT ADDRESS: %s' % type(self.laddress)) raise RuntimeError('INCONSISTENT ADDRESS: %s' % type(self.laddress))
@@ -3150,7 +3156,7 @@ class DumperBase():
val = self.dumper.Value(self.dumper) val = self.dumper.Value(self.dumper)
val.name = field.name val.name = field.name
val.isBaseClass = field.isBase val.isBaseClass = field.isBase
val.type = field.fieldType() val._type = field.fieldType()
if field.isArtificial: if field.isArtificial:
if self.laddress is not None: if self.laddress is not None:
@@ -3244,7 +3250,7 @@ class DumperBase():
val = self.dumper.Value(self.dumper) val = self.dumper.Value(self.dumper)
val.laddress = None val.laddress = None
val.ldata = bytes(struct.pack(self.dumper.packCode + 'Q', address)) val.ldata = bytes(struct.pack(self.dumper.packCode + 'Q', address))
val.type = self.type val._type = self._type
return val return val
raise RuntimeError('BAD DATA TO ADD TO: %s %s' % (self.type, other)) raise RuntimeError('BAD DATA TO ADD TO: %s %s' % (self.type, other))
@@ -3267,17 +3273,17 @@ class DumperBase():
val.laddress = self.pointer() val.laddress = self.pointer()
if val.laddress is None and self.laddress is not None: if val.laddress is None and self.laddress is not None:
val.laddress = self.laddress val.laddress = self.laddress
val.type = self.type.dereference() val._type = self.type.dereference()
if self.dumper.useDynamicType: if self.dumper.useDynamicType:
val.type = self.dumper.nativeDynamicType(val.laddress, val.type) val._type = self.dumper.nativeDynamicType(val.laddress, val.type)
else: else:
val = self.dumper.nativeValueDereferenceReference(self) val = self.dumper.nativeValueDereferenceReference(self)
elif self.type.code == TypeCode.Pointer: elif self.type.code == TypeCode.Pointer:
if self.nativeValue is None: if self.nativeValue is None:
val.laddress = self.pointer() val.laddress = self.pointer()
val.type = self.type.dereference() val._type = self.type.dereference()
if self.dumper.useDynamicType: if self.dumper.useDynamicType:
val.type = self.dumper.nativeDynamicType(val.laddress, val.type) val._type = self.dumper.nativeDynamicType(val.laddress, val.type)
else: else:
val = self.dumper.nativeValueDereferencePointer(self) val = self.dumper.nativeValueDereferencePointer(self)
else: else:
@@ -3286,7 +3292,7 @@ class DumperBase():
#DumperBase.warn("DEREFERENCING TO: %s" % val) #DumperBase.warn("DEREFERENCING TO: %s" % val)
#dynTypeName = val.type.dynamicTypeName(val.laddress) #dynTypeName = val.type.dynamicTypeName(val.laddress)
#if dynTypeName is not None: #if dynTypeName is not None:
# val.type = self.dumper.createType(dynTypeName) # val._type = self.dumper.createType(dynTypeName)
return val return val
def detypedef(self): def detypedef(self):
@@ -3294,7 +3300,7 @@ class DumperBase():
if self.type.code != TypeCode.Typedef: if self.type.code != TypeCode.Typedef:
raise RuntimeError("WRONG") raise RuntimeError("WRONG")
val = self.copy() val = self.copy()
val.type = self.type.ltarget val._type = self.type.ltarget
#DumperBase.warn("DETYPEDEF FROM: %s" % self) #DumperBase.warn("DETYPEDEF FROM: %s" % self)
#DumperBase.warn("DETYPEDEF TO: %s" % val) #DumperBase.warn("DETYPEDEF TO: %s" % val)
return val return val
@@ -3323,7 +3329,7 @@ class DumperBase():
val.laddress = self.laddress val.laddress = self.laddress
val.lbitsize = self.lbitsize val.lbitsize = self.lbitsize
val.ldata = self.ldata val.ldata = self.ldata
val.type = self.dumper.createType(typish) val._type = self.dumper.createType(typish)
return val return val
def address(self): def address(self):
@@ -3736,7 +3742,7 @@ class DumperBase():
targetType = self.createType(targetTypish) targetType = self.createType(targetTypish)
if self.useDynamicType: if self.useDynamicType:
targetType = targetType.dynamicType(targetAddress) targetType = targetType.dynamicType(targetAddress)
val.type = self.createPointerType(targetType) val._type = self.createPointerType(targetType)
return val return val
def createReferenceValue(self, targetAddress, targetType): def createReferenceValue(self, targetAddress, targetType):
@@ -3750,7 +3756,7 @@ class DumperBase():
val.ldata = self.toPointerData(targetAddress) val.ldata = self.toPointerData(targetAddress)
if self.useDynamicType: if self.useDynamicType:
targetType = targetType.dynamicType(targetAddress) targetType = targetType.dynamicType(targetAddress)
val.type = self.createReferenceType(targetType) val._type = self.createReferenceType(targetType)
return val return val
def createPointerType(self, targetType): def createPointerType(self, targetType):
@@ -3926,12 +3932,12 @@ class DumperBase():
def createValue(self, datish, typish): def createValue(self, datish, typish):
val = self.Value(self) val = self.Value(self)
val.type = self.createType(typish) val._type = self.createType(typish)
if self.isInt(datish): # Used as address. if self.isInt(datish): # Used as address.
#DumperBase.warn('CREATING %s AT 0x%x' % (val.type.name, datish)) #DumperBase.warn('CREATING %s AT 0x%x' % (val.type.name, datish))
val.laddress = datish val.laddress = datish
if self.useDynamicType: if self.useDynamicType:
val.type = val.type.dynamicType(datish) val._type = val.type.dynamicType(datish)
return val return val
if isinstance(datish, bytes): if isinstance(datish, bytes):
#DumperBase.warn('CREATING %s WITH DATA %s' % (val.type.name, self.hexencode(datish))) #DumperBase.warn('CREATING %s WITH DATA %s' % (val.type.name, self.hexencode(datish)))
@@ -3947,7 +3953,7 @@ class DumperBase():
tdata.code = TypeCode.Struct tdata.code = TypeCode.Struct
self.registerType(type_name, tdata) self.registerType(type_name, tdata)
val = self.Value(self) val = self.Value(self)
val.type = self.Type(self, type_name) val._type = self.Type(self, type_name)
val.ldata = proxy_data val.ldata = proxy_data
return val return val

View File

@@ -236,6 +236,9 @@ class Dumper(DumperBase):
pass pass
return self.fromNativeValue(val) return self.fromNativeValue(val)
def nativeValueType(self, nativeValue):
return self.fromNativeType(nativeValue.type)
def fromNativeValue(self, nativeValue): def fromNativeValue(self, nativeValue):
#DumperBase.warn('FROM NATIVE VALUE: %s' % nativeValue) #DumperBase.warn('FROM NATIVE VALUE: %s' % nativeValue)
self.check(isinstance(nativeValue, gdb.Value)) self.check(isinstance(nativeValue, gdb.Value))
@@ -297,7 +300,7 @@ class Dumper(DumperBase):
pass pass
val.ldata = bytes(buf) val.ldata = bytes(buf)
val.type = self.fromNativeType(nativeType) val._type = self.fromNativeType(nativeType)
val.lIsInScope = not nativeValue.is_optimized_out val.lIsInScope = not nativeValue.is_optimized_out
code = nativeType.code code = nativeType.code
if code == gdb.TYPE_CODE_ENUM: if code == gdb.TYPE_CODE_ENUM:
@@ -496,7 +499,7 @@ class Dumper(DumperBase):
if nativeMember is None: if nativeMember is None:
val = self.Value(self) val = self.Value(self)
val.name = fieldName val.name = fieldName
val.type = self.fromNativeType(nativeField.type) val._type = self.fromNativeType(nativeField.type)
val.lIsInScope = False val.lIsInScope = False
return val return val
val = self.fromNativeValue(nativeMember) val = self.fromNativeValue(nativeMember)
@@ -505,7 +508,7 @@ class Dumper(DumperBase):
val.lvalue = int(nativeMember) val.lvalue = int(nativeMember)
val.laddress = None val.laddress = None
fieldType = self.fromNativeType(nativeFieldType) fieldType = self.fromNativeType(nativeFieldType)
val.type = self.createBitfieldType(fieldType, nativeField.bitsize) val._type = self.createBitfieldType(fieldType, nativeField.bitsize)
val.isBaseClass = nativeField.is_base_class val.isBaseClass = nativeField.is_base_class
val.name = fieldName val.name = fieldName
return val return val

View File

@@ -196,7 +196,7 @@ class Dumper(DumperBase):
if hasattr(nativeTargetType, 'GetCanonicalType'): if hasattr(nativeTargetType, 'GetCanonicalType'):
nativeTargetType = nativeTargetType.GetCanonicalType() nativeTargetType = nativeTargetType.GetCanonicalType()
val = self.fromNativeValue(nativeValue.Cast(nativeTargetType)) val = self.fromNativeValue(nativeValue.Cast(nativeTargetType))
val.type = self.fromNativeType(nativeType) val._type = self.fromNativeType(nativeType)
#DumperBase.warn('CREATED TYPEDEF: %s' % val) #DumperBase.warn('CREATED TYPEDEF: %s' % val)
else: else:
val = self.Value(self) val = self.Value(self)
@@ -215,7 +215,7 @@ class Dumper(DumperBase):
except: except:
pass pass
val.type = self.fromNativeType(nativeType) val._type = self.fromNativeType(nativeType)
if code == lldb.eTypeClassEnumeration: if code == lldb.eTypeClassEnumeration:
intval = nativeValue.GetValueAsSigned() intval = nativeValue.GetValueAsSigned()
@@ -331,7 +331,7 @@ class Dumper(DumperBase):
if fieldType.GetNumberOfDirectBaseClasses() == 0: if fieldType.GetNumberOfDirectBaseClasses() == 0:
member = self.Value(self) member = self.Value(self)
fieldName = fieldObj.GetName() fieldName = fieldObj.GetName()
member.type = self.fromNativeType(fieldType) member._type = self.fromNativeType(fieldType)
member.name = fieldName member.name = fieldName
member.fields = [] member.fields = []
if False: if False: