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:
|
||||
name() -> string # Full name of this type
|
||||
bitsize() -> int # Size of type in bits
|
||||
arrayType() -> bool # Is this an array?
|
||||
pointerType() -> bool # Is this a pointer
|
||||
referenceType() -> bool # ...
|
||||
functionType() -> bool
|
||||
typedefedType() -> bool
|
||||
enumType() -> bool
|
||||
integralType() -> bool
|
||||
floatingPointType() -> bool
|
||||
code() -> TypeCodeTypedef
|
||||
| TypeCodeStruct
|
||||
| TypeCodeVoid
|
||||
| TypeCodeIntegral
|
||||
| TypeCodeFloat
|
||||
| TypeCodeEnum
|
||||
| TypeCodePointer
|
||||
| TypeCodeArray
|
||||
| TypeCodeComplex
|
||||
| TypeCodeReference
|
||||
| TypeCodeFunction
|
||||
| TypeCodeMemberPointer
|
||||
|
||||
unqualified() -> Type # Type without const/volatile
|
||||
target() -> Type # Type dereferenced if it is a pointer type, element if array etc
|
||||
|
@@ -212,8 +212,7 @@ class Children:
|
||||
return True
|
||||
|
||||
class PairedChildrenData:
|
||||
def __init__(self, d, pairType, keyType, valueType, useKeyAndValue):
|
||||
self.useKeyAndValue = useKeyAndValue
|
||||
def __init__(self, d, pairType, keyType, valueType):
|
||||
self.pairType = pairType
|
||||
self.keyType = keyType
|
||||
self.valueType = valueType
|
||||
@@ -228,7 +227,9 @@ class PairedChildren(Children):
|
||||
keyType = pairType[0].unqualified()
|
||||
if valueType is None:
|
||||
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,
|
||||
d.pairData.childType,
|
||||
@@ -671,7 +672,10 @@ class DumperBase:
|
||||
|
||||
def putIntItem(self, name, value):
|
||||
with SubItem(self, name):
|
||||
self.putValue(value)
|
||||
if isinstance(value, self.Value):
|
||||
self.putValue(value.display())
|
||||
else:
|
||||
self.putValue(value)
|
||||
self.putType("int")
|
||||
self.putNumChild(0)
|
||||
|
||||
@@ -682,28 +686,23 @@ class DumperBase:
|
||||
self.putNumChild(0)
|
||||
|
||||
def putPairItem(self, index, pair):
|
||||
if isinstance(pair, tuple):
|
||||
(first, second) = pair
|
||||
elif self.pairData.useKeyAndValue:
|
||||
(first, second) = (pair["key"], pair["value"])
|
||||
else:
|
||||
(first, second) = (pair["first"], pair["second"])
|
||||
|
||||
(first, second) = pair if isinstance(pair, tuple) else pair.members()
|
||||
with SubItem(self, index):
|
||||
self.putNumChild(2)
|
||||
(keystr, keyenc, valstr, valenc) = (None, None, None, None)
|
||||
with Children(self):
|
||||
with SubItem(self, "key"):
|
||||
self.putItem(first, True)
|
||||
with SubItem(self, self.pairData.kname):
|
||||
self.putItem(first)
|
||||
keystr = self.currentValue.value
|
||||
keyenc = self.currentValue.encoding
|
||||
with SubItem(self, "value"):
|
||||
self.putItem(second, True)
|
||||
with SubItem(self, self.pairData.vname):
|
||||
self.putItem(second)
|
||||
valstr = self.currentValue.value
|
||||
valenc = self.currentValue.encoding
|
||||
if index is not None:
|
||||
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)
|
||||
|
||||
def putCallItem(self, name, rettype, value, func, *args):
|
||||
@@ -713,9 +712,8 @@ class DumperBase:
|
||||
except Exception as error:
|
||||
if self.passExceptions:
|
||||
raise error
|
||||
else:
|
||||
children = [('error', error)]
|
||||
self.putSpecialValue("notcallable", children=children)
|
||||
children = [('error', error)]
|
||||
self.putSpecialValue("notcallable", children=children)
|
||||
else:
|
||||
self.putItem(result)
|
||||
|
||||
@@ -772,7 +770,7 @@ class DumperBase:
|
||||
self.put('name="[%s]",' % field.name)
|
||||
self.put('sortgroup="%s"' % (1000 - field.baseIndex))
|
||||
self.putAddress(baseValue.address())
|
||||
self.putItem(baseValue, False)
|
||||
self.putItem(baseValue)
|
||||
continue
|
||||
|
||||
with SubItem(self, field.name):
|
||||
@@ -1004,9 +1002,8 @@ class DumperBase:
|
||||
|
||||
def putCStyleArray(self, value):
|
||||
arrayType = value.type.unqualified()
|
||||
if self.isGdb and value.nativeValue is not None:
|
||||
innerType = self.fromNativeType(value.nativeValue[0].type)
|
||||
else:
|
||||
innerType = arrayType.ltarget
|
||||
if innerType is None:
|
||||
innerType = value.type.target()
|
||||
innerTypeName = innerType.unqualified().name
|
||||
address = value.address()
|
||||
@@ -1332,22 +1329,22 @@ class DumperBase:
|
||||
# warn("NO QOBJECT: %s" % value.type)
|
||||
pass
|
||||
|
||||
def couldBeQObject(self, objectPtr):
|
||||
def canBePointer(p):
|
||||
if self.ptrSize() == 4:
|
||||
return p > 100000 and (p & 0x3 == 0)
|
||||
else:
|
||||
return p > 100000 and (p & 0x7 == 0) and (p < 0x7fffffffffff)
|
||||
def canBePointer(self, p):
|
||||
if self.ptrSize() == 4:
|
||||
return p > 100000 and (p & 0x3 == 0)
|
||||
else:
|
||||
return p > 100000 and (p & 0x7 == 0) and (p < 0x7fffffffffff)
|
||||
|
||||
def couldBeQObject(self, objectPtr):
|
||||
try:
|
||||
(vtablePtr, dd) = self.split('pp', objectPtr)
|
||||
except:
|
||||
self.bump("nostruct-1")
|
||||
return False
|
||||
if not canBePointer(vtablePtr):
|
||||
if not self.canBePointer(vtablePtr):
|
||||
self.bump("vtable")
|
||||
return False
|
||||
if not canBePointer(dd):
|
||||
if not self.canBePointer(dd):
|
||||
self.bump("d_d_ptr")
|
||||
return False
|
||||
|
||||
@@ -1358,7 +1355,7 @@ class DumperBase:
|
||||
self.bump("nostruct-2")
|
||||
return False
|
||||
#warn("STRUCT DD: %s 0x%x" % (self.currentIName, qptr))
|
||||
if not canBePointer(dvtablePtr):
|
||||
if not self.canBePointer(dvtablePtr):
|
||||
self.bump("dvtable")
|
||||
#warn("DVT: 0x%x" % dvtablePtr)
|
||||
return False
|
||||
@@ -1367,11 +1364,11 @@ class DumperBase:
|
||||
#warn("QPTR: 0x%x 0x%x" % (qptr, objectPtr))
|
||||
self.bump("q_ptr")
|
||||
return False
|
||||
if parentPtr and not canBePointer(parentPtr):
|
||||
if parentPtr and not self.canBePointer(parentPtr):
|
||||
#warn("PAREN")
|
||||
self.bump("parent")
|
||||
return False
|
||||
if not canBePointer(childrenDPtr):
|
||||
if not self.canBePointer(childrenDPtr):
|
||||
#warn("CHILD")
|
||||
self.bump("children")
|
||||
return False
|
||||
@@ -1380,7 +1377,7 @@ class DumperBase:
|
||||
# self.bump("flags")
|
||||
# return False
|
||||
#warn("OK")
|
||||
#if dynMetaObjectPtr and not canBePointer(dynMetaObjectPtr):
|
||||
#if dynMetaObjectPtr and not self.canBePointer(dynMetaObjectPtr):
|
||||
# self.bump("dynmo")
|
||||
# return False
|
||||
|
||||
@@ -1926,13 +1923,13 @@ class DumperBase:
|
||||
displayFormat = self.typeformats.get(needle, AutomaticFormat)
|
||||
return displayFormat
|
||||
|
||||
def putSubItem(self, component, value, tryDynamic=True):
|
||||
def putSubItem(self, component, value):
|
||||
if not isinstance(value, self.Value):
|
||||
error("WRONG VALUE TYPE IN putSubItem: %s" % type(value))
|
||||
if not isinstance(value.type, self.Type):
|
||||
error("WRONG TYPE TYPE IN putSubItem: %s" % type(value.type))
|
||||
with SubItem(self, component):
|
||||
self.putItem(value, tryDynamic)
|
||||
self.putItem(value)
|
||||
|
||||
def putArrayData(self, base, n, innerType, childNumChild = None, maxNumChild = 10000):
|
||||
self.checkIntType(base)
|
||||
@@ -2431,20 +2428,17 @@ class DumperBase:
|
||||
return True
|
||||
return False
|
||||
|
||||
def putItem(self, value, tryDynamic=True):
|
||||
def putItem(self, value):
|
||||
#warn("ITEM: %s" % value.stringify())
|
||||
|
||||
typeobj = value.type #unqualified()
|
||||
typeName = typeobj.name
|
||||
|
||||
tryDynamic &= self.useDynamicType
|
||||
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.putValue("optimizedout: %s" % value.nativeValue)
|
||||
#self.putType(typeobj)
|
||||
#self.putSpecialValue('outofscope')
|
||||
self.putNumChild(0)
|
||||
@@ -2500,50 +2494,13 @@ class DumperBase:
|
||||
return
|
||||
|
||||
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:
|
||||
targetType = value.type.target()
|
||||
item = value.cast(targetType.pointer()).dereference()
|
||||
self.putItem(item)
|
||||
self.putBetterType(value.type.name)
|
||||
return
|
||||
|
||||
item = value.cast(typeobj.target().pointer()).dereference()
|
||||
else:
|
||||
if tryDynamic:
|
||||
try:
|
||||
# Dynamic references are not supported by gdb, see
|
||||
# http://sourceware.org/bugzilla/show_bug.cgi?id=14077.
|
||||
# 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
|
||||
item = value.cast(typeobj.target().unqualified())
|
||||
self.putItem(item)
|
||||
self.putBetterType(typeobj.name)
|
||||
return
|
||||
|
||||
if typeobj.code == TypeCodeComplex:
|
||||
self.putType(typeobj)
|
||||
@@ -2625,8 +2582,8 @@ class DumperBase:
|
||||
self.type = None
|
||||
self.ldata = None
|
||||
self.laddress = None
|
||||
self.nativeValue = None
|
||||
self.lIsInScope = True
|
||||
self.ldisplay = None
|
||||
|
||||
def check(self):
|
||||
if self.laddress is not None and not self.dumper.isInt(self.laddress):
|
||||
@@ -2639,11 +2596,9 @@ class DumperBase:
|
||||
return self.stringify()
|
||||
|
||||
def stringify(self):
|
||||
self.check()
|
||||
addr = "None" if self.laddress is None else ("0x%x" % self.laddress)
|
||||
return "Value(name='%s',type=%s,data=%s,address=%s,nativeValue=%s)" \
|
||||
% (self.name, self.type.stringify(), self.dumper.hexencode(self.ldata),
|
||||
addr, self.nativeValue)
|
||||
return "Value(name='%s',type=%s,data=%s,address=%s)" \
|
||||
% (self.name, self.type.stringify(), self.dumper.hexencode(self.ldata), addr)
|
||||
|
||||
def display(self):
|
||||
if self.type.code == TypeCodeEnum:
|
||||
@@ -2651,21 +2606,14 @@ class DumperBase:
|
||||
simple = self.value()
|
||||
if simple is not None:
|
||||
return str(simple)
|
||||
if self.type.code == TypeCodeComplex:
|
||||
if self.nativeValue is not None:
|
||||
if self.dumper.isLldb:
|
||||
return str(self.nativeValue.GetValue())
|
||||
else:
|
||||
return str( self.nativeValue)
|
||||
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.ldisplay is not None:
|
||||
return self.ldisplay
|
||||
#if self.ldata is not None:
|
||||
# if sys.version_info[0] == 2 and isinstance(self.ldata, buffer):
|
||||
# return bytes(self.ldata).encode("hex")
|
||||
# return self.ldata.encode("hex")
|
||||
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>"
|
||||
|
||||
def simpleDisplay(self, showAddress=True):
|
||||
@@ -2741,66 +2689,52 @@ class DumperBase:
|
||||
return self.extractField(field)
|
||||
|
||||
def extractField(self, field):
|
||||
#warn("PARENT BASE 0x%x" % self.address())
|
||||
if self.type.code == TypeCodeTypedef:
|
||||
error("WRONG")
|
||||
self.dumper.check(self.type.code != TypeCodeTypedef)
|
||||
if not isinstance(field, self.dumper.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)
|
||||
fieldType = field.fieldType()
|
||||
fieldBitsize = field.bitsize()
|
||||
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.type = fieldType
|
||||
val.name = field.name
|
||||
val = self.dumper.Value(self.dumper)
|
||||
val.name = field.name
|
||||
|
||||
if self.laddress is not None:
|
||||
#warn("ADDRESS")
|
||||
fieldBitpos = field.bitpos()
|
||||
fieldOffset = None if fieldBitpos is None else fieldBitpos >> 3
|
||||
if fieldBitpos is not None:
|
||||
#warn("BITPOS: %s" % fieldBitpos)
|
||||
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")
|
||||
if self.laddress is not None:
|
||||
val.laddress = self.laddress + fieldOffset
|
||||
elif self.ldata is not None:
|
||||
val.ldata = self.ldata[fieldOffset:fieldOffset + fieldSize]
|
||||
else:
|
||||
self.dumper.check(False)
|
||||
|
||||
#warn("BITPOS %s BITSIZE: %s" % (fieldBitpos, fieldBitsize))
|
||||
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 = data >> (fieldBitpos & 3)
|
||||
data = data >> fieldBitpos
|
||||
data = data & ((1 << fieldBitsize) - 1)
|
||||
val.laddress = None
|
||||
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))
|
||||
val.check()
|
||||
val.lbitsize = field.bitsize()
|
||||
val.lbitsize = fieldBitsize
|
||||
return val
|
||||
|
||||
def members(self):
|
||||
@@ -2813,37 +2747,25 @@ class DumperBase:
|
||||
def __add__(self, other):
|
||||
self.check()
|
||||
if self.dumper.isInt(other):
|
||||
#warn("OTHER INT: %s" % other)
|
||||
if self.nativeValue is not None:
|
||||
#warn("OTHER NATIVE: %s" % self.nativeValue)
|
||||
#warn("OTHER RESULT 1: %s" % (self.nativeValue + other))
|
||||
res = self.dumper.fromNativeValue(self.nativeValue + other)
|
||||
#warn("OTHER RESULT 2: %s" % (self.nativeValue + other))
|
||||
#warn("OTHER COOKED: 0x%x" % res.pointer())
|
||||
#warn("OTHER COOKED X: 0x%x" % res.nativeValue)
|
||||
return res
|
||||
stripped = self.type.stripTypedefs()
|
||||
if stripped.code == TypeCodePointer:
|
||||
address = self.pointer() + stripped.dereference().size()
|
||||
val = self.dumper.Value(self.dumper)
|
||||
val.laddress = None
|
||||
val.ldata = bytes(struct.pack('Q', address))
|
||||
val.type = self.type
|
||||
return val
|
||||
error("BAD DATA TO ADD TO: %s %s" % (self.type, other))
|
||||
|
||||
def dereference(self):
|
||||
self.check()
|
||||
if self.nativeValue is not None:
|
||||
res = self.dumper.nativeValueDereference(self.nativeValue)
|
||||
if res is not None:
|
||||
return res
|
||||
if self.laddress is not None:
|
||||
val = self.dumper.Value(self.dumper)
|
||||
val.type = self.type.dereference()
|
||||
#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)))
|
||||
val = self.dumper.Value(self.dumper)
|
||||
val.type = self.type.dereference()
|
||||
val.laddress = self.pointer()
|
||||
dynTypeName = self.dumper.dynamicTypeName(val.type, val.laddress)
|
||||
if dynTypeName is not None:
|
||||
val.type = self.dumper.createType(dynTypeName)
|
||||
return val
|
||||
|
||||
def extend(self, size):
|
||||
if self.type.size() < size:
|
||||
@@ -2860,28 +2782,16 @@ class DumperBase:
|
||||
|
||||
def cast(self, typish):
|
||||
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.laddress = self.laddress
|
||||
val.ldata = self.ldata
|
||||
val.type = typeobj
|
||||
#warn("CAST %s %s" % (self.type.stringify(), typeobj.stringify()))
|
||||
val.type = self.dumper.createType(typish)
|
||||
return val
|
||||
|
||||
def downcast(self):
|
||||
self.check()
|
||||
if self.nativeValue is not None:
|
||||
return self.dumper.nativeValueDownCast(self.nativeValue)
|
||||
return self
|
||||
|
||||
def isInScope(self):
|
||||
return self.lIsInScope
|
||||
|
||||
def address(self):
|
||||
self.check()
|
||||
return self.laddress
|
||||
@@ -2896,38 +2806,28 @@ class DumperBase:
|
||||
return self.ldata
|
||||
if size < len(self.ldata):
|
||||
return self.ldata[:size]
|
||||
error("DATA PRESENT, BUT NOT BIG ENOUGH: %s WANT: %s"
|
||||
% (self.stringify(), size))
|
||||
if self.laddress is not None:
|
||||
if size is None:
|
||||
size = self.type.size()
|
||||
res = self.dumper.readRawMemory(self.laddress, size)
|
||||
if len(res) > 0:
|
||||
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)
|
||||
|
||||
def extractInteger(self, bitsize, unsigned):
|
||||
self.check()
|
||||
size = (bitsize + 7) >> 3
|
||||
if size == 8:
|
||||
if bitsize > 32:
|
||||
size = 8
|
||||
code = "Q" if unsigned else "q"
|
||||
elif size == 4:
|
||||
elif bitsize > 16:
|
||||
size = 4
|
||||
code = "I" if unsigned else "i"
|
||||
elif size == 2:
|
||||
elif bitsize > 8:
|
||||
size = 2
|
||||
code = "H" if unsigned else "h"
|
||||
elif size == 1:
|
||||
code = "B" if unsigned else "b"
|
||||
else:
|
||||
code = None
|
||||
if code is None:
|
||||
return None
|
||||
size = 1
|
||||
code = "B" if unsigned else "b"
|
||||
rawBytes = self.data(size)
|
||||
try:
|
||||
return struct.unpack_from(code, rawBytes, 0)[0]
|
||||
@@ -2971,6 +2871,18 @@ class DumperBase:
|
||||
ptr = p if self.isInt(p) else p.pointer()
|
||||
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:
|
||||
def __init__(self, dumper):
|
||||
self.dumper = dumper
|
||||
@@ -2979,6 +2891,7 @@ class DumperBase:
|
||||
self.lfields = None
|
||||
self.lbitsize = None
|
||||
self.lbitpos = None
|
||||
self.ltarget = None # Inner type for arrays
|
||||
self.templateArguments = None
|
||||
self.code = None
|
||||
|
||||
@@ -3206,7 +3119,9 @@ class DumperBase:
|
||||
def __str__(self):
|
||||
return ("Field(name='%s',ltype=%s,parentType=%s,bpos=%s,bsize=%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.baseIndex, self.nativeIndex)
|
||||
|
||||
@@ -3294,32 +3209,22 @@ class DumperBase:
|
||||
#warn("CREATE TYPE: %s" % typeobj)
|
||||
typeobj.check()
|
||||
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))
|
||||
|
||||
def createValue(self, datish, typish):
|
||||
val = self.Value(self)
|
||||
val.type = self.createType(typish)
|
||||
if self.isInt(datish): # Used as address.
|
||||
#warn("CREATING %s AT 0x%x" % (typish, address))
|
||||
val = self.Value(self)
|
||||
val.laddress = datish
|
||||
val.type = self.createType(typish)
|
||||
val.check()
|
||||
return val
|
||||
if isinstance(datish, bytes):
|
||||
#warn("CREATING %s WITH DATA %s" % (typish, self.hexencode(datish)))
|
||||
val = self.Value(self)
|
||||
#warn("CREATING %s AT 0x%x" % (val.type.name, address))
|
||||
elif isinstance(datish, bytes):
|
||||
val.ldata = datish
|
||||
val.type = self.createType(typish)
|
||||
val.type.lbitsize = 8 * len(datish)
|
||||
val.check()
|
||||
return val
|
||||
error("EXPECTING ADDRESS OR BYTES, GOT %s" % type(datish))
|
||||
#warn("CREATING %s WITH DATA %s" % (val.type.name, self.hexencode(datish)))
|
||||
else:
|
||||
error("EXPECTING ADDRESS OR BYTES, GOT %s" % type(datish))
|
||||
val.check()
|
||||
return val
|
||||
|
||||
def createListItem(self, data, innerTypish):
|
||||
innerType = self.createType(innerTypish)
|
||||
|
@@ -248,13 +248,32 @@ class Dumper(DumperBase):
|
||||
return self.fromNativeValue(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.nativeValue = nativeValue
|
||||
if not nativeValue.address is None:
|
||||
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
|
||||
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
|
||||
|
||||
def fromNativeType(self, nativeType):
|
||||
@@ -285,18 +304,6 @@ class Dumper(DumperBase):
|
||||
}[nativeType.code]
|
||||
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):
|
||||
return self.fromNativeType(nativeType.strip_typedefs().target())
|
||||
|
||||
@@ -402,25 +409,6 @@ class Dumper(DumperBase):
|
||||
typeobj = typeobj.strip_typedefs().unqualified()
|
||||
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):
|
||||
frame = gdb.selected_frame()
|
||||
|
||||
@@ -571,20 +559,6 @@ class Dumper(DumperBase):
|
||||
return None
|
||||
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):
|
||||
# args is a tuple.
|
||||
arg = ""
|
||||
@@ -963,47 +937,16 @@ class Dumper(DumperBase):
|
||||
cmd = "set variable (%s)=%s" % (expr, value)
|
||||
gdb.execute(cmd)
|
||||
|
||||
def hasVTable(self, typeobj):
|
||||
fields = typeobj.fields()
|
||||
if len(fields) == 0:
|
||||
return False
|
||||
if fields[0].isBaseClass:
|
||||
return hasVTable(fields[0].type)
|
||||
return str(fields[0].type) == "int (**)(void)"
|
||||
|
||||
def dynamicTypeName(self, value):
|
||||
if self.hasVTable(value.type):
|
||||
#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 nativeDynamicTypeName(self, address, baseType):
|
||||
vtbl = gdb.execute("info symbol {%s*}0x%x" % (baseType.name, address), to_string = True)
|
||||
pos1 = vtbl.find("vtable ")
|
||||
if pos1 == -1:
|
||||
return None
|
||||
pos1 += 11
|
||||
pos2 = vtbl.find(" +", pos1)
|
||||
if pos2 == -1:
|
||||
return None
|
||||
return vtbl[pos1 : pos2]
|
||||
|
||||
def enumExpression(self, enumType, enumValue):
|
||||
return self.qtNamespace() + "Qt::" + enumValue
|
||||
|
@@ -57,20 +57,6 @@ def check(exp):
|
||||
if not exp:
|
||||
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):
|
||||
def __init__(self):
|
||||
DumperBase.__init__(self)
|
||||
@@ -154,15 +140,42 @@ class Dumper(DumperBase):
|
||||
|
||||
def fromNativeValue(self, nativeValue):
|
||||
nativeValue.SetPreferSyntheticValue(False)
|
||||
nativeType = nativeValue.GetType()
|
||||
val = self.Value(self)
|
||||
val.nativeValue = nativeValue
|
||||
val.type = self.fromNativeType(nativeValue.type)
|
||||
val.type = self.fromNativeType(nativeType)
|
||||
val.lIsInScope = nativeValue.IsInScope()
|
||||
#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())
|
||||
except:
|
||||
pass
|
||||
if code == lldb.eTypeClassEnumeration:
|
||||
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
|
||||
|
||||
def fromNativeType(self, nativeType):
|
||||
@@ -217,6 +230,7 @@ class Dumper(DumperBase):
|
||||
addr = 0x7fffffffe0a0
|
||||
sbaddr = lldb.SBAddress(addr, self.target)
|
||||
dummyValue = self.target.CreateValueFromAddress('x', sbaddr, nativeType)
|
||||
dummyValue.SetPreferSyntheticValue(False)
|
||||
|
||||
anonNumber = 0
|
||||
|
||||
@@ -246,8 +260,8 @@ class Dumper(DumperBase):
|
||||
anonNumber += 1
|
||||
fieldName = "#%s" % anonNumber
|
||||
fieldType = dummyChild.GetType()
|
||||
#warn("CHILD AT: %s: %s %s" % (i, fieldName, fieldType))
|
||||
#warn(" 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.GetName()))
|
||||
caddr = dummyChild.AddressOf().GetValueAsUnsigned()
|
||||
child = self.Value(self)
|
||||
child.type = self.fromNativeType(fieldType)
|
||||
@@ -298,15 +312,6 @@ class Dumper(DumperBase):
|
||||
#warn("FIELDS: %s" % 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):
|
||||
return self.fromNativeType(nativeType.GetUnqualifiedType())
|
||||
|
||||
@@ -318,46 +323,6 @@ class Dumper(DumperBase):
|
||||
return self.fromNativeType(typeobj.GetCanonicalType())
|
||||
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):
|
||||
#warn("FIRST BASE FROM: %s" % nativeType)
|
||||
if nativeType.GetNumberOfDirectBaseClasses() == 0:
|
||||
@@ -378,6 +343,13 @@ class Dumper(DumperBase):
|
||||
return "%s (%d)" % ('::'.join(path), 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):
|
||||
try:
|
||||
# See db.StateType
|
||||
@@ -480,9 +452,6 @@ class Dumper(DumperBase):
|
||||
#warn("INNER: %s" % inner)
|
||||
return self.lookupType(inner)
|
||||
|
||||
def nativeValueAddressOf(self, nativeValue):
|
||||
return int(value.GetLoadAddress())
|
||||
|
||||
def nativeTypeDereference(self, nativeType):
|
||||
return self.fromNativeType(nativeType.GetPointeeType())
|
||||
|
||||
@@ -917,15 +886,6 @@ class Dumper(DumperBase):
|
||||
return bytes()
|
||||
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):
|
||||
symbolName = self.mangleName(typeName + '::staticMetaObject')
|
||||
symbol = self.target.FindFirstGlobalVariable(symbolName)
|
||||
@@ -983,6 +943,7 @@ class Dumper(DumperBase):
|
||||
if len(statics):
|
||||
for i in xrange(len(statics)):
|
||||
staticVar = statics[i]
|
||||
staticVar.SetPreferSyntheticValue(False)
|
||||
typename = staticVar.GetType().GetName()
|
||||
name = staticVar.GetName()
|
||||
with SubItem(self, i):
|
||||
@@ -1004,6 +965,7 @@ class Dumper(DumperBase):
|
||||
|
||||
variables = []
|
||||
for val in values:
|
||||
val.SetPreferSyntheticValue(False)
|
||||
if not val.IsValid():
|
||||
continue
|
||||
self.currentContextValue = val
|
||||
|
@@ -887,11 +887,11 @@ def qdump__QLocale(d, value):
|
||||
#d.check(index <= qqLocalesCount)
|
||||
dd = value.extractPointer()
|
||||
ns = d.qtNamespace()
|
||||
(data, ref, numberOptions) = d.split("pi{int}", dd)
|
||||
(data, ref, numberOptions) = d.split("pi4s", dd)
|
||||
(languageId, scriptId, countryId,
|
||||
decimal, group, listt, percent, zero,
|
||||
minus, plus, exponential) \
|
||||
= d.split('{short}{short}{QChar}'
|
||||
= d.split('2s{short}2s'
|
||||
+ '{QChar}{QChar}{short}{QChar}{QChar}'
|
||||
+ '{QChar}{QChar}{QChar}', data)
|
||||
d.putStringValue(d.call("const char *", value, "name"))
|
||||
@@ -899,9 +899,9 @@ def qdump__QLocale(d, value):
|
||||
if d.isExpanded():
|
||||
with Children(d):
|
||||
prefix = ns + "QLocale::"
|
||||
d.putSubItem("country", countryId.extend(4).cast(prefix + "Country"))
|
||||
d.putSubItem("language", languageId.extend(4).cast(prefix + "Language"))
|
||||
d.putSubItem("numberOptions", numberOptions.cast(prefix + "NumberOptions"))
|
||||
d.putSubItem("country", d.createValue(countryId, prefix + "Country"))
|
||||
d.putSubItem("language", d.createValue(languageId, prefix + "Language"))
|
||||
d.putSubItem("numberOptions", d.createValue(numberOptions, prefix + "NumberOptions"))
|
||||
d.putSubItem("decimalPoint", decimal)
|
||||
d.putSubItem("exponential", exponential)
|
||||
d.putSubItem("percent", percent)
|
||||
@@ -1189,7 +1189,7 @@ def qdump__QSet(d, value):
|
||||
typeCode = 'Pi@{%s}' % keyType.name
|
||||
(pnext, hashval, padding1, key) = d.split(typeCode, node)
|
||||
with SubItem(d, i):
|
||||
d.putItem(key, i)
|
||||
d.putItem(key)
|
||||
node = hashDataNextNode(node)
|
||||
|
||||
|
||||
|
@@ -227,12 +227,11 @@ def qdump__std__map(d, value):
|
||||
pairPointer = pairType.pointer()
|
||||
with PairedChildren(d, size, pairType=pairType, maxNumChild=1000):
|
||||
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():
|
||||
pair = (node + 1).cast(pairPointer).dereference()
|
||||
d.putPairItem(i, pair)
|
||||
#(pp, pad1, key, pad2, value) = d.split(typeCode, node.integer())
|
||||
#d.putPairItem(i, (key, value))
|
||||
(pad1, key, pad2, value) = d.split(typeCode, node.pointer() + nodeSize)
|
||||
d.putPairItem(i, (key, value))
|
||||
if node["_M_right"].integer() == 0:
|
||||
parent = node["_M_parent"]
|
||||
while True:
|
||||
@@ -384,9 +383,12 @@ def qdump__std__set(d, value):
|
||||
if d.isExpanded():
|
||||
valueType = value.type[0]
|
||||
node = impl["_M_header"]["_M_left"]
|
||||
nodeSize = node.dereference().type.size()
|
||||
typeCode = "@{%s}" % valueType.name
|
||||
with Children(d, size, maxNumChild=1000, childType=valueType):
|
||||
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:
|
||||
parent = node["_M_parent"]
|
||||
while node == parent["_M_right"]:
|
||||
|
@@ -4106,34 +4106,34 @@ void tst_Dumpers::dumper_data()
|
||||
+ CoreProfile()
|
||||
|
||||
+ 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.second", "", "Foo")
|
||||
+ 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.second", "", "Foo")
|
||||
+ Check("map1.2.second.a", "44", "int")
|
||||
|
||||
+ 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 *")
|
||||
// FIXME
|
||||
//+ Check("map2.0.first.0", "50", "char")
|
||||
+ Check("map2.0.second", "", "Foo")
|
||||
+ 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 *")
|
||||
//+ Check("map2.1.first.*first", "51 '3'", "char")
|
||||
+ Check("map2.1.second", "", "Foo")
|
||||
+ Check("map2.1.second.a", "33", "int")
|
||||
|
||||
+ 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.second", "<1 items>", "@QStringList")
|
||||
+ 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.second", "<1 items>", "@QStringList")
|
||||
+ 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("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.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.second", FloatValue("22"), "float")
|
||||
|
||||
+ 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.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.second", "\"22.0\"", "@QString")
|
||||
|
||||
+ 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.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");
|
||||
|
||||
|
||||
@@ -4948,9 +4948,10 @@ void tst_Dumpers::dumper_data()
|
||||
QTest::newRow("Bitfields")
|
||||
<< Data("struct S\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 y : 4;\n"
|
||||
" unsigned int z : 18;\n"
|
||||
" bool c : 1;\n"
|
||||
" bool b;\n"
|
||||
" float f;\n"
|
||||
@@ -4966,7 +4967,8 @@ void tst_Dumpers::dumper_data()
|
||||
+ Check("s.d", FloatValue("6"), "double")
|
||||
+ Check("s.i", "7", "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")
|
||||
|
Reference in New Issue
Block a user