Debugger: Improve QMetaObject dumper

Change-Id: I690e95f5f4651331f6b2407636253770a9bb92a0
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
hjk
2016-07-13 14:17:18 +02:00
committed by hjk
parent 56d786a492
commit a12420c995
2 changed files with 165 additions and 123 deletions

View File

@@ -1409,16 +1409,8 @@ class DumperBase:
# This is called is when a QObject derived class is expanded # This is called is when a QObject derived class is expanded
def putQObjectGuts(self, qobject, smo): def putQObjectGuts(self, qobject, smo):
intSize = self.intSize()
ptrSize = self.ptrSize() ptrSize = self.ptrSize()
# dd = value["d_ptr"]["d"] is just behind the vtable.
dd = self.extractPointer(qobject, offset=ptrSize) dd = self.extractPointer(qobject, offset=ptrSize)
isQt5 = self.qtVersion() >= 0x50000
extraDataOffset = 5 * ptrSize + 8 if isQt5 else 6 * ptrSize + 8
extraData = self.extractPointer(dd + extraDataOffset)
#with SubItem(self, "[extradata]"):
# self.putValue("0x%x" % toInteger(extraData))
# Parent and children. # Parent and children.
try: try:
@@ -1428,51 +1420,161 @@ class DumperBase:
except: except:
pass pass
with SubItem(self, "[properties]"): # dd = value["d_ptr"]["d"] is just behind the vtable.
propertyCount = 0 isQt5 = self.qtVersion() >= 0x50000
usesVector = self.qtVersion() >= 0x50700 extraDataOffset = 5 * ptrSize + 8 if isQt5 else 6 * ptrSize + 8
if self.isExpanded(): extraData = self.extractPointer(dd + extraDataOffset)
propertyNames = self.staticQObjectPropertyNames(smo) self.putQObjectGutsHelper(extraData, dd, smo)
propertyCount = len(propertyNames) # Doesn't include dynamic properties.
with Children(self):
# Static properties.
for i in range(propertyCount):
name = propertyNames[i]
self.putCallItem(str(name), qobject, "property", '"' + name + '"')
# Dynamic properties.
if extraData: def putQObjectGutsHelper(self, extraData, dd, smo):
byteArrayType = self.lookupQtType("QByteArray") intSize = self.intSize()
variantType = self.lookupQtType("QVariant") ptrSize = self.ptrSize()
names = self.listChildrenGenerator(extraData + ptrSize, byteArrayType) data = smo["d"]["data"]
if usesVector: #warn("DATA: %s" % data)
values = self.vectorChildrenGenerator(extraData + 2 * ptrSize, variantType)
else: def metaString(offset):
values = self.listChildrenGenerator(extraData + 2 * ptrSize, variantType) ddata = self.extractPointer(data)
for (k, v) in zip(names, values): sd = self.extractPointer(smo["d"]["stringdata"])
with SubItem(self, propertyCount):
self.put('key="%s",' % self.encodeByteArray(k)) metaObjectVersion = self.extractInt(ddata)
self.put('keyencoded="latin1",') if metaObjectVersion >= 7: # Qt 5.
self.putItem(v) byteArrayDataType = self.lookupType(self.qtNamespace() + "QByteArrayData")
propertyCount += 1 byteArrayDataSize = byteArrayDataType.sizeof
self.putItemCount(propertyCount) literal = sd + offset * byteArrayDataSize
else: ldata, lsize, lalloc = self.byteArrayDataHelper(literal)
# We need a handle to [x] for the user to expand the item return self.extractBlob(ldata, lsize).toString()
# before we know whether there are actual children. Counting else: # Qt 4.
# them is too expensive. ldata = sd + offset
self.putNumChild(1) return self.extractCString(ldata).decode("utf8")
self.putSpecialValue("minimumitemcount", 0)
def walker(base):
ptr = toInteger(base)
while True:
yield self.extractInt(ptr)
ptr += intSize
def put1(name, p):
x = p.next()
with SubItem(self, name):
self.putValue(x)
self.putType("uint")
self.putNumChild(0)
return x
def put2(name, p):
xy = (p.next(), p.next())
with SubItem(self, name):
self.putValue("%s %s" % xy)
self.putType("uint")
self.putNumChild(0)
return xy[0]
def putt(name, value):
with SubItem(self, name):
self.putValue(value)
self.putType(" ")
self.putNumChild(0)
with SubItem(self, "[raw]"):
self.putEmptyValue()
self.putNumChild(1)
if self.isExpanded():
self.put('sortable="0"')
p = walker(data)
with Children(self):
put1("revision", p)
put1("classname", p)
put2("classinfo", p)
methodCount = put2("methods", p)
put2("properties", p)
put2("enums/sets", p)
put2("constructors", p)
put1("flags", p)
signalCount = put1("signalCount", p)
if extraData:
with SubItem(self, "[extraData]"):
self.putValue("0x%x" % toInteger(extraData))
self.putType("void *")
self.putNumChild(0)
with SubItem(self, "[properties]"):
propertyCount = 0
usesVector = self.qtVersion() >= 0x50700
if self.isExpanded():
propertyNames = self.staticQObjectPropertyNames(smo)
propertyCount = len(propertyNames) # Doesn't include dynamic properties.
with Children(self):
# Static properties.
for i in range(propertyCount):
name = propertyNames[i]
self.putCallItem(str(name), qobject, "property", '"' + name + '"')
# Dynamic properties.
if extraData:
byteArrayType = self.lookupQtType("QByteArray")
variantType = self.lookupQtType("QVariant")
names = self.listChildrenGenerator(extraData + ptrSize, byteArrayType)
if usesVector:
values = self.vectorChildrenGenerator(extraData + 2 * ptrSize, variantType)
else:
values = self.listChildrenGenerator(extraData + 2 * ptrSize, variantType)
for (k, v) in zip(names, values):
with SubItem(self, propertyCount):
self.put('key="%s",' % self.encodeByteArray(k))
self.put('keyencoded="latin1",')
self.putItem(v)
propertyCount += 1
self.putItemCount(propertyCount)
else:
# 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", 0)
#with SubItem(self, "[methods]"):
# methodCount = self.staticQObjectMethodCount(smo)
# self.putItemCount(methodCount)
# if self.isExpanded():
# methodNames = self.staticQObjectMethodNames(smo)
# with Children(self):
# for i in range(methodCount):
# k = methodNames[i]
# with SubItem(self, k):
# self.putEmptyValue()
#
with SubItem(self, "[methods]"): with SubItem(self, "[methods]"):
methodCount = self.staticQObjectMethodCount(smo) methodCount = self.staticQObjectMethodCount(smo)
self.putItemCount(methodCount) self.putItemCount(methodCount)
if self.isExpanded(): if self.isExpanded():
methodNames = self.staticQObjectMethodNames(smo)
with Children(self): with Children(self):
p = walker(toInteger(data) + 14 * 4)
for i in range(methodCount): for i in range(methodCount):
k = methodNames[i] t = (p.next(), p.next(), p.next(), p.next(), p.next())
with SubItem(self, k): name = metaString(t[0])
self.putEmptyValue() with SubItem(self, "[%s]" % i):
self.putValue(name)
self.putType(" ")
self.putNumChild(1)
with Children(self):
putt("name", name)
putt("nameindex", t[0])
flags = t[4]
if flags == 0x06:
putt("type", "signal")
elif flags == 0x0a:
putt("type", "slot")
elif flags == 0x0a:
putt("type", "invokable")
putt("argc", t[1])
putt("parameter", t[2])
putt("tag", t[3])
putt("flags", t[4])
with SubItem(self, "[signals]"): with SubItem(self, "[signals]"):
signalCount = self.staticQObjectSignalCount(smo) signalCount = self.staticQObjectSignalCount(smo)
@@ -1485,16 +1587,16 @@ class DumperBase:
k = signalNames[i] k = signalNames[i]
with SubItem(self, k): with SubItem(self, k):
self.putEmptyValue() self.putEmptyValue()
self.putQObjectConnections(qobject) if dd:
self.putQObjectConnections(dd)
def putQObjectConnections(self, qobject): def putQObjectConnections(self, dd):
with SubItem(self, "[connections]"): with SubItem(self, "[connections]"):
ptrSize = self.ptrSize() ptrSize = self.ptrSize()
self.putNoType() self.putNoType()
ns = self.qtNamespace() ns = self.qtNamespace()
privateTypeName = ns + "QObjectPrivate" privateTypeName = ns + "QObjectPrivate"
privateType = self.lookupType(privateTypeName) privateType = self.lookupType(privateTypeName)
dd = qobject["d_ptr"]["d"]
d_ptr = dd.cast(privateType.pointer()).dereference() d_ptr = dd.cast(privateType.pointer()).dereference()
connections = d_ptr["connectionLists"] connections = d_ptr["connectionLists"]
if self.isNull(connections): if self.isNull(connections):

View File

@@ -1121,82 +1121,22 @@ def qdump__QMetaObject(d, value):
dd = value["d"] dd = value["d"]
d.putSubItem("d", dd) d.putSubItem("d", dd)
data = d.extractPointer(dd["data"]) data = d.extractPointer(dd["data"])
d.putQObjectGutsHelper(0, 0, value)
propertyNames = d.staticQObjectPropertyNames(value)
propertyIndex = 0
for propertyName in propertyNames:
with SubItem(d, "property_%s" % propertyIndex):
d.putValue(propertyName)
propertyIndex += 1
#byteArrayDataType = d.lookupType(d.qtNamespace() + "QByteArrayData")
#byteArrayDataSize = byteArrayDataType.sizeof
#sd = d.extractPointer(dd["stringdata"])
#stringdata, size, alloc = d.byteArrayDataHelper(sd)
#propertyCount = d.extractInt(data + 24)
#propertyData = d.extractInt(data + 28)
## This is the 'data' member in the qt_meta_stringdata_qobject__*_t struct
#d.putIntItem("_byteArrayDataSize", byteArrayDataSize)
#d.putAddressItem("_data", data)
#d.putAddressItem("_sd_", stringdata)
#with SubItem(d, "_sd"):
# d.putValue(d.readMemory(stringdata, size), "latin1")
#with SubItem(d, "_cn"):
# d.putValue(d.readMemory(stringdata + d.extractInt(data + 4), size), "latin1")
#for i in range(propertyCount):
# with SubItem(d, "property_%s" % i):
# x = data + (propertyData + 3 * i) * 4
# literal = sd + d.extractInt(x) * byteArrayDataSize
# ldata, lsize, lalloc = d.byteArrayDataHelper(literal)
# d.putValue(d.readMemory(ldata, lsize), "latin1")
# d.putNumChild(1)
# if d.isExpanded():
# with Children(d):
# if d.isExpanded():
# d.putAddressItem("_literal", literal)
# d.putIntItem("__data", ldata)
# d.putIntItem("__size", lsize)
# d.putIntItem("__alloc", lalloc)
# d.putIntItem("name", d.extractInt(x))
# d.putIntItem("type", d.extractInt(x + 4))
# d.putIntItem("flags", d.extractInt(x + 8))
methodCount = d.extractInt(data + 16)
methodData = d.extractInt(data + 20)
for i in range(methodCount):
with SubItem(d, "method_%s" % i):
x = data + (methodData + 5 * i) * 4
#d.putEmptyValue()
d.putValue(d.readCString(stringdata + d.extractInt(x)))
d.putNumChild(1)
if d.isExpanded():
with Children(d):
if d.isExpanded():
d.putIntItem("name", d.extractInt(x))
d.putIntItem("argc", d.extractInt(x + 4))
d.putIntItem("argv", d.extractInt(x + 8))
d.putIntItem("type", d.extractInt(x + 12))
d.putIntItem("flags", d.extractInt(x + 16))
d.putSubItem("stringData", dd["stringdata"]) d.putSubItem("stringData", dd["stringdata"])
d.putIntItem("revision", d.extractInt(data)) #d.putIntItem("revision", d.extractInt(data))
d.putIntItem("className", d.extractInt(data + 4)) #d.putIntItem("className", d.extractInt(data + 4))
d.putIntItem("classInfoCount", d.extractInt(data + 8)) #d.putIntItem("classInfoCount", d.extractInt(data + 8))
d.putIntItem("className", d.extractInt(data + 12)) #d.putIntItem("className", d.extractInt(data + 12))
d.putIntItem("methodCount", d.extractInt(data + 16)) #d.putIntItem("methodCount", d.extractInt(data + 16))
d.putIntItem("methodData", d.extractInt(data + 20)) #d.putIntItem("methodData", d.extractInt(data + 20))
d.putIntItem("propertyCount", d.extractInt(data + 24)) #d.putIntItem("propertyCount", d.extractInt(data + 24))
d.putIntItem("propertyData", d.extractInt(data + 28)) #d.putIntItem("propertyData", d.extractInt(data + 28))
d.putIntItem("enumeratorCount", d.extractInt(data + 32)) #d.putIntItem("enumeratorCount", d.extractInt(data + 32))
d.putIntItem("enumeratorData", d.extractInt(data + 36)) #d.putIntItem("enumeratorData", d.extractInt(data + 36))
d.putIntItem("constructorCount", d.extractInt(data + 40)) #d.putIntItem("constructorCount", d.extractInt(data + 40))
d.putIntItem("constructorData", d.extractInt(data + 44)) #d.putIntItem("constructorData", d.extractInt(data + 44))
d.putIntItem("flags", d.extractInt(data + 48)) #d.putIntItem("flags", d.extractInt(data + 48))
d.putIntItem("signalCount", d.extractInt(data + 52)) #d.putIntItem("signalCount", d.extractInt(data + 52))
def _qdump__QObject(d, value): def _qdump__QObject(d, value):
d.putQObjectNameValue(value) d.putQObjectNameValue(value)