summaryrefslogtreecommitdiff
path: root/share
diff options
context:
space:
mode:
authorhjk <hjk@theqtcompany.com>2016-07-22 10:20:01 +0200
committerhjk <hjk@qt.io>2016-07-22 08:22:03 +0000
commit539e33da0289dcb66f71734ba2ac06f6ec910819 (patch)
treee9e9aeeb88424017f985a1ea5025439562d0e0e6 /share
parent96e877d3ca985970d4cad6bc5f10064514df2fd1 (diff)
downloadqt-creator-539e33da0289dcb66f71734ba2ac06f6ec910819.tar.gz
Debugger: Improve QObject related dumpers in release builds
Make QMeta* dumper work without debug info. Show QObject parent and children list in this case. QObject properties are not visible, and neither actual type of QObject children. Change-Id: I05417a7d78084234403a964f683db6867b6686f0 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'share')
-rw-r--r--share/qtcreator/debugger/dumper.py476
-rw-r--r--share/qtcreator/debugger/gdbbridge.py27
-rw-r--r--share/qtcreator/debugger/lldbbridge.py7
-rw-r--r--share/qtcreator/debugger/qttypes.py2
4 files changed, 349 insertions, 163 deletions
diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py
index 99db06848c..959c81ab5e 100644
--- a/share/qtcreator/debugger/dumper.py
+++ b/share/qtcreator/debugger/dumper.py
@@ -344,6 +344,7 @@ class DumperBase:
self.displayStringLimit = 100
self.resetCaches()
+ self.resetStats()
self.childrenPrefix = 'children=['
self.childrenSuffix = '],'
@@ -376,6 +377,35 @@ class DumperBase:
# to not be QObject derived, it contains a 0 value.
self.knownStaticMetaObjects = {}
+ self.counts = {}
+ self.pretimings = {}
+ self.timings = []
+
+ def resetStats(self):
+ # Timing collection
+ self.pretimings = {}
+ self.timings = []
+ pass
+
+ def dumpStats(self):
+ msg = [self.counts, self.timings]
+ self.resetStats()
+ return msg
+
+ def bump(self, key):
+ if key in self.counts:
+ self.counts[key] += 1
+ else:
+ self.counts[key] = 1
+
+ def preping(self, key):
+ import time
+ self.pretimings[key] = time.time()
+
+ def ping(self, key):
+ import time
+ elapsed = int(1000000 * (time.time() - self.pretimings[key]))
+ self.timings.append([key, elapsed])
def putNewline(self):
pass
@@ -1260,67 +1290,171 @@ class DumperBase:
pass
- def extractStaticMetaObjectHelper(self, typeobj):
- """
- Checks whether type has a Q_OBJECT macro.
- Returns the staticMetaObject, or 0.
- """
+ def extractMetaObjectPtr(self, objectPtr, typeobj):
+ """ objectPtr - address of *potential* instance of QObject derived class
+ typeobj - type of *objectPtr if known, None otherwise. """
- if self.isSimpleType(typeobj):
- return 0
+ def canBePointer(p):
+ if ptrSize == 4:
+ return p > 100000 and (p & 0x3 == 0)
+ else:
+ return p > 100000 and (p & 0x7 == 0) and (p < 0x7fffffffffff)
- typeName = str(typeobj)
- isQObjectProper = typeName == self.qtNamespace() + "QObject"
+ def couldBeQObject():
+ (vtablePtr, dd) \
+ = self.extractStruct('PP', objectPtr, 2 * ptrSize)
+ if not canBePointer(vtablePtr):
+ self.bump("vtable")
+ return False
+ if not canBePointer(dd):
+ self.bump("d_d_ptr")
+ return False
- if not isQObjectProper:
- if self.directBaseClass(typeobj, 0) is None:
- return 0
+ (dvtablePtr, qptr, parentPtr, childrenDPtr, flags) \
+ = self.extractStruct('PPPPI', dd, 4 * ptrSize + 4)
+ #warn("STRUCT DD: %s %s" % (self.currentIName, x))
+ if not canBePointer(dvtablePtr):
+ self.bump("dvtable")
+ #warn("DVT: 0x%x" % dvtablePtr)
+ return False
+ # Check d_ptr.d.q_ptr == objectPtr
+ if qptr != objectPtr:
+ #warn("QPTR: 0x%x 0x%x" % (qptr, objectPtr))
+ self.bump("q_ptr")
+ return False
+ if parentPtr and not canBePointer(parentPtr):
+ #warn("PAREN")
+ self.bump("parent")
+ return False
+ if not canBePointer(childrenDPtr):
+ #warn("CHILD")
+ self.bump("children")
+ return False
+ #if flags >= 0x80: # Only 7 flags are defined
+ # warn("FLAGS: 0x%x %s" % (flags, self.currentIName))
+ # self.bump("flags")
+ # return False
+ #warn("OK")
+ #if dynMetaObjectPtr and not canBePointer(dynMetaObjectPtr):
+ # self.bump("dynmo")
+ # return False
+
+ self.bump("couldBeQObject")
+ return True
+
+ def extractMetaObjectPtrFromAddress():
+ # Try vtable, metaObject() is the first entry.
+ vtablePtr = self.extractPointer(objectPtr)
+ metaObjectFunc = self.extractPointer(vtablePtr)
+ cmd = "((void*(*)(void *))0x%x)(0x%x)" % (metaObjectFunc, objectPtr)
+ try:
+ #warn("MO CMD: %s" % cmd)
+ res = self.parseAndEvaluate(cmd)
+ #warn("MO RES: %s" % res)
+ self.bump("successfulMetaObjectCall")
+ return toInteger(res)
+ except:
+ self.bump("failedMetaObjectCall")
+ #warn("COULD NOT EXECUTE: %s" % cmd)
+ return 0
- # No templates for now.
- if typeName.find('<') >= 0:
+ def extractStaticMetaObjectFromTypeHelper(typeobj):
+ if self.isSimpleType(typeobj):
return 0
- result = self.findStaticMetaObject(typeName)
+ typeName = str(typeobj)
+ isQObjectProper = typeName == self.qtNamespace() + "QObject"
+
+ if not isQObjectProper:
+ if self.directBaseClass(typeobj, 0) is None:
+ return 0
+
+ # No templates for now.
+ if typeName.find('<') >= 0:
+ return 0
+
+ result = self.findStaticMetaObject(typeName)
+
+ # We need to distinguish Q_OBJECT from Q_GADGET:
+ # a Q_OBJECT SMO has a non-null superdata (unless it's QObject itself),
+ # a Q_GADGET SMO has a null superdata (hopefully)
+ if result and not isQObjectProper:
+ superdata = self.extractPointer(result)
+ if superdata == 0:
+ # This looks like a Q_GADGET
+ return 0
- # We need to distinguish Q_OBJECT from Q_GADGET:
- # a Q_OBJECT SMO has a non-null superdata (unless it's QObject itself),
- # a Q_GADGET SMO has a null superdata (hopefully)
- if result and not isQObjectProper:
- superdata = self.extractPointer(result)
- if toInteger(superdata) == 0:
- # This looks like a Q_GADGET
+ return result
+
+ def extractStaticMetaObjectPtrFromType(someTypeObj):
+ if someTypeObj is None:
return 0
+ someTypeName = str(someTypeObj)
+ self.bump('metaObjectFromType')
+ known = self.knownStaticMetaObjects.get(someTypeName, None)
+ if known is not None: # Is 0 or the static metaobject.
+ return known
+
+ result = 0
+ #try:
+ result = extractStaticMetaObjectFromTypeHelper(someTypeObj)
+ #except RuntimeError as error:
+ # warn("METAOBJECT EXTRACTION FAILED: %s" % error)
+ #except:
+ # warn("METAOBJECT EXTRACTION FAILED FOR UNKNOWN REASON")
+
+ if not result:
+ base = self.directBaseClass(typeobj, 0)
+ if base != someTypeObj: # sanity check
+ result = extractStaticMetaObjectPtrFromType(base)
+
+ self.knownStaticMetaObjects[someTypeName] = result
+ return result
- return result
- def extractStaticMetaObject(self, typeobj):
- """
- Checks recursively whether a type derives from QObject.
- """
if not self.useFancy:
return 0
+ ptrSize = self.ptrSize()
+
typeName = str(typeobj)
result = self.knownStaticMetaObjects.get(typeName, None)
if result is not None: # Is 0 or the static metaobject.
+ self.bump("typecached")
+ #warn("CACHED RESULT: %s %s 0x%x" % (self.currentIName, typeName, result))
return result
- try:
- result = self.extractStaticMetaObjectHelper(typeobj)
- except RuntimeError as error:
- warn("METAOBJECT EXTRACTION FAILED: %s" % error)
- result = 0
- except:
- warn("METAOBJECT EXTRACTION FAILED FOR UNKNOWN REASON")
- result = 0
+ if not couldBeQObject():
+ self.bump('cannotBeQObject')
+ #warn("DOES NOT LOOK LIKE A QOBJECT: %s" % self.currentIName)
+ return 0
- if not result:
- base = self.directBaseClass(typeobj, 0)
- if base:
- result = self.extractStaticMetaObject(base)
-
- self.knownStaticMetaObjects[typeName] = result
- return result
+ metaObjectPtr = 0
+ if not metaObjectPtr:
+ # measured: 3 ms (example had one level of inheritance)
+ self.preping("metaObjectType-" + self.currentIName)
+ metaObjectPtr = extractStaticMetaObjectPtrFromType(typeobj)
+ self.ping("metaObjectType-" + self.currentIName)
+
+ if not metaObjectPtr:
+ # measured: 200 ms (example had one level of inheritance)
+ self.preping("metaObjectCall-" + self.currentIName)
+ metaObjectPtr = extractMetaObjectPtrFromAddress()
+ self.ping("metaObjectCall-" + self.currentIName)
+
+ #if metaObjectPtr:
+ # self.bump('foundMetaObject')
+ # self.knownStaticMetaObjects[typeName] = metaObjectPtr
+
+ return metaObjectPtr
+
+ def extractStruct(self, pattern, base, size):
+ #warn("PATTERN: '%s'" % pattern)
+ pointerReplacement = 'Q' if self.ptrSize() == 8 else 'I'
+ pattern = pattern.replace('P', pointerReplacement)
+ mem = self.readRawMemory(base, size)
+ #warn("OUT: '%s'" % str(struct.unpack_from(pattern, mem)))
+ return struct.unpack_from(pattern, mem)
def extractCString(self, addr):
result = bytearray()
@@ -1361,88 +1495,74 @@ class DumperBase:
def putStructGuts(self, value):
self.putEmptyValue()
+ #metaObjectPtr = self.extractMetaObjectPtr(self.addressOf(value), value.type)
if self.showQObjectNames:
- staticMetaObject = self.extractStaticMetaObject(value.type)
- if staticMetaObject:
+ self.preping(self.currentIName)
+ metaObjectPtr = self.extractMetaObjectPtr(self.addressOf(value), value.type)
+ self.ping(self.currentIName)
+ if metaObjectPtr:
self.context = value
self.putQObjectNameValue(value)
+ #warn("STRUCT GUTS: %s MO: 0x%x " % (self.currentIName, metaObjectPtr))
if self.isExpanded():
self.put('sortable="1"')
with Children(self, 1, childType=None):
self.putFields(value)
if not self.showQObjectNames:
- staticMetaObject = self.extractStaticMetaObject(value.type)
- if staticMetaObject:
- self.putQObjectGuts(value, staticMetaObject)
+ metaObjectPtr = self.extractMetaObjectPtr(self.addressOf(value), value.type)
+ if metaObjectPtr:
+ self.putQObjectGuts(value, metaObjectPtr)
# This is called is when a QObject derived class is expanded
- def putQObjectGuts(self, qobject, smo):
- ptrSize = self.ptrSize()
- dd = self.extractPointer(qobject, offset=ptrSize)
-
- # Parent and children.
- try:
- if qobject:
- d_ptr = qobject["d_ptr"]["d"]
- with SubItem(self, "[parent]"):
- self.putItem(d_ptr["parent"])
- self.put('sortgroup="9"')
- with SubItem(self, "[children]"):
- self.putItem(d_ptr["children"])
- self.put('sortgroup="1"')
- except:
- pass
+ def putQObjectGuts(self, qobject, metaObjectPtr):
+ self.putQObjectGutsHelper(qobject, self.addressOf(qobject), -1, metaObjectPtr, "QObject")
- # dd = value["d_ptr"]["d"] is just behind the vtable.
- isQt5 = self.qtVersion() >= 0x50000
- extraDataOffset = 5 * ptrSize + 8 if isQt5 else 6 * ptrSize + 8
- extraData = self.extractPointer(dd + extraDataOffset)
- self.putQObjectGutsHelper(qobject, extraData, -1, smo, "QObject")
-
- def metaString(self, metaObject, index, revision = 7):
- sd = self.extractPointer(metaObject["d"]["stringdata"])
+ def metaString(self, metaObjectPtr, index, revision = 7):
+ #stringData = self.extractPointer(metaObjectPtr["d"]["stringdata"])
+ ptrSize = self.ptrSize()
+ stringdata = self.extractPointer(toInteger(metaObjectPtr) + ptrSize)
if revision >= 7: # Qt 5.
- byteArrayDataType = self.lookupQtType("QByteArrayData")
- byteArrayDataSize = byteArrayDataType.sizeof
- literal = toInteger(sd) + toInteger(index) * byteArrayDataSize
+ #byteArrayDataType = self.lookupQtType("QByteArrayData")
+ #byteArrayDataSize = byteArrayDataType.sizeof
+ byteArrayDataSize = 24 if ptrSize == 8 else 16
+ literal = stringdata + toInteger(index) * byteArrayDataSize
ldata, lsize, lalloc = self.byteArrayDataHelper(literal)
try:
return self.extractBlob(ldata, lsize).toString()
except:
- return "<unavailable>"
+ return "<not available>"
else: # Qt 4.
- ldata = sd + index
+ ldata = stringdata + index
return self.extractCString(ldata).decode("utf8")
def putQMetaStuff(self, value, origType):
- metaObject = value["mobj"]
- if not metaObject:
- self.putEmptyValue()
+ metaObjectPtr = value["mobj"]
+ if toInteger(metaObjectPtr):
+ handle = toInteger(value["handle"])
+ index = toInteger(metaObjectPtr["d"]["data"][handle])
+ name = self.metaString(metaObjectPtr, index)
+ self.putValue(name)
+ self.putNumChild(1)
if self.isExpanded():
with Children(self):
self.putFields(value)
+ self.putQObjectGutsHelper(0, 0, handle, toInteger(metaObjectPtr), origType)
else:
- handle = toInteger(value["handle"])
- index = toInteger(metaObject["d"]["data"][handle])
- name = self.metaString(metaObject.dereference(), index)
- self.putValue(name)
- self.putNumChild(1)
+ self.putEmptyValue()
if self.isExpanded():
with Children(self):
self.putFields(value)
- self.putQObjectGutsHelper(0, 0, handle, metaObject, origType)
- def putQObjectGutsHelper(self, qobject, extraData, handle, metaObject, origType):
+ # basically all meta things go through this here.
+ # qobject and qobjectPtr are non-null if coming from a real structure display
+ # qobject == 0, qobjectPtr != 0 is possible for builds without QObject debug info
+ # if qobject == 0, properties and d-ptr cannot be shown.
+ # handle is what's store in QMetaMethod etc, pass -1 for QObject/QMetaObject itself
+ # metaObjectPtr needs to point to a valid QMetaObject.
+ def putQObjectGutsHelper(self, qobject, qobjectPtr, handle, metaObjectPtr, origType):
intSize = self.intSize()
ptrSize = self.ptrSize()
- data = metaObject["d"]["data"]
-
- def walker(base):
- ptr = toInteger(base)
- while True:
- yield self.extractInt(ptr)
- ptr += intSize
def putt(name, value, typeName = ' '):
with SubItem(self, name):
@@ -1450,63 +1570,103 @@ class DumperBase:
self.putType(typeName)
self.putNumChild(0)
- def superData(mo):
- return mo['d']['superdata']
+ def extractSuperDataPtr(someMetaObjectPtr):
+ #return someMetaObjectPtr['d']['superdata']
+ return self.extractPointer(someMetaObjectPtr)
+
+ def extractDataPtr(someMetaObjectPtr):
+ # dataPtr = metaObjectPtr["d"]["data"]
+ return self.extractPointer(someMetaObjectPtr + 2 * ptrSize)
isQMetaObject = origType == "QMetaObject"
isQObject = origType == "QObject"
- p = walker(data)
- revision = p.next()
- classname = p.next()
- classinfo = p.next()
- classinfo2 = p.next()
- methodCount = p.next()
- methods = p.next()
- propertyCount = p.next()
- properties = p.next()
- enumCount = p.next()
- enums = p.next()
- constructorCount = p.next()
- constructors = p.next()
- flags = p.next()
- signalCount = p.next()
-
- globalOffset = 0
- superdata = superData(metaObject)
- while toInteger(superdata):
- sdata = superdata["d"]["data"]
- p = walker(sdata)
- revision = p.next()
- classname = p.next()
- classinfo = p.next()
- classinfo2 = p.next()
- methodCount = p.next()
- globalOffset += methodCount
- superdata = superData(superdata)
+ #warn("OBJECT GUTS: %s 0x%x " % (self.currentIName, metaObjectPtr))
+ dataPtr = extractDataPtr(metaObjectPtr)
+ #warn("DATA PTRS: %s 0x%x " % (self.currentIName, dataPtr))
+ (revision, classname,
+ classinfo, classinfo2,
+ methodCount, methods,
+ propertyCount, properties,
+ enumCount, enums,
+ constructorCount, constructors,
+ flags, signalCount) = self.extractStruct('IIIIIIIIIIIIII', dataPtr, 56)
largestStringIndex = -1
for i in range(methodCount):
- t = (p.next(), p.next(), p.next(), p.next(), p.next())
+ t = self.extractStruct('IIIII', dataPtr + 56 + i * 20, 20)
if largestStringIndex < t[0]:
largestStringIndex = t[0]
- if isQMetaObject:
- with SubItem(self, "[strings]"):
- self.put('sortgroup="2"')
- self.putSpecialValue("minimumitemcount", largestStringIndex + 1)
- self.putNumChild(1)
+ extraData = 0
+ if qobjectPtr:
+ isQt5 = self.qtVersion() >= 0x50000
+ extraDataOffset = 5 * ptrSize + 8 if isQt5 else 6 * ptrSize + 8
+ # dd = value["d_ptr"]["d"] is just behind the vtable.
+ dd = self.extractPointer(qobjectPtr + ptrSize)
+ extraData = self.extractPointer(dd + extraDataOffset)
+
+ if qobjectPtr:
+ qobjectType = self.lookupQtType("QObject")
+ badType = qobjectType is None
+ with SubItem(self, "[parent]"):
+ self.put('sortgroup="9"')
+ parentPtrType = self.voidPtrType() if badType else qobjectType.pointer()
+ self.putItem(self.createValue(dd + 2 * ptrSize, parentPtrType))
+ with SubItem(self, "[children]"):
+ self.put('sortgroup="8"')
+ base = self.extractPointer(dd + 3 * ptrSize) # It's a QList<QObject *>
+ begin = self.extractInt(base + 8)
+ end = self.extractInt(base + 12)
+ array = base + 16
+ if self.qtVersion() < 0x50000:
+ array += ptrSize
+ self.check(begin >= 0 and end >= 0 and end <= 1000 * 1000 * 1000)
+ size = end - begin
+ self.check(size >= 0)
+ self.putItemCount(size)
if self.isExpanded():
- with Children(self, largestStringIndex + 1):
+ addrBase = array + begin * ptrSize
+ with Children(self, size):
for i in self.childRange():
with SubItem(self, i):
- self.putValue(self.hexencode(self.metaString(metaObject, i)), "latin1")
- self.putNumChild(0)
+ childPtr = self.extractPointer(addrBase + i * ptrSize)
+ if badType:
+ # release build
+ childMetaObjectPtr = self.extractMetaObjectPtr(childPtr, None)
+ if childMetaObjectPtr:
+ # release build + live process
+ self.putNumChild(1)
+ self.putAddress(childPtr)
+ if self.isExpanded():
+ with Children(self):
+ self.putQObjectGutsHelper(0, childPtr, -1, childMetaObjectPtr, "QObject")
+ else:
+ # release build + core dump
+ self.putItem(self.createValue(addrBase + i * ptrSize, self.voidPtrType()))
+ else:
+ # debug info
+ self.putItem(self.createValue(childPtr, qobjectType))
+
+ if isQMetaObject:
+ with SubItem(self, "[strings]"):
+ self.put('sortgroup="2"')
+ if largestStringIndex > 0:
+ self.putSpecialValue("minimumitemcount", largestStringIndex)
+ self.putNumChild(1)
+ if self.isExpanded():
+ with Children(self, largestStringIndex + 1):
+ for i in self.childRange():
+ with SubItem(self, i):
+ self.putValue(self.hexencode(self.metaString(metaObjectPtr, i)), "latin1")
+ self.putNumChild(0)
+ else:
+ self.putValue(" ")
+ self.putNumChild(0)
if isQMetaObject:
with SubItem(self, "[raw]"):
self.put('sortgroup="1"')
- p = walker(data)
self.putEmptyValue()
self.putNumChild(1)
if self.isExpanded():
@@ -1520,9 +1680,8 @@ class DumperBase:
putt("constructors", "%d %d" % (constructorCount, constructors))
putt("flags", flags)
putt("signalCount", signalCount)
- p = walker(toInteger(data) + 14 * 4)
for i in range(methodCount):
- t = (p.next(), p.next(), p.next(), p.next(), p.next())
+ t = self.extractStruct('IIIII', dataPtr + 56 + i * 20, 20)
putt("method %d" % i, "%s %s %s %s %s" % t)
putt("[extraData]", "0x%x" % toInteger(extraData), "void *")
@@ -1535,10 +1694,9 @@ class DumperBase:
usesVector = self.qtVersion() >= 0x50700
with Children(self):
# Static properties.
- p = walker(toInteger(data) + properties * 4)
for i in range(propertyCount):
- t = (p.next(), p.next(), p.next())
- name = self.metaString(metaObject, t[0])
+ t = self.extractStruct("III", dataPtr + properties * 4 + 12 * i, 12)
+ name = self.metaString(metaObjectPtr, t[0])
if qobject:
self.putCallItem(name, qobject, "property", '"' + name + '"')
else:
@@ -1563,8 +1721,17 @@ class DumperBase:
# We need a handle to [x] for the user to expand the item
# before we know whether there are actual children. Counting
# them is too expensive.
- self.putNumChild(1)
self.putSpecialValue("minimumitemcount", propertyCount)
+ self.putNumChild(1)
+
+ superDataPtr = extractSuperDataPtr(metaObjectPtr)
+
+ globalOffset = 0
+ superDataIterator = superDataPtr
+ while superDataIterator:
+ sdata = extractDataPtr(superDataIterator)
+ globalOffset += self.extractInt(sdata + 16) # methodCount member
+ superDataIterator = extractSuperDataPtr(superDataIterator)
if isQMetaObject or isQObject:
with SubItem(self, "[methods]"):
@@ -1572,10 +1739,9 @@ class DumperBase:
self.putItemCount(methodCount)
if self.isExpanded():
with Children(self):
- p = walker(toInteger(data) + 14 * 4)
for i in range(methodCount):
- t = (p.next(), p.next(), p.next(), p.next(), p.next())
- name = self.metaString(metaObject, t[0])
+ t = self.extractStruct("IIIII", dataPtr + 56 + 20 * i, 20)
+ name = self.metaString(metaObjectPtr, t[0])
with SubItem(self, i):
self.putValue(name)
self.putType(" ")
@@ -1602,29 +1768,39 @@ class DumperBase:
putt("[globalindex]", str(globalOffset + i))
if isQObject:
- self.putSubItem("[metaObject]", metaObject)
+ with SubItem(self, "[metaObject]"):
+ self.putAddress(metaObjectPtr)
+ self.putNumChild(1)
+ if self.isExpanded():
+ with Children(self):
+ self.putQObjectGutsHelper(0, 0, -1, metaObjectPtr, "QMetaObject")
if isQObject:
with SubItem(self, "d"):
self.put('sortgroup="15"')
- self.putItem(qobject["d_ptr"]["d"])
+ try:
+ self.putItem(qobject["d_ptr"]["d"])
+ except:
+ self.putNumChild(0)
+ self.putSpecialValue("notaccessible")
if isQMetaObject:
with SubItem(self, "[superdata]"):
self.put('sortgroup="12"')
- superdata = superData(metaObject)
- self.putValue("0x%x" % superdata)
- if toInteger(superdata):
+ if superDataPtr:
+ self.putType(self.qtNamespace() + "QMetaObject")
+ self.putAddress(superDataPtr)
self.putNumChild(1)
if self.isExpanded():
with Children(self):
- self.putSubItem('*', superdata)
+ self.putQObjectGutsHelper(0, 0, -1, superDataPtr, "QMetaObject")
else:
+ self.putType(self.qtNamespace() + "QMetaObject *")
+ self.putValue("0x0")
self.putNumChild(0)
- self.putType(superdata.type)
if handle >= 0:
- localIndex = (handle - methods) / 5
+ localIndex = int((handle - methods) / 5)
with SubItem(self, "[localindex]"):
self.put('sortgroup="12"')
self.putValue(localIndex)
diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py
index 24abf794d0..3e6c6f15aa 100644
--- a/share/qtcreator/debugger/gdbbridge.py
+++ b/share/qtcreator/debugger/gdbbridge.py
@@ -383,13 +383,9 @@ class Dumper(DumperBase):
def canCallLocale(self):
return False if self.is32bit() else True
- def reportTime(self, hint):
- #from datetime import datetime
- #warn("%s: %s" % (hint, datetime.now().time().isoformat()))
- pass
-
def fetchVariables(self, args):
- self.reportTime("begin fetch")
+ self.resetStats()
+ self.preping("locals")
self.prepare(args)
partialVariable = args.get("partialvar", "")
isPartial = len(partialVariable) > 0
@@ -425,7 +421,7 @@ class Dumper(DumperBase):
else:
locals = self.listOfLocals()
- self.reportTime("locals")
+ self.ping("locals")
# Take care of the return value of the last function call.
if len(self.resultVarName) > 0:
@@ -449,12 +445,16 @@ class Dumper(DumperBase):
else:
# A "normal" local variable or parameter.
with TopLevelItem(self, item.iname):
+ self.preping("all-" + item.iname)
self.put('iname="%s",' % item.iname)
self.put('name="%s",' % item.name)
self.putItem(value)
+ self.ping("all-" + item.iname)
+ self.preping("watches")
with OutputSafer(self):
self.handleWatches(args)
+ self.ping("watches")
self.output.append('],typeinfo=[')
for name in self.typesToReport.keys():
@@ -475,9 +475,10 @@ class Dumper(DumperBase):
self.output.append(',partial="%d"' % isPartial)
- self.reportTime("before print: %s" % len(self.output))
+ self.preping('safePrint')
safePrint(''.join(self.output))
- self.reportTime("after print")
+ self.ping('safePrint')
+ safePrint('"%s"' % str(self.dumpStats()))
def enterSubItem(self, item):
if not item.iname:
@@ -800,10 +801,12 @@ class Dumper(DumperBase):
return struct.unpack("b", self.readRawMemory(address, 1))[0]
def findStaticMetaObject(self, typename):
- return self.findSymbol(typename + "::staticMetaObject")
+ symbol = gdb.lookup_global_symbol(typename + "::staticMetaObject")
+ return toInteger(symbol.value().address) if symbol else 0
def findSymbol(self, symbolName):
try:
+ self.bump('findSymbol1')
result = gdb.lookup_global_symbol(symbolName)
return result.value() if result else 0
except:
@@ -812,9 +815,11 @@ class Dumper(DumperBase):
try:
address = gdb.parse_and_eval("&'%s'" % symbolName)
typeobj = gdb.lookup_type(self.qtNamespace() + "QMetaObject")
+ self.bump('findSymbol2')
return self.createPointerValue(address, typeobj)
except:
- return 0
+ self.bump('findSymbol3')
+ return 0
def put(self, value):
self.output.append(value)
diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py
index 36768998da..8e4cb83ef1 100644
--- a/share/qtcreator/debugger/lldbbridge.py
+++ b/share/qtcreator/debugger/lldbbridge.py
@@ -900,6 +900,10 @@ class Dumper(DumperBase):
# logview pane feature.
self.report('token(\"%s\")' % args["token"])
+ def readRawMemory(self, address, size):
+ error = lldb.SBError()
+ return self.process.ReadMemory(address, size, error)
+
def extractBlob(self, base, size):
if size == 0:
return Blob("")
@@ -923,7 +927,8 @@ class Dumper(DumperBase):
def findStaticMetaObject(self, typeName):
symbolName = self.mangleName(typeName + '::staticMetaObject')
- return self.target.FindFirstGlobalVariable(symbolName)
+ symbol = self.target.FindFirstGlobalVariable(symbolName)
+ return int(symbol.AddressOf()) if symbol.IsValid() else 0
def findSymbol(self, symbolName):
return self.target.FindFirstGlobalVariable(symbolName)
diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py
index 095f30a8ff..f0bc8ccc37 100644
--- a/share/qtcreator/debugger/qttypes.py
+++ b/share/qtcreator/debugger/qttypes.py
@@ -1106,7 +1106,7 @@ def qdump__QMetaObject(d, value):
d.putNumChild(1)
if d.isExpanded():
with Children(d):
- d.putQObjectGutsHelper(0, 0, -1, value, "QMetaObject")
+ d.putQObjectGutsHelper(0, 0, -1, d.addressOf(value), "QMetaObject")
d.putMembersItem(value)