forked from qt-creator/qt-creator
Debugger: Replace 'first base' guessing logic
Use the fact that the order of the first three vtable entries of a QObject is fixed and the size of their implementations is roughly known. Change-Id: I3d13f594cb1c1f162a520da18b2bc2aaba852092 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -1444,12 +1444,19 @@ class DumperBase:
|
||||
else:
|
||||
return p > 100000 and (p & 0x7 == 0) and (p < 0x7fffffffffff)
|
||||
|
||||
def canBeVTableEntry(self, p):
|
||||
if self.ptrSize() == 4:
|
||||
return p > 100000 and (p & 0x1 == 0)
|
||||
else:
|
||||
return p > 100000 and (p & 0x1 == 0) and (p < 0x7fffffffffff)
|
||||
|
||||
def couldBeQObject(self, objectPtr):
|
||||
try:
|
||||
(vtablePtr, dd) = self.split('pp', objectPtr)
|
||||
except:
|
||||
self.bump('nostruct-1')
|
||||
return False
|
||||
|
||||
if not self.canBePointer(vtablePtr):
|
||||
self.bump('vtable')
|
||||
return False
|
||||
@@ -1457,6 +1464,33 @@ class DumperBase:
|
||||
self.bump('d_d_ptr')
|
||||
return False
|
||||
|
||||
try:
|
||||
metaObjectFunc, metaCastFunc, metaCallFunc = self.split('ppp', vtablePtr)
|
||||
except:
|
||||
return False
|
||||
|
||||
# The first three entries are in a fairly rigid relationship defined
|
||||
# by the Q_OBJECT macro.
|
||||
if not self.canBeVTableEntry(metaObjectFunc):
|
||||
return False
|
||||
if not self.canBeVTableEntry(metaCastFunc):
|
||||
return False
|
||||
if not self.canBeVTableEntry(metaCallFunc):
|
||||
return False
|
||||
if metaCastFunc < metaObjectFunc or metaCastFunc > metaObjectFunc + 200:
|
||||
# The metaObject implementation is just that:
|
||||
# QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject()
|
||||
# : &staticMetaObject;
|
||||
# That should not exceed 200 bytes. Observed on x86_64 debug 72.
|
||||
return False
|
||||
if metaCallFunc < metaCastFunc or metaCallFunc > metaCastFunc + 200:
|
||||
# if (!_clname) return nullptr;
|
||||
# if (!strcmp(_clname, qt_meta_stringdata_Bar__TestObject.stringdata0))
|
||||
# return static_cast<void*>(const_cast< TestObject*>(this));
|
||||
# return QWidget::qt_metacast(_clname);
|
||||
# That should not exceed 200 bytes. Observed on x86_64 debug 80.
|
||||
return False
|
||||
|
||||
try:
|
||||
(dvtablePtr, qptr, parentPtr, childrenDPtr, flags) \
|
||||
= self.split('ppppI', dd)
|
||||
@@ -1529,14 +1563,9 @@ class DumperBase:
|
||||
typeName = someTypeObj.name
|
||||
isQObjectProper = typeName == self.qtNamespace() + 'QObject'
|
||||
|
||||
if not isQObjectProper:
|
||||
#if someTypeObj.firstBase() is None:
|
||||
# warn("FIRST BASE IS NONE")
|
||||
# return 0
|
||||
|
||||
# No templates for now.
|
||||
if typeName.find('<') >= 0:
|
||||
return 0
|
||||
# No templates for now.
|
||||
if typeName.find('<') >= 0:
|
||||
return 0
|
||||
|
||||
result = self.findStaticMetaObject(typeName)
|
||||
|
||||
@@ -1568,10 +1597,10 @@ class DumperBase:
|
||||
#except:
|
||||
# warn('METAOBJECT EXTRACTION FAILED FOR UNKNOWN REASON')
|
||||
|
||||
if not result:
|
||||
base = someTypeObj.firstBase()
|
||||
if base is not None and base != someTypeObj: # sanity check
|
||||
result = extractStaticMetaObjectPtrFromType(base)
|
||||
#if not result:
|
||||
# base = someTypeObj.firstBase()
|
||||
# if base is not None and base != someTypeObj: # sanity check
|
||||
# result = extractStaticMetaObjectPtrFromType(base)
|
||||
|
||||
self.knownStaticMetaObjects[someTypeName] = result
|
||||
return result
|
||||
@@ -1999,7 +2028,7 @@ class DumperBase:
|
||||
self.putItemCount(0)
|
||||
else:
|
||||
connections = connections.dereference()
|
||||
connections = connections.cast(connections.type.firstBase())
|
||||
#connections = connections.cast(connections.type.firstBase())
|
||||
self.putSpecialValue('minimumitemcount', 0)
|
||||
self.putNumChild(1)
|
||||
if self.isExpanded():
|
||||
@@ -3085,7 +3114,6 @@ class DumperBase:
|
||||
self.lalignment = None # Function returning alignment of this struct
|
||||
self.lbitsize = None
|
||||
self.lbitpos = None
|
||||
self.lfirstBase = None
|
||||
self.ltarget = None # Inner type for arrays
|
||||
self.templateArguments = []
|
||||
self.code = None
|
||||
@@ -3100,7 +3128,6 @@ class DumperBase:
|
||||
tdata.lalignment = self.lalignment
|
||||
tdata.lbitsize = self.lbitsize
|
||||
tdata.lbitpos = self.lbitpos
|
||||
tdata.lfirstBase = self.lfirstBase
|
||||
tdata.ltarget = self.ltarget
|
||||
tdata.templateArguments = self.templateArguments
|
||||
tdata.code = self.code
|
||||
@@ -3294,13 +3321,6 @@ class DumperBase:
|
||||
return tdata.lfields(value)
|
||||
return []
|
||||
|
||||
def firstBase(self):
|
||||
#lfields = self.fields()
|
||||
#if len(lfields) > 0 and lfields[0].isBaseClass:
|
||||
# return lfields[0].ltype
|
||||
#return None
|
||||
return self.typeData().lfirstBase
|
||||
|
||||
def field(self, value, name, bitoffset = 0):
|
||||
#warn('GETTING FIELD %s FOR: %s' % (name, self.name))
|
||||
for f in self.fields(value):
|
||||
|
||||
@@ -420,10 +420,6 @@ class Dumper(DumperBase):
|
||||
tdata.code = TypeCodeComplex
|
||||
elif code in (lldb.eTypeClassClass, lldb.eTypeClassStruct, lldb.eTypeClassUnion):
|
||||
tdata.code = TypeCodeStruct
|
||||
#if nativeType.GetNumberOfDirectBaseClasses() > 0:
|
||||
# firstBase = nativeType.GetDirectBaseClassAtIndex(0).GetType()
|
||||
# if firstBase.GetByteSize() >= 2 * self.ptrSize():
|
||||
# tdata.lfirstBase = self.fromNativeType(firstBase)
|
||||
tdata.lalignment = lambda : \
|
||||
self.nativeStructAlignment(nativeType)
|
||||
tdata.lfields = lambda value : \
|
||||
|
||||
Reference in New Issue
Block a user