Lldb: Use qtHookData to retrieve Qt version

Adds caching of Qt version information.

In case that qVersion() can not be found, use qtHookData[2] to retrieve
the Qt Library version number.

In case that also fails, we now use self.fallbackQtVersion instead
of just returning 0x50200.

Previously debugging apps in the iOS Simulator would fail to correctly
detect the Qt Version, as qVersion might be optimized out, especially
for very simple applications.

Change-Id: I9183c1e9793bd899f296a231c693cd5bc146ab96
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Marcus Tillmanns
2022-08-19 12:45:59 +02:00
parent 9cb21d2879
commit b2b6577d5c

View File

@@ -719,7 +719,18 @@ class Dumper(DumperBase):
pass pass
return '0x%x' % address return '0x%x' % address
def qtVersionAndNamespace(self): def fetchInternalFunctions(self):
funcs = self.target.FindFunctions('QObject::customEvent')
if len(funcs):
symbol = funcs[0].GetSymbol()
self.qtCustomEventFunc = symbol.GetStartAddress().GetLoadAddress(self.target)
funcs = self.target.FindFunctions('QObject::property')
if len(funcs):
symbol = funcs[0].GetSymbol()
self.qtPropertyFunc = symbol.GetStartAddress().GetLoadAddress(self.target)
def fetchQtVersionAndNamespace(self):
for func in self.target.FindFunctions('qVersion'): for func in self.target.FindFunctions('qVersion'):
name = func.GetSymbol().GetName() name = func.GetSymbol().GetName()
if name.endswith('()'): if name.endswith('()'):
@@ -755,24 +766,41 @@ class Dumper(DumperBase):
qtVersion = 0x10000 * int(major) + 0x100 * int(minor) + int(patch) qtVersion = 0x10000 * int(major) + 0x100 * int(minor) + int(patch)
self.qtVersion = lambda: qtVersion self.qtVersion = lambda: qtVersion
funcs = self.target.FindFunctions('QObject::customEvent')
if len(funcs):
symbol = funcs[0].GetSymbol()
self.qtCustomEventFunc = symbol.GetStartAddress().GetLoadAddress(self.target)
funcs = self.target.FindFunctions('QObject::property')
if len(funcs):
symbol = funcs[0].GetSymbol()
self.qtPropertyFunc = symbol.GetStartAddress().GetLoadAddress(self.target)
return (qtNamespace, qtVersion) return (qtNamespace, qtVersion)
return ('', 0x50200) try:
versionValue = self.target.EvaluateExpression('qtHookData[2]')
if versionValue.IsValid():
return ('', versionValue.unsigned)
except:
pass
return ('', self.fallbackQtVersion)
def qtVersionAndNamespace(self):
qtVersionAndNamespace = None
try:
qtVersionAndNamespace = self.fetchQtVersionAndNamespace()
DumperBase.warn("Detected Qt Version: 0x%0x (namespace='%s')" %
(qtVersionAndNamespace[1], qtVersionAndNamespace[0] or "no namespace"))
except Exception as e:
DumperBase.warn('[lldb] Error detecting Qt version: %s' % e)
try:
self.fetchInternalFunctions()
DumperBase.warn('Found function QObject::property: 0x%0x' % self.qtPropertyFunc)
DumperBase.warn('Found function QObject::customEvent: 0x%0x' % self.qtCustomEventFunc)
except Exception as e:
DumperBase.warn('[lldb] Error fetching internal Qt functions: %s' % e)
# Cache version information by overriding this function.
self.qtVersionAndNamespace = lambda: qtVersionAndNamespace
return qtVersionAndNamespace
def qtNamespace(self): def qtNamespace(self):
return self.qtVersionAndNamespace()[0] return self.qtVersionAndNamespace()[0]
def qtVersion(self): def qtVersion(self):
self.qtVersionAndNamespace()
return self.qtVersionAndNamespace()[1] return self.qtVersionAndNamespace()[1]
def handleCommand(self, command): def handleCommand(self, command):