From b2b6577d5c23ef3edec31b76bf34a391833dade8 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Fri, 19 Aug 2022 12:45:59 +0200 Subject: [PATCH] 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 --- share/qtcreator/debugger/lldbbridge.py | 52 ++++++++++++++++++++------ 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 7d094e736ed..211d74b2061 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -719,7 +719,18 @@ class Dumper(DumperBase): pass 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'): name = func.GetSymbol().GetName() if name.endswith('()'): @@ -755,24 +766,41 @@ class Dumper(DumperBase): qtVersion = 0x10000 * int(major) + 0x100 * int(minor) + int(patch) 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 ('', 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): return self.qtVersionAndNamespace()[0] def qtVersion(self): - self.qtVersionAndNamespace() return self.qtVersionAndNamespace()[1] def handleCommand(self, command):