diff --git a/share/qtcreator/dumper/gbridge.py b/share/qtcreator/dumper/gbridge.py index c137b1840eb13e944d42bffc9645a471edcab1a6..80bbd9e6fb1ae8b68e2f894edc9b4455c933e8a9 100644 --- a/share/qtcreator/dumper/gbridge.py +++ b/share/qtcreator/dumper/gbridge.py @@ -29,12 +29,6 @@ def directBaseClass(typeobj, index = 0): # FIXME: Check it's really a base. return typeobj.fields()[index] -def createPointerValue(context, address, pointeeType): - return gdb.Value(address).cast(pointeeType.pointer()) - -def createReferenceValue(context, address, referencedType): - return gdb.Value(address).cast(referencedType.pointer()).dereference() - def savePrint(output): try: print(output) @@ -1548,12 +1542,34 @@ class Dumper: def voidPtrType(self): return self.lookupType('void*') - def voidPtrSize(self): - return self.voidPtrType().sizeof - def addressOf(self, value): return long(value.address) + def createPointerValue(self, address, pointeeType): + return gdb.Value(address).cast(pointeeType.pointer()) + + def intSize(self): + return 4 + + def ptrSize(self): + return self.lookupType('void*').sizeof + + def createValue(self, address, referencedType): + return gdb.Value(address).cast(referencedType.pointer()).dereference() + + # Returns the address stored at another address. + def derefAddress(self, addr): + return long(gdb.Value(addr).cast(self.voidPtrType())) + + def dereference(self, addr): + return long(gdb.Value(addr).cast(self.voidPtrType().pointer()).dereference()) + + def extractInt(self, addr): + return long(gdb.Value(addr).cast(self.intPtrType()).dereference()) + + def dereferenceValue(self, value): + return self.dereference(value.address) + def isQObject(self, value): entryType = self.lookupType("int").pointer().pointer() try: diff --git a/share/qtcreator/dumper/lbridge.py b/share/qtcreator/dumper/lbridge.py index 8fc10117da46029c71a20a5a9368e628e33e80b4..222e11cdda9219fc0fce9a82d8169a897df643c9 100644 --- a/share/qtcreator/dumper/lbridge.py +++ b/share/qtcreator/dumper/lbridge.py @@ -252,14 +252,6 @@ Value = lldb.SBValue def pointerValue(value): return value.GetValueAsUnsigned() -def createPointerValue(context, address, pointeeType): - addr = int(address) & 0xFFFFFFFFFFFFFFFF - return context.CreateValueFromAddress(None, addr, pointeeType).AddressOf() - -def createReferenceValue(context, address, referencedType): - addr = int(address) & 0xFFFFFFFFFFFFFFFF - return context.CreateValueFromAddress(None, addr, referencedType) - def impl_SBValue__add__(self, offset): if self.GetType().IsPointerType(): if isinstance(offset, int) or isinstance(offset, long): @@ -751,6 +743,14 @@ class Dumper: def parseAndEvalute(self, expr): return expr + def createPointerValue(self, address, pointeeType): + addr = int(address) & 0xFFFFFFFFFFFFFFFF + return self.context.CreateValueFromAddress(None, addr, pointeeType).AddressOf() + + def createValue(self, address, referencedType): + addr = int(address) & 0xFFFFFFFFFFFFFFFF + return self.context.CreateValueFromAddress(None, addr, referencedType) + def putCallItem(self, name, value, func, *args): result = call2(value, func, args) with SubItem(self, name): diff --git a/share/qtcreator/dumper/qttypes.py b/share/qtcreator/dumper/qttypes.py index 51ac36de56b61ab2a5608a81494d3035da266029..df6075d4a6cf9815cfb0c973fea42ba916170be8 100644 --- a/share/qtcreator/dumper/qttypes.py +++ b/share/qtcreator/dumper/qttypes.py @@ -18,6 +18,7 @@ movableTypes = set([ "QXmlStreamNotationDeclaration", "QXmlStreamEntityDeclaration" ]) + def checkSimpleRef(ref): count = int(ref["_q_value"]) check(count > 0) @@ -34,37 +35,34 @@ def checkRef(ref): check(count >= minimum) check(count < 1000000) -def qByteArrayDataData(d, value): - intType = d.intType() - base = d.addressOf(value) +def qByteArrayDataData(d, addr): + intSize = d.intSize() + ptrSize = d.ptrSize() if d.qtVersion() >= 0x050000: # QTypedArray: # - QtPrivate::RefCount ref # - int size # - uint alloc : 31, capacityReserved : 1 # - qptrdiff offset - size = int(createReferenceValue(value, base + intType.sizeof, intType)) - alloc = int(createReferenceValue(value, base + 2 * intType.sizeof, intType)) \ - & 0x7ffffff - data = base + pointerValue(createReferenceValue(value, - base + 2 * intType.sizeof + intType.pointer().sizeof, - d.charPtrType())) + size = d.extractInt(addr + intSize) + alloc = d.extractInt(addr + 2 * intSize) & 0x7ffffff + data = addr + d.dereference(addr + 2 * intSize + ptrSize) else: # Data: # - QBasicAtomicInt ref; # - int alloc, size; # - char *data; # - char array[1]; - alloc = int(createReferenceValue(value, base + intType.sizeof, intType)) - size = int(createReferenceValue(value, base + 2 * intType.sizeof, intType)) - data = pointerCbase + 3 * intType.sizeof + intType.pointer().sizeof + alloc = d.extractInt(addr + intSize) + size = d.extractInt(addr + 2 * intSize) + data = addr + 3 * intSize + ptrSize return data, size, alloc -def qByteArrayData(d, value): - return d.byteArrayDataData(value['d'].dereference()) +def qByteArrayData(d, addr): + return qByteArrayDataData(d, d.derefAddress(addr)) -def qEncodeByteArray(d, value, limit = None): - data, size, alloc = d.byteArrayData(value) +def qEncodeByteArray(d, addr, limit = None): + data, size, alloc = d.byteArrayData(addr) if alloc != 0: check(0 <= size and size <= alloc and alloc <= 100*1000*1000) limit = d.computeLimit(size, limit) @@ -73,8 +71,8 @@ def qEncodeByteArray(d, value, limit = None): s += "2e2e2e" return s -def qEncodeString(d, value, limit = 0): - data, size, alloc = d.stringData(value) +def qEncodeString(d, addr, limit = 0): + data, size, alloc = qByteArrayData(d, addr) if alloc != 0: check(0 <= size and size <= alloc and alloc <= 100*1000*1000) limit = d.computeLimit(size, limit) @@ -118,21 +116,20 @@ Dumper.putStringValue = \ lambda d, value: d.putValue(d.encodeString(value), Hex4EncodedLittleEndian) Dumper.encodeString = qEncodeString -Dumper.stringData = Dumper.byteArrayData +Dumper.stringData = qByteArrayData Dumper.putMapName = qPutMapName Dumper.isMapCompact = \ lambda d, keyType, valueType: qMapCompact(d.currentItemFormat(), keyType, valueType) -def putQObjectNameValue(d, value): +def qPutQObjectNameValue(d, value): try: - intType = d.lookupType("int") - ptrType = intType.pointer() + intSize = d.intSize() + ptrSize = d.ptrSize() # dd = value["d_ptr"]["d"] is just behind the vtable. - dd = createReferenceValue(value, d.addressOf(value) + ptrType.sizeof, ptrType) + dd = d.dereference(d.addressOf(value) + ptrSize) - objectName = None if d.qtVersion() < 0x050000: # Size of QObjectData: 5 pointer + 2 int # - vtable @@ -146,9 +143,8 @@ def putQObjectNameValue(d, value): # Offset of objectName in QObjectPrivate: 5 pointer + 2 int # - [QObjectData base] # - QString objectName - objectName = createReferenceValue(value, - pointerValue(dd) + 5 * ptrType.sizeof + 2 * intType.sizeof, - d.lookupType(d.ns + "QString")) + objectName = d.dereference(dd + 5 * ptrSize + 2 * intSize) + else: # Size of QObjectData: 5 pointer + 2 int # - vtable @@ -158,8 +154,9 @@ def putQObjectNameValue(d, value): # - uint isWidget : 1; etc... # - int postedEvents; # - QDynamicMetaObjectData *metaObject; - offset = 5 * ptrType.sizeof + 2 * intType.sizeof - extra = createReferenceValue(value, pointerValue(dd) + offset, ptrType) + extra = d.dereference(dd + 5 * ptrSize + 2 * intSize) + if extra == 0: + return # Offset of objectName in ExtraData: 6 pointer # - QVector<QObjectUserData *> userData; only #ifndef QT_NO_USERDATA @@ -168,20 +165,17 @@ def putQObjectNameValue(d, value): # - QVector<int> runningTimers; # - QList<QPointer<QObject> > eventFilters; # - QString objectName - if pointerValue(extra): - objectName = createReferenceValue(value, - pointerValue(extra) + 5 * ptrType.sizeof, - d.lookupType(d.ns + "QString")) - - if not objectName is None: - data, size, alloc = d.stringData(objectName) - if size > 0: - str = d.readRawMemory(data, 2 * size) - d.putValue(str, Hex4EncodedLittleEndian, 1) + objectName = d.dereference(extra + 5 * ptrSize) + + data, size, alloc = d.stringData(objectName) + if size > 0: + str = d.readRawMemory(data, 2 * size) + d.putValue(str, Hex4EncodedLittleEndian, 1) + except: pass -Dumper.putQObjectNameValue = putQObjectNameValue +Dumper.putQObjectNameValue = qPutQObjectNameValue ################################################################################### @@ -403,12 +397,10 @@ def qdump__QTime(d, value): # This relies on the Qt4/Qt5 internal structure layout: # {sharedref(4), date(8), time(4+x)} def qdump__QDateTime(d, value): - intType = d.lookupType("int") - intPtrType = intType.pointer() - base = pointerValue(value.cast(intPtrType)) - mds = int(createReferenceValue(value, base + intPtrType.sizeof + 8, intType)) + base = d.dereferenceValue(value) + mds = d.extractInt(base + d.ptrSize() + 8) if mds >= 0: - jd = int(createReferenceValue(value, base + intPtrType.sizeof, intType)) + jd = d.extractInt(base + d.ptrSize()) d.putValue("%s/%s" % (jd, mds), JulianDateAndMillisecondsSinceMidnight) d.putNumChild(1) if d.isExpanded(): @@ -737,15 +729,15 @@ def qdump__QList(d, value): addr = d.addressOf(array) + begin * stepSize if isInternal: if innerSize == stepSize: - p = createPointerValue(value, addr, innerType) + p = d.createPointerValue(addr, innerType) d.putArrayData(innerType, p, size) else: with Children(d, size, childType=innerType): for i in d.childRange(): - p = createPointerValue(value, addr + i * stepSize, innerType) - d.putSubItem(i, p.dereference()) + p = d.createValue(addr + i * stepSize, innerType) + d.putSubItem(i, p) else: - p = createPointerValue(value, addr, innerType.pointer()) + p = d.createPointerValue(addr, innerType.pointer()) # about 0.5s / 1000 items with Children(d, size, maxNumChild=2000, childType=innerType): for i in d.childRange(): @@ -759,7 +751,7 @@ def qdump__QImage(d, value): # This relies on current QImage layout intPtrType = d.lookupType("int").pointer() offset = (3 if d.qtVersion() >= 0x050000 else 2) * intPtrType.sizeof - base = createReferenceValue(value, d.addressOf(value) + offset, intPtrType) + base = d.createValue(d.addressOf(value) + offset, intPtrType) width = int(base[1]) height = int(base[2]) d.putValue("(%dx%d)" % (width, height)) @@ -1438,7 +1430,7 @@ def qdump__QObject(d, value): def qdump__QPixmap(d, value): intPtrType = d.lookupType("int").pointer() offset = (3 if d.qtVersion() >= 0x050000 else 2) * intPtrType.sizeof - base = createReferenceValue(value, d.addressOf(value) + offset, intPtrType) + base = d.createValue(d.addressOf(value) + offset, intPtrType) d.putValue("(%dx%d)" % (base[1], base[2])) d.putNumChild(0) @@ -1751,12 +1743,27 @@ def qdump__QUrl(d, value): data = value["d"].dereference() d.putByteArrayValue(data["encodedOriginal"]) else: - data = value["d"].dereference() - str = d.encodeString(data["scheme"]) + # QUrlPrivate: + # - QAtomicInt ref; + # - int port; + # - QString scheme; + # - QString userName; + # - QString password; + # - QString host; + # - QString path; + # - QString query; + # - QString fragment; + schemeAddr = d.dereferenceValue(value) + 2 * d.intSize() + scheme = d.dereference(schemeAddr) + host = d.dereference(schemeAddr + 3 * d.ptrSize()) + path = d.dereference(schemeAddr + 4 * d.ptrSize()) + + str = d.encodeString(scheme) str += "3a002f002f00" - str += d.encodeString(data["host"]) - str += d.encodeString(data["path"]) + str += d.encodeString(host) + str += d.encodeString(path) d.putValue(str, Hex4EncodedLittleEndian) + d.putNumChild(1) if d.isExpanded(): with Children(d): diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index c055e5a39ddb4f512c884d90126e4dc65941b4a6..9bb97778270ef8d80417b0fa9d5f442d02f610ba 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -776,7 +776,7 @@ void tst_Dumpers::dumper() "run " + nograb + "\n" "up\n" "python print('@%sS@%s@' % ('N', qtNamespace()))\n" - "bb options:fancy,autoderef,dyntype vars: expanded:" + expanded + " typeformats:\n"; + "bb options:fancy,autoderef,dyntype,pe vars: expanded:" + expanded + " typeformats:\n"; } else { cmds += "run\n"; foreach (const Check &check, data.checks) {