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>
This commit is contained in:
hjk
2016-07-22 10:20:01 +02:00
committed by hjk
parent 96e877d3ca
commit 539e33da02
4 changed files with 350 additions and 164 deletions
+327 -151
View File
@@ -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):
def canBePointer(p):
if ptrSize == 4:
return p > 100000 and (p & 0x3 == 0)
else:
return p > 100000 and (p & 0x7 == 0) and (p < 0x7fffffffffff)
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
(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
typeName = str(typeobj)
isQObjectProper = typeName == self.qtNamespace() + "QObject"
if not isQObjectProper:
if self.directBaseClass(typeobj, 0) is None:
def extractStaticMetaObjectFromTypeHelper(typeobj):
if self.isSimpleType(typeobj):
return 0
# No templates for now.
if typeName.find('<') >= 0:
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
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 = self.findStaticMetaObject(typeName)
result = 0
#try:
result = extractStaticMetaObjectFromTypeHelper(someTypeObj)
#except RuntimeError as error:
# warn("METAOBJECT EXTRACTION FAILED: %s" % error)
#except:
# warn("METAOBJECT EXTRACTION FAILED FOR UNKNOWN REASON")
# 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 0
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)
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)
self.knownStaticMetaObjects[typeName] = result
return result
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):
def putQObjectGuts(self, qobject, metaObjectPtr):
self.putQObjectGutsHelper(qobject, self.addressOf(qobject), -1, metaObjectPtr, "QObject")
def metaString(self, metaObjectPtr, index, revision = 7):
#stringData = self.extractPointer(metaObjectPtr["d"]["stringdata"])
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
# 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"])
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()
if self.isExpanded():
with Children(self):
self.putFields(value)
else:
metaObjectPtr = value["mobj"]
if toInteger(metaObjectPtr):
handle = toInteger(value["handle"])
index = toInteger(metaObject["d"]["data"][handle])
name = self.metaString(metaObject.dereference(), index)
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, metaObject, origType)
self.putQObjectGutsHelper(0, 0, handle, toInteger(metaObjectPtr), origType)
else:
self.putEmptyValue()
if self.isExpanded():
with Children(self):
self.putFields(value)
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]
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():
addrBase = array + begin * ptrSize
with Children(self, size):
for i in self.childRange():
with SubItem(self, i):
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"')
self.putSpecialValue("minimumitemcount", largestStringIndex + 1)
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(metaObject, i)), "latin1")
self.putNumChild(0)
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)
+16 -11
View File
@@ -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)
+6 -1
View File
@@ -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)
+1 -1
View File
@@ -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)