forked from qt-creator/qt-creator
Debugger: Remove use of native values in dumper.py
Lowers the barrier for other debugger backends. Change-Id: I09e0ad09548b6b4220175245cc0d845ac5aa29d0 Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -89,14 +89,18 @@ class Value:
|
|||||||
class Type:
|
class Type:
|
||||||
name() -> string # Full name of this type
|
name() -> string # Full name of this type
|
||||||
bitsize() -> int # Size of type in bits
|
bitsize() -> int # Size of type in bits
|
||||||
arrayType() -> bool # Is this an array?
|
code() -> TypeCodeTypedef
|
||||||
pointerType() -> bool # Is this a pointer
|
| TypeCodeStruct
|
||||||
referenceType() -> bool # ...
|
| TypeCodeVoid
|
||||||
functionType() -> bool
|
| TypeCodeIntegral
|
||||||
typedefedType() -> bool
|
| TypeCodeFloat
|
||||||
enumType() -> bool
|
| TypeCodeEnum
|
||||||
integralType() -> bool
|
| TypeCodePointer
|
||||||
floatingPointType() -> bool
|
| TypeCodeArray
|
||||||
|
| TypeCodeComplex
|
||||||
|
| TypeCodeReference
|
||||||
|
| TypeCodeFunction
|
||||||
|
| TypeCodeMemberPointer
|
||||||
|
|
||||||
unqualified() -> Type # Type without const/volatile
|
unqualified() -> Type # Type without const/volatile
|
||||||
target() -> Type # Type dereferenced if it is a pointer type, element if array etc
|
target() -> Type # Type dereferenced if it is a pointer type, element if array etc
|
||||||
|
@@ -212,8 +212,7 @@ class Children:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
class PairedChildrenData:
|
class PairedChildrenData:
|
||||||
def __init__(self, d, pairType, keyType, valueType, useKeyAndValue):
|
def __init__(self, d, pairType, keyType, valueType):
|
||||||
self.useKeyAndValue = useKeyAndValue
|
|
||||||
self.pairType = pairType
|
self.pairType = pairType
|
||||||
self.keyType = keyType
|
self.keyType = keyType
|
||||||
self.valueType = valueType
|
self.valueType = valueType
|
||||||
@@ -228,7 +227,9 @@ class PairedChildren(Children):
|
|||||||
keyType = pairType[0].unqualified()
|
keyType = pairType[0].unqualified()
|
||||||
if valueType is None:
|
if valueType is None:
|
||||||
valueType = pairType[1]
|
valueType = pairType[1]
|
||||||
d.pairData = PairedChildrenData(d, pairType, keyType, valueType, useKeyAndValue)
|
d.pairData = PairedChildrenData(d, pairType, keyType, valueType)
|
||||||
|
d.pairData.kname = "key" if useKeyAndValue else "first"
|
||||||
|
d.pairData.vname = "value" if useKeyAndValue else "second"
|
||||||
|
|
||||||
Children.__init__(self, d, numChild,
|
Children.__init__(self, d, numChild,
|
||||||
d.pairData.childType,
|
d.pairData.childType,
|
||||||
@@ -671,7 +672,10 @@ class DumperBase:
|
|||||||
|
|
||||||
def putIntItem(self, name, value):
|
def putIntItem(self, name, value):
|
||||||
with SubItem(self, name):
|
with SubItem(self, name):
|
||||||
self.putValue(value)
|
if isinstance(value, self.Value):
|
||||||
|
self.putValue(value.display())
|
||||||
|
else:
|
||||||
|
self.putValue(value)
|
||||||
self.putType("int")
|
self.putType("int")
|
||||||
self.putNumChild(0)
|
self.putNumChild(0)
|
||||||
|
|
||||||
@@ -682,28 +686,23 @@ class DumperBase:
|
|||||||
self.putNumChild(0)
|
self.putNumChild(0)
|
||||||
|
|
||||||
def putPairItem(self, index, pair):
|
def putPairItem(self, index, pair):
|
||||||
if isinstance(pair, tuple):
|
(first, second) = pair if isinstance(pair, tuple) else pair.members()
|
||||||
(first, second) = pair
|
|
||||||
elif self.pairData.useKeyAndValue:
|
|
||||||
(first, second) = (pair["key"], pair["value"])
|
|
||||||
else:
|
|
||||||
(first, second) = (pair["first"], pair["second"])
|
|
||||||
|
|
||||||
with SubItem(self, index):
|
with SubItem(self, index):
|
||||||
self.putNumChild(2)
|
|
||||||
(keystr, keyenc, valstr, valenc) = (None, None, None, None)
|
(keystr, keyenc, valstr, valenc) = (None, None, None, None)
|
||||||
with Children(self):
|
with Children(self):
|
||||||
with SubItem(self, "key"):
|
with SubItem(self, self.pairData.kname):
|
||||||
self.putItem(first, True)
|
self.putItem(first)
|
||||||
keystr = self.currentValue.value
|
keystr = self.currentValue.value
|
||||||
keyenc = self.currentValue.encoding
|
keyenc = self.currentValue.encoding
|
||||||
with SubItem(self, "value"):
|
with SubItem(self, self.pairData.vname):
|
||||||
self.putItem(second, True)
|
self.putItem(second)
|
||||||
valstr = self.currentValue.value
|
valstr = self.currentValue.value
|
||||||
valenc = self.currentValue.encoding
|
valenc = self.currentValue.encoding
|
||||||
if index is not None:
|
if index is not None:
|
||||||
self.put('keyprefix="[%s] ",' % index)
|
self.put('keyprefix="[%s] ",' % index)
|
||||||
self.put('keyencoded="%s",key="%s",' % (keyenc, keystr))
|
self.put('key="%s",' % keystr)
|
||||||
|
if keyenc is not None:
|
||||||
|
self.put('keyencoded="%s",' % keyenc)
|
||||||
self.putValue(valstr, valenc)
|
self.putValue(valstr, valenc)
|
||||||
|
|
||||||
def putCallItem(self, name, rettype, value, func, *args):
|
def putCallItem(self, name, rettype, value, func, *args):
|
||||||
@@ -713,9 +712,8 @@ class DumperBase:
|
|||||||
except Exception as error:
|
except Exception as error:
|
||||||
if self.passExceptions:
|
if self.passExceptions:
|
||||||
raise error
|
raise error
|
||||||
else:
|
children = [('error', error)]
|
||||||
children = [('error', error)]
|
self.putSpecialValue("notcallable", children=children)
|
||||||
self.putSpecialValue("notcallable", children=children)
|
|
||||||
else:
|
else:
|
||||||
self.putItem(result)
|
self.putItem(result)
|
||||||
|
|
||||||
@@ -772,7 +770,7 @@ class DumperBase:
|
|||||||
self.put('name="[%s]",' % field.name)
|
self.put('name="[%s]",' % field.name)
|
||||||
self.put('sortgroup="%s"' % (1000 - field.baseIndex))
|
self.put('sortgroup="%s"' % (1000 - field.baseIndex))
|
||||||
self.putAddress(baseValue.address())
|
self.putAddress(baseValue.address())
|
||||||
self.putItem(baseValue, False)
|
self.putItem(baseValue)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
with SubItem(self, field.name):
|
with SubItem(self, field.name):
|
||||||
@@ -1004,9 +1002,8 @@ class DumperBase:
|
|||||||
|
|
||||||
def putCStyleArray(self, value):
|
def putCStyleArray(self, value):
|
||||||
arrayType = value.type.unqualified()
|
arrayType = value.type.unqualified()
|
||||||
if self.isGdb and value.nativeValue is not None:
|
innerType = arrayType.ltarget
|
||||||
innerType = self.fromNativeType(value.nativeValue[0].type)
|
if innerType is None:
|
||||||
else:
|
|
||||||
innerType = value.type.target()
|
innerType = value.type.target()
|
||||||
innerTypeName = innerType.unqualified().name
|
innerTypeName = innerType.unqualified().name
|
||||||
address = value.address()
|
address = value.address()
|
||||||
@@ -1332,22 +1329,22 @@ class DumperBase:
|
|||||||
# warn("NO QOBJECT: %s" % value.type)
|
# warn("NO QOBJECT: %s" % value.type)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def couldBeQObject(self, objectPtr):
|
def canBePointer(self, p):
|
||||||
def canBePointer(p):
|
if self.ptrSize() == 4:
|
||||||
if self.ptrSize() == 4:
|
return p > 100000 and (p & 0x3 == 0)
|
||||||
return p > 100000 and (p & 0x3 == 0)
|
else:
|
||||||
else:
|
return p > 100000 and (p & 0x7 == 0) and (p < 0x7fffffffffff)
|
||||||
return p > 100000 and (p & 0x7 == 0) and (p < 0x7fffffffffff)
|
|
||||||
|
|
||||||
|
def couldBeQObject(self, objectPtr):
|
||||||
try:
|
try:
|
||||||
(vtablePtr, dd) = self.split('pp', objectPtr)
|
(vtablePtr, dd) = self.split('pp', objectPtr)
|
||||||
except:
|
except:
|
||||||
self.bump("nostruct-1")
|
self.bump("nostruct-1")
|
||||||
return False
|
return False
|
||||||
if not canBePointer(vtablePtr):
|
if not self.canBePointer(vtablePtr):
|
||||||
self.bump("vtable")
|
self.bump("vtable")
|
||||||
return False
|
return False
|
||||||
if not canBePointer(dd):
|
if not self.canBePointer(dd):
|
||||||
self.bump("d_d_ptr")
|
self.bump("d_d_ptr")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -1358,7 +1355,7 @@ class DumperBase:
|
|||||||
self.bump("nostruct-2")
|
self.bump("nostruct-2")
|
||||||
return False
|
return False
|
||||||
#warn("STRUCT DD: %s 0x%x" % (self.currentIName, qptr))
|
#warn("STRUCT DD: %s 0x%x" % (self.currentIName, qptr))
|
||||||
if not canBePointer(dvtablePtr):
|
if not self.canBePointer(dvtablePtr):
|
||||||
self.bump("dvtable")
|
self.bump("dvtable")
|
||||||
#warn("DVT: 0x%x" % dvtablePtr)
|
#warn("DVT: 0x%x" % dvtablePtr)
|
||||||
return False
|
return False
|
||||||
@@ -1367,11 +1364,11 @@ class DumperBase:
|
|||||||
#warn("QPTR: 0x%x 0x%x" % (qptr, objectPtr))
|
#warn("QPTR: 0x%x 0x%x" % (qptr, objectPtr))
|
||||||
self.bump("q_ptr")
|
self.bump("q_ptr")
|
||||||
return False
|
return False
|
||||||
if parentPtr and not canBePointer(parentPtr):
|
if parentPtr and not self.canBePointer(parentPtr):
|
||||||
#warn("PAREN")
|
#warn("PAREN")
|
||||||
self.bump("parent")
|
self.bump("parent")
|
||||||
return False
|
return False
|
||||||
if not canBePointer(childrenDPtr):
|
if not self.canBePointer(childrenDPtr):
|
||||||
#warn("CHILD")
|
#warn("CHILD")
|
||||||
self.bump("children")
|
self.bump("children")
|
||||||
return False
|
return False
|
||||||
@@ -1380,7 +1377,7 @@ class DumperBase:
|
|||||||
# self.bump("flags")
|
# self.bump("flags")
|
||||||
# return False
|
# return False
|
||||||
#warn("OK")
|
#warn("OK")
|
||||||
#if dynMetaObjectPtr and not canBePointer(dynMetaObjectPtr):
|
#if dynMetaObjectPtr and not self.canBePointer(dynMetaObjectPtr):
|
||||||
# self.bump("dynmo")
|
# self.bump("dynmo")
|
||||||
# return False
|
# return False
|
||||||
|
|
||||||
@@ -1926,13 +1923,13 @@ class DumperBase:
|
|||||||
displayFormat = self.typeformats.get(needle, AutomaticFormat)
|
displayFormat = self.typeformats.get(needle, AutomaticFormat)
|
||||||
return displayFormat
|
return displayFormat
|
||||||
|
|
||||||
def putSubItem(self, component, value, tryDynamic=True):
|
def putSubItem(self, component, value):
|
||||||
if not isinstance(value, self.Value):
|
if not isinstance(value, self.Value):
|
||||||
error("WRONG VALUE TYPE IN putSubItem: %s" % type(value))
|
error("WRONG VALUE TYPE IN putSubItem: %s" % type(value))
|
||||||
if not isinstance(value.type, self.Type):
|
if not isinstance(value.type, self.Type):
|
||||||
error("WRONG TYPE TYPE IN putSubItem: %s" % type(value.type))
|
error("WRONG TYPE TYPE IN putSubItem: %s" % type(value.type))
|
||||||
with SubItem(self, component):
|
with SubItem(self, component):
|
||||||
self.putItem(value, tryDynamic)
|
self.putItem(value)
|
||||||
|
|
||||||
def putArrayData(self, base, n, innerType, childNumChild = None, maxNumChild = 10000):
|
def putArrayData(self, base, n, innerType, childNumChild = None, maxNumChild = 10000):
|
||||||
self.checkIntType(base)
|
self.checkIntType(base)
|
||||||
@@ -2431,20 +2428,17 @@ class DumperBase:
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def putItem(self, value, tryDynamic=True):
|
def putItem(self, value):
|
||||||
#warn("ITEM: %s" % value.stringify())
|
#warn("ITEM: %s" % value.stringify())
|
||||||
|
|
||||||
typeobj = value.type #unqualified()
|
typeobj = value.type #unqualified()
|
||||||
typeName = typeobj.name
|
typeName = typeobj.name
|
||||||
|
|
||||||
tryDynamic &= self.useDynamicType
|
|
||||||
self.addToCache(typeobj) # Fill type cache
|
self.addToCache(typeobj) # Fill type cache
|
||||||
if tryDynamic:
|
self.putAddress(value.address())
|
||||||
self.putAddress(value.address())
|
|
||||||
|
|
||||||
if not value.isInScope():
|
if not value.lIsInScope:
|
||||||
self.putSpecialValue("optimizedout")
|
self.putSpecialValue("optimizedout")
|
||||||
#self.putValue("optimizedout: %s" % value.nativeValue)
|
|
||||||
#self.putType(typeobj)
|
#self.putType(typeobj)
|
||||||
#self.putSpecialValue('outofscope')
|
#self.putSpecialValue('outofscope')
|
||||||
self.putNumChild(0)
|
self.putNumChild(0)
|
||||||
@@ -2500,50 +2494,13 @@ class DumperBase:
|
|||||||
return
|
return
|
||||||
|
|
||||||
if typeobj.code == TypeCodeReference:
|
if typeobj.code == TypeCodeReference:
|
||||||
try:
|
|
||||||
# Try to recognize null references explicitly.
|
|
||||||
if value.address() is 0:
|
|
||||||
self.putSpecialValue("nullreference")
|
|
||||||
self.putNumChild(0)
|
|
||||||
self.putType(typeobj)
|
|
||||||
return
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if self.isLldb:
|
if self.isLldb:
|
||||||
targetType = value.type.target()
|
item = value.cast(typeobj.target().pointer()).dereference()
|
||||||
item = value.cast(targetType.pointer()).dereference()
|
|
||||||
self.putItem(item)
|
|
||||||
self.putBetterType(value.type.name)
|
|
||||||
return
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if tryDynamic:
|
item = value.cast(typeobj.target().unqualified())
|
||||||
try:
|
self.putItem(item)
|
||||||
# Dynamic references are not supported by gdb, see
|
self.putBetterType(typeobj.name)
|
||||||
# http://sourceware.org/bugzilla/show_bug.cgi?id=14077.
|
return
|
||||||
# Find the dynamic type manually using referenced_type.
|
|
||||||
val = value.referenced_value()
|
|
||||||
val = val.cast(val.dynamic_type)
|
|
||||||
self.putItem(val)
|
|
||||||
self.putBetterType("%s &" % typeobj)
|
|
||||||
return
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
# FIXME: This throws "RuntimeError: Attempt to dereference a
|
|
||||||
# generic pointer." with MinGW's gcc 4.5 when it "identifies"
|
|
||||||
# a "QWidget &" as "void &" and with optimized out code.
|
|
||||||
self.putItem(value.cast(typeobj.target().unqualified()))
|
|
||||||
self.putBetterType("%s &" % self.currentType.value)
|
|
||||||
return
|
|
||||||
except Exception as error:
|
|
||||||
self.putSpecialValue("optimizedout")
|
|
||||||
#self.putValue("optimizedout: %s" % error)
|
|
||||||
self.putType(typeobj)
|
|
||||||
self.putNumChild(0)
|
|
||||||
return
|
|
||||||
|
|
||||||
if typeobj.code == TypeCodeComplex:
|
if typeobj.code == TypeCodeComplex:
|
||||||
self.putType(typeobj)
|
self.putType(typeobj)
|
||||||
@@ -2625,8 +2582,8 @@ class DumperBase:
|
|||||||
self.type = None
|
self.type = None
|
||||||
self.ldata = None
|
self.ldata = None
|
||||||
self.laddress = None
|
self.laddress = None
|
||||||
self.nativeValue = None
|
|
||||||
self.lIsInScope = True
|
self.lIsInScope = True
|
||||||
|
self.ldisplay = None
|
||||||
|
|
||||||
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):
|
||||||
@@ -2639,11 +2596,9 @@ class DumperBase:
|
|||||||
return self.stringify()
|
return self.stringify()
|
||||||
|
|
||||||
def stringify(self):
|
def stringify(self):
|
||||||
self.check()
|
|
||||||
addr = "None" if self.laddress is None else ("0x%x" % self.laddress)
|
addr = "None" if self.laddress is None else ("0x%x" % self.laddress)
|
||||||
return "Value(name='%s',type=%s,data=%s,address=%s,nativeValue=%s)" \
|
return "Value(name='%s',type=%s,data=%s,address=%s)" \
|
||||||
% (self.name, self.type.stringify(), self.dumper.hexencode(self.ldata),
|
% (self.name, self.type.stringify(), self.dumper.hexencode(self.ldata), addr)
|
||||||
addr, self.nativeValue)
|
|
||||||
|
|
||||||
def display(self):
|
def display(self):
|
||||||
if self.type.code == TypeCodeEnum:
|
if self.type.code == TypeCodeEnum:
|
||||||
@@ -2651,21 +2606,14 @@ class DumperBase:
|
|||||||
simple = self.value()
|
simple = self.value()
|
||||||
if simple is not None:
|
if simple is not None:
|
||||||
return str(simple)
|
return str(simple)
|
||||||
if self.type.code == TypeCodeComplex:
|
if self.ldisplay is not None:
|
||||||
if self.nativeValue is not None:
|
return self.ldisplay
|
||||||
if self.dumper.isLldb:
|
#if self.ldata is not None:
|
||||||
return str(self.nativeValue.GetValue())
|
# if sys.version_info[0] == 2 and isinstance(self.ldata, buffer):
|
||||||
else:
|
# return bytes(self.ldata).encode("hex")
|
||||||
return str( self.nativeValue)
|
# return self.ldata.encode("hex")
|
||||||
if self.nativeValue is not None:
|
|
||||||
return str(self.nativeValue)
|
|
||||||
#return "Value(nativeValue=%s)" % self.nativeValue
|
|
||||||
if self.ldata is not None:
|
|
||||||
if sys.version_info[0] == 2 and isinstance(self.ldata, buffer):
|
|
||||||
return bytes(self.data).encode("hex")
|
|
||||||
return self.data.encode("hex")
|
|
||||||
if self.laddress is not None:
|
if self.laddress is not None:
|
||||||
return "value of type %s at address 0x%x" % (self.type, self.laddress)
|
return "value of type %s at address 0x%x" % (self.type.name, self.laddress)
|
||||||
return "<unknown data>"
|
return "<unknown data>"
|
||||||
|
|
||||||
def simpleDisplay(self, showAddress=True):
|
def simpleDisplay(self, showAddress=True):
|
||||||
@@ -2741,66 +2689,52 @@ class DumperBase:
|
|||||||
return self.extractField(field)
|
return self.extractField(field)
|
||||||
|
|
||||||
def extractField(self, field):
|
def extractField(self, field):
|
||||||
#warn("PARENT BASE 0x%x" % self.address())
|
self.dumper.check(self.type.code != TypeCodeTypedef)
|
||||||
if self.type.code == TypeCodeTypedef:
|
|
||||||
error("WRONG")
|
|
||||||
if not isinstance(field, self.dumper.Field):
|
if not isinstance(field, self.dumper.Field):
|
||||||
error("BAD INDEX TYPE %s" % type(field))
|
error("BAD INDEX TYPE %s" % type(field))
|
||||||
|
|
||||||
val = None
|
|
||||||
if self.nativeValue is not None:
|
|
||||||
#warn("NATIVE, FIELD TYPE: %s " % field)
|
|
||||||
val = self.dumper.nativeValueChildFromField(self.nativeValue, field)
|
|
||||||
#warn("BAD INDEX XX VAL: %s TYPE: %s INDEX TYPE: %s "
|
|
||||||
# % (self, self.type, type(field)))
|
|
||||||
|
|
||||||
#warn("FIELD: %s " % field)
|
#warn("FIELD: %s " % field)
|
||||||
fieldType = field.fieldType()
|
|
||||||
fieldBitsize = field.bitsize()
|
fieldBitsize = field.bitsize()
|
||||||
fieldSize = None if fieldBitsize is None else fieldBitsize >> 3
|
fieldSize = None if fieldBitsize is None else fieldBitsize >> 3
|
||||||
#warn("BITPOS %s BITSIZE: %s" % (fieldBitpos, fieldBitsize))
|
fieldBitpos = field.bitpos()
|
||||||
|
fieldOffset = fieldBitpos >> 3
|
||||||
|
fieldBitpos -= fieldOffset * 8
|
||||||
|
|
||||||
if val is None:
|
val = self.dumper.Value(self.dumper)
|
||||||
val = self.dumper.Value(self.dumper)
|
val.name = field.name
|
||||||
val.type = fieldType
|
|
||||||
val.name = field.name
|
|
||||||
|
|
||||||
if self.laddress is not None:
|
if self.laddress is not None:
|
||||||
#warn("ADDRESS")
|
val.laddress = self.laddress + fieldOffset
|
||||||
fieldBitpos = field.bitpos()
|
elif self.ldata is not None:
|
||||||
fieldOffset = None if fieldBitpos is None else fieldBitpos >> 3
|
val.ldata = self.ldata[fieldOffset:fieldOffset + fieldSize]
|
||||||
if fieldBitpos is not None:
|
else:
|
||||||
#warn("BITPOS: %s" % fieldBitpos)
|
self.dumper.check(False)
|
||||||
val.laddress = self.laddress + fieldOffset
|
|
||||||
else:
|
|
||||||
error("NO IDEA 1")
|
|
||||||
elif len(self.ldata) > 0:
|
|
||||||
#warn("DATA")
|
|
||||||
fieldBitpos = field.bitpos()
|
|
||||||
fieldOffset = None if fieldBitpos is None else fieldBitpos >> 3
|
|
||||||
if fieldBitpos is not None:
|
|
||||||
val.ldata = self.ldata[fieldOffset:fieldOffset + fieldSize]
|
|
||||||
else:
|
|
||||||
error("NO IDEA 2")
|
|
||||||
else:
|
|
||||||
error("NO IDEA 3")
|
|
||||||
|
|
||||||
#warn("BITPOS %s BITSIZE: %s" % (fieldBitpos, fieldBitsize))
|
|
||||||
if fieldBitsize is not None and fieldBitsize % 8 != 0:
|
if fieldBitsize is not None and fieldBitsize % 8 != 0:
|
||||||
fieldBitpos = field.bitpos()
|
|
||||||
#warn("CORRECTING: FITPOS %s BITSIZE: %s" % (fieldBitpos, fieldBitsize))
|
|
||||||
typeobj = fieldType
|
|
||||||
typeobj.lbitsize = fieldBitsize
|
|
||||||
data = val.extractInteger(fieldBitsize, True)
|
data = val.extractInteger(fieldBitsize, True)
|
||||||
data = data >> (fieldBitpos & 3)
|
data = data >> fieldBitpos
|
||||||
data = data & ((1 << fieldBitsize) - 1)
|
data = data & ((1 << fieldBitsize) - 1)
|
||||||
val.laddress = None
|
val.laddress = None
|
||||||
val.ldata = bytes(struct.pack('Q', data))
|
val.ldata = bytes(struct.pack('Q', data))
|
||||||
val.type = typeobj
|
|
||||||
|
val.type = None
|
||||||
|
fieldType = field.fieldType()
|
||||||
|
if val.laddress is not None and fieldType is not None:
|
||||||
|
if fieldType.code in (TypeCodePointer, TypeCodeReference):
|
||||||
|
baseType = fieldType.dereference()
|
||||||
|
address = self.dumper.extractPointer(val.laddress)
|
||||||
|
dynTypeName = self.dumper.dynamicTypeName(baseType, address)
|
||||||
|
if dynTypeName is not None:
|
||||||
|
if fieldType.code == TypeCodePointer:
|
||||||
|
val.type = self.dumper.createType(dynTypeName + '*')
|
||||||
|
else:
|
||||||
|
val.type = self.dumper.createType(dynTypeName + ' &')
|
||||||
|
if val.type is None:
|
||||||
|
val.type = fieldType
|
||||||
|
|
||||||
#warn("GOT VAL %s FOR FIELD %s" % (val, field))
|
#warn("GOT VAL %s FOR FIELD %s" % (val, field))
|
||||||
val.check()
|
val.check()
|
||||||
val.lbitsize = field.bitsize()
|
val.lbitsize = fieldBitsize
|
||||||
return val
|
return val
|
||||||
|
|
||||||
def members(self):
|
def members(self):
|
||||||
@@ -2813,37 +2747,25 @@ class DumperBase:
|
|||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
self.check()
|
self.check()
|
||||||
if self.dumper.isInt(other):
|
if self.dumper.isInt(other):
|
||||||
#warn("OTHER INT: %s" % other)
|
stripped = self.type.stripTypedefs()
|
||||||
if self.nativeValue is not None:
|
if stripped.code == TypeCodePointer:
|
||||||
#warn("OTHER NATIVE: %s" % self.nativeValue)
|
address = self.pointer() + stripped.dereference().size()
|
||||||
#warn("OTHER RESULT 1: %s" % (self.nativeValue + other))
|
val = self.dumper.Value(self.dumper)
|
||||||
res = self.dumper.fromNativeValue(self.nativeValue + other)
|
val.laddress = None
|
||||||
#warn("OTHER RESULT 2: %s" % (self.nativeValue + other))
|
val.ldata = bytes(struct.pack('Q', address))
|
||||||
#warn("OTHER COOKED: 0x%x" % res.pointer())
|
val.type = self.type
|
||||||
#warn("OTHER COOKED X: 0x%x" % res.nativeValue)
|
return val
|
||||||
return res
|
|
||||||
error("BAD DATA TO ADD TO: %s %s" % (self.type, other))
|
error("BAD DATA TO ADD TO: %s %s" % (self.type, other))
|
||||||
|
|
||||||
def dereference(self):
|
def dereference(self):
|
||||||
self.check()
|
self.check()
|
||||||
if self.nativeValue is not None:
|
val = self.dumper.Value(self.dumper)
|
||||||
res = self.dumper.nativeValueDereference(self.nativeValue)
|
val.type = self.type.dereference()
|
||||||
if res is not None:
|
val.laddress = self.pointer()
|
||||||
return res
|
dynTypeName = self.dumper.dynamicTypeName(val.type, val.laddress)
|
||||||
if self.laddress is not None:
|
if dynTypeName is not None:
|
||||||
val = self.dumper.Value(self.dumper)
|
val.type = self.dumper.createType(dynTypeName)
|
||||||
val.type = self.type.dereference()
|
return val
|
||||||
#val.ldata = bytes(self.dumper.readRawMemory(self.laddress, val.type.size()))
|
|
||||||
#val.laddress = self.dumper.extractPointer(self.laddress)
|
|
||||||
#val.ldata = bytes(self.data(self.dumper.ptrSize()))
|
|
||||||
#val.laddress = self.__int__()
|
|
||||||
bitsize = self.dumper.ptrSize() * 8
|
|
||||||
val.laddress = self.integer()
|
|
||||||
#warn("DEREFERENCING %s AT 0x%x -- %s TO %s AT 0x%x --- %s" %
|
|
||||||
# (self.type, self.laddress, self.dumper.hexencode(self.data),
|
|
||||||
# val.type, val.laddress, self.dumper.hexencode(val.data)))
|
|
||||||
return val
|
|
||||||
error("BAD DATA TO DEREFERENCE: %s %s" % (self.type, type(self)))
|
|
||||||
|
|
||||||
def extend(self, size):
|
def extend(self, size):
|
||||||
if self.type.size() < size:
|
if self.type.size() < size:
|
||||||
@@ -2860,28 +2782,16 @@ class DumperBase:
|
|||||||
|
|
||||||
def cast(self, typish):
|
def cast(self, typish):
|
||||||
self.check()
|
self.check()
|
||||||
typeobj = self.dumper.createType(typish)
|
|
||||||
if self.nativeValue is not None and typeobj.nativeType is not None:
|
|
||||||
res = self.dumper.nativeValueCast(self.nativeValue, typeobj.nativeType)
|
|
||||||
if res is not None:
|
|
||||||
return res
|
|
||||||
#error("BAD NATIVE DATA TO CAST: %s %s" % (self.type, typeobj))
|
|
||||||
val = self.dumper.Value(self.dumper)
|
val = self.dumper.Value(self.dumper)
|
||||||
val.laddress = self.laddress
|
val.laddress = self.laddress
|
||||||
val.ldata = self.ldata
|
val.ldata = self.ldata
|
||||||
val.type = typeobj
|
val.type = self.dumper.createType(typish)
|
||||||
#warn("CAST %s %s" % (self.type.stringify(), typeobj.stringify()))
|
|
||||||
return val
|
return val
|
||||||
|
|
||||||
def downcast(self):
|
def downcast(self):
|
||||||
self.check()
|
self.check()
|
||||||
if self.nativeValue is not None:
|
|
||||||
return self.dumper.nativeValueDownCast(self.nativeValue)
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def isInScope(self):
|
|
||||||
return self.lIsInScope
|
|
||||||
|
|
||||||
def address(self):
|
def address(self):
|
||||||
self.check()
|
self.check()
|
||||||
return self.laddress
|
return self.laddress
|
||||||
@@ -2896,38 +2806,28 @@ class DumperBase:
|
|||||||
return self.ldata
|
return self.ldata
|
||||||
if size < len(self.ldata):
|
if size < len(self.ldata):
|
||||||
return self.ldata[:size]
|
return self.ldata[:size]
|
||||||
error("DATA PRESENT, BUT NOT BIG ENOUGH: %s WANT: %s"
|
|
||||||
% (self.stringify(), size))
|
|
||||||
if self.laddress is not None:
|
if self.laddress is not None:
|
||||||
if size is None:
|
if size is None:
|
||||||
size = self.type.size()
|
size = self.type.size()
|
||||||
res = self.dumper.readRawMemory(self.laddress, size)
|
res = self.dumper.readRawMemory(self.laddress, size)
|
||||||
if len(res) > 0:
|
if len(res) > 0:
|
||||||
return res
|
return res
|
||||||
if self.nativeValue is not None:
|
|
||||||
if size is None:
|
|
||||||
size = self.type.size()
|
|
||||||
res = self.dumper.nativeValueAsBytes(self.nativeValue, size)
|
|
||||||
if len(res) > 0:
|
|
||||||
return res
|
|
||||||
return res
|
|
||||||
error("CANNOT CONVERT TO BYTES: %s" % self)
|
error("CANNOT CONVERT TO BYTES: %s" % self)
|
||||||
|
|
||||||
def extractInteger(self, bitsize, unsigned):
|
def extractInteger(self, bitsize, unsigned):
|
||||||
self.check()
|
self.check()
|
||||||
size = (bitsize + 7) >> 3
|
if bitsize > 32:
|
||||||
if size == 8:
|
size = 8
|
||||||
code = "Q" if unsigned else "q"
|
code = "Q" if unsigned else "q"
|
||||||
elif size == 4:
|
elif bitsize > 16:
|
||||||
|
size = 4
|
||||||
code = "I" if unsigned else "i"
|
code = "I" if unsigned else "i"
|
||||||
elif size == 2:
|
elif bitsize > 8:
|
||||||
|
size = 2
|
||||||
code = "H" if unsigned else "h"
|
code = "H" if unsigned else "h"
|
||||||
elif size == 1:
|
|
||||||
code = "B" if unsigned else "b"
|
|
||||||
else:
|
else:
|
||||||
code = None
|
size = 1
|
||||||
if code is None:
|
code = "B" if unsigned else "b"
|
||||||
return None
|
|
||||||
rawBytes = self.data(size)
|
rawBytes = self.data(size)
|
||||||
try:
|
try:
|
||||||
return struct.unpack_from(code, rawBytes, 0)[0]
|
return struct.unpack_from(code, rawBytes, 0)[0]
|
||||||
@@ -2971,6 +2871,18 @@ class DumperBase:
|
|||||||
ptr = p if self.isInt(p) else p.pointer()
|
ptr = p if self.isInt(p) else p.pointer()
|
||||||
self.readRawMemory(ptr, 1)
|
self.readRawMemory(ptr, 1)
|
||||||
|
|
||||||
|
def dynamicTypeName(self, baseType, address):
|
||||||
|
if baseType.code != TypeCodeStruct:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
vtbl = self.extractPointer(address)
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
#warn("VTBL: 0x%x" % vtbl)
|
||||||
|
if not self.canBePointer(vtbl):
|
||||||
|
return None
|
||||||
|
return self.nativeDynamicTypeName(address, baseType)
|
||||||
|
|
||||||
class Type:
|
class Type:
|
||||||
def __init__(self, dumper):
|
def __init__(self, dumper):
|
||||||
self.dumper = dumper
|
self.dumper = dumper
|
||||||
@@ -2979,6 +2891,7 @@ class DumperBase:
|
|||||||
self.lfields = None
|
self.lfields = None
|
||||||
self.lbitsize = None
|
self.lbitsize = None
|
||||||
self.lbitpos = None
|
self.lbitpos = None
|
||||||
|
self.ltarget = None # Inner type for arrays
|
||||||
self.templateArguments = None
|
self.templateArguments = None
|
||||||
self.code = None
|
self.code = None
|
||||||
|
|
||||||
@@ -3206,7 +3119,9 @@ class DumperBase:
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return ("Field(name='%s',ltype=%s,parentType=%s,bpos=%s,bsize=%s,"
|
return ("Field(name='%s',ltype=%s,parentType=%s,bpos=%s,bsize=%s,"
|
||||||
+ "bidx=%s,nidx=%s)") \
|
+ "bidx=%s,nidx=%s)") \
|
||||||
% (self.name, self.ltype, self.parentType,
|
% (self.name,
|
||||||
|
None if self.ltype is None else self.ltype.name,
|
||||||
|
None if self.parentType is None else self.parentType.name,
|
||||||
self.lbitpos, self.lbitsize,
|
self.lbitpos, self.lbitsize,
|
||||||
self.baseIndex, self.nativeIndex)
|
self.baseIndex, self.nativeIndex)
|
||||||
|
|
||||||
@@ -3294,32 +3209,22 @@ class DumperBase:
|
|||||||
#warn("CREATE TYPE: %s" % typeobj)
|
#warn("CREATE TYPE: %s" % typeobj)
|
||||||
typeobj.check()
|
typeobj.check()
|
||||||
return typeobj
|
return typeobj
|
||||||
if self.isInt(typish):
|
|
||||||
# Assume it is an typecode, create an "anonymous" Type
|
|
||||||
typeobj = self.Type(self)
|
|
||||||
typeobj.code = typish
|
|
||||||
typeobj.lbitsize = 8 * size
|
|
||||||
typeobj.name = ' '
|
|
||||||
return typeobj
|
|
||||||
error("NEED TYPE, NOT %s" % type(typish))
|
error("NEED TYPE, NOT %s" % type(typish))
|
||||||
|
|
||||||
def createValue(self, datish, typish):
|
def createValue(self, datish, typish):
|
||||||
|
val = self.Value(self)
|
||||||
|
val.type = self.createType(typish)
|
||||||
if self.isInt(datish): # Used as address.
|
if self.isInt(datish): # Used as address.
|
||||||
#warn("CREATING %s AT 0x%x" % (typish, address))
|
|
||||||
val = self.Value(self)
|
|
||||||
val.laddress = datish
|
val.laddress = datish
|
||||||
val.type = self.createType(typish)
|
#warn("CREATING %s AT 0x%x" % (val.type.name, address))
|
||||||
val.check()
|
elif isinstance(datish, bytes):
|
||||||
return val
|
|
||||||
if isinstance(datish, bytes):
|
|
||||||
#warn("CREATING %s WITH DATA %s" % (typish, self.hexencode(datish)))
|
|
||||||
val = self.Value(self)
|
|
||||||
val.ldata = datish
|
val.ldata = datish
|
||||||
val.type = self.createType(typish)
|
|
||||||
val.type.lbitsize = 8 * len(datish)
|
val.type.lbitsize = 8 * len(datish)
|
||||||
val.check()
|
#warn("CREATING %s WITH DATA %s" % (val.type.name, self.hexencode(datish)))
|
||||||
return val
|
else:
|
||||||
error("EXPECTING ADDRESS OR BYTES, GOT %s" % type(datish))
|
error("EXPECTING ADDRESS OR BYTES, GOT %s" % type(datish))
|
||||||
|
val.check()
|
||||||
|
return val
|
||||||
|
|
||||||
def createListItem(self, data, innerTypish):
|
def createListItem(self, data, innerTypish):
|
||||||
innerType = self.createType(innerTypish)
|
innerType = self.createType(innerTypish)
|
||||||
|
@@ -248,13 +248,32 @@ class Dumper(DumperBase):
|
|||||||
return self.fromNativeValue(nativeValue)
|
return self.fromNativeValue(nativeValue)
|
||||||
|
|
||||||
def fromNativeValue(self, nativeValue):
|
def fromNativeValue(self, nativeValue):
|
||||||
#self.check(isinstance(nativeType, gdb.Value))
|
#self.check(isinstance(nativeValue, gdb.Value))
|
||||||
|
nativeType = nativeValue.type
|
||||||
val = self.Value(self)
|
val = self.Value(self)
|
||||||
val.nativeValue = nativeValue
|
|
||||||
if not nativeValue.address is None:
|
if not nativeValue.address is None:
|
||||||
val.laddress = toInteger(nativeValue.address)
|
val.laddress = toInteger(nativeValue.address)
|
||||||
val.type = self.fromNativeType(nativeValue.type)
|
else:
|
||||||
|
size = nativeType.sizeof
|
||||||
|
chars = self.lookupNativeType("unsigned char")
|
||||||
|
y = nativeValue.cast(chars.array(0, int(nativeType.sizeof - 1)))
|
||||||
|
buf = bytearray(struct.pack('x' * size))
|
||||||
|
for i in range(size):
|
||||||
|
buf[i] = int(y[i])
|
||||||
|
val.ldata = bytes(buf)
|
||||||
|
|
||||||
|
val.type = self.fromNativeType(nativeType)
|
||||||
val.lIsInScope = not nativeValue.is_optimized_out
|
val.lIsInScope = not nativeValue.is_optimized_out
|
||||||
|
code = nativeType.code
|
||||||
|
if code == gdb.TYPE_CODE_ENUM:
|
||||||
|
val.ldisplay = str(nativeValue)
|
||||||
|
intval = int(nativeValue)
|
||||||
|
if val.ldisplay != intval:
|
||||||
|
val.ldisplay += ' (%s)' % intval
|
||||||
|
elif code == gdb.TYPE_CODE_COMPLEX:
|
||||||
|
val.ldisplay = str(nativeValue)
|
||||||
|
elif code == gdb.TYPE_CODE_ARRAY:
|
||||||
|
val.type.ltarget = nativeValue[0].type.unqualified()
|
||||||
return val
|
return val
|
||||||
|
|
||||||
def fromNativeType(self, nativeType):
|
def fromNativeType(self, nativeType):
|
||||||
@@ -285,18 +304,6 @@ class Dumper(DumperBase):
|
|||||||
}[nativeType.code]
|
}[nativeType.code]
|
||||||
return typeobj
|
return typeobj
|
||||||
|
|
||||||
def nativeValueDereference(self, nativeValue):
|
|
||||||
return self.nativeValueDownCast(nativeValue.dereference())
|
|
||||||
|
|
||||||
def nativeValueCast(self, nativeValue, nativeType):
|
|
||||||
try:
|
|
||||||
return self.fromNativeValue(nativeValue.cast(nativeType))
|
|
||||||
except:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def nativeValueAddressOf(self, nativeValue):
|
|
||||||
return toInteger(nativeValue.address)
|
|
||||||
|
|
||||||
def nativeTypeDereference(self, nativeType):
|
def nativeTypeDereference(self, nativeType):
|
||||||
return self.fromNativeType(nativeType.strip_typedefs().target())
|
return self.fromNativeType(nativeType.strip_typedefs().target())
|
||||||
|
|
||||||
@@ -402,25 +409,6 @@ class Dumper(DumperBase):
|
|||||||
typeobj = typeobj.strip_typedefs().unqualified()
|
typeobj = typeobj.strip_typedefs().unqualified()
|
||||||
return self.fromNativeType(typeobj)
|
return self.fromNativeType(typeobj)
|
||||||
|
|
||||||
def nativeValueChildFromField(self, nativeValue, field):
|
|
||||||
#warn("EXTRACTING: %s FROM %s" % (field, nativeValue))
|
|
||||||
if field.nativeIndex is not None:
|
|
||||||
nativeField = nativeValue.type.fields()[field.nativeIndex]
|
|
||||||
#warn("NATIVE FIELD: %s" % nativeField)
|
|
||||||
if nativeField.is_base_class:
|
|
||||||
return self.fromNativeValue(nativeValue.cast(nativeField.type))
|
|
||||||
try:
|
|
||||||
# Fails with GDB 7.5.
|
|
||||||
return self.nativeValueDownCast(nativeValue[nativeField])
|
|
||||||
except:
|
|
||||||
# The generic handling is almost good enough, but does not
|
|
||||||
# downcast the produced values.
|
|
||||||
return None
|
|
||||||
if field.name is not None:
|
|
||||||
return self.nativeValueDownCast(nativeValue[field.name])
|
|
||||||
error("FIELD EXTARCTION FAILED: %s" % field)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def listOfLocals(self, partialVar):
|
def listOfLocals(self, partialVar):
|
||||||
frame = gdb.selected_frame()
|
frame = gdb.selected_frame()
|
||||||
|
|
||||||
@@ -571,20 +559,6 @@ class Dumper(DumperBase):
|
|||||||
return None
|
return None
|
||||||
return self.fromNativeValue(val)
|
return self.fromNativeValue(val)
|
||||||
|
|
||||||
def nativeValueAsBytes(self, nativeValue, size):
|
|
||||||
# Assume it's a (backend specific) Value.
|
|
||||||
if nativeValue.address:
|
|
||||||
return self.readRawMemory(nativeValue.address, size)
|
|
||||||
# No address. Possibly the result of an inferior call.
|
|
||||||
# Note: Only a cast to unsigned char[sizeof(origtype)] succeeds
|
|
||||||
# in this situation in gdb.
|
|
||||||
chars = self.lookupNativeType("unsigned char")
|
|
||||||
y = nativeValue.cast(chars.array(0, int(nativeValue.type.sizeof - 1)))
|
|
||||||
buf = bytearray(struct.pack('x' * size))
|
|
||||||
for i in range(size):
|
|
||||||
buf[i] = int(y[i])
|
|
||||||
return bytes(buf)
|
|
||||||
|
|
||||||
def callHelper(self, rettype, value, function, args):
|
def callHelper(self, rettype, value, function, args):
|
||||||
# args is a tuple.
|
# args is a tuple.
|
||||||
arg = ""
|
arg = ""
|
||||||
@@ -963,47 +937,16 @@ class Dumper(DumperBase):
|
|||||||
cmd = "set variable (%s)=%s" % (expr, value)
|
cmd = "set variable (%s)=%s" % (expr, value)
|
||||||
gdb.execute(cmd)
|
gdb.execute(cmd)
|
||||||
|
|
||||||
def hasVTable(self, typeobj):
|
def nativeDynamicTypeName(self, address, baseType):
|
||||||
fields = typeobj.fields()
|
vtbl = gdb.execute("info symbol {%s*}0x%x" % (baseType.name, address), to_string = True)
|
||||||
if len(fields) == 0:
|
pos1 = vtbl.find("vtable ")
|
||||||
return False
|
if pos1 == -1:
|
||||||
if fields[0].isBaseClass:
|
return None
|
||||||
return hasVTable(fields[0].type)
|
pos1 += 11
|
||||||
return str(fields[0].type) == "int (**)(void)"
|
pos2 = vtbl.find(" +", pos1)
|
||||||
|
if pos2 == -1:
|
||||||
def dynamicTypeName(self, value):
|
return None
|
||||||
if self.hasVTable(value.type):
|
return vtbl[pos1 : pos2]
|
||||||
#vtbl = str(gdb.parse_and_eval("{int(*)(int)}%s" % int(value.address)))
|
|
||||||
try:
|
|
||||||
# Fails on 7.1 due to the missing to_string.
|
|
||||||
vtbl = gdb.execute("info symbol {int*}%s" % int(value.address),
|
|
||||||
to_string = True)
|
|
||||||
pos1 = vtbl.find("vtable ")
|
|
||||||
if pos1 != -1:
|
|
||||||
pos1 += 11
|
|
||||||
pos2 = vtbl.find(" +", pos1)
|
|
||||||
if pos2 != -1:
|
|
||||||
return vtbl[pos1 : pos2]
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return str(value.type)
|
|
||||||
|
|
||||||
def nativeValueDownCast(self, nativeValue):
|
|
||||||
try:
|
|
||||||
return self.fromNativeValue(nativeValue.cast(nativeValue.dynamic_type))
|
|
||||||
except:
|
|
||||||
return self.fromNativeValue(nativeValue)
|
|
||||||
|
|
||||||
def expensiveDowncast(self, value):
|
|
||||||
try:
|
|
||||||
return value.cast(value.dynamic_type)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
return value.cast(self.lookupType(self.dynamicTypeName(value)))
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return value
|
|
||||||
|
|
||||||
def enumExpression(self, enumType, enumValue):
|
def enumExpression(self, enumType, enumValue):
|
||||||
return self.qtNamespace() + "Qt::" + enumValue
|
return self.qtNamespace() + "Qt::" + enumValue
|
||||||
|
@@ -57,20 +57,6 @@ def check(exp):
|
|||||||
if not exp:
|
if not exp:
|
||||||
raise RuntimeError("Check failed")
|
raise RuntimeError("Check failed")
|
||||||
|
|
||||||
def impl_SBValue__add__(self, offset):
|
|
||||||
if self.GetType().IsPointerType():
|
|
||||||
itemsize = self.GetType().GetPointeeType().GetByteSize()
|
|
||||||
address = self.GetValueAsUnsigned() + offset * itemsize
|
|
||||||
address = address & 0xFFFFFFFFFFFFFFFF # Force unsigned
|
|
||||||
return self.CreateValueFromAddress(None, address,
|
|
||||||
self.GetType().GetPointeeType()).AddressOf()
|
|
||||||
|
|
||||||
raise RuntimeError("SBValue.__add__ not implemented: %s" % self.GetType())
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
|
|
||||||
lldb.SBValue.__add__ = impl_SBValue__add__
|
|
||||||
|
|
||||||
class Dumper(DumperBase):
|
class Dumper(DumperBase):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
DumperBase.__init__(self)
|
DumperBase.__init__(self)
|
||||||
@@ -154,15 +140,42 @@ class Dumper(DumperBase):
|
|||||||
|
|
||||||
def fromNativeValue(self, nativeValue):
|
def fromNativeValue(self, nativeValue):
|
||||||
nativeValue.SetPreferSyntheticValue(False)
|
nativeValue.SetPreferSyntheticValue(False)
|
||||||
|
nativeType = nativeValue.GetType()
|
||||||
val = self.Value(self)
|
val = self.Value(self)
|
||||||
val.nativeValue = nativeValue
|
val.type = self.fromNativeType(nativeType)
|
||||||
val.type = self.fromNativeType(nativeValue.type)
|
|
||||||
val.lIsInScope = nativeValue.IsInScope()
|
val.lIsInScope = nativeValue.IsInScope()
|
||||||
#val.name = nativeValue.GetName()
|
#val.name = nativeValue.GetName()
|
||||||
try:
|
data = nativeValue.GetData()
|
||||||
|
error = lldb.SBError()
|
||||||
|
size = nativeValue.GetType().GetByteSize()
|
||||||
|
if size > 0: # Happens regularly e.g. for cross-shared-object types.
|
||||||
|
val.ldata = data.ReadRawData(error, 0, size)
|
||||||
|
code = nativeType.GetTypeClass()
|
||||||
|
if code not in (lldb.eTypeClassPointer, lldb.eTypeClassReference):
|
||||||
val.laddress = int(nativeValue.GetLoadAddress())
|
val.laddress = int(nativeValue.GetLoadAddress())
|
||||||
except:
|
if code == lldb.eTypeClassEnumeration:
|
||||||
pass
|
intval = nativeValue.GetValueAsSigned()
|
||||||
|
if hasattr(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.
|
||||||
|
diff = enumMember.GetValueAsSigned() - intval
|
||||||
|
mask = (1 << nativeType.GetByteSize() * 8) - 1
|
||||||
|
if diff & mask == 0:
|
||||||
|
path = nativeType.GetName().split('::')
|
||||||
|
path[-1] = enumMember.GetName()
|
||||||
|
val.ldisplay = "%s (%d)" % ('::'.join(path), intval)
|
||||||
|
val.ldisplay = "%d" % intval
|
||||||
|
elif code in (lldb.eTypeClassComplexInteger, lldb.eTypeClassComplexFloat):
|
||||||
|
val.ldisplay = str(nativeValue.GetValue())
|
||||||
|
elif code == lldb.eTypeClassArray:
|
||||||
|
if hasattr(nativeType, "GetArrayElementType"): # New in 3.8(?) / 350.x
|
||||||
|
val.type.ltarget = self.fromNativeType(nativeType.GetArrayElementType())
|
||||||
|
else:
|
||||||
|
fields = nativeType.get_fields_array()
|
||||||
|
if len(fields):
|
||||||
|
val.type.ltarget = self.fromNativeType(fields[0])
|
||||||
|
elif code == lldb.eTypeClassVector:
|
||||||
|
val.type.ltarget = self.fromNativeType(nativeType.GetVectorElementType())
|
||||||
return val
|
return val
|
||||||
|
|
||||||
def fromNativeType(self, nativeType):
|
def fromNativeType(self, nativeType):
|
||||||
@@ -217,6 +230,7 @@ class Dumper(DumperBase):
|
|||||||
addr = 0x7fffffffe0a0
|
addr = 0x7fffffffe0a0
|
||||||
sbaddr = lldb.SBAddress(addr, self.target)
|
sbaddr = lldb.SBAddress(addr, self.target)
|
||||||
dummyValue = self.target.CreateValueFromAddress('x', sbaddr, nativeType)
|
dummyValue = self.target.CreateValueFromAddress('x', sbaddr, nativeType)
|
||||||
|
dummyValue.SetPreferSyntheticValue(False)
|
||||||
|
|
||||||
anonNumber = 0
|
anonNumber = 0
|
||||||
|
|
||||||
@@ -246,8 +260,8 @@ class Dumper(DumperBase):
|
|||||||
anonNumber += 1
|
anonNumber += 1
|
||||||
fieldName = "#%s" % anonNumber
|
fieldName = "#%s" % anonNumber
|
||||||
fieldType = dummyChild.GetType()
|
fieldType = dummyChild.GetType()
|
||||||
#warn("CHILD AT: %s: %s %s" % (i, fieldName, fieldType))
|
#warn("CHILD AT: %s: %s %s" % (i, fieldName, fieldType.GetName()))
|
||||||
#warn(" AT: %s: %s %s" % (i, fieldName, fieldType))
|
#warn(" AT: %s: %s %s" % (i, fieldName, fieldType.GetName()))
|
||||||
caddr = dummyChild.AddressOf().GetValueAsUnsigned()
|
caddr = dummyChild.AddressOf().GetValueAsUnsigned()
|
||||||
child = self.Value(self)
|
child = self.Value(self)
|
||||||
child.type = self.fromNativeType(fieldType)
|
child.type = self.fromNativeType(fieldType)
|
||||||
@@ -298,15 +312,6 @@ class Dumper(DumperBase):
|
|||||||
#warn("FIELDS: %s" % fields)
|
#warn("FIELDS: %s" % fields)
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
def nativeValueDereference(self, nativeValue):
|
|
||||||
result = nativeValue.Dereference()
|
|
||||||
if not result.IsValid():
|
|
||||||
return None
|
|
||||||
return self.fromNativeValue(result)
|
|
||||||
|
|
||||||
def nativeValueCast(self, nativeValue, nativeType):
|
|
||||||
return self.fromNativeValue(nativeValue.Cast(nativeType))
|
|
||||||
|
|
||||||
def nativeTypeUnqualified(self, nativeType):
|
def nativeTypeUnqualified(self, nativeType):
|
||||||
return self.fromNativeType(nativeType.GetUnqualifiedType())
|
return self.fromNativeType(nativeType.GetUnqualifiedType())
|
||||||
|
|
||||||
@@ -318,46 +323,6 @@ class Dumper(DumperBase):
|
|||||||
return self.fromNativeType(typeobj.GetCanonicalType())
|
return self.fromNativeType(typeobj.GetCanonicalType())
|
||||||
return self.fromNativeType(typeobj)
|
return self.fromNativeType(typeobj)
|
||||||
|
|
||||||
def nativeValueChildFromNameHelper(self, nativeValue, fieldName):
|
|
||||||
val = nativeValue.GetChildMemberWithName(fieldName)
|
|
||||||
if val.IsValid():
|
|
||||||
return val
|
|
||||||
nativeType = nativeValue.GetType()
|
|
||||||
for i in xrange(nativeType.GetNumberOfDirectBaseClasses()):
|
|
||||||
baseField = nativeType.GetDirectBaseClassAtIndex(i)
|
|
||||||
baseType = baseField.GetType()
|
|
||||||
base = nativeValue.Cast(baseType)
|
|
||||||
val = self.nativeValueChildFromNameHelper(base, fieldName)
|
|
||||||
if val is not None:
|
|
||||||
return val
|
|
||||||
return None
|
|
||||||
|
|
||||||
def nativeValueChildFromField(self, nativeValue, field):
|
|
||||||
val = None
|
|
||||||
if field.isVirtualBase is True:
|
|
||||||
#warn("FETCHING VIRTUAL BASE: %s: %s" % (field.baseIndex, field.name))
|
|
||||||
pass
|
|
||||||
if field.nativeIndex is not None:
|
|
||||||
#warn("FETCHING BY NATIVE INDEX: %s: %s" % (field.nativeIndex, field.name))
|
|
||||||
val = nativeValue.GetChildAtIndex(field.nativeIndex)
|
|
||||||
if val.IsValid():
|
|
||||||
return self.fromNativeValue(val)
|
|
||||||
elif field.baseIndex is not None:
|
|
||||||
baseClass = nativeValue.GetType().GetDirectBaseClassAtIndex(field.baseIndex)
|
|
||||||
if baseClass.IsValid():
|
|
||||||
#warn("BASE IS VALID, TYPE: %s" % baseClass.GetType())
|
|
||||||
#warn("BASE BITPOS: %s" % field.lbitpos)
|
|
||||||
#warn("BASE BITSIZE: %s" % field.lbitsize)
|
|
||||||
# FIXME: This is wrong for virtual bases.
|
|
||||||
return None # Let standard behavior kick in.
|
|
||||||
else:
|
|
||||||
#warn("FETCHING BY NAME: %s: %s" % (field, field.name))
|
|
||||||
val = self.nativeValueChildFromNameHelper(nativeValue, field.name)
|
|
||||||
if val is not None:
|
|
||||||
return self.fromNativeValue(val)
|
|
||||||
raise RuntimeError("No such member '%s' in %s" % (field.name, nativeValue.type))
|
|
||||||
return None
|
|
||||||
|
|
||||||
def nativeTypeFirstBase(self, nativeType):
|
def nativeTypeFirstBase(self, nativeType):
|
||||||
#warn("FIRST BASE FROM: %s" % nativeType)
|
#warn("FIRST BASE FROM: %s" % nativeType)
|
||||||
if nativeType.GetNumberOfDirectBaseClasses() == 0:
|
if nativeType.GetNumberOfDirectBaseClasses() == 0:
|
||||||
@@ -378,6 +343,13 @@ class Dumper(DumperBase):
|
|||||||
return "%s (%d)" % ('::'.join(path), intval)
|
return "%s (%d)" % ('::'.join(path), intval)
|
||||||
return "%d" % intval
|
return "%d" % intval
|
||||||
|
|
||||||
|
def nativeDynamicTypeName(self, address, baseType):
|
||||||
|
return None # FIXME: Seems sufficient, no idea why.
|
||||||
|
addr = self.target.ResolveLoadAddress(address)
|
||||||
|
ctx = self.target.ResolveSymbolContextForAddress(addr, 0)
|
||||||
|
sym = ctx.GetSymbol()
|
||||||
|
return sym.GetName()
|
||||||
|
|
||||||
def stateName(self, s):
|
def stateName(self, s):
|
||||||
try:
|
try:
|
||||||
# See db.StateType
|
# See db.StateType
|
||||||
@@ -480,9 +452,6 @@ class Dumper(DumperBase):
|
|||||||
#warn("INNER: %s" % inner)
|
#warn("INNER: %s" % inner)
|
||||||
return self.lookupType(inner)
|
return self.lookupType(inner)
|
||||||
|
|
||||||
def nativeValueAddressOf(self, nativeValue):
|
|
||||||
return int(value.GetLoadAddress())
|
|
||||||
|
|
||||||
def nativeTypeDereference(self, nativeType):
|
def nativeTypeDereference(self, nativeType):
|
||||||
return self.fromNativeType(nativeType.GetPointeeType())
|
return self.fromNativeType(nativeType.GetPointeeType())
|
||||||
|
|
||||||
@@ -917,15 +886,6 @@ class Dumper(DumperBase):
|
|||||||
return bytes()
|
return bytes()
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def nativeValueAsBytes(self, nativeValue, size):
|
|
||||||
data = nativeValue.GetData()
|
|
||||||
buf = bytearray(struct.pack('x' * size))
|
|
||||||
error = lldb.SBError()
|
|
||||||
#data.ReadRawData(error, 0, buf)
|
|
||||||
for i in range(size):
|
|
||||||
buf[i] = data.GetUnsignedInt8(error, i)
|
|
||||||
return bytes(buf)
|
|
||||||
|
|
||||||
def findStaticMetaObject(self, typeName):
|
def findStaticMetaObject(self, typeName):
|
||||||
symbolName = self.mangleName(typeName + '::staticMetaObject')
|
symbolName = self.mangleName(typeName + '::staticMetaObject')
|
||||||
symbol = self.target.FindFirstGlobalVariable(symbolName)
|
symbol = self.target.FindFirstGlobalVariable(symbolName)
|
||||||
@@ -983,6 +943,7 @@ class Dumper(DumperBase):
|
|||||||
if len(statics):
|
if len(statics):
|
||||||
for i in xrange(len(statics)):
|
for i in xrange(len(statics)):
|
||||||
staticVar = statics[i]
|
staticVar = statics[i]
|
||||||
|
staticVar.SetPreferSyntheticValue(False)
|
||||||
typename = staticVar.GetType().GetName()
|
typename = staticVar.GetType().GetName()
|
||||||
name = staticVar.GetName()
|
name = staticVar.GetName()
|
||||||
with SubItem(self, i):
|
with SubItem(self, i):
|
||||||
@@ -1004,6 +965,7 @@ class Dumper(DumperBase):
|
|||||||
|
|
||||||
variables = []
|
variables = []
|
||||||
for val in values:
|
for val in values:
|
||||||
|
val.SetPreferSyntheticValue(False)
|
||||||
if not val.IsValid():
|
if not val.IsValid():
|
||||||
continue
|
continue
|
||||||
self.currentContextValue = val
|
self.currentContextValue = val
|
||||||
|
@@ -887,11 +887,11 @@ def qdump__QLocale(d, value):
|
|||||||
#d.check(index <= qqLocalesCount)
|
#d.check(index <= qqLocalesCount)
|
||||||
dd = value.extractPointer()
|
dd = value.extractPointer()
|
||||||
ns = d.qtNamespace()
|
ns = d.qtNamespace()
|
||||||
(data, ref, numberOptions) = d.split("pi{int}", dd)
|
(data, ref, numberOptions) = d.split("pi4s", dd)
|
||||||
(languageId, scriptId, countryId,
|
(languageId, scriptId, countryId,
|
||||||
decimal, group, listt, percent, zero,
|
decimal, group, listt, percent, zero,
|
||||||
minus, plus, exponential) \
|
minus, plus, exponential) \
|
||||||
= d.split('{short}{short}{QChar}'
|
= d.split('2s{short}2s'
|
||||||
+ '{QChar}{QChar}{short}{QChar}{QChar}'
|
+ '{QChar}{QChar}{short}{QChar}{QChar}'
|
||||||
+ '{QChar}{QChar}{QChar}', data)
|
+ '{QChar}{QChar}{QChar}', data)
|
||||||
d.putStringValue(d.call("const char *", value, "name"))
|
d.putStringValue(d.call("const char *", value, "name"))
|
||||||
@@ -899,9 +899,9 @@ def qdump__QLocale(d, value):
|
|||||||
if d.isExpanded():
|
if d.isExpanded():
|
||||||
with Children(d):
|
with Children(d):
|
||||||
prefix = ns + "QLocale::"
|
prefix = ns + "QLocale::"
|
||||||
d.putSubItem("country", countryId.extend(4).cast(prefix + "Country"))
|
d.putSubItem("country", d.createValue(countryId, prefix + "Country"))
|
||||||
d.putSubItem("language", languageId.extend(4).cast(prefix + "Language"))
|
d.putSubItem("language", d.createValue(languageId, prefix + "Language"))
|
||||||
d.putSubItem("numberOptions", numberOptions.cast(prefix + "NumberOptions"))
|
d.putSubItem("numberOptions", d.createValue(numberOptions, prefix + "NumberOptions"))
|
||||||
d.putSubItem("decimalPoint", decimal)
|
d.putSubItem("decimalPoint", decimal)
|
||||||
d.putSubItem("exponential", exponential)
|
d.putSubItem("exponential", exponential)
|
||||||
d.putSubItem("percent", percent)
|
d.putSubItem("percent", percent)
|
||||||
@@ -1189,7 +1189,7 @@ def qdump__QSet(d, value):
|
|||||||
typeCode = 'Pi@{%s}' % keyType.name
|
typeCode = 'Pi@{%s}' % keyType.name
|
||||||
(pnext, hashval, padding1, key) = d.split(typeCode, node)
|
(pnext, hashval, padding1, key) = d.split(typeCode, node)
|
||||||
with SubItem(d, i):
|
with SubItem(d, i):
|
||||||
d.putItem(key, i)
|
d.putItem(key)
|
||||||
node = hashDataNextNode(node)
|
node = hashDataNextNode(node)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -227,12 +227,11 @@ def qdump__std__map(d, value):
|
|||||||
pairPointer = pairType.pointer()
|
pairPointer = pairType.pointer()
|
||||||
with PairedChildren(d, size, pairType=pairType, maxNumChild=1000):
|
with PairedChildren(d, size, pairType=pairType, maxNumChild=1000):
|
||||||
node = impl["_M_header"]["_M_left"]
|
node = impl["_M_header"]["_M_left"]
|
||||||
typeCode = "p@{%s}@{%s}" % (pairType[0].name, pairType[1].name)
|
nodeSize = node.dereference().type.size()
|
||||||
|
typeCode = "@{%s}@{%s}" % (pairType[0].name, pairType[1].name)
|
||||||
for i in d.childRange():
|
for i in d.childRange():
|
||||||
pair = (node + 1).cast(pairPointer).dereference()
|
(pad1, key, pad2, value) = d.split(typeCode, node.pointer() + nodeSize)
|
||||||
d.putPairItem(i, pair)
|
d.putPairItem(i, (key, value))
|
||||||
#(pp, pad1, key, pad2, value) = d.split(typeCode, node.integer())
|
|
||||||
#d.putPairItem(i, (key, value))
|
|
||||||
if node["_M_right"].integer() == 0:
|
if node["_M_right"].integer() == 0:
|
||||||
parent = node["_M_parent"]
|
parent = node["_M_parent"]
|
||||||
while True:
|
while True:
|
||||||
@@ -384,9 +383,12 @@ def qdump__std__set(d, value):
|
|||||||
if d.isExpanded():
|
if d.isExpanded():
|
||||||
valueType = value.type[0]
|
valueType = value.type[0]
|
||||||
node = impl["_M_header"]["_M_left"]
|
node = impl["_M_header"]["_M_left"]
|
||||||
|
nodeSize = node.dereference().type.size()
|
||||||
|
typeCode = "@{%s}" % valueType.name
|
||||||
with Children(d, size, maxNumChild=1000, childType=valueType):
|
with Children(d, size, maxNumChild=1000, childType=valueType):
|
||||||
for i in d.childRange():
|
for i in d.childRange():
|
||||||
d.putSubItem(i, (node + 1).cast(valueType.pointer()).dereference())
|
(pad, val) = d.split(typeCode, node.pointer() + nodeSize)
|
||||||
|
d.putSubItem(i, val)
|
||||||
if node["_M_right"].integer() == 0:
|
if node["_M_right"].integer() == 0:
|
||||||
parent = node["_M_parent"]
|
parent = node["_M_parent"]
|
||||||
while node == parent["_M_right"]:
|
while node == parent["_M_right"]:
|
||||||
|
@@ -4106,34 +4106,34 @@ void tst_Dumpers::dumper_data()
|
|||||||
+ CoreProfile()
|
+ CoreProfile()
|
||||||
|
|
||||||
+ Check("map1", "<3 items>", "std::map<@QString, Foo>")
|
+ Check("map1", "<3 items>", "std::map<@QString, Foo>")
|
||||||
+ Check("map1.0", "[0]", "", "std::pair<@QString const, Foo>")
|
+ Check("map1.0", "[0] \"22.0\"", "", "std::pair<@QString const, Foo>")
|
||||||
+ Check("map1.0.first", "\"22.0\"", "@QString")
|
+ Check("map1.0.first", "\"22.0\"", "@QString")
|
||||||
+ Check("map1.0.second", "", "Foo")
|
+ Check("map1.0.second", "", "Foo")
|
||||||
+ Check("map1.0.second.a", "22", "int")
|
+ Check("map1.0.second.a", "22", "int")
|
||||||
+ Check("map1.1", "[1]", "", "std::pair<@QString const, Foo>")
|
+ Check("map1.1", "[1] \"33.0\"", "", "std::pair<@QString const, Foo>")
|
||||||
+ Check("map1.2.first", "\"44.0\"", "@QString")
|
+ Check("map1.2.first", "\"44.0\"", "@QString")
|
||||||
+ Check("map1.2.second", "", "Foo")
|
+ Check("map1.2.second", "", "Foo")
|
||||||
+ Check("map1.2.second.a", "44", "int")
|
+ Check("map1.2.second.a", "44", "int")
|
||||||
|
|
||||||
+ Check("map2", "<2 items>", "std::map<char const*, Foo>")
|
+ Check("map2", "<2 items>", "std::map<char const*, Foo>")
|
||||||
+ Check("map2.0", "[0]", "", "std::pair<char const* const, Foo>")
|
+ Check("map2.0", "[0] \"22.0\"", "", "std::pair<char const* const, Foo>")
|
||||||
+ CheckType("map2.0.first", "char *")
|
+ CheckType("map2.0.first", "char *")
|
||||||
// FIXME
|
// FIXME
|
||||||
//+ Check("map2.0.first.0", "50", "char")
|
//+ Check("map2.0.first.0", "50", "char")
|
||||||
+ Check("map2.0.second", "", "Foo")
|
+ Check("map2.0.second", "", "Foo")
|
||||||
+ Check("map2.0.second.a", "22", "int")
|
+ Check("map2.0.second.a", "22", "int")
|
||||||
+ Check("map2.1", "[1]", "", "std::pair<char const* const, Foo>")
|
+ Check("map2.1", "[1] \"33.0\"", "", "std::pair<char const* const, Foo>")
|
||||||
+ CheckType("map2.1.first", "char *")
|
+ CheckType("map2.1.first", "char *")
|
||||||
//+ Check("map2.1.first.*first", "51 '3'", "char")
|
//+ Check("map2.1.first.*first", "51 '3'", "char")
|
||||||
+ Check("map2.1.second", "", "Foo")
|
+ Check("map2.1.second", "", "Foo")
|
||||||
+ Check("map2.1.second.a", "33", "int")
|
+ Check("map2.1.second.a", "33", "int")
|
||||||
|
|
||||||
+ Check("map3", "<2 items>", "std::map<unsigned int, @QStringList>")
|
+ Check("map3", "<2 items>", "std::map<unsigned int, @QStringList>")
|
||||||
+ Check("map3.0", "[0]", "", "std::pair<unsigned int const, @QStringList>")
|
+ Check("map3.0", "[0] 11", "<1 items>", "std::pair<unsigned int const, @QStringList>")
|
||||||
+ Check("map3.0.first", "11", "unsigned int")
|
+ Check("map3.0.first", "11", "unsigned int")
|
||||||
+ Check("map3.0.second", "<1 items>", "@QStringList")
|
+ Check("map3.0.second", "<1 items>", "@QStringList")
|
||||||
+ Check("map3.0.second.0", "[0]", "\"11\"", "@QString")
|
+ Check("map3.0.second.0", "[0]", "\"11\"", "@QString")
|
||||||
+ Check("map3.1", "[1]", "", "std::pair<unsigned int const, @QStringList>")
|
+ Check("map3.1", "[1] 22", "<1 items>", "std::pair<unsigned int const, @QStringList>")
|
||||||
+ Check("map3.1.first", "22", "unsigned int")
|
+ Check("map3.1.first", "22", "unsigned int")
|
||||||
+ Check("map3.1.second", "<1 items>", "@QStringList")
|
+ Check("map3.1.second", "<1 items>", "@QStringList")
|
||||||
+ Check("map3.1.second.0", "[0]", "\"22\"", "@QString")
|
+ Check("map3.1.second.0", "[0]", "\"22\"", "@QString")
|
||||||
@@ -4141,26 +4141,26 @@ void tst_Dumpers::dumper_data()
|
|||||||
+ Check("map4.1.second.0", "[0]", "\"22\"", "@QString")
|
+ Check("map4.1.second.0", "[0]", "\"22\"", "@QString")
|
||||||
|
|
||||||
+ Check("map5", "<2 items>", "std::map<@QString, float>")
|
+ Check("map5", "<2 items>", "std::map<@QString, float>")
|
||||||
+ Check("map5.0", "[0]", "", "std::pair<@QString const, float>")
|
+ Check("map5.0", "[0] \"11.0\"", FloatValue("11"), "std::pair<@QString const, float>")
|
||||||
+ Check("map5.0.first", "\"11.0\"", "@QString")
|
+ Check("map5.0.first", "\"11.0\"", "@QString")
|
||||||
+ Check("map5.0.second", FloatValue("11"), "float")
|
+ Check("map5.0.second", FloatValue("11"), "float")
|
||||||
+ Check("map5.1", "[1]", "", "std::pair<@QString const, float>")
|
+ Check("map5.1", "[1] \"22.0\"", FloatValue("22"), "std::pair<@QString const, float>")
|
||||||
+ Check("map5.1.first", "\"22.0\"", "@QString")
|
+ Check("map5.1.first", "\"22.0\"", "@QString")
|
||||||
+ Check("map5.1.second", FloatValue("22"), "float")
|
+ Check("map5.1.second", FloatValue("22"), "float")
|
||||||
|
|
||||||
+ Check("map6", "<2 items>", "std::map<int, @QString>")
|
+ Check("map6", "<2 items>", "std::map<int, @QString>")
|
||||||
+ Check("map6.0", "[0]", "", "std::pair<int const, @QString>")
|
+ Check("map6.0", "[0] 11", "\"11.0\"", "std::pair<int const, @QString>")
|
||||||
+ Check("map6.0.first", "11", "int")
|
+ Check("map6.0.first", "11", "int")
|
||||||
+ Check("map6.0.second", "\"11.0\"", "@QString")
|
+ Check("map6.0.second", "\"11.0\"", "@QString")
|
||||||
+ Check("map6.1", "[1]", "", "std::pair<int const, @QString>")
|
+ Check("map6.1", "[1] 22", "\"22.0\"", "std::pair<int const, @QString>")
|
||||||
+ Check("map6.1.first", "22", "int")
|
+ Check("map6.1.first", "22", "int")
|
||||||
+ Check("map6.1.second", "\"22.0\"", "@QString")
|
+ Check("map6.1.second", "\"22.0\"", "@QString")
|
||||||
|
|
||||||
+ Check("map7", "<3 items>", "std::map<@QString, @QPointer<@QObject>>")
|
+ Check("map7", "<3 items>", "std::map<@QString, @QPointer<@QObject>>")
|
||||||
+ Check("map7.0", "[0]", "", "std::pair<@QString const, @QPointer<@QObject>>")
|
+ Check("map7.0", "[0] \".\"", "", "std::pair<@QString const, @QPointer<@QObject>>")
|
||||||
+ Check("map7.0.first", "\".\"", "@QString")
|
+ Check("map7.0.first", "\".\"", "@QString")
|
||||||
+ Check("map7.0.second", "", "@QPointer<@QObject>")
|
+ Check("map7.0.second", "", "@QPointer<@QObject>")
|
||||||
+ Check("map7.2", "[2]", "", "std::pair<@QString const, @QPointer<@QObject>>")
|
+ Check("map7.2", "[2] \"Welt\"", "", "std::pair<@QString const, @QPointer<@QObject>>")
|
||||||
+ Check("map7.2.first", "\"Welt\"", "@QString");
|
+ Check("map7.2.first", "\"Welt\"", "@QString");
|
||||||
|
|
||||||
|
|
||||||
@@ -4948,9 +4948,10 @@ void tst_Dumpers::dumper_data()
|
|||||||
QTest::newRow("Bitfields")
|
QTest::newRow("Bitfields")
|
||||||
<< Data("struct S\n"
|
<< Data("struct S\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" S() : x(2), y(3), c(1), b(0), f(5), d(6), i(7) {}\n"
|
" S() : x(2), y(3), z(39), c(1), b(0), f(5), d(6), i(7) {}\n"
|
||||||
" unsigned int x : 3;\n"
|
" unsigned int x : 3;\n"
|
||||||
" unsigned int y : 4;\n"
|
" unsigned int y : 4;\n"
|
||||||
|
" unsigned int z : 18;\n"
|
||||||
" bool c : 1;\n"
|
" bool c : 1;\n"
|
||||||
" bool b;\n"
|
" bool b;\n"
|
||||||
" float f;\n"
|
" float f;\n"
|
||||||
@@ -4966,7 +4967,8 @@ void tst_Dumpers::dumper_data()
|
|||||||
+ Check("s.d", FloatValue("6"), "double")
|
+ Check("s.d", FloatValue("6"), "double")
|
||||||
+ Check("s.i", "7", "int")
|
+ Check("s.i", "7", "int")
|
||||||
+ Check("s.x", "2", "unsigned int")
|
+ Check("s.x", "2", "unsigned int")
|
||||||
+ Check("s.y", "3", "unsigned int");
|
+ Check("s.y", "3", "unsigned int")
|
||||||
|
+ Check("s.z", "39", "unsigned int");
|
||||||
|
|
||||||
|
|
||||||
QTest::newRow("Function")
|
QTest::newRow("Function")
|
||||||
|
Reference in New Issue
Block a user