forked from qt-creator/qt-creator
Debugger: Some qobject dumper speedup
Slight change in behavior: Only classes with Q_OBJECT macro are now recognized as QObjects. Change-Id: If2df6c31ef6d098944e317e27dfcbc21d60f61ee Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
@@ -80,6 +80,10 @@ class Blob(object):
|
||||
data = ''.join([c for c in data])
|
||||
return data
|
||||
|
||||
def toString(self):
|
||||
data = self.toBytes()
|
||||
return data if sys.version_info[0] == 2 else data.decode("utf8")
|
||||
|
||||
def extractByte(self, offset = 0):
|
||||
return struct.unpack_from("b", self.data, offset)[0]
|
||||
|
||||
@@ -917,7 +921,7 @@ class DumperBase:
|
||||
x = data + (propertyData + 3 * i) * 4
|
||||
literal = sd + self.extractInt(x) * byteArrayDataSize
|
||||
ldata, lsize, lalloc = self.byteArrayDataHelper(literal)
|
||||
properties.append(self.readCArray(ldata, lsize))
|
||||
properties.append(self.extractBlob(ldata, lsize).toString())
|
||||
return properties
|
||||
|
||||
|
||||
@@ -928,10 +932,11 @@ class DumperBase:
|
||||
propertyCount = len(propertyNames)
|
||||
self.putItemCount(propertyCount)
|
||||
self.putNumChild(propertyCount)
|
||||
with Children(self):
|
||||
for i in range(propertyCount):
|
||||
name = propertyNames[i]
|
||||
self.putCallItem(name, qobject, "property", '"' + name + '"')
|
||||
if self.isExpanded():
|
||||
with Children(self):
|
||||
for i in range(propertyCount):
|
||||
name = propertyNames[i]
|
||||
self.putCallItem(name, qobject, "property", '"' + name + '"')
|
||||
|
||||
|
||||
def isKnownMovableType(self, type):
|
||||
|
||||
@@ -963,46 +963,27 @@ class Dumper(DumperBase):
|
||||
return True
|
||||
if typeName in self.knownNonQObjectTypes:
|
||||
return False
|
||||
|
||||
smo = typeName + "::staticMetaObject"
|
||||
try:
|
||||
vtable = self.dereference(toInteger(value.address)) # + ptrSize
|
||||
if vtable & 0x3: # This is not a pointer.
|
||||
return False
|
||||
metaObjectEntry = self.dereference(vtable) # It's the first entry.
|
||||
if metaObjectEntry & 0x1: # This is not a pointer.
|
||||
return False
|
||||
#warn("MO: 0x%x " % metaObjectEntry)
|
||||
s = gdb.execute("info symbol 0x%x" % metaObjectEntry, to_string=True)
|
||||
#warn("S: %s " % s)
|
||||
#return s.find("::metaObject() const") > 0
|
||||
#return str(metaObjectEntry).find("::metaObject() const") > 0
|
||||
if s.find("::metaObject() const") > 0 or s.find("10metaObjectEv") > 0:
|
||||
result = gdb.lookup_global_symbol(smo)
|
||||
if result:
|
||||
self.knownQObjectTypes.add(typeName)
|
||||
return True
|
||||
else:
|
||||
self.knownNonQObjectTypes.add(typeName)
|
||||
return False
|
||||
return result
|
||||
except:
|
||||
pass
|
||||
|
||||
# Older GDB...
|
||||
try:
|
||||
gdb.parse_and_eval(smo)
|
||||
self.knownQObjectTypes.add(typeName)
|
||||
return True
|
||||
except:
|
||||
self.knownNonQObjectTypes.add(typeName)
|
||||
return False
|
||||
|
||||
def isQObject_B(self, value):
|
||||
# Alternative: Check for specific values, like targeting the
|
||||
# 'childEvent' member which is typically not overwritten, slot 8.
|
||||
# ~"Symbol \"Myns::QObject::childEvent(Myns::QChildEvent*)\" is a
|
||||
# function at address 0xb70f691a.\n"
|
||||
if self.childEventAddress == None:
|
||||
try:
|
||||
loc = gdb.execute("info address ::QObject::childEvent", to_string=True)
|
||||
self.childEventAddress = toInteger(loc[loc.rfind(' '):-2], 16)
|
||||
except:
|
||||
self.childEventAddress = 0
|
||||
|
||||
try:
|
||||
vtable = self.dereference(toInteger(value.address))
|
||||
return self.childEventAddress == self.dereference(vtable + 8 * self.ptrSize())
|
||||
except:
|
||||
return False
|
||||
|
||||
def put(self, value):
|
||||
self.output.append(value)
|
||||
|
||||
@@ -1446,25 +1427,6 @@ class Dumper(DumperBase):
|
||||
inferior = self.selectedInferior()
|
||||
return Blob(inferior.read_memory(base, size))
|
||||
|
||||
def readCArray(self, base, size):
|
||||
inferior = self.selectedInferior()
|
||||
if sys.version_info[0] >= 3:
|
||||
mem = bytes()
|
||||
for i in range(size):
|
||||
char = inferior.read_memory(base + i, 1)[0]
|
||||
if not char:
|
||||
break
|
||||
mem += char
|
||||
return mem.decode("utf8")
|
||||
else:
|
||||
mem = ""
|
||||
for i in range(size):
|
||||
char = inferior.read_memory(base + i, 1)[0]
|
||||
if not char:
|
||||
break
|
||||
mem += char
|
||||
return mem
|
||||
|
||||
def readCString(self, base):
|
||||
inferior = self.selectedInferior()
|
||||
mem = ""
|
||||
|
||||
@@ -851,9 +851,6 @@ class Dumper(DumperBase):
|
||||
error = lldb.SBError()
|
||||
return Blob(self.process.ReadMemory(base, size, error))
|
||||
|
||||
def readCArray(self, base, size):
|
||||
return self.extractBlob(base, size).toBytes()
|
||||
|
||||
def toBlob(self, value):
|
||||
data = value.GetData()
|
||||
size = int(data.GetByteSize())
|
||||
|
||||
@@ -5049,7 +5049,7 @@ void tst_Dumpers::dumper_data()
|
||||
"file.setObjectName(\"A file\");\n")
|
||||
% CoreProfile()
|
||||
% QtVersion(50000)
|
||||
% Check("file", "\"A file\"", "MyFile")
|
||||
% Check("file", "", "MyFile")
|
||||
% Check("file.@1", "[@QFile]", "\"/tmp/tt\"", "@QFile");
|
||||
// FIXME: The classname in the iname is sub-optimal.
|
||||
//% Check("file.@1.[QFileDevice]", "[@QFileDevice]", "\"A file\"", "@QFileDevice");
|
||||
|
||||
Reference in New Issue
Block a user