diff options
author | hjk <hjk@theqtcompany.com> | 2016-07-22 10:20:01 +0200 |
---|---|---|
committer | hjk <hjk@qt.io> | 2016-07-22 08:22:03 +0000 |
commit | 539e33da0289dcb66f71734ba2ac06f6ec910819 (patch) | |
tree | e9e9aeeb88424017f985a1ea5025439562d0e0e6 /share | |
parent | 96e877d3ca985970d4cad6bc5f10064514df2fd1 (diff) | |
download | qt-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.py | 476 | ||||
-rw-r--r-- | share/qtcreator/debugger/gdbbridge.py | 27 | ||||
-rw-r--r-- | share/qtcreator/debugger/lldbbridge.py | 7 | ||||
-rw-r--r-- | share/qtcreator/debugger/qttypes.py | 2 |
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) |