Revert "Debugger: Drop support for backends relying on Python 2"

This reverts commit 43bcf91121.

GDB coming with MinGW shipped by Qt (e.g. 5.15  official) are still Python2 based.

Change-Id: Iad658de7a242345cc7f6081f26f0238071668a06
Reviewed-by: Denis Shienkov <denis.shienkov@gmail.com>
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Christian Stenger
2021-09-23 12:31:49 +00:00
parent 6b1421af8d
commit dde5a52693
3 changed files with 63 additions and 35 deletions

View File

@@ -46,6 +46,12 @@ except:
pass pass
if sys.version_info[0] >= 3:
toInteger = int
else:
toInteger = long
class ReportItem(): class ReportItem():
""" """
Helper structure to keep temporary 'best' information about a value Helper structure to keep temporary 'best' information about a value
@@ -511,7 +517,7 @@ class DumperBase():
item = item[:-1] item = item[:-1]
if item.endswith('u'): if item.endswith('u'):
item = item[:-1] item = item[:-1]
val = int(item) val = toInteger(item)
if val > 0x80000000: if val > 0x80000000:
val -= 0x100000000 val -= 0x100000000
res.append(val) res.append(val)
@@ -523,6 +529,9 @@ class DumperBase():
# Hex decoding operating on str, return str. # Hex decoding operating on str, return str.
@staticmethod @staticmethod
def hexdecode(s, encoding='utf8'): def hexdecode(s, encoding='utf8'):
if sys.version_info[0] == 2:
# For python2 we need an extra str() call to return str instead of unicode
return str(s.decode('hex').decode(encoding))
return bytes.fromhex(s).decode(encoding) return bytes.fromhex(s).decode(encoding)
# Hex encoding operating on str or bytes, return str. # Hex encoding operating on str or bytes, return str.
@@ -530,6 +539,10 @@ class DumperBase():
def hexencode(s): def hexencode(s):
if s is None: if s is None:
s = '' s = ''
if sys.version_info[0] == 2:
if isinstance(s, buffer):
return bytes(s).encode('hex')
return s.encode('hex')
if isinstance(s, str): if isinstance(s, str):
s = s.encode('utf8') s = s.encode('utf8')
return base64.b16encode(s).decode('utf8') return base64.b16encode(s).decode('utf8')
@@ -885,7 +898,7 @@ class DumperBase():
self.check(ref < 1000000) self.check(ref < 1000000)
def checkIntType(self, thing): def checkIntType(self, thing):
if not isinstance(thing, int): if not self.isInt(thing):
raise RuntimeError('Expected an integral value, got %s' % type(thing)) raise RuntimeError('Expected an integral value, got %s' % type(thing))
def readToFirstZero(self, base, tsize, maximum): def readToFirstZero(self, base, tsize, maximum):
@@ -1024,7 +1037,8 @@ class DumperBase():
def putType(self, typish, priority=0): def putType(self, typish, priority=0):
# Higher priority values override lower ones. # Higher priority values override lower ones.
if priority >= self.currentType.priority: if priority >= self.currentType.priority:
if isinstance(typish, str): types = (str) if sys.version_info[0] >= 3 else (str, unicode)
if isinstance(typish, types):
self.currentType.value = typish self.currentType.value = typish
else: else:
self.currentType.value = typish.name self.currentType.value = typish.name
@@ -1138,7 +1152,7 @@ class DumperBase():
def cleanAddress(self, addr): def cleanAddress(self, addr):
if addr is None: if addr is None:
return '<no address>' return '<no address>'
return '0x%x' % int(hex(addr), 16) return '0x%x' % toInteger(hex(addr), 16)
def stripNamespaceFromType(self, typeName): def stripNamespaceFromType(self, typeName):
ns = self.qtNamespace() ns = self.qtNamespace()
@@ -1708,7 +1722,7 @@ class DumperBase():
def split(self, pattern, value): def split(self, pattern, value):
if isinstance(value, self.Value): if isinstance(value, self.Value):
return value.split(pattern) return value.split(pattern)
if isinstance(value, int): if self.isInt(value):
val = self.Value(self) val = self.Value(self)
val.laddress = value val.laddress = value
return val.split(pattern) return val.split(pattern)
@@ -1773,12 +1787,12 @@ class DumperBase():
stringdataOffset = ptrSize stringdataOffset = ptrSize
if self.isWindowsTarget() and self.qtVersion() >= 0x060000: if self.isWindowsTarget() and self.qtVersion() >= 0x060000:
stringdataOffset += ptrSize # indirect super data member stringdataOffset += ptrSize # indirect super data member
stringdata = self.extractPointer(int(metaObjectPtr) + stringdataOffset) stringdata = self.extractPointer(toInteger(metaObjectPtr) + stringdataOffset)
def unpackString(base, size): def unpackString(base, size):
try: try:
s = struct.unpack_from('%ds' % size, self.readRawMemory(base, size))[0] s = struct.unpack_from('%ds' % size, self.readRawMemory(base, size))[0]
return s.decode('utf8') return s if sys.version_info[0] == 2 else s.decode('utf8')
except: except:
return '<not available>' return '<not available>'
@@ -1788,7 +1802,7 @@ class DumperBase():
if revision >= 7: # Qt 5. if revision >= 7: # Qt 5.
byteArrayDataSize = 24 if ptrSize == 8 else 16 byteArrayDataSize = 24 if ptrSize == 8 else 16
literal = stringdata + int(index) * byteArrayDataSize literal = stringdata + toInteger(index) * byteArrayDataSize
base, size, _ = self.qArrayDataHelper(literal) base, size, _ = self.qArrayDataHelper(literal)
return unpackString(base, size) return unpackString(base, size)
@@ -2324,7 +2338,7 @@ class DumperBase():
return self.extractSomething(value, 'b', 8) return self.extractSomething(value, 'b', 8)
def extractSomething(self, value, pattern, bitsize): def extractSomething(self, value, pattern, bitsize):
if isinstance(value, int): if self.isInt(value):
val = self.Value(self) val = self.Value(self)
val.laddress = value val.laddress = value
return val.extractSomething(pattern, bitsize) return val.extractSomething(pattern, bitsize)
@@ -2521,10 +2535,13 @@ class DumperBase():
return msg return msg
def reloadDumpers(self, args): def reloadDumpers(self, args):
import importlib
for mod in self.dumpermodules: for mod in self.dumpermodules:
m = sys.modules[mod] m = sys.modules[mod]
importlib.reload(m) if sys.version_info[0] >= 3:
import importlib
importlib.reload(m)
else:
reload(m)
self.setupDumpers(args) self.setupDumpers(args)
def loadDumpers(self, args): def loadDumpers(self, args):
@@ -2708,9 +2725,12 @@ class DumperBase():
def extractInterpreterStack(self): def extractInterpreterStack(self):
return self.sendInterpreterRequest('backtrace', {'limit': 10}) return self.sendInterpreterRequest('backtrace', {'limit': 10})
def isInt(self, thing): # Unused since 6.0 def isInt(self, thing):
if isinstance(thing, int): if isinstance(thing, int):
return True return True
if sys.version_info[0] == 2:
if isinstance(thing, long):
return True
return False return False
def putItems(self, count, generator, maxNumChild=10000): def putItems(self, count, generator, maxNumChild=10000):
@@ -2943,7 +2963,7 @@ class DumperBase():
return self._type return self._type
def check(self): def check(self):
if self.laddress is not None and not isinstance(self.laddress, int): if self.laddress is not None and not self.dumper.isInt(self.laddress):
raise RuntimeError('INCONSISTENT ADDRESS: %s' % type(self.laddress)) raise RuntimeError('INCONSISTENT ADDRESS: %s' % type(self.laddress))
if self.type is not None and not isinstance(self.type, self.dumper.Type): if self.type is not None and not isinstance(self.type, self.dumper.Type):
raise RuntimeError('INCONSISTENT TYPE: %s' % type(self.type)) raise RuntimeError('INCONSISTENT TYPE: %s' % type(self.type))
@@ -2975,6 +2995,8 @@ class DumperBase():
if simple is not None: if simple is not None:
return str(simple) return str(simple)
#if self.ldata is not None: #if self.ldata is not None:
# if sys.version_info[0] == 2 and isinstance(self.ldata, buffer):
# return bytes(self.ldata).encode('hex')
# return self.ldata.encode('hex') # return self.ldata.encode('hex')
if self.laddress is not None: if self.laddress is not None:
return 'value of type %s at address 0x%x' % (self.type.name, self.laddress) return 'value of type %s at address 0x%x' % (self.type.name, self.laddress)
@@ -3116,7 +3138,7 @@ class DumperBase():
return res return res
elif isinstance(index, self.dumper.Field): elif isinstance(index, self.dumper.Field):
field = index field = index
elif isinstance(index, int): elif self.dumper.isInt(index):
if self.type.code == TypeCode.Array: if self.type.code == TypeCode.Array:
addr = self.laddress + int(index) * self.type.ltarget.size() addr = self.laddress + int(index) * self.type.ltarget.size()
return self.dumper.createValue(addr, self.type.ltarget) return self.dumper.createValue(addr, self.type.ltarget)
@@ -3179,7 +3201,10 @@ class DumperBase():
lbyte = ldata[i] lbyte = ldata[i]
else: else:
lbyte = ldata[fieldOffset + fieldSize - 1 - i] lbyte = ldata[fieldOffset + fieldSize - 1 - i]
data += lbyte if sys.version_info[0] >= 3:
data += lbyte
else:
data += ord(lbyte)
data = data >> fieldBitpos data = data >> fieldBitpos
data = data & ((1 << fieldBitsize) - 1) data = data & ((1 << fieldBitsize) - 1)
val.lvalue = data val.lvalue = data
@@ -3238,7 +3263,7 @@ class DumperBase():
def __add__(self, other): def __add__(self, other):
self.check() self.check()
if isinstance(other, int): if self.dumper.isInt(other):
stripped = self.type.stripTypedefs() stripped = self.type.stripTypedefs()
if stripped.code == TypeCode.Pointer: if stripped.code == TypeCode.Pointer:
address = self.pointer() + stripped.dereference().size() * other address = self.pointer() + stripped.dereference().size() * other
@@ -3312,7 +3337,10 @@ class DumperBase():
def zeroExtend(self, data, size): def zeroExtend(self, data, size):
ext = '\0' * (size - len(data)) ext = '\0' * (size - len(data))
pad = bytes(ext, encoding='latin1') if sys.version_info[0] == 3:
pad = bytes(ext, encoding='latin1')
else:
pad = bytes(ext)
return pad + data if self.dumper.isBigEndian else data + pad return pad + data if self.dumper.isBigEndian else data + pad
def cast(self, typish): def cast(self, typish):
@@ -3406,7 +3434,7 @@ class DumperBase():
return tuple(map(structFixer, fields, result)) return tuple(map(structFixer, fields, result))
def checkPointer(self, p, align=1): def checkPointer(self, p, align=1):
ptr = p if isinstance(p, int) else p.pointer() ptr = p if self.isInt(p) else p.pointer()
self.readRawMemory(ptr, 1) self.readRawMemory(ptr, 1)
def type(self, typeId): def type(self, typeId):
@@ -3522,7 +3550,7 @@ class DumperBase():
% (tdata.name, tdata.lbitsize, tdata.code) % (tdata.name, tdata.lbitsize, tdata.code)
def __getitem__(self, index): def __getitem__(self, index):
if isinstance(index, int): if self.dumper.isInt(index):
return self.templateArgument(index) return self.templateArgument(index)
raise RuntimeError('CANNOT INDEX TYPE') raise RuntimeError('CANNOT INDEX TYPE')
@@ -3715,7 +3743,7 @@ class DumperBase():
return 'I' if self.ptrSize() == 4 else 'Q' return 'I' if self.ptrSize() == 4 else 'Q'
def toPointerData(self, address): def toPointerData(self, address):
if not isinstance(address, int): if not self.isInt(address):
raise RuntimeError('wrong') raise RuntimeError('wrong')
return bytes(struct.pack(self.packCode + self.ptrCode(), address)) return bytes(struct.pack(self.packCode + self.ptrCode(), address))
@@ -3726,7 +3754,7 @@ class DumperBase():
if not isinstance(targetTypish, self.Type) and not isinstance(targetTypish, str): if not isinstance(targetTypish, self.Type) and not isinstance(targetTypish, str):
raise RuntimeError('Expected type in createPointerValue(), got %s' raise RuntimeError('Expected type in createPointerValue(), got %s'
% type(targetTypish)) % type(targetTypish))
if not isinstance(targetAddress, int): if not self.isInt(targetAddress):
raise RuntimeError('Expected integral address value in createPointerValue(), got %s' raise RuntimeError('Expected integral address value in createPointerValue(), got %s'
% type(targetTypish)) % type(targetTypish))
val = self.Value(self) val = self.Value(self)
@@ -3741,7 +3769,7 @@ class DumperBase():
if not isinstance(targetType, self.Type): if not isinstance(targetType, self.Type):
raise RuntimeError('Expected type in createReferenceValue(), got %s' raise RuntimeError('Expected type in createReferenceValue(), got %s'
% type(targetType)) % type(targetType))
if not isinstance(targetAddress, int): if not self.isInt(targetAddress):
raise RuntimeError('Expected integral address value in createReferenceValue(), got %s' raise RuntimeError('Expected integral address value in createReferenceValue(), got %s'
% type(targetType)) % type(targetType))
val = self.Value(self) val = self.Value(self)
@@ -3925,7 +3953,7 @@ class DumperBase():
def createValue(self, datish, typish): def createValue(self, datish, typish):
val = self.Value(self) val = self.Value(self)
val._type = self.createType(typish) val._type = self.createType(typish)
if isinstance(datish, int): # Used as address. if self.isInt(datish): # Used as address.
#DumperBase.warn('CREATING %s AT 0x%x' % (val.type.name, datish)) #DumperBase.warn('CREATING %s AT 0x%x' % (val.type.name, datish))
val.laddress = datish val.laddress = datish
if self.useDynamicType: if self.useDynamicType:

View File

@@ -36,7 +36,7 @@ import sys
import struct import struct
import tempfile import tempfile
from dumper import DumperBase, Children, TopLevelItem from dumper import DumperBase, Children, toInteger, TopLevelItem
from utils import TypeCode from utils import TypeCode
from gdbtracepoint import * from gdbtracepoint import *
@@ -259,7 +259,7 @@ class Dumper(DumperBase):
code = nativeType.code code = nativeType.code
if code == gdb.TYPE_CODE_REF: if code == gdb.TYPE_CODE_REF:
targetType = self.fromNativeType(nativeType.target().unqualified()) targetType = self.fromNativeType(nativeType.target().unqualified())
val = self.createReferenceValue(int(nativeValue.address), targetType) val = self.createReferenceValue(toInteger(nativeValue.address), targetType)
val.nativeValue = nativeValue val.nativeValue = nativeValue
#DumperBase.warn('CREATED REF: %s' % val) #DumperBase.warn('CREATED REF: %s' % val)
return val return val
@@ -269,7 +269,7 @@ class Dumper(DumperBase):
except: except:
nativeTargetValue = None nativeTargetValue = None
targetType = self.fromNativeType(nativeType.target().unqualified()) targetType = self.fromNativeType(nativeType.target().unqualified())
val = self.createPointerValue(int(nativeValue), targetType) val = self.createPointerValue(toInteger(nativeValue), targetType)
# The nativeValue is needed in case of multiple inheritance, see # The nativeValue is needed in case of multiple inheritance, see
# QTCREATORBUG-17823. Using it triggers nativeValueDereferencePointer() # QTCREATORBUG-17823. Using it triggers nativeValueDereferencePointer()
# later which # later which
@@ -277,7 +277,7 @@ class Dumper(DumperBase):
val.nativeValue = nativeValue val.nativeValue = nativeValue
#DumperBase.warn('CREATED PTR 1: %s' % val) #DumperBase.warn('CREATED PTR 1: %s' % val)
if nativeValue.address is not None: if nativeValue.address is not None:
val.laddress = int(nativeValue.address) val.laddress = toInteger(nativeValue.address)
#DumperBase.warn('CREATED PTR 2: %s' % val) #DumperBase.warn('CREATED PTR 2: %s' % val)
return val return val
if code == gdb.TYPE_CODE_TYPEDEF: if code == gdb.TYPE_CODE_TYPEDEF:
@@ -300,7 +300,7 @@ class Dumper(DumperBase):
val.nativeValue = nativeValue val.nativeValue = nativeValue
if nativeValue.address is not None: if nativeValue.address is not None:
val.laddress = int(nativeValue.address) val.laddress = toInteger(nativeValue.address)
else: else:
size = nativeType.sizeof size = nativeType.sizeof
chars = self.lookupNativeType('unsigned char') chars = self.lookupNativeType('unsigned char')
@@ -834,7 +834,7 @@ class Dumper(DumperBase):
#DumperBase.warn('EXP: %s' % exp) #DumperBase.warn('EXP: %s' % exp)
res = gdb.parse_and_eval(exp) res = gdb.parse_and_eval(exp)
#DumperBase.warn('RES: %s' % res) #DumperBase.warn('RES: %s' % res)
return int(res) return toInteger(res)
def releaseValue(self, address): def releaseValue(self, address):
gdb.parse_and_eval('free(0x%x)' % address) gdb.parse_and_eval('free(0x%x)' % address)
@@ -874,12 +874,12 @@ class Dumper(DumperBase):
return 0 return 0
try: try:
# Older GDB ~7.4 don't have gdb.Symbol.value() # Older GDB ~7.4 don't have gdb.Symbol.value()
return int(symbol.value().address) return toInteger(symbol.value().address)
except: except:
pass pass
address = gdb.parse_and_eval("&'%s'" % symbolName) address = gdb.parse_and_eval("&'%s'" % symbolName)
return int(address) return toInteger(address)
def isArmArchitecture(self): def isArmArchitecture(self):
return 'arm' in gdb.TARGET_CONFIG.lower() return 'arm' in gdb.TARGET_CONFIG.lower()
@@ -1059,7 +1059,7 @@ class Dumper(DumperBase):
def findSymbol(self, symbolName): def findSymbol(self, symbolName):
try: try:
return int(gdb.parse_and_eval("(size_t)&'%s'" % symbolName)) return toInteger(gdb.parse_and_eval("(size_t)&'%s'" % symbolName))
except: except:
return 0 return 0
@@ -1371,7 +1371,7 @@ class Dumper(DumperBase):
if typeobj.code == gdb.TYPE_CODE_PTR: if typeobj.code == gdb.TYPE_CODE_PTR:
dereftype = typeobj.target().unqualified() dereftype = typeobj.target().unqualified()
if dereftype.name == needle: if dereftype.name == needle:
addr = int(value) addr = toInteger(value)
res = None res = None
for pat in pats: for pat in pats:
try: try:

View File

@@ -26,7 +26,7 @@
import platform import platform
import struct import struct
import re import re
from dumper import Children, SubItem, UnnamedSubItem, DumperBase from dumper import Children, SubItem, UnnamedSubItem, toInteger, DumperBase
from utils import DisplayFormat, TypeCode from utils import DisplayFormat, TypeCode
@@ -3106,7 +3106,7 @@ def qdumpHelper_QJsonValue(d, data, base, pv):
if t == 2: if t == 2:
d.putType('QJsonValue (Number)') d.putType('QJsonValue (Number)')
if latinOrIntValue: if latinOrIntValue:
w = int(v) w = toInteger(v)
if w >= 0x4000000: if w >= 0x4000000:
w -= 0x8000000 w -= 0x8000000
d.putValue(w) d.putValue(w)